Setup wizard - considerations + syschecks UI fixes

This commit is contained in:
NGPixel 2017-03-14 21:23:14 -04:00
parent bfcec5a91c
commit 40685410f0
9 changed files with 86 additions and 22 deletions

View File

@ -39,3 +39,10 @@ deploy:
repo: Requarks/wiki repo: Requarks/wiki
tags: true tags: true
node: '7' node: '7'
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/56b27cb2ec4692419db9
on_success: change
on_failure: always
on_start: never

View File

@ -6,7 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Added ### Added
- Interactive setup - Interactive setup
- GitHub and Slack authentication providers are now available - GitHub and Slack authentication providers are now available
- Experimental: LDAP authentication provider - LDAP authentication provider
### Changed ### Changed
- Content headers are now showing an anchor icon instead of a # - Content headers are now showing an anchor icon instead of a #
@ -21,6 +21,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Missing icons on login page - Missing icons on login page
- Image alignement center and right should now behave correctly - Image alignement center and right should now behave correctly
- Error notification when upload is too large for server - Error notification when upload is too large for server
- Authentication would fail if email has uppercase chars and provider callback is in lowercase
## [v1.0.0-beta.8] - 2017-02-19 ## [v1.0.0-beta.8] - 2017-02-19
### Added ### Added

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
"use strict";jQuery(document).ready(function(e){new Vue({el:"main",data:{loading:!1,state:"welcome",syscheck:{ok:!1,error:""},conf:{title:"Wiki",host:"",port:80,lang:"en",db:"mongodb://localhost:27017/wiki"}},methods:{proceedToWelcome:function(e){this.state="welcome",this.loading=!1},proceedToSyscheck:function(e){var o=this;this.state="syscheck",this.loading=!0,_.delay(function(){axios.post("/syscheck").then(function(e){e.data.ok===!0?o.syscheck.ok=!0:(o.syscheck.ok=!1,o.syscheck.error=e.data.error),o.loading=!1}).catch(function(e){window.alert(e.message)})},1e3)},proceedToGeneral:function(e){this.state="general",this.loading=!1},proceedToDb:function(e){this.state="db",this.loading=!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}}})});

View File

@ -7,10 +7,11 @@ jQuery(document).ready(function ($) {
el: 'main', el: 'main',
data: { data: {
loading: false, loading: false,
state: 'welcome', state: 'considerations',
syscheck: { syscheck: {
ok: false, ok: false,
error: '' error: '',
results: []
}, },
conf: { conf: {
title: 'Wiki', title: 'Wiki',
@ -18,6 +19,11 @@ jQuery(document).ready(function ($) {
port: 80, port: 80,
lang: 'en', lang: 'en',
db: 'mongodb://localhost:27017/wiki' db: 'mongodb://localhost:27017/wiki'
},
considerations: {
https: false,
port: false,
localhost: false
} }
}, },
methods: { methods: {
@ -29,16 +35,23 @@ jQuery(document).ready(function ($) {
let self = this let self = this
this.state = 'syscheck' this.state = 'syscheck'
this.loading = true this.loading = true
self.syscheck = {
ok: false,
error: '',
results: []
}
_.delay(() => { _.delay(() => {
axios.post('/syscheck').then(resp => { axios.post('/syscheck').then(resp => {
if (resp.data.ok === true) { if (resp.data.ok === true) {
self.syscheck.ok = true self.syscheck.ok = true
self.syscheck.results = resp.data.results
} else { } else {
self.syscheck.ok = false self.syscheck.ok = false
self.syscheck.error = resp.data.error self.syscheck.error = resp.data.error
} }
self.loading = false self.loading = false
self.$nextTick()
}).catch(err => { }).catch(err => {
window.alert(err.message) window.alert(err.message)
}) })
@ -48,6 +61,15 @@ jQuery(document).ready(function ($) {
this.state = 'general' this.state = 'general'
this.loading = false this.loading = false
}, },
proceedToConsiderations: function (ev) {
this.considerations = {
https: !_.startsWith(this.conf.host, 'https'),
port: false, // TODO
localhost: _.includes(this.conf.host, 'localhost')
}
this.state = 'considerations'
this.loading = false
},
proceedToDb: function (ev) { proceedToDb: function (ev) {
this.state = 'db' this.state = 'db'
this.loading = false this.loading = false

View File

@ -36,6 +36,9 @@ i.icon-check {
i.icon-square-cross { i.icon-square-cross {
color: mc('red', '500') color: mc('red', '500')
} }
i.icon-warning-outline {
color: mc('orange', '500')
}
.tst-welcome-leave-active, .tst-welcome-enter-active { .tst-welcome-leave-active, .tst-welcome-enter-active {
transition: all .5s; transition: all .5s;

View File

@ -56,23 +56,16 @@ module.exports = (port, spinner) => {
() => { () => {
const semver = require('semver') const semver = require('semver')
if (!semver.satisfies(semver.clean(process.version), '>=4.6.0')) { if (!semver.satisfies(semver.clean(process.version), '>=4.6.0')) {
throw new Error('Node.js version is too old. Minimum is 4.6.0.') throw new Error('Node.js version is too old. Minimum is v4.6.0.')
} }
return true return 'Node.js ' + process.version + ' detected. Minimum is v4.6.0.'
},
() => {
const os = require('os')
if (os.totalmem() < 1024 * 1024 * 512) {
throw new Error('Not enough memory. Minimum is 512 MB.')
}
return true
}, },
() => { () => {
return Promise.try(() => { return Promise.try(() => {
require('crypto') require('crypto')
}).catch(err => { // eslint-disable-line handle-callback-err }).catch(err => { // eslint-disable-line handle-callback-err
throw new Error('Crypto Node.js module is not available.') throw new Error('Crypto Node.js module is not available.')
}).return(true) }).return('Node.js Crypto module is available.')
}, },
() => { () => {
const exec = require('child_process').exec const exec = require('child_process').exec
@ -84,22 +77,29 @@ module.exports = (port, spinner) => {
} }
let gitver = _.chain(stdout.replace(/[^\d.]/g, '')).split('.').take(3).join('.').value() let gitver = _.chain(stdout.replace(/[^\d.]/g, '')).split('.').take(3).join('.').value()
if (!semver.satisfies(semver.clean(gitver), '>=2.11.0')) { if (!semver.satisfies(semver.clean(gitver), '>=2.11.0')) {
reject(new Error('Git version is too old. Minimum is 2.11.0.')) reject(new Error('Git version is too old. Minimum is v2.11.0.'))
} }
resolve(true) resolve('Git v' + gitver + ' detected. Minimum is v2.11.0.')
}) })
}) })
}, },
() => {
const os = require('os')
if (os.totalmem() < 1024 * 1024 * 768) {
throw new Error('Not enough memory. Minimum is 768 MB.')
}
return _.round(os.totalmem() / (1024 * 1024)) + ' MB of system memory available. Minimum is 768 MB.'
},
() => { () => {
let fs = require('fs') let fs = require('fs')
return Promise.try(() => { return Promise.try(() => {
fs.accessSync(path.join(ROOTPATH, 'config.yml'), (fs.constants || fs).W_OK) fs.accessSync(path.join(ROOTPATH, 'config.yml'), (fs.constants || fs).W_OK)
}).catch(err => { // eslint-disable-line handle-callback-err }).catch(err => { // eslint-disable-line handle-callback-err
throw new Error('config.yml file is not writable by Node.js process or was not created properly.') throw new Error('config.yml file is not writable by Node.js process or was not created properly.')
}).return(true) }).return('config.yml is writable by the setup process.')
} }
], test => { return test() }).then(results => { ], test => { return test() }).then(results => {
res.json({ ok: true }) res.json({ ok: true, results })
}).catch(err => { }).catch(err => {
res.json({ ok: false, error: err.message }) res.json({ ok: false, error: err.message })
}) })

View File

@ -54,7 +54,12 @@ html
i(v-if='loading') i(v-if='loading')
.panel-content.is-text .panel-content.is-text
p(v-if='loading') #[i.icon-loader.animated.rotateIn.infinite] Checking your system for compatibility... p(v-if='loading') #[i.icon-loader.animated.rotateIn.infinite] Checking your system for compatibility...
p(v-if='!loading && syscheck.ok') #[i.icon-check] Looks great! No issues so far. p(v-if='!loading && syscheck.ok')
ul
li(v-for='rs in syscheck.results') #[i.icon-check] {{rs}}
p(v-if='!loading && syscheck.ok')
i.icon-check
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
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
@ -90,6 +95,32 @@ html
p.desc The language in which navigation, help and other UI elements will be displayed. p.desc The language in which navigation, help and other UI elements will be displayed.
.panel-footer .panel-footer
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
template(v-else-if='state === "considerations"')
.panel
h2.panel-title.is-featured
span Important Considerations
i(v-if='loading')
.panel-content.is-text
h3 Is Wiki.js going to be behind a web server (e.g. nginx / apache / IIS) or proxy?
p
ul
li - Make sure the upload limit is sufficient. Most web servers have a low limit (e.g. 2 MB) by default.
li - Make sure your web server is configured to allow web sockets. Wiki.js will fallback to standard XHR queries if not available.
li - Do not rewrite URLs after the domain. This can cause unexpected issues in Wiki.js navigation.
li - Do not remove or alter the client IP when proxying the requests. This can cause the authentication brute force protection to engage unexpectedly.
template(v-if='considerations.https')
h3 The site will not be using HTTPS? #[i.icon-warning-outline.animated.fadeOut.infinite]
p The host URL you specified is not HTTPS. It is highly recommended to use HTTPS. You must use a web server / proxy (e.g. nginx / apache / IIS) in front of Wiki.js to use HTTPS. Wiki.js does not provide HTTPS handling by itself.
template(v-if='considerations.port')
h3 You are using a non-standard port.
p If you are not planning on using a web server / proxy in front of Wiki.js, be aware that users will need to specify the port when accessing the wiki. Make sure this is the intended behavior. Otherwise set a standard HTTP port such as 80.
template(v-if='considerations.localhost')
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
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
template(v-else-if='state === "db"') template(v-else-if='state === "db"')
@ -104,7 +135,7 @@ html
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')
p.desc The connection string to your MongoDB server. Leave the default localhost value if MongoDB is installed on the same server. p.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
button.button.is-indigo.is-outlined(v-on:click='proceedToGeneral', 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='proceedToSyscheck', v-bind:disabled='loading') Connect
footer.footer footer.footer