Commit d8fa6ecc authored by NGPixel's avatar NGPixel

setup wizard intro + syscheck

parent 48e7ea2e
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
"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}}})});
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
'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,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;
}
......@@ -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
// ----------------------------------------
......
......@@ -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',
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment