Browse Source

setup wizard intro + syscheck

pull/33/head
NGPixel 8 years ago
parent
commit
d8fa6ecc27
11 changed files with 205 additions and 51 deletions
  1. 2
      assets/css/app.css
  2. 2
      assets/css/configure.css
  3. 2
      assets/css/error.css
  4. 1
      assets/js/configure.js
  5. 52
      assets/js/libs.js
  6. 46
      client/js/configure.js
  7. 25
      client/scss/configure.scss
  8. 56
      configure.js
  9. 1
      gulpfile.js
  10. 1
      package.json
  11. 68
      views/configure/index.pug

2
assets/css/app.css
File diff suppressed because it is too large
View File

2
assets/css/configure.css
File diff suppressed because it is too large
View File

2
assets/css/error.css
File diff suppressed because it is too large
View File

1
assets/js/configure.js

@ -0,0 +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:""}},methods:{proceedToSyscheck:function(e){var t=this;this.state="syscheck",this.loading=!0,_.delay(function(){axios.post("/syscheck").then(function(e){e.data.ok===!0?t.syscheck.ok=!0:(t.syscheck.ok=!1,t.syscheck.error=e.data.error),t.loading=!1}).catch(function(e){window.alert(e.message)})},1e3)},proceedToGeneral:function(e){this.state="general",this.loading=!0}}})});

52
assets/js/libs.js
File diff suppressed because it is too large
View File

46
client/js/configure.js

@ -0,0 +1,46 @@
'use strict'
/* global jQuery, _, Vue, axios */
jQuery(document).ready(function ($) {
new Vue({ // eslint-disable-line no-new
el: 'main',
data: {
loading: false,
state: 'welcome',
syscheck: {
ok: false,
error: ''
},
conf: {
title: 'Wiki',
host: ''
}
},
methods: {
proceedToSyscheck: function (ev) {
let self = this
this.state = 'syscheck'
this.loading = true
_.delay(() => {
axios.post('/syscheck').then(resp => {
if (resp.data.ok === true) {
self.syscheck.ok = true
} else {
self.syscheck.ok = false
self.syscheck.error = resp.data.error
}
self.loading = false
}).catch(err => {
window.alert(err.message)
})
}, 1000)
},
proceedToGeneral: function (ev) {
this.state = 'general'
this.loading = true
}
}
})
})

25
client/scss/configure.scss

@ -25,3 +25,28 @@ $primary: 'indigo';
}
}
i.icon-loader {
display: inline-block;
color: mc('indigo', '500')
}
i.icon-check {
color: mc('green', '500')
}
i.icon-square-cross {
color: mc('red', '500')
}
.tst-welcome-leave-active {
transition: all .5s;
overflow-y: hidden;
}
.tst-welcome-leave {
opacity: 1;
max-height: 200px;
}
.tst-welcome-leave-to {
opacity: 0;
max-height: 0;
padding-top: 0;
}

56
configure.js

@ -14,6 +14,8 @@ module.exports = (port, spinner) => {
const favicon = require('serve-favicon')
const http = require('http')
const path = require('path')
const Promise = require('bluebird')
const _ = require('lodash')
// ----------------------------------------
// Define Express App
@ -49,6 +51,60 @@ module.exports = (port, spinner) => {
res.render('configure/index')
})
app.post('/syscheck', (req, res) => {
Promise.mapSeries([
() => {
const semver = require('semver')
if (!semver.satisfies(semver.clean(process.version), '>=4.6.0')) {
throw new Error('Node.js version is too old. Minimum is 4.6.0.')
}
return true
},
() => {
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(() => {
require('crypto')
}).catch(err => { // eslint-disable-line handle-callback-err
throw new Error('Crypto Node.js module is not available.')
}).return(true)
},
() => {
const exec = require('child_process').exec
const semver = require('semver')
return new Promise((resolve, reject) => {
exec('git --version', (err, stdout, stderr) => {
if (err || stdout.length < 3) {
reject(new Error('Git is not installed or not reachable from PATH.'))
}
let gitver = _.chain(stdout.replace(/[^\d.]/g, '')).split('.').take(3).join('.').value()
if (!semver.satisfies(semver.clean(gitver), '>=2.11.0')) {
reject(new Error('Git version is too old. Minimum is 2.11.0.'))
}
resolve(true)
})
})
},
() => {
let fs = require('fs')
return Promise.try(() => {
fs.accessSync(path.join(ROOTPATH, 'config.yml'), (fs.constants || fs).W_OK)
}).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.')
}).return(true)
}
], test => { return test() }).then(results => {
res.json({ ok: true })
}).catch(err => {
res.json({ ok: false, error: err.message })
})
})
// ----------------------------------------
// Error handling
// ----------------------------------------

1
gulpfile.js

@ -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/axios/dist/axios.min.js',
'./node_modules/jquery-smooth-scroll/jquery.smooth-scroll.min.js',
'./node_modules/jquery-simple-upload/simpleUpload.min.js',
'./node_modules/jquery-contextmenu/dist/jquery.contextMenu.min.js',

1
package.json

@ -97,6 +97,7 @@
"request": "^2.79.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",
"simplemde": "^1.11.2",
"socket.io": "^1.7.3",

68
views/configure/index.pug

@ -15,7 +15,7 @@ html
// JS
script(type='text/javascript', src='/js/libs.js')
//script(type='text/javascript', src='/js/app.js')
script(type='text/javascript', src='/js/configure.js')
block head
@ -24,32 +24,56 @@ html
#header-container
nav.nav#header
.nav-left
a.nav-item(href='/')
a.nav-item
h1
i.icon-layers
| Wiki.js
main
.container
.welcome(style={'padding-bottom': '5px'})
img(src='/favicons/android-icon-96x96.png', alt='Wiki.js')
h1 Welcome to Wiki.js!
h2(style={'margin-bottom': 0}) Fill in the fields below to get up and running.
.content
.panel
h2.panel-title
span General
i(v-if='loading')
.panel-content.form-sections
section
p.control.is-fullwidth
label.label Site Title
input(type='text', placeholder='e.g. Wiki', v-model='title')
section
p.control.is-fullwidth
label.label Host
input(type='text', placeholder='http://', v-model='host')
.panel-footer
button.button.is-indigo(v-on:click='add', v-bind:disabled='loading') Continue
transition(name='tst-welcome')
.welcome(style={'padding-bottom': '5px'}, v-if='state === "welcome"')
img(src='/favicons/android-icon-96x96.png', alt='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
.content(v-cloak)
template(v-if='state === "welcome"')
.panel
h2.panel-title.is-featured
span Introduction
i(v-if='loading')
.panel-content.is-text
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
button.button.is-indigo(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Start
template(v-else-if='state === "syscheck"')
.panel
h2.panel-title.is-featured
span System Check
i(v-if='loading')
.panel-content.is-text
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') #[i.icon-square-cross] Error: {{ syscheck.error }}
.panel-footer
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
template(v-else-if='state === "general"')
.panel
h2.panel-title.is-featured
span General
i(v-if='loading')
.panel-content.form-sections
section
p.control.is-fullwidth
label.label Site Title
input(type='text', placeholder='e.g. Wiki', v-model='conf.title')
section
p.control.is-fullwidth
label.label Host
input(type='text', placeholder='http://', v-model='conf.host')
.panel-footer
button.button.is-indigo(v-on:click='proceedToSyscheck', v-bind:disabled='loading') Continue
footer.footer
span
| Powered by

Loading…
Cancel
Save