Setup wizard - all UI steps
This commit is contained in:
@@ -18,6 +18,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Auth: Authentication would fail if email has uppercase chars and provider callback is in lowercase
|
- 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 index should now update upon article creation
|
||||||
- Search: Search results are no longer duplicated upon article update
|
- Search: Search results are no longer duplicated upon article update
|
||||||
- UI: Missing icons on login page
|
- UI: Missing icons on login page
|
||||||
|
|||||||
@@ -49,38 +49,41 @@ var Cron = require('cron').CronJob
|
|||||||
// Start Cron
|
// Start Cron
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
|
|
||||||
|
var job
|
||||||
var jobIsBusy = false
|
var jobIsBusy = false
|
||||||
var jobUplWatchStarted = false
|
var jobUplWatchStarted = false
|
||||||
|
|
||||||
var job = new Cron({
|
db.onReady.then(() => {
|
||||||
cronTime: '0 */5 * * * *',
|
return db.Entry.remove({})
|
||||||
onTick: () => {
|
}).then(() => {
|
||||||
// Make sure we don't start two concurrent jobs
|
job = new Cron({
|
||||||
|
cronTime: '0 */5 * * * *',
|
||||||
|
onTick: () => {
|
||||||
|
// Make sure we don't start two concurrent jobs
|
||||||
|
|
||||||
if (jobIsBusy) {
|
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)')
|
winston.warn('[AGENT] Previous job has not completed gracefully or is still running! Skipping for now. (This is not normal, you should investigate)')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
winston.info('[AGENT] Running all jobs...')
|
winston.info('[AGENT] Running all jobs...')
|
||||||
jobIsBusy = true
|
jobIsBusy = true
|
||||||
|
|
||||||
// Prepare async job collector
|
// Prepare async job collector
|
||||||
|
|
||||||
let jobs = []
|
let jobs = []
|
||||||
let repoPath = path.resolve(ROOTPATH, appconfig.paths.repo)
|
let repoPath = path.resolve(ROOTPATH, appconfig.paths.repo)
|
||||||
let dataPath = path.resolve(ROOTPATH, appconfig.paths.data)
|
let dataPath = path.resolve(ROOTPATH, appconfig.paths.data)
|
||||||
let uploadsTempPath = path.join(dataPath, 'temp-upload')
|
let uploadsTempPath = path.join(dataPath, 'temp-upload')
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
// REGULAR JOBS
|
// REGULAR JOBS
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
|
|
||||||
//* ****************************************
|
//* ****************************************
|
||||||
// -> Sync with Git remote
|
// -> Sync with Git remote
|
||||||
//* ****************************************
|
//* ****************************************
|
||||||
|
|
||||||
jobs.push(git.onReady.then(() => {
|
jobs.push(git.resync().then(() => {
|
||||||
return git.resync().then(() => {
|
|
||||||
// -> Stream all documents
|
// -> Stream all documents
|
||||||
|
|
||||||
let cacheJobs = []
|
let cacheJobs = []
|
||||||
@@ -131,55 +134,56 @@ var job = new Cron({
|
|||||||
})
|
})
|
||||||
|
|
||||||
return jobCbStreamDocs
|
return jobCbStreamDocs
|
||||||
})
|
}))
|
||||||
}))
|
|
||||||
|
|
||||||
//* ****************************************
|
//* ****************************************
|
||||||
// -> Clear failed temporary upload files
|
// -> Clear failed temporary upload files
|
||||||
//* ****************************************
|
//* ****************************************
|
||||||
|
|
||||||
jobs.push(
|
jobs.push(
|
||||||
fs.readdirAsync(uploadsTempPath).then((ls) => {
|
fs.readdirAsync(uploadsTempPath).then((ls) => {
|
||||||
let fifteenAgo = moment().subtract(15, 'minutes')
|
let fifteenAgo = moment().subtract(15, 'minutes')
|
||||||
|
|
||||||
return Promise.map(ls, (f) => {
|
return Promise.map(ls, (f) => {
|
||||||
return fs.statAsync(path.join(uploadsTempPath, f)).then((s) => { return { filename: f, stat: s } })
|
return fs.statAsync(path.join(uploadsTempPath, f)).then((s) => { return { filename: f, stat: s } })
|
||||||
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
|
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
|
||||||
return Promise.map(arrFiles, (f) => {
|
return Promise.map(arrFiles, (f) => {
|
||||||
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
|
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
|
||||||
return fs.unlinkAsync(path.join(uploadsTempPath, f.filename))
|
return fs.unlinkAsync(path.join(uploadsTempPath, f.filename))
|
||||||
} else {
|
} else {
|
||||||
return true
|
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
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
|
|||||||
@@ -50,4 +50,26 @@ defaults:
|
|||||||
signature:
|
signature:
|
||||||
name: Wiki
|
name: Wiki
|
||||||
email: wiki@example.com
|
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
|
||||||
# ---------------------------------
|
# ---------------------------------
|
||||||
|
|||||||
+2
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
-2
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){}}})});
|
||||||
+33
-32
File diff suppressed because one or more lines are too long
@@ -93,6 +93,7 @@ if ($('#mk-editor').length === 1) {
|
|||||||
mdeModalOpenState = true;
|
mdeModalOpenState = true;
|
||||||
$('#modal-editor-link').slideToggle();
|
$('#modal-editor-link').slideToggle();
|
||||||
} */
|
} */
|
||||||
|
window.alert('Coming soon!')
|
||||||
},
|
},
|
||||||
className: 'icon-link2',
|
className: 'icon-link2',
|
||||||
title: 'Insert Link'
|
title: 'Insert Link'
|
||||||
@@ -163,6 +164,7 @@ if ($('#mk-editor').length === 1) {
|
|||||||
{
|
{
|
||||||
name: 'table',
|
name: 'table',
|
||||||
action: (editor) => {
|
action: (editor) => {
|
||||||
|
window.alert('Coming soon!')
|
||||||
// todo
|
// todo
|
||||||
},
|
},
|
||||||
className: 'icon-table',
|
className: 'icon-table',
|
||||||
|
|||||||
+196
-8
@@ -1,24 +1,63 @@
|
|||||||
'use strict'
|
'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 ($) {
|
jQuery(document).ready(function ($) {
|
||||||
new Vue({ // eslint-disable-line no-new
|
new Vue({ // eslint-disable-line no-new
|
||||||
el: 'main',
|
el: 'main',
|
||||||
data: {
|
data: {
|
||||||
loading: false,
|
loading: false,
|
||||||
state: 'considerations',
|
state: 'welcome',
|
||||||
syscheck: {
|
syscheck: {
|
||||||
ok: false,
|
ok: false,
|
||||||
error: '',
|
error: '',
|
||||||
results: []
|
results: []
|
||||||
},
|
},
|
||||||
|
dbcheck: {
|
||||||
|
ok: false,
|
||||||
|
error: ''
|
||||||
|
},
|
||||||
|
gitcheck: {
|
||||||
|
ok: false,
|
||||||
|
error: ''
|
||||||
|
},
|
||||||
|
final: {
|
||||||
|
ok: false,
|
||||||
|
error: '',
|
||||||
|
results: []
|
||||||
|
},
|
||||||
conf: {
|
conf: {
|
||||||
title: 'Wiki',
|
title: 'Wiki',
|
||||||
host: '',
|
host: 'http://',
|
||||||
port: 80,
|
port: 80,
|
||||||
lang: 'en',
|
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: {
|
considerations: {
|
||||||
https: false,
|
https: false,
|
||||||
@@ -26,6 +65,44 @@ jQuery(document).ready(function ($) {
|
|||||||
localhost: false
|
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: {
|
methods: {
|
||||||
proceedToWelcome: function (ev) {
|
proceedToWelcome: function (ev) {
|
||||||
this.state = 'welcome'
|
this.state = 'welcome'
|
||||||
@@ -58,8 +135,12 @@ jQuery(document).ready(function ($) {
|
|||||||
}, 1000)
|
}, 1000)
|
||||||
},
|
},
|
||||||
proceedToGeneral: function (ev) {
|
proceedToGeneral: function (ev) {
|
||||||
this.state = 'general'
|
let self = this
|
||||||
this.loading = false
|
self.state = 'general'
|
||||||
|
self.loading = false
|
||||||
|
self.$nextTick(() => {
|
||||||
|
self.$validator.validateAll('general')
|
||||||
|
})
|
||||||
},
|
},
|
||||||
proceedToConsiderations: function (ev) {
|
proceedToConsiderations: function (ev) {
|
||||||
this.considerations = {
|
this.considerations = {
|
||||||
@@ -71,8 +152,115 @@ jQuery(document).ready(function ($) {
|
|||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
proceedToDb: function (ev) {
|
proceedToDb: function (ev) {
|
||||||
this.state = 'db'
|
let self = this
|
||||||
this.loading = false
|
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) {
|
if ($('#page-type-edit').length) {
|
||||||
let pageEntryPath = $('#page-type-edit').data('entrypath') // eslint-disable-line no-unused-vars
|
let pageEntryPath = $('#page-type-edit').data('entrypath') // eslint-disable-line no-unused-vars
|
||||||
|
// let pageCleanExit = false
|
||||||
|
|
||||||
// -> Discard
|
// -> Discard
|
||||||
|
|
||||||
@@ -9,6 +10,10 @@ if ($('#page-type-edit').length) {
|
|||||||
$('#modal-edit-discard').toggleClass('is-active')
|
$('#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 */
|
/* eslint-disable spaced-comment */
|
||||||
//=include ../components/editor.js
|
//=include ../components/editor.js
|
||||||
/* eslint-enable spaced-comment */
|
/* eslint-enable spaced-comment */
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
|
|
||||||
.editor-toolbar {
|
.editor-toolbar {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
background-color: rgba(0,0,0,0.75);
|
background-color: mc('indigo', '900');
|
||||||
border: none;
|
border: none;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 51px;
|
top: 50px;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ #btn-editor-image-upload, #btn-editor-file-upload {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ .editor-modal-image-choices {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ .editor-modal-image-choices {
|
|||||||
|
|
||||||
> span {
|
> span {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
> strong {
|
> strong {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -358,4 +358,4 @@ #source-display, #codeblock-editor {
|
|||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,3 +53,24 @@ .tst-welcome-leave-to, .tst-welcome-enter {
|
|||||||
max-height: 0;
|
max-height: 0;
|
||||||
padding-top: 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
+115
-1
@@ -15,8 +15,11 @@ module.exports = (port, spinner) => {
|
|||||||
const http = require('http')
|
const http = require('http')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const Promise = require('bluebird')
|
const Promise = require('bluebird')
|
||||||
|
const fs = require('fs-extra')
|
||||||
|
const yaml = require('js-yaml')
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
// Define Express App
|
// Define Express App
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
@@ -48,9 +51,20 @@ module.exports = (port, spinner) => {
|
|||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
|
|
||||||
app.get('*', (req, res) => {
|
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) => {
|
app.post('/syscheck', (req, res) => {
|
||||||
Promise.mapSeries([
|
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
|
// Error handling
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const paths = {
|
|||||||
'./node_modules/socket.io-client/dist/socket.io.min.js',
|
'./node_modules/socket.io-client/dist/socket.io.min.js',
|
||||||
'./node_modules/jquery/dist/jquery.min.js',
|
'./node_modules/jquery/dist/jquery.min.js',
|
||||||
'./node_modules/vue/dist/vue.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/axios/dist/axios.min.js',
|
||||||
'./node_modules/jquery-smooth-scroll/jquery.smooth-scroll.min.js',
|
'./node_modules/jquery-smooth-scroll/jquery.smooth-scroll.min.js',
|
||||||
'./node_modules/jquery-simple-upload/simpleUpload.min.js',
|
'./node_modules/jquery-simple-upload/simpleUpload.min.js',
|
||||||
|
|||||||
+2
-58
@@ -152,7 +152,7 @@ module.exports = {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}).catch((err) => { // eslint-disable-line handle-callback-err
|
}).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,
|
_id: content.entryPath,
|
||||||
title: content.meta.title || content.entryPath,
|
title: content.meta.title || content.entryPath,
|
||||||
subtitle: content.meta.subtitle || '',
|
subtitle: content.meta.subtitle || '',
|
||||||
parent: content.parent.title || '',
|
parent: content.parent.title || ''
|
||||||
content: content.text || ''
|
|
||||||
}, {
|
}, {
|
||||||
new: true,
|
new: true,
|
||||||
upsert: true
|
upsert: true
|
||||||
@@ -396,60 +395,5 @@ module.exports = {
|
|||||||
return fs.readFileAsync(path.join(ROOTPATH, 'client/content/create.md'), 'utf8').then((contents) => {
|
return fs.readFileAsync(path.join(ROOTPATH, 'client/content/create.md'), 'utf8').then((contents) => {
|
||||||
return _.replace(contents, new RegExp('{TITLE}', 'g'), formattedTitle)
|
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) {
|
generateThumbnail (sourcePath, destPath) {
|
||||||
return jimp.read(sourcePath).then(img => {
|
return jimp.read(sourcePath).then(img => {
|
||||||
return img.cover(150, 150)
|
return img
|
||||||
.background(0xFFFFFFFF)
|
.contain(150, 150)
|
||||||
.opaque()
|
|
||||||
.rgba(false)
|
|
||||||
.write(destPath)
|
.write(destPath)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,10 +21,6 @@ var entrySchema = Mongoose.Schema({
|
|||||||
parent: {
|
parent: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
|
||||||
content: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -32,19 +28,4 @@ var entrySchema = Mongoose.Schema({
|
|||||||
timestamps: {}
|
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)
|
module.exports = Mongoose.model('Entry', entrySchema)
|
||||||
|
|||||||
+25
-22
@@ -41,7 +41,7 @@
|
|||||||
"bcryptjs-then": "^1.0.1",
|
"bcryptjs-then": "^1.0.1",
|
||||||
"bluebird": "^3.4.7",
|
"bluebird": "^3.4.7",
|
||||||
"body-parser": "^1.17.1",
|
"body-parser": "^1.17.1",
|
||||||
"bunyan": "^1.8.8",
|
"bunyan": "^1.8.9",
|
||||||
"cheerio": "^0.22.0",
|
"cheerio": "^0.22.0",
|
||||||
"child-process-promise": "^2.2.0",
|
"child-process-promise": "^2.2.0",
|
||||||
"chokidar": "^1.6.0",
|
"chokidar": "^1.6.0",
|
||||||
@@ -51,21 +51,22 @@
|
|||||||
"connect-mongo": "^1.3.2",
|
"connect-mongo": "^1.3.2",
|
||||||
"cookie-parser": "^1.4.3",
|
"cookie-parser": "^1.4.3",
|
||||||
"cron": "^1.2.1",
|
"cron": "^1.2.1",
|
||||||
|
"execa": "^0.6.3",
|
||||||
"express": "^4.15.2",
|
"express": "^4.15.2",
|
||||||
"express-brute": "^1.0.0",
|
"express-brute": "^1.0.0",
|
||||||
"express-brute-mongoose": "0.0.7",
|
"express-brute-mongoose": "0.0.7",
|
||||||
"express-session": "^1.15.1",
|
"express-session": "^1.15.1",
|
||||||
"file-type": "^4.0.0",
|
"file-type": "^4.0.0",
|
||||||
"filesize.js": "^1.0.2",
|
"filesize.js": "^1.0.2",
|
||||||
"follow-redirects": "^1.2.1",
|
"follow-redirects": "^1.2.3",
|
||||||
"fs-extra": "^2.0.0",
|
"fs-extra": "^2.1.2",
|
||||||
"git-wrapper2-promise": "^0.2.9",
|
"git-wrapper2-promise": "^0.2.9",
|
||||||
"highlight.js": "^9.9.0",
|
"highlight.js": "^9.9.0",
|
||||||
"i18next": "^7.1.1",
|
"i18next": "^7.1.3",
|
||||||
"i18next-express-middleware": "^1.0.2",
|
"i18next-express-middleware": "^1.0.3",
|
||||||
"i18next-node-fs-backend": "^0.1.3",
|
"i18next-node-fs-backend": "^0.1.3",
|
||||||
"image-size": "^0.5.1",
|
"image-size": "^0.5.1",
|
||||||
"jimp": "github:NGPixel/jimp",
|
"jimp": "github:ngpixel/jimp",
|
||||||
"js-yaml": "^3.8.1",
|
"js-yaml": "^3.8.1",
|
||||||
"klaw": "^1.3.1",
|
"klaw": "^1.3.1",
|
||||||
"levelup": "^1.3.5",
|
"levelup": "^1.3.5",
|
||||||
@@ -80,12 +81,13 @@
|
|||||||
"markdown-it-footnote": "^3.0.1",
|
"markdown-it-footnote": "^3.0.1",
|
||||||
"markdown-it-task-lists": "^1.4.1",
|
"markdown-it-task-lists": "^1.4.1",
|
||||||
"memdown": "^1.2.4",
|
"memdown": "^1.2.4",
|
||||||
"mime-types": "^2.1.13",
|
"mime-types": "^2.1.15",
|
||||||
"moment": "^2.17.1",
|
"moment": "^2.18.1",
|
||||||
"moment-timezone": "^0.5.11",
|
"moment-timezone": "^0.5.11",
|
||||||
"mongoose": "^4.8.5",
|
"mongodb": "^2.2.25",
|
||||||
|
"mongoose": "^4.9.1",
|
||||||
"multer": "^1.2.1",
|
"multer": "^1.2.1",
|
||||||
"ora": "^1.1.0",
|
"ora": "^1.2.0",
|
||||||
"passport": "^0.3.2",
|
"passport": "^0.3.2",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"passport.socketio": "^3.7.0",
|
"passport.socketio": "^3.7.0",
|
||||||
@@ -94,11 +96,11 @@
|
|||||||
"read-chunk": "^2.0.0",
|
"read-chunk": "^2.0.0",
|
||||||
"remove-markdown": "^0.1.0",
|
"remove-markdown": "^0.1.0",
|
||||||
"requarks-core": "^0.2.2",
|
"requarks-core": "^0.2.2",
|
||||||
"request": "^2.80.0",
|
"request": "^2.81.0",
|
||||||
"search-index-adder": "github:NGPixel/search-index-adder",
|
"search-index-adder": "github:ngpixel/search-index-adder",
|
||||||
"search-index-searcher": "github:NGPixel/search-index-searcher",
|
"search-index-searcher": "github:ngpixel/search-index-searcher",
|
||||||
"semver": "^5.3.0",
|
"semver": "^5.3.0",
|
||||||
"serve-favicon": "^2.4.1",
|
"serve-favicon": "^2.4.2",
|
||||||
"simplemde": "^1.11.2",
|
"simplemde": "^1.11.2",
|
||||||
"socket.io": "^1.7.3",
|
"socket.io": "^1.7.3",
|
||||||
"sticky-js": "^1.0.7",
|
"sticky-js": "^1.0.7",
|
||||||
@@ -112,16 +114,16 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ace-builds": "^1.2.6",
|
"ace-builds": "^1.2.6",
|
||||||
"babel-preset-es2015": "^6.16.0",
|
"babel-preset-es2015": "^6.24.0",
|
||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
"chai-as-promised": "^6.0.0",
|
"chai-as-promised": "^6.0.0",
|
||||||
"codacy-coverage": "^2.0.0",
|
"codacy-coverage": "^2.0.0",
|
||||||
"eslint": "^3.16.1",
|
"eslint": "^3.18.0",
|
||||||
"eslint-plugin-promise": "^3.5.0",
|
"eslint-plugin-promise": "^3.5.0",
|
||||||
"eslint-plugin-standard": "^2.1.1",
|
"eslint-plugin-standard": "^2.1.1",
|
||||||
"gulp": "^3.9.1",
|
"gulp": "^3.9.1",
|
||||||
"gulp-babel": "^6.1.2",
|
"gulp-babel": "^6.1.2",
|
||||||
"gulp-clean-css": "^3.0.3",
|
"gulp-clean-css": "^3.0.4",
|
||||||
"gulp-concat": "^2.6.1",
|
"gulp-concat": "^2.6.1",
|
||||||
"gulp-gzip": "^1.4.0",
|
"gulp-gzip": "^1.4.0",
|
||||||
"gulp-include": "^2.3.1",
|
"gulp-include": "^2.3.1",
|
||||||
@@ -129,12 +131,12 @@
|
|||||||
"gulp-plumber": "^1.1.0",
|
"gulp-plumber": "^1.1.0",
|
||||||
"gulp-sass": "^3.0.0",
|
"gulp-sass": "^3.0.0",
|
||||||
"gulp-tar": "^1.9.0",
|
"gulp-tar": "^1.9.0",
|
||||||
"gulp-uglify": "^2.0.0",
|
"gulp-uglify": "^2.1.2",
|
||||||
"gulp-watch": "^4.3.11",
|
"gulp-watch": "^4.3.11",
|
||||||
"gulp-zip": "^4.0.0",
|
"gulp-zip": "^4.0.0",
|
||||||
"istanbul": "^0.4.5",
|
"istanbul": "^0.4.5",
|
||||||
"jquery": "^3.1.1",
|
"jquery": "^3.2.1",
|
||||||
"jquery-contextmenu": "^2.4.3",
|
"jquery-contextmenu": "^2.4.4",
|
||||||
"jquery-simple-upload": "^1.0.0",
|
"jquery-simple-upload": "^1.0.0",
|
||||||
"jquery-smooth-scroll": "^2.0.0",
|
"jquery-smooth-scroll": "^2.0.0",
|
||||||
"merge-stream": "^1.0.1",
|
"merge-stream": "^1.0.1",
|
||||||
@@ -144,10 +146,11 @@
|
|||||||
"pug-lint": "^2.4.0",
|
"pug-lint": "^2.4.0",
|
||||||
"run-sequence": "^1.2.2",
|
"run-sequence": "^1.2.2",
|
||||||
"snyk": "^1.25.1",
|
"snyk": "^1.25.1",
|
||||||
"standard": "^9.0.0",
|
"standard": "^9.0.2",
|
||||||
"sticky-js": "^1.1.9",
|
"sticky-js": "^1.1.9",
|
||||||
"twemoji-awesome": "^1.0.4",
|
"twemoji-awesome": "^1.0.4",
|
||||||
"vue": "^2.2.1"
|
"vee-validate": "^2.0.0-beta.25",
|
||||||
|
"vue": "^2.2.5"
|
||||||
},
|
},
|
||||||
"standard": {
|
"standard": {
|
||||||
"globals": [
|
"globals": [
|
||||||
|
|||||||
+238
-12
@@ -36,6 +36,11 @@ html
|
|||||||
h1 Welcome to Wiki.js!
|
h1 Welcome to Wiki.js!
|
||||||
h2(style={'margin-bottom': 0}) A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown
|
h2(style={'margin-bottom': 0}) A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown
|
||||||
.content(v-cloak)
|
.content(v-cloak)
|
||||||
|
|
||||||
|
//- ==============================================
|
||||||
|
//- WELCOME
|
||||||
|
//- ==============================================
|
||||||
|
|
||||||
template(v-if='state === "welcome"')
|
template(v-if='state === "welcome"')
|
||||||
.panel
|
.panel
|
||||||
h2.panel-title.is-featured
|
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 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].
|
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
|
.panel-footer
|
||||||
|
.progress-bar: div(v-bind:style='{width: currentProgress}')
|
||||||
button.button.is-indigo(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Start
|
button.button.is-indigo(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Start
|
||||||
|
|
||||||
|
//- ==============================================
|
||||||
|
//- SYSTEM CHECK
|
||||||
|
//- ==============================================
|
||||||
|
|
||||||
template(v-else-if='state === "syscheck"')
|
template(v-else-if='state === "syscheck"')
|
||||||
.panel
|
.panel
|
||||||
h2.panel-title.is-featured
|
h2.panel-title.is-featured
|
||||||
@@ -62,10 +72,15 @@ html
|
|||||||
strong Looks good! No issues so far.
|
strong Looks good! No issues so far.
|
||||||
p(v-if='!loading && !syscheck.ok') #[i.icon-square-cross] Error: {{ syscheck.error }}
|
p(v-if='!loading && !syscheck.ok') #[i.icon-square-cross] Error: {{ syscheck.error }}
|
||||||
.panel-footer
|
.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-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-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
|
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"')
|
template(v-else-if='state === "general"')
|
||||||
.panel
|
.panel
|
||||||
h2.panel-title.is-featured
|
h2.panel-title.is-featured
|
||||||
@@ -75,27 +90,33 @@ html
|
|||||||
section
|
section
|
||||||
p.control.is-fullwidth
|
p.control.is-fullwidth
|
||||||
label.label Site Title
|
label.label Site Title
|
||||||
input(type='text', placeholder='e.g. Wiki', v-model='conf.title')
|
input(type='text', placeholder='e.g. Wiki', v-model='conf.title', data-vv-scope='general', name='ipt-title', v-validate='{ required: true, min: 2 }')
|
||||||
p.desc The site title will appear in the top left corner on every page and within the window title bar.
|
span.desc The site title will appear in the top left corner on every page and within the window title bar.
|
||||||
section
|
section
|
||||||
p.control.is-fullwidth
|
p.control.is-fullwidth
|
||||||
label.label Host
|
label.label Host
|
||||||
input(type='text', placeholder='http://', v-model='conf.host')
|
input(type='text', placeholder='http://', v-model='conf.host', data-vv-scope='general', name='ipt-host', v-validate='{ required: true, url: true }')
|
||||||
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.
|
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
|
section
|
||||||
p.control
|
p.control
|
||||||
label.label Port
|
label.label Port
|
||||||
input(type='text', placeholder='e.g. 80', v-model='conf.port')
|
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 }')
|
||||||
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.
|
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
|
section
|
||||||
p.control
|
p.control
|
||||||
label.label Site UI Language
|
label.label Site UI Language
|
||||||
select(v-model='conf.lang')
|
select(v-model='conf.lang')
|
||||||
option(value='en') English
|
each lg in langs
|
||||||
p.desc The language in which navigation, help and other UI elements will be displayed.
|
option(value=lg.id)= lg.name
|
||||||
|
span.desc The language in which navigation, help and other UI elements will be displayed.
|
||||||
.panel-footer
|
.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.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"')
|
template(v-else-if='state === "considerations"')
|
||||||
.panel
|
.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]
|
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!
|
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
|
.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.is-outlined(v-on:click='proceedToGeneral', v-bind:disabled='loading') Back
|
||||||
button.button.is-indigo(v-on:click='proceedToDb', v-bind:disabled='loading') Continue
|
button.button.is-indigo(v-on:click='proceedToDb', v-bind:disabled='loading') Continue
|
||||||
|
|
||||||
|
//- ==============================================
|
||||||
|
//- DATABASE
|
||||||
|
//- ==============================================
|
||||||
|
|
||||||
template(v-else-if='state === "db"')
|
template(v-else-if='state === "db"')
|
||||||
.panel
|
.panel
|
||||||
h2.panel-title.is-featured
|
h2.panel-title.is-featured
|
||||||
span Database
|
span Database
|
||||||
i(v-if='loading')
|
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
|
.panel-content.form-sections
|
||||||
section
|
section
|
||||||
p.control.is-fullwidth
|
p.control.is-fullwidth
|
||||||
label.label MongoDB Connection String
|
label.label MongoDB Connection String
|
||||||
input(type='text', placeholder='e.g. mongodb://localhost:27017/wiki', v-model='conf.db')
|
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 }')
|
||||||
p.desc The connection string to your MongoDB server. Leave the default localhost value if MongoDB is installed on the same server.
|
span.desc The connection string to your MongoDB server. Leave the default localhost value if MongoDB is installed on the same server.
|
||||||
.panel-footer
|
.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.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
|
footer.footer
|
||||||
span
|
span
|
||||||
|
|||||||
Reference in New Issue
Block a user