Setup wizard - all UI steps
This commit is contained in:
parent
04be7ebab3
commit
bb45618447
@ -18,6 +18,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
### Fixed
|
||||
- Auth: Authentication would fail if email has uppercase chars and provider callback is in lowercase
|
||||
- Markdown: Fixed potential crash on markdown processing of video links
|
||||
- Search: Search index should now update upon article creation
|
||||
- Search: Search results are no longer duplicated upon article update
|
||||
- UI: Missing icons on login page
|
||||
|
134
agent.js
134
agent.js
@ -49,38 +49,41 @@ var Cron = require('cron').CronJob
|
||||
// Start Cron
|
||||
// ----------------------------------------
|
||||
|
||||
var job
|
||||
var jobIsBusy = false
|
||||
var jobUplWatchStarted = false
|
||||
|
||||
var job = new Cron({
|
||||
cronTime: '0 */5 * * * *',
|
||||
onTick: () => {
|
||||
// Make sure we don't start two concurrent jobs
|
||||
db.onReady.then(() => {
|
||||
return db.Entry.remove({})
|
||||
}).then(() => {
|
||||
job = new Cron({
|
||||
cronTime: '0 */5 * * * *',
|
||||
onTick: () => {
|
||||
// Make sure we don't start two concurrent jobs
|
||||
|
||||
if (jobIsBusy) {
|
||||
winston.warn('[AGENT] Previous job has not completed gracefully or is still running! Skipping for now. (This is not normal, you should investigate)')
|
||||
return
|
||||
}
|
||||
winston.info('[AGENT] Running all jobs...')
|
||||
jobIsBusy = true
|
||||
if (jobIsBusy) {
|
||||
winston.warn('[AGENT] Previous job has not completed gracefully or is still running! Skipping for now. (This is not normal, you should investigate)')
|
||||
return
|
||||
}
|
||||
winston.info('[AGENT] Running all jobs...')
|
||||
jobIsBusy = true
|
||||
|
||||
// Prepare async job collector
|
||||
// Prepare async job collector
|
||||
|
||||
let jobs = []
|
||||
let repoPath = path.resolve(ROOTPATH, appconfig.paths.repo)
|
||||
let dataPath = path.resolve(ROOTPATH, appconfig.paths.data)
|
||||
let uploadsTempPath = path.join(dataPath, 'temp-upload')
|
||||
let jobs = []
|
||||
let repoPath = path.resolve(ROOTPATH, appconfig.paths.repo)
|
||||
let dataPath = path.resolve(ROOTPATH, appconfig.paths.data)
|
||||
let uploadsTempPath = path.join(dataPath, 'temp-upload')
|
||||
|
||||
// ----------------------------------------
|
||||
// REGULAR JOBS
|
||||
// ----------------------------------------
|
||||
// ----------------------------------------
|
||||
// REGULAR JOBS
|
||||
// ----------------------------------------
|
||||
|
||||
//* ****************************************
|
||||
// -> Sync with Git remote
|
||||
//* ****************************************
|
||||
//* ****************************************
|
||||
// -> Sync with Git remote
|
||||
//* ****************************************
|
||||
|
||||
jobs.push(git.onReady.then(() => {
|
||||
return git.resync().then(() => {
|
||||
jobs.push(git.resync().then(() => {
|
||||
// -> Stream all documents
|
||||
|
||||
let cacheJobs = []
|
||||
@ -131,55 +134,56 @@ var job = new Cron({
|
||||
})
|
||||
|
||||
return jobCbStreamDocs
|
||||
})
|
||||
}))
|
||||
}))
|
||||
|
||||
//* ****************************************
|
||||
// -> Clear failed temporary upload files
|
||||
//* ****************************************
|
||||
//* ****************************************
|
||||
// -> Clear failed temporary upload files
|
||||
//* ****************************************
|
||||
|
||||
jobs.push(
|
||||
fs.readdirAsync(uploadsTempPath).then((ls) => {
|
||||
let fifteenAgo = moment().subtract(15, 'minutes')
|
||||
jobs.push(
|
||||
fs.readdirAsync(uploadsTempPath).then((ls) => {
|
||||
let fifteenAgo = moment().subtract(15, 'minutes')
|
||||
|
||||
return Promise.map(ls, (f) => {
|
||||
return fs.statAsync(path.join(uploadsTempPath, f)).then((s) => { return { filename: f, stat: s } })
|
||||
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
|
||||
return Promise.map(arrFiles, (f) => {
|
||||
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
|
||||
return fs.unlinkAsync(path.join(uploadsTempPath, f.filename))
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
return Promise.map(ls, (f) => {
|
||||
return fs.statAsync(path.join(uploadsTempPath, f)).then((s) => { return { filename: f, stat: s } })
|
||||
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
|
||||
return Promise.map(arrFiles, (f) => {
|
||||
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
|
||||
return fs.unlinkAsync(path.join(uploadsTempPath, f.filename))
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
// ----------------------------------------
|
||||
// Run
|
||||
// ----------------------------------------
|
||||
|
||||
Promise.all(jobs).then(() => {
|
||||
winston.info('[AGENT] All jobs completed successfully! Going to sleep for now.')
|
||||
|
||||
if (!jobUplWatchStarted) {
|
||||
jobUplWatchStarted = true
|
||||
upl.initialScan().then(() => {
|
||||
job.start()
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
}).catch((err) => {
|
||||
winston.error('[AGENT] One or more jobs have failed: ', err)
|
||||
}).finally(() => {
|
||||
jobIsBusy = false
|
||||
})
|
||||
)
|
||||
},
|
||||
start: false,
|
||||
timeZone: 'UTC',
|
||||
runOnInit: true
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// Run
|
||||
// ----------------------------------------
|
||||
|
||||
Promise.all(jobs).then(() => {
|
||||
winston.info('[AGENT] All jobs completed successfully! Going to sleep for now.')
|
||||
|
||||
if (!jobUplWatchStarted) {
|
||||
jobUplWatchStarted = true
|
||||
upl.initialScan().then(() => {
|
||||
job.start()
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
}).catch((err) => {
|
||||
winston.error('[AGENT] One or more jobs have failed: ', err)
|
||||
}).finally(() => {
|
||||
jobIsBusy = false
|
||||
})
|
||||
},
|
||||
start: false,
|
||||
timeZone: 'UTC',
|
||||
runOnInit: true
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
|
22
app/data.yml
22
app/data.yml
@ -50,4 +50,26 @@ defaults:
|
||||
signature:
|
||||
name: Wiki
|
||||
email: wiki@example.com
|
||||
langs:
|
||||
-
|
||||
id: en
|
||||
name: English
|
||||
-
|
||||
id: fr
|
||||
name: French - Français
|
||||
-
|
||||
id: de
|
||||
name: German - Deutsch
|
||||
-
|
||||
id: ko
|
||||
name: Korean - 한국어
|
||||
-
|
||||
id: pt
|
||||
name: Portuguese - Português
|
||||
-
|
||||
id: ru
|
||||
name: Russian - Русский
|
||||
-
|
||||
id: es
|
||||
name: Spanish - Español
|
||||
# ---------------------------------
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
"use strict";jQuery(document).ready(function(t){new Vue({el:"main",data:{loading:!1,state:"considerations",syscheck:{ok:!1,error:"",results:[]},conf:{title:"Wiki",host:"",port:80,lang:"en",db:"mongodb://localhost:27017/wiki"},considerations:{https:!1,port:!1,localhost:!1}},methods:{proceedToWelcome:function(t){this.state="welcome",this.loading=!1},proceedToSyscheck:function(t){var s=this;this.state="syscheck",this.loading=!0,s.syscheck={ok:!1,error:"",results:[]},_.delay(function(){axios.post("/syscheck").then(function(t){t.data.ok===!0?(s.syscheck.ok=!0,s.syscheck.results=t.data.results):(s.syscheck.ok=!1,s.syscheck.error=t.data.error),s.loading=!1,s.$nextTick()}).catch(function(t){window.alert(t.message)})},1e3)},proceedToGeneral:function(t){this.state="general",this.loading=!1},proceedToConsiderations:function(t){this.considerations={https:!_.startsWith(this.conf.host,"https"),port:!1,localhost:_.includes(this.conf.host,"localhost")},this.state="considerations",this.loading=!1},proceedToDb:function(t){this.state="db",this.loading=!1}}})});
|
||||
"use strict";Vue.use(VeeValidate,{enableAutoClasses:!0,classNames:{touched:"is-touched",untouched:"is-untouched",valid:"is-valid",invalid:"is-invalid",pristine:"is-pristine",dirty:"is-dirty"}}),jQuery(document).ready(function(t){new Vue({el:"main",data:{loading:!1,state:"welcome",syscheck:{ok:!1,error:"",results:[]},dbcheck:{ok:!1,error:""},gitcheck:{ok:!1,error:""},final:{ok:!1,error:"",results:[]},conf:{title:"Wiki",host:"http://",port:80,lang:"en",db:"mongodb://localhost:27017/wiki",pathData:"./data",pathRepo:"./repo",gitUrl:"",gitBranch:"master",gitAuthType:"ssh",gitAuthSSHKey:"",gitAuthUser:"",gitAuthPass:"",gitAuthSSL:!0,gitSignatureName:"",gitSignatureEmail:"",adminEmail:"",adminPassword:"",adminPasswordConfirm:""},considerations:{https:!1,port:!1,localhost:!1}},computed:{currentProgress:function(){var t="0%";switch(this.state){case"welcome":t="0%";break;case"syscheck":t=this.syscheck.ok?"15%":"5%";break;case"general":t="20%";break;case"considerations":t="30%";break;case"db":t="35%";break;case"dbcheck":t=this.dbcheck.ok?"50%":"40%";break;case"paths":t="55%";break;case"git":t="60%";break;case"gitcheck":t=this.gitcheck.ok?"75%":"65%";break;case"admin":t="80%"}return t}},methods:{proceedToWelcome:function(t){this.state="welcome",this.loading=!1},proceedToSyscheck:function(t){var e=this;this.state="syscheck",this.loading=!0,e.syscheck={ok:!1,error:"",results:[]},_.delay(function(){axios.post("/syscheck").then(function(t){t.data.ok===!0?(e.syscheck.ok=!0,e.syscheck.results=t.data.results):(e.syscheck.ok=!1,e.syscheck.error=t.data.error),e.loading=!1,e.$nextTick()}).catch(function(t){window.alert(t.message)})},1e3)},proceedToGeneral:function(t){var e=this;e.state="general",e.loading=!1,e.$nextTick(function(){e.$validator.validateAll("general")})},proceedToConsiderations:function(t){this.considerations={https:!_.startsWith(this.conf.host,"https"),port:!1,localhost:_.includes(this.conf.host,"localhost")},this.state="considerations",this.loading=!1},proceedToDb:function(t){var e=this;e.state="db",e.loading=!1,e.$nextTick(function(){e.$validator.validateAll("db")})},proceedToDbcheck:function(t){var e=this;this.state="dbcheck",this.loading=!0,e.dbcheck={ok:!1,error:""},_.delay(function(){axios.post("/dbcheck",{db:e.conf.db}).then(function(t){t.data.ok===!0?e.dbcheck.ok=!0:(e.dbcheck.ok=!1,e.dbcheck.error=t.data.error),e.loading=!1,e.$nextTick()}).catch(function(t){window.alert(t.message)})},1e3)},proceedToPaths:function(t){var e=this;e.state="paths",e.loading=!1,e.$nextTick(function(){e.$validator.validateAll("paths")})},proceedToGit:function(t){var e=this;e.state="git",e.loading=!1,e.$nextTick(function(){e.$validator.validateAll("git")})},proceedToGitCheck:function(t){var e=this;this.state="gitcheck",this.loading=!0,e.dbcheck={ok:!1,error:""},_.delay(function(){axios.post("/gitcheck",e.conf).then(function(t){t.data.ok===!0?e.gitcheck.ok=!0:(e.gitcheck.ok=!1,e.gitcheck.error=t.data.error),e.loading=!1,e.$nextTick()}).catch(function(t){window.alert(t.message)})},1e3)},proceedToAdmin:function(t){var e=this;e.state="admin",e.loading=!1,e.$nextTick(function(){e.$validator.validateAll("admin")})},proceedToFinal:function(t){var e=this;e.state="final",e.loading=!0,e.final={ok:!1,error:"",results:[]},_.delay(function(){axios.post("/finalize",e.conf).then(function(t){t.data.ok===!0?(e.final.ok=!0,e.final.results=t.data.results):(e.final.ok=!1,e.final.error=t.data.error),e.loading=!1,e.$nextTick()}).catch(function(t){window.alert(t.message)})},1e3)},finish:function(t){}}})});
|
File diff suppressed because one or more lines are too long
@ -93,6 +93,7 @@ if ($('#mk-editor').length === 1) {
|
||||
mdeModalOpenState = true;
|
||||
$('#modal-editor-link').slideToggle();
|
||||
} */
|
||||
window.alert('Coming soon!')
|
||||
},
|
||||
className: 'icon-link2',
|
||||
title: 'Insert Link'
|
||||
@ -163,6 +164,7 @@ if ($('#mk-editor').length === 1) {
|
||||
{
|
||||
name: 'table',
|
||||
action: (editor) => {
|
||||
window.alert('Coming soon!')
|
||||
// todo
|
||||
},
|
||||
className: 'icon-table',
|
||||
|
@ -1,24 +1,63 @@
|
||||
'use strict'
|
||||
|
||||
/* global jQuery, _, Vue, axios */
|
||||
/* global jQuery, _, Vue, VeeValidate, axios */
|
||||
|
||||
Vue.use(VeeValidate, {
|
||||
enableAutoClasses: true,
|
||||
classNames: {
|
||||
touched: 'is-touched', // the control has been blurred
|
||||
untouched: 'is-untouched', // the control hasn't been blurred
|
||||
valid: 'is-valid', // model is valid
|
||||
invalid: 'is-invalid', // model is invalid
|
||||
pristine: 'is-pristine', // control has not been interacted with
|
||||
dirty: 'is-dirty' // control has been interacted with
|
||||
}
|
||||
})
|
||||
|
||||
jQuery(document).ready(function ($) {
|
||||
new Vue({ // eslint-disable-line no-new
|
||||
el: 'main',
|
||||
data: {
|
||||
loading: false,
|
||||
state: 'considerations',
|
||||
state: 'welcome',
|
||||
syscheck: {
|
||||
ok: false,
|
||||
error: '',
|
||||
results: []
|
||||
},
|
||||
dbcheck: {
|
||||
ok: false,
|
||||
error: ''
|
||||
},
|
||||
gitcheck: {
|
||||
ok: false,
|
||||
error: ''
|
||||
},
|
||||
final: {
|
||||
ok: false,
|
||||
error: '',
|
||||
results: []
|
||||
},
|
||||
conf: {
|
||||
title: 'Wiki',
|
||||
host: '',
|
||||
host: 'http://',
|
||||
port: 80,
|
||||
lang: 'en',
|
||||
db: 'mongodb://localhost:27017/wiki'
|
||||
db: 'mongodb://localhost:27017/wiki',
|
||||
pathData: './data',
|
||||
pathRepo: './repo',
|
||||
gitUrl: '',
|
||||
gitBranch: 'master',
|
||||
gitAuthType: 'ssh',
|
||||
gitAuthSSHKey: '',
|
||||
gitAuthUser: '',
|
||||
gitAuthPass: '',
|
||||
gitAuthSSL: true,
|
||||
gitSignatureName: '',
|
||||
gitSignatureEmail: '',
|
||||
adminEmail: '',
|
||||
adminPassword: '',
|
||||
adminPasswordConfirm: ''
|
||||
},
|
||||
considerations: {
|
||||
https: false,
|
||||
@ -26,6 +65,44 @@ jQuery(document).ready(function ($) {
|
||||
localhost: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentProgress: function () {
|
||||
let perc = '0%'
|
||||
switch (this.state) {
|
||||
case 'welcome':
|
||||
perc = '0%'
|
||||
break
|
||||
case 'syscheck':
|
||||
perc = (this.syscheck.ok) ? '15%' : '5%'
|
||||
break
|
||||
case 'general':
|
||||
perc = '20%'
|
||||
break
|
||||
case 'considerations':
|
||||
perc = '30%'
|
||||
break
|
||||
case 'db':
|
||||
perc = '35%'
|
||||
break
|
||||
case 'dbcheck':
|
||||
perc = (this.dbcheck.ok) ? '50%' : '40%'
|
||||
break
|
||||
case 'paths':
|
||||
perc = '55%'
|
||||
break
|
||||
case 'git':
|
||||
perc = '60%'
|
||||
break
|
||||
case 'gitcheck':
|
||||
perc = (this.gitcheck.ok) ? '75%' : '65%'
|
||||
break
|
||||
case 'admin':
|
||||
perc = '80%'
|
||||
break
|
||||
}
|
||||
return perc
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
proceedToWelcome: function (ev) {
|
||||
this.state = 'welcome'
|
||||
@ -58,8 +135,12 @@ jQuery(document).ready(function ($) {
|
||||
}, 1000)
|
||||
},
|
||||
proceedToGeneral: function (ev) {
|
||||
this.state = 'general'
|
||||
this.loading = false
|
||||
let self = this
|
||||
self.state = 'general'
|
||||
self.loading = false
|
||||
self.$nextTick(() => {
|
||||
self.$validator.validateAll('general')
|
||||
})
|
||||
},
|
||||
proceedToConsiderations: function (ev) {
|
||||
this.considerations = {
|
||||
@ -71,8 +152,115 @@ jQuery(document).ready(function ($) {
|
||||
this.loading = false
|
||||
},
|
||||
proceedToDb: function (ev) {
|
||||
this.state = 'db'
|
||||
this.loading = false
|
||||
let self = this
|
||||
self.state = 'db'
|
||||
self.loading = false
|
||||
self.$nextTick(() => {
|
||||
self.$validator.validateAll('db')
|
||||
})
|
||||
},
|
||||
proceedToDbcheck: function (ev) {
|
||||
let self = this
|
||||
this.state = 'dbcheck'
|
||||
this.loading = true
|
||||
self.dbcheck = {
|
||||
ok: false,
|
||||
error: ''
|
||||
}
|
||||
|
||||
_.delay(() => {
|
||||
axios.post('/dbcheck', {
|
||||
db: self.conf.db
|
||||
}).then(resp => {
|
||||
if (resp.data.ok === true) {
|
||||
self.dbcheck.ok = true
|
||||
} else {
|
||||
self.dbcheck.ok = false
|
||||
self.dbcheck.error = resp.data.error
|
||||
}
|
||||
self.loading = false
|
||||
self.$nextTick()
|
||||
}).catch(err => {
|
||||
window.alert(err.message)
|
||||
})
|
||||
}, 1000)
|
||||
},
|
||||
proceedToPaths: function (ev) {
|
||||
let self = this
|
||||
self.state = 'paths'
|
||||
self.loading = false
|
||||
self.$nextTick(() => {
|
||||
self.$validator.validateAll('paths')
|
||||
})
|
||||
},
|
||||
proceedToGit: function (ev) {
|
||||
let self = this
|
||||
self.state = 'git'
|
||||
self.loading = false
|
||||
self.$nextTick(() => {
|
||||
self.$validator.validateAll('git')
|
||||
})
|
||||
},
|
||||
proceedToGitCheck: function (ev) {
|
||||
let self = this
|
||||
this.state = 'gitcheck'
|
||||
this.loading = true
|
||||
self.dbcheck = {
|
||||
ok: false,
|
||||
error: ''
|
||||
}
|
||||
|
||||
_.delay(() => {
|
||||
axios.post('/gitcheck', self.conf).then(resp => {
|
||||
if (resp.data.ok === true) {
|
||||
self.gitcheck.ok = true
|
||||
} else {
|
||||
self.gitcheck.ok = false
|
||||
self.gitcheck.error = resp.data.error
|
||||
}
|
||||
self.loading = false
|
||||
self.$nextTick()
|
||||
}).catch(err => {
|
||||
window.alert(err.message)
|
||||
})
|
||||
}, 1000)
|
||||
},
|
||||
proceedToAdmin: function (ev) {
|
||||
let self = this
|
||||
self.state = 'admin'
|
||||
self.loading = false
|
||||
self.$nextTick(() => {
|
||||
self.$validator.validateAll('admin')
|
||||
})
|
||||
},
|
||||
proceedToFinal: function (ev) {
|
||||
let self = this
|
||||
self.state = 'final'
|
||||
self.loading = true
|
||||
self.final = {
|
||||
ok: false,
|
||||
error: '',
|
||||
results: []
|
||||
}
|
||||
|
||||
_.delay(() => {
|
||||
axios.post('/finalize', self.conf).then(resp => {
|
||||
if (resp.data.ok === true) {
|
||||
self.final.ok = true
|
||||
self.final.results = resp.data.results
|
||||
} else {
|
||||
self.final.ok = false
|
||||
self.final.error = resp.data.error
|
||||
}
|
||||
self.loading = false
|
||||
self.$nextTick()
|
||||
}).catch(err => {
|
||||
window.alert(err.message)
|
||||
})
|
||||
}, 1000)
|
||||
},
|
||||
finish: function (ev) {
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
if ($('#page-type-edit').length) {
|
||||
let pageEntryPath = $('#page-type-edit').data('entrypath') // eslint-disable-line no-unused-vars
|
||||
// let pageCleanExit = false
|
||||
|
||||
// -> Discard
|
||||
|
||||
@ -9,6 +10,10 @@ if ($('#page-type-edit').length) {
|
||||
$('#modal-edit-discard').toggleClass('is-active')
|
||||
})
|
||||
|
||||
// window.onbeforeunload = function () {
|
||||
// return (pageCleanExit) ? true : 'Unsaved modifications will be lost. Are you sure you want to navigate away from this page?'
|
||||
// }
|
||||
|
||||
/* eslint-disable spaced-comment */
|
||||
//=include ../components/editor.js
|
||||
/* eslint-enable spaced-comment */
|
||||
|
@ -1,13 +1,13 @@
|
||||
|
||||
.editor-toolbar {
|
||||
z-index: 2;
|
||||
background-color: rgba(0,0,0,0.75);
|
||||
background-color: mc('indigo', '900');
|
||||
border: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
opacity: 1;
|
||||
position: fixed;
|
||||
top: 51px;
|
||||
top: 50px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
|
||||
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
@ -140,7 +140,7 @@
|
||||
|
||||
> span {
|
||||
font-size: 12px;
|
||||
|
||||
|
||||
> strong {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@ -358,4 +358,4 @@
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
@ -53,3 +53,24 @@ i.icon-warning-outline {
|
||||
max-height: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 150px;
|
||||
height: 10px;
|
||||
background-color: mc('indigo', '50');
|
||||
border:1px solid mc('indigo', '100');
|
||||
border-radius: 3px;
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 21px;
|
||||
padding: 1px;
|
||||
|
||||
> div {
|
||||
width: 5px;
|
||||
height: 6px;
|
||||
background-color: mc('indigo', '200');
|
||||
border-radius: 2px;
|
||||
transition: all 1s ease;
|
||||
}
|
||||
|
||||
}
|
||||
|
116
configure.js
116
configure.js
@ -15,8 +15,11 @@ module.exports = (port, spinner) => {
|
||||
const http = require('http')
|
||||
const path = require('path')
|
||||
const Promise = require('bluebird')
|
||||
const fs = require('fs-extra')
|
||||
const yaml = require('js-yaml')
|
||||
const _ = require('lodash')
|
||||
|
||||
|
||||
// ----------------------------------------
|
||||
// Define Express App
|
||||
// ----------------------------------------
|
||||
@ -48,9 +51,20 @@ module.exports = (port, spinner) => {
|
||||
// ----------------------------------------
|
||||
|
||||
app.get('*', (req, res) => {
|
||||
res.render('configure/index')
|
||||
let langs = []
|
||||
try {
|
||||
langs = yaml.safeLoad(fs.readFileSync('./app/data.yml', 'utf8')).langs
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
res.render('configure/index', {
|
||||
langs
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Perform basic system checks
|
||||
*/
|
||||
app.post('/syscheck', (req, res) => {
|
||||
Promise.mapSeries([
|
||||
() => {
|
||||
@ -105,6 +119,106 @@ module.exports = (port, spinner) => {
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Check the DB connection
|
||||
*/
|
||||
app.post('/dbcheck', (req, res) => {
|
||||
let mongo = require('mongodb').MongoClient
|
||||
mongo.connect(req.body.db, {
|
||||
autoReconnect: false,
|
||||
reconnectTries: 2,
|
||||
reconnectInterval: 1000,
|
||||
connectTimeoutMS: 5000,
|
||||
socketTimeoutMS: 5000
|
||||
}, (err, db) => {
|
||||
if (err === null) {
|
||||
// Try to create a test collection
|
||||
db.createCollection('test', (err, results) => {
|
||||
if (err === null) {
|
||||
// Try to drop test collection
|
||||
db.dropCollection('test', (err, results) => {
|
||||
if (err === null) {
|
||||
res.json({ ok: true })
|
||||
} else {
|
||||
res.json({ ok: false, error: 'Unable to delete test collection. Verify permissions. ' + err.message })
|
||||
}
|
||||
db.close()
|
||||
})
|
||||
} else {
|
||||
res.json({ ok: false, error: 'Unable to create test collection. Verify permissions. ' + err.message })
|
||||
db.close()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
res.json({ ok: false, error: err.message })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Check the Git connection
|
||||
*/
|
||||
app.post('/gitcheck', (req, res) => {
|
||||
const exec = require('execa')
|
||||
|
||||
const dataDir = path.resolve(ROOTPATH, req.body.pathData)
|
||||
const gitDir = path.resolve(ROOTPATH, req.body.pathRepo)
|
||||
let results = []
|
||||
|
||||
fs.ensureDir(dataDir).then(() => {
|
||||
results.push('Data directory path is valid.')
|
||||
return fs.ensureDir(gitDir).then(() => {
|
||||
results.push('Git directory path is valid.')
|
||||
return true
|
||||
})
|
||||
}).then(() => {
|
||||
return exec.stdout('git', ['init'], { cwd: gitDir }).then(result => {
|
||||
results.push('Git local repository initialized.')
|
||||
return true
|
||||
})
|
||||
}).then(() => {
|
||||
return res.json({ ok: true, results })
|
||||
}).catch(err => {
|
||||
res.json({ ok: false, error: err.message })
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Check the DB connection
|
||||
*/
|
||||
app.post('/finalize', (req, res) => {
|
||||
let mongo = require('mongodb').MongoClient
|
||||
mongo.connect(req.body.db, {
|
||||
autoReconnect: false,
|
||||
reconnectTries: 2,
|
||||
reconnectInterval: 1000,
|
||||
connectTimeoutMS: 5000,
|
||||
socketTimeoutMS: 5000
|
||||
}, (err, db) => {
|
||||
if (err === null) {
|
||||
// Try to create a test collection
|
||||
db.createCollection('test', (err, results) => {
|
||||
if (err === null) {
|
||||
// Try to drop test collection
|
||||
db.dropCollection('test', (err, results) => {
|
||||
if (err === null) {
|
||||
res.json({ ok: true })
|
||||
} else {
|
||||
res.json({ ok: false, error: 'Unable to delete test collection. Verify permissions. ' + err.message })
|
||||
}
|
||||
db.close()
|
||||
})
|
||||
} else {
|
||||
res.json({ ok: false, error: 'Unable to create test collection. Verify permissions. ' + err.message })
|
||||
db.close()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
res.json({ ok: false, error: err.message })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// Error handling
|
||||
// ----------------------------------------
|
||||
|
@ -27,6 +27,7 @@ const paths = {
|
||||
'./node_modules/socket.io-client/dist/socket.io.min.js',
|
||||
'./node_modules/jquery/dist/jquery.min.js',
|
||||
'./node_modules/vue/dist/vue.min.js',
|
||||
'./node_modules/vee-validate/dist/vee-validate.min.js',
|
||||
'./node_modules/axios/dist/axios.min.js',
|
||||
'./node_modules/jquery-smooth-scroll/jquery.smooth-scroll.min.js',
|
||||
'./node_modules/jquery-simple-upload/simpleUpload.min.js',
|
||||
|
@ -152,7 +152,7 @@ module.exports = {
|
||||
return false
|
||||
}
|
||||
}).catch((err) => { // eslint-disable-line handle-callback-err
|
||||
return Promise.reject(new Promise.OperationalError('Entry ' + entryPath + ' does not exist!'))
|
||||
throw new Promise.OperationalError('Entry ' + entryPath + ' does not exist!')
|
||||
})
|
||||
},
|
||||
|
||||
@ -299,8 +299,7 @@ module.exports = {
|
||||
_id: content.entryPath,
|
||||
title: content.meta.title || content.entryPath,
|
||||
subtitle: content.meta.subtitle || '',
|
||||
parent: content.parent.title || '',
|
||||
content: content.text || ''
|
||||
parent: content.parent.title || ''
|
||||
}, {
|
||||
new: true,
|
||||
upsert: true
|
||||
@ -396,60 +395,5 @@ module.exports = {
|
||||
return fs.readFileAsync(path.join(ROOTPATH, 'client/content/create.md'), 'utf8').then((contents) => {
|
||||
return _.replace(contents, new RegExp('{TITLE}', 'g'), formattedTitle)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Searches entries based on terms.
|
||||
*
|
||||
* @param {String} terms The terms to search for
|
||||
* @return {Promise<Object>} Promise of the search results
|
||||
*/
|
||||
search (terms) {
|
||||
terms = _.chain(terms)
|
||||
.deburr()
|
||||
.toLower()
|
||||
.trim()
|
||||
.replace(/[^a-z0-9\- ]/g, '')
|
||||
.split(' ')
|
||||
.filter((f) => { return !_.isEmpty(f) })
|
||||
.join(' ')
|
||||
.value()
|
||||
|
||||
return db.Entry.find(
|
||||
{ $text: { $search: terms } },
|
||||
{ score: { $meta: 'textScore' }, title: 1 }
|
||||
)
|
||||
.sort({ score: { $meta: 'textScore' } })
|
||||
.limit(10)
|
||||
.exec()
|
||||
.then((hits) => {
|
||||
if (hits.length < 5) {
|
||||
let regMatch = new RegExp('^' + _.split(terms, ' ')[0])
|
||||
return db.Entry.find({
|
||||
_id: { $regex: regMatch }
|
||||
}, '_id')
|
||||
.sort('_id')
|
||||
.limit(5)
|
||||
.exec()
|
||||
.then((matches) => {
|
||||
return {
|
||||
match: hits,
|
||||
suggest: (matches) ? _.map(matches, '_id') : []
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return {
|
||||
match: _.filter(hits, (h) => { return h._doc.score >= 1 }),
|
||||
suggest: []
|
||||
}
|
||||
}
|
||||
}).catch((err) => {
|
||||
winston.error(err)
|
||||
return {
|
||||
match: [],
|
||||
suggest: []
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -231,10 +231,8 @@ module.exports = {
|
||||
*/
|
||||
generateThumbnail (sourcePath, destPath) {
|
||||
return jimp.read(sourcePath).then(img => {
|
||||
return img.cover(150, 150)
|
||||
.background(0xFFFFFFFF)
|
||||
.opaque()
|
||||
.rgba(false)
|
||||
return img
|
||||
.contain(150, 150)
|
||||
.write(destPath)
|
||||
})
|
||||
},
|
||||
|
@ -21,10 +21,6 @@ var entrySchema = Mongoose.Schema({
|
||||
parent: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
|
||||
},
|
||||
@ -32,19 +28,4 @@ var entrySchema = Mongoose.Schema({
|
||||
timestamps: {}
|
||||
})
|
||||
|
||||
entrySchema.index({
|
||||
_id: 'text',
|
||||
title: 'text',
|
||||
subtitle: 'text',
|
||||
content: 'text'
|
||||
}, {
|
||||
weights: {
|
||||
_id: 3,
|
||||
title: 10,
|
||||
subtitle: 5,
|
||||
content: 1
|
||||
},
|
||||
name: 'EntriesTextIndex'
|
||||
})
|
||||
|
||||
module.exports = Mongoose.model('Entry', entrySchema)
|
||||
|
47
package.json
47
package.json
@ -41,7 +41,7 @@
|
||||
"bcryptjs-then": "^1.0.1",
|
||||
"bluebird": "^3.4.7",
|
||||
"body-parser": "^1.17.1",
|
||||
"bunyan": "^1.8.8",
|
||||
"bunyan": "^1.8.9",
|
||||
"cheerio": "^0.22.0",
|
||||
"child-process-promise": "^2.2.0",
|
||||
"chokidar": "^1.6.0",
|
||||
@ -51,21 +51,22 @@
|
||||
"connect-mongo": "^1.3.2",
|
||||
"cookie-parser": "^1.4.3",
|
||||
"cron": "^1.2.1",
|
||||
"execa": "^0.6.3",
|
||||
"express": "^4.15.2",
|
||||
"express-brute": "^1.0.0",
|
||||
"express-brute-mongoose": "0.0.7",
|
||||
"express-session": "^1.15.1",
|
||||
"file-type": "^4.0.0",
|
||||
"filesize.js": "^1.0.2",
|
||||
"follow-redirects": "^1.2.1",
|
||||
"fs-extra": "^2.0.0",
|
||||
"follow-redirects": "^1.2.3",
|
||||
"fs-extra": "^2.1.2",
|
||||
"git-wrapper2-promise": "^0.2.9",
|
||||
"highlight.js": "^9.9.0",
|
||||
"i18next": "^7.1.1",
|
||||
"i18next-express-middleware": "^1.0.2",
|
||||
"i18next": "^7.1.3",
|
||||
"i18next-express-middleware": "^1.0.3",
|
||||
"i18next-node-fs-backend": "^0.1.3",
|
||||
"image-size": "^0.5.1",
|
||||
"jimp": "github:NGPixel/jimp",
|
||||
"jimp": "github:ngpixel/jimp",
|
||||
"js-yaml": "^3.8.1",
|
||||
"klaw": "^1.3.1",
|
||||
"levelup": "^1.3.5",
|
||||
@ -80,12 +81,13 @@
|
||||
"markdown-it-footnote": "^3.0.1",
|
||||
"markdown-it-task-lists": "^1.4.1",
|
||||
"memdown": "^1.2.4",
|
||||
"mime-types": "^2.1.13",
|
||||
"moment": "^2.17.1",
|
||||
"mime-types": "^2.1.15",
|
||||
"moment": "^2.18.1",
|
||||
"moment-timezone": "^0.5.11",
|
||||
"mongoose": "^4.8.5",
|
||||
"mongodb": "^2.2.25",
|
||||
"mongoose": "^4.9.1",
|
||||
"multer": "^1.2.1",
|
||||
"ora": "^1.1.0",
|
||||
"ora": "^1.2.0",
|
||||
"passport": "^0.3.2",
|
||||
"passport-local": "^1.0.0",
|
||||
"passport.socketio": "^3.7.0",
|
||||
@ -94,11 +96,11 @@
|
||||
"read-chunk": "^2.0.0",
|
||||
"remove-markdown": "^0.1.0",
|
||||
"requarks-core": "^0.2.2",
|
||||
"request": "^2.80.0",
|
||||
"search-index-adder": "github:NGPixel/search-index-adder",
|
||||
"search-index-searcher": "github:NGPixel/search-index-searcher",
|
||||
"request": "^2.81.0",
|
||||
"search-index-adder": "github:ngpixel/search-index-adder",
|
||||
"search-index-searcher": "github:ngpixel/search-index-searcher",
|
||||
"semver": "^5.3.0",
|
||||
"serve-favicon": "^2.4.1",
|
||||
"serve-favicon": "^2.4.2",
|
||||
"simplemde": "^1.11.2",
|
||||
"socket.io": "^1.7.3",
|
||||
"sticky-js": "^1.0.7",
|
||||
@ -112,16 +114,16 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"ace-builds": "^1.2.6",
|
||||
"babel-preset-es2015": "^6.16.0",
|
||||
"babel-preset-es2015": "^6.24.0",
|
||||
"chai": "^3.5.0",
|
||||
"chai-as-promised": "^6.0.0",
|
||||
"codacy-coverage": "^2.0.0",
|
||||
"eslint": "^3.16.1",
|
||||
"eslint": "^3.18.0",
|
||||
"eslint-plugin-promise": "^3.5.0",
|
||||
"eslint-plugin-standard": "^2.1.1",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-babel": "^6.1.2",
|
||||
"gulp-clean-css": "^3.0.3",
|
||||
"gulp-clean-css": "^3.0.4",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-gzip": "^1.4.0",
|
||||
"gulp-include": "^2.3.1",
|
||||
@ -129,12 +131,12 @@
|
||||
"gulp-plumber": "^1.1.0",
|
||||
"gulp-sass": "^3.0.0",
|
||||
"gulp-tar": "^1.9.0",
|
||||
"gulp-uglify": "^2.0.0",
|
||||
"gulp-uglify": "^2.1.2",
|
||||
"gulp-watch": "^4.3.11",
|
||||
"gulp-zip": "^4.0.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"jquery": "^3.1.1",
|
||||
"jquery-contextmenu": "^2.4.3",
|
||||
"jquery": "^3.2.1",
|
||||
"jquery-contextmenu": "^2.4.4",
|
||||
"jquery-simple-upload": "^1.0.0",
|
||||
"jquery-smooth-scroll": "^2.0.0",
|
||||
"merge-stream": "^1.0.1",
|
||||
@ -144,10 +146,11 @@
|
||||
"pug-lint": "^2.4.0",
|
||||
"run-sequence": "^1.2.2",
|
||||
"snyk": "^1.25.1",
|
||||
"standard": "^9.0.0",
|
||||
"standard": "^9.0.2",
|
||||
"sticky-js": "^1.1.9",
|
||||
"twemoji-awesome": "^1.0.4",
|
||||
"vue": "^2.2.1"
|
||||
"vee-validate": "^2.0.0-beta.25",
|
||||
"vue": "^2.2.5"
|
||||
},
|
||||
"standard": {
|
||||
"globals": [
|
||||
|
@ -36,6 +36,11 @@ html
|
||||
h1 Welcome to Wiki.js!
|
||||
h2(style={'margin-bottom': 0}) A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown
|
||||
.content(v-cloak)
|
||||
|
||||
//- ==============================================
|
||||
//- WELCOME
|
||||
//- ==============================================
|
||||
|
||||
template(v-if='state === "welcome"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
@ -45,8 +50,13 @@ html
|
||||
p This installation wizard will guide you through the steps needed to get your wiki up and running in no time!
|
||||
p Detailed information about installation and usage can be found on the #[a(href='https://docs.wiki.requarks.io/') official documentation site]. #[br] Should you have any question or would like to report something that doesn't look right, feel free to create a new issue on the #[a(href='https://github.com/Requarks/wiki/issues') GitHub project].
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Start
|
||||
|
||||
//- ==============================================
|
||||
//- SYSTEM CHECK
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "syscheck"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
@ -62,10 +72,15 @@ html
|
||||
strong Looks good! No issues so far.
|
||||
p(v-if='!loading && !syscheck.ok') #[i.icon-square-cross] Error: {{ syscheck.error }}
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToWelcome', v-bind:disabled='loading') Back
|
||||
button.button.is-teal(v-on:click='proceedToSyscheck', v-if='!loading && !syscheck.ok') Check Again
|
||||
button.button.is-indigo(v-on:click='proceedToGeneral', v-if='loading || syscheck.ok', v-bind:disabled='loading') Continue
|
||||
|
||||
//- ==============================================
|
||||
//- GENERAL
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "general"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
@ -75,27 +90,33 @@ html
|
||||
section
|
||||
p.control.is-fullwidth
|
||||
label.label Site Title
|
||||
input(type='text', placeholder='e.g. Wiki', v-model='conf.title')
|
||||
p.desc The site title will appear in the top left corner on every page and within the window title bar.
|
||||
input(type='text', placeholder='e.g. Wiki', v-model='conf.title', data-vv-scope='general', name='ipt-title', v-validate='{ required: true, min: 2 }')
|
||||
span.desc The site title will appear in the top left corner on every page and within the window title bar.
|
||||
section
|
||||
p.control.is-fullwidth
|
||||
label.label Host
|
||||
input(type='text', placeholder='http://', v-model='conf.host')
|
||||
p.desc The full URL to your wiki, without the trailing slash. E.g.: http://wiki.domain.com. Note that sub-folders are not supported.
|
||||
input(type='text', placeholder='http://', v-model='conf.host', data-vv-scope='general', name='ipt-host', v-validate='{ required: true, url: true }')
|
||||
span.desc The full URL to your wiki, without the trailing slash. E.g.: http://wiki.domain.com. Note that sub-folders are not supported.
|
||||
section
|
||||
p.control
|
||||
label.label Port
|
||||
input(type='text', placeholder='e.g. 80', v-model='conf.port')
|
||||
p.desc The port on which Wiki.js will listen to. Usually port 80 if connecting directly, or a random port (e.g. 3000) if using a web server in front of it.
|
||||
input(type='text', placeholder='e.g. 80', v-model.number='conf.port', data-vv-scope='general', name='ipt-port', v-validate='{ required: true, numeric: true, min_value: 1, max_value: 65535 }')
|
||||
span.desc The port on which Wiki.js will listen to. Usually port 80 if connecting directly, or a random port (e.g. 3000) if using a web server in front of it.
|
||||
section
|
||||
p.control
|
||||
label.label Site UI Language
|
||||
select(v-model='conf.lang')
|
||||
option(value='en') English
|
||||
p.desc The language in which navigation, help and other UI elements will be displayed.
|
||||
each lg in langs
|
||||
option(value=lg.id)= lg.name
|
||||
span.desc The language in which navigation, help and other UI elements will be displayed.
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Back
|
||||
button.button.is-indigo(v-on:click='proceedToConsiderations', v-bind:disabled='loading') Continue
|
||||
button.button.is-indigo(v-on:click='proceedToConsiderations', v-bind:disabled='loading || errors.any("general")') Continue
|
||||
|
||||
//- ==============================================
|
||||
//- CONSIDERATIONS
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "considerations"')
|
||||
.panel
|
||||
@ -120,23 +141,228 @@ html
|
||||
h3 Are you sure you want to use localhost as the host base URL? #[i.icon-warning-outline.animated.fadeOut.infinite]
|
||||
p The host URL you specified is localhost. Unless you are a developer running Wiki.js locally on your machine, this is not recommended!
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToGeneral', v-bind:disabled='loading') Back
|
||||
button.button.is-indigo(v-on:click='proceedToDb', v-bind:disabled='loading') Continue
|
||||
|
||||
//- ==============================================
|
||||
//- DATABASE
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "db"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
span Database
|
||||
i(v-if='loading')
|
||||
.panel-content.is-text
|
||||
p Wiki.js stores administrative data such as users, permissions and assets metadata in a MongoDB database. Article contents and uploads are <u>not</u> stored in the DB. Instead, they are stored on-disk and synced automatically with a remote git repository of your choice.
|
||||
.panel-content.form-sections
|
||||
section
|
||||
p.control.is-fullwidth
|
||||
label.label MongoDB Connection String
|
||||
input(type='text', placeholder='e.g. mongodb://localhost:27017/wiki', v-model='conf.db')
|
||||
p.desc The connection string to your MongoDB server. Leave the default localhost value if MongoDB is installed on the same server.
|
||||
input(type='text', placeholder='e.g. mongodb://localhost:27017/wiki', v-model='conf.db', data-vv-scope='db', name='ipt-db', v-validate='{ required: true, min: 14 }')
|
||||
span.desc The connection string to your MongoDB server. Leave the default localhost value if MongoDB is installed on the same server.
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToConsiderations', v-bind:disabled='loading') Back
|
||||
button.button.is-indigo(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Connect
|
||||
button.button.is-indigo(v-on:click='proceedToDbcheck', v-bind:disabled='loading || errors.any("db")') Connect
|
||||
|
||||
//- ==============================================
|
||||
//- DATABASE CHECK
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "dbcheck"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
span Database Check
|
||||
i(v-if='loading')
|
||||
.panel-content.is-text
|
||||
p(v-if='loading') #[i.icon-loader.animated.rotateIn.infinite] Testing the connection to MongoDB...
|
||||
p(v-if='!loading && dbcheck.ok')
|
||||
i.icon-check
|
||||
strong Connected successfully!
|
||||
p(v-if='!loading && !dbcheck.ok') #[i.icon-square-cross] Error: {{ dbcheck.error }}
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToDb', v-bind:disabled='loading') Back
|
||||
button.button.is-teal(v-on:click='proceedToDbcheck', v-if='!loading && !dbcheck.ok') Try Again
|
||||
button.button.is-indigo(v-on:click='proceedToPaths', v-if='loading || dbcheck.ok', v-bind:disabled='loading') Continue
|
||||
|
||||
//- ==============================================
|
||||
//- PATHS
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "paths"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
span Paths
|
||||
i(v-if='loading')
|
||||
.panel-content.is-text
|
||||
p It is recommended to leave the default values.
|
||||
.panel-content.form-sections
|
||||
section
|
||||
p.control.is-fullwidth
|
||||
label.label Local Data Path
|
||||
input(type='text', placeholder='e.g. ./data', v-model='conf.pathData', data-vv-scope='paths', name='ipt-datapath', v-validate='{ required: true, min: 2 }')
|
||||
span.desc The path where cache (processed content, thumbnails, search index, etc.) will be stored on disk.
|
||||
section
|
||||
p.control.is-fullwidth
|
||||
label.label Local Repository Path
|
||||
input(type='text', placeholder='e.g. ./repo', v-model='conf.pathRepo', data-vv-scope='paths', name='ipt-repopath', v-validate='{ required: true, min: 2 }')
|
||||
span.desc The path where the local git repository will be created, used to store content in markdown files and uploads.
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToDb', v-bind:disabled='loading') Back
|
||||
button.button.is-indigo(v-on:click='proceedToGit', v-bind:disabled='loading || errors.any("paths")') Continue
|
||||
|
||||
//- ==============================================
|
||||
//- GIT
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "git"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
span Git Repository
|
||||
i(v-if='loading')
|
||||
.panel-content.is-text
|
||||
p Wiki.js stores article content and uploads locally on disk. All content is then regularly kept in sync with a remote git repository. This acts a backup protection and provides history / revert features. While optional, it is <strong>HIGHLY</strong> recommended to setup the remote git repository connection.
|
||||
.panel-content.form-sections
|
||||
section.columns
|
||||
.column.is-two-thirds
|
||||
p.control.is-fullwidth
|
||||
label.label Repository URL
|
||||
input(type='text', placeholder='e.g. git@github.com/org/repo.git or https://github.com/org/repo', v-model='conf.gitUrl', data-vv-scope='git', name='ipt-giturl', v-validate='{ required: true, min: 5 }')
|
||||
span.desc The full git repository URL to connect to.
|
||||
.column
|
||||
p.control.is-fullwidth
|
||||
label.label Branch
|
||||
input(type='text', placeholder='e.g. master', v-model='conf.gitBranch', data-vv-scope='git', name='ipt-gitbranch', v-validate='{ required: true, min: 2 }')
|
||||
span.desc The git branch to use when synchronizing changes.
|
||||
section.columns
|
||||
.column.is-one-third
|
||||
p.control.is-fullwidth
|
||||
label.label Authentication
|
||||
select(v-model='conf.gitAuthType')
|
||||
option(value='ssh') SSH (recommended)
|
||||
option(value='basic') Basic
|
||||
span.desc The authentication method used to connect to your remote Git repository.
|
||||
p.control.is-fullwidth
|
||||
input#ipt-git-verify-ssl(type='checkbox', v-model='conf.gitAuthSSL')
|
||||
label.label(for='ipt-git-verify-ssl') Verify SSL
|
||||
.column(v-show='conf.gitAuthType === "basic"')
|
||||
p.control.is-fullwidth
|
||||
label.label Username
|
||||
input(type='text', v-model='conf.gitUrl')
|
||||
span.desc The username for the remote git connection.
|
||||
.column(v-show='conf.gitAuthType === "basic"')
|
||||
p.control.is-fullwidth
|
||||
label.label Password
|
||||
input(type='password', v-model='conf.gitUrl')
|
||||
span.desc The password for the remote git connection.
|
||||
.column(v-show='conf.gitAuthType === "ssh"')
|
||||
p.control.is-fullwidth
|
||||
label.label Private Key location
|
||||
input(type='text', placeholder='e.g. /etc/wiki/keys/git.pem')
|
||||
span.desc The full path to the private key on disk.
|
||||
section.columns
|
||||
.column
|
||||
p.control.is-fullwidth
|
||||
label.label Sync User Name
|
||||
input(type='text', placeholder='e.g. John Smith', v-model.number='conf.gitSignatureName', data-vv-scope='git', name='ipt-gitsigname', v-validate='{ required: true }')
|
||||
span.desc The name to use when pushing commits to the git repository.
|
||||
.column
|
||||
p.control.is-fullwidth
|
||||
label.label Sync User Email
|
||||
input(type='text', placeholder='e.g. user@example.com', v-model.number='conf.gitSignatureEmail', data-vv-scope='git', name='ipt-gitsigemail', v-validate='{ required: true, email: true }')
|
||||
span.desc The email to use when pushing commits to the git repository.
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToDb', v-bind:disabled='loading') Back
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToAdmin', v-bind:disabled='loading') Skip this step
|
||||
button.button.is-indigo(v-on:click='proceedToGitCheck', v-bind:disabled='loading || errors.any("git")') Continue
|
||||
|
||||
//- ==============================================
|
||||
//- GIT CHECK
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "gitcheck"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
span Git Repository Check
|
||||
i(v-if='loading')
|
||||
.panel-content.is-text
|
||||
p(v-if='loading') #[i.icon-loader.animated.rotateIn.infinite] Testing the connection to Git repository...
|
||||
p(v-if='!loading && gitcheck.ok')
|
||||
ul
|
||||
li(v-for='rs in gitcheck.results') #[i.icon-check] {{rs}}
|
||||
p(v-if='!loading && gitcheck.ok')
|
||||
i.icon-check
|
||||
strong Git settings are correct!
|
||||
p(v-if='!loading && !gitcheck.ok') #[i.icon-square-cross] Error: {{ gitcheck.error }}
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToGit', v-bind:disabled='loading') Back
|
||||
button.button.is-teal(v-on:click='proceedToGitCheck', v-if='!loading && !gitcheck.ok') Try Again
|
||||
button.button.is-indigo(v-on:click='proceedToAdmin', v-if='loading || gitcheck.ok', v-bind:disabled='loading') Continue
|
||||
|
||||
//- ==============================================
|
||||
//- ADMINISTRATOR ACCOUNT
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "admin"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
span Administrator Account
|
||||
i(v-if='loading')
|
||||
.panel-content.is-text
|
||||
p An administrator account will be created for local authentication. From this account, you can create or authorize more users.
|
||||
.panel-content.form-sections
|
||||
section
|
||||
p.control.is-fullwidth
|
||||
label.label Administrator Email
|
||||
input(type='text', placeholder='e.g. admin@example.com', v-model='conf.adminEmail', data-vv-scope='admin', name='ipt-adminemail', v-validate='{ required: true, email: true }')
|
||||
span.desc The full git repository URL to connect to.
|
||||
section.columns
|
||||
.column
|
||||
p.control.is-fullwidth
|
||||
label.label Password
|
||||
input(type='password', v-model='conf.adminPassword', data-vv-scope='admin', name='ipt-adminpwd', v-validate='{ required: true, min: 8 }')
|
||||
span.desc The full git repository URL to connect to.
|
||||
.column
|
||||
p.control.is-fullwidth
|
||||
label.label Confirm Password
|
||||
input(type='password', v-model='conf.adminPasswordConfirm', data-vv-scope='admin', name='ipt-adminpwd2', v-validate='{ required: true, confirmed: "ipt-adminpwd" }')
|
||||
span.desc The git branch to use when synchronizing changes.
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToGit', v-bind:disabled='loading') Back
|
||||
button.button.is-indigo(v-on:click='proceedToFinal', v-bind:disabled='loading || errors.any("admin")') Continue
|
||||
|
||||
//- ==============================================
|
||||
//- FINAL
|
||||
//- ==============================================
|
||||
|
||||
template(v-else-if='state === "final"')
|
||||
.panel
|
||||
h2.panel-title.is-featured
|
||||
span Finalizing
|
||||
i(v-if='loading')
|
||||
.panel-content.is-text
|
||||
p(v-if='loading') #[i.icon-loader.animated.rotateIn.infinite] Finalizing your installation...
|
||||
p(v-if='!loading && final.ok')
|
||||
ul
|
||||
li(v-for='rs in final.results') #[i.icon-check] {{rs}}
|
||||
p(v-if='!loading && final.ok')
|
||||
i.icon-check
|
||||
strong Wiki.js was configured successfully and is now ready for use.
|
||||
p(v-if='!loading && final.ok')
|
||||
| Click the <strong>Start</strong> button below to start the Wiki.js server.
|
||||
p(v-if='!loading && !final.ok') #[i.icon-square-cross] Error: {{ final.error }}
|
||||
.panel-footer
|
||||
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||
button.button.is-indigo.is-outlined(v-on:click='proceedToWelcome', v-bind:disabled='loading') Back
|
||||
button.button.is-teal(v-on:click='proceedToFinal', v-if='!loading && !final.ok') Try Again
|
||||
button.button.is-green(v-on:click='finish', v-if='loading || final.ok', v-bind:disabled='loading') Start
|
||||
|
||||
footer.footer
|
||||
span
|
||||
|
Loading…
Reference in New Issue
Block a user