< template lang = "pug" >
v - app . setup
v - content
v - container
v - layout
v - flex ( xs12 , lg6 , offset - lg3 )
v - card . elevation - 20. radius - 7. animated . fadeInUp
. text - center
img . setup - logo . animated . fadeInUp . wait - p2s ( src = '/svg/logo-wikijs-full.svg' , alt = 'Wiki.js Logo' )
v - alert ( v - model = 'error' , type = 'error' , icon = 'mdi-alert' , tile , dismissible ) { { errorMessage } }
v - alert ( v - if = '!error' , tile , color = 'blue lighten-5' , : value = 'true' )
v - icon . mr - 3 ( color = 'blue' ) mdi - package - variant
span . blue -- text You are about to install Wiki . js # [ strong { { wikiVersion } } ] .
v - card - text
. overline . pl - 3 Administrator Account
v - container . pa - 3. mt - 3 ( grid - list - xl )
v - layout ( row , wrap )
v - flex ( xs12 )
v - text - field (
outlined
v - model = 'conf.adminEmail' ,
label = 'Administrator Email' ,
hint = 'The email address of the administrator account.' ,
persistent - hint
required
ref = 'adminEmailInput'
)
v - flex ( xs6 )
v - text - field (
outlined
ref = 'adminPassword' ,
counter = '255'
v - model = 'conf.adminPassword' ,
label = 'Password' ,
: append - icon = "pwdMode ? 'mdi-eye-off' : 'mdi-eye'"
@ click : append = "() => (pwdMode = !pwdMode)"
: type = "pwdMode ? 'password' : 'text'"
hint = 'At least 8 characters long.' ,
persistent - hint
)
v - flex ( xs6 )
v - text - field (
outlined
ref = 'adminPasswordConfirm' ,
counter = '255'
v - model = 'conf.adminPasswordConfirm' ,
label = 'Confirm Password' ,
: append - icon = "pwdConfirmMode ? 'mdi-eye-off' : 'mdi-eye'"
@ click : append = "() => (pwdConfirmMode = !pwdConfirmMode)"
: type = "pwdConfirmMode ? 'password' : 'text'"
hint = 'Verify your password again.' ,
persistent - hint
)
v - divider . mb - 4
. overline . pl - 3. mb - 5 Site URL
v - text - field . mb - 4. mx - 3 (
outlined
ref = 'adminSiteUrl' ,
v - model = 'conf.siteUrl' ,
label = 'Site URL' ,
hint = 'Full URL to your wiki, without the trailing slash (e.g. https://wiki.example.com). This should be the public facing URL, not the internal one if using a reverse-proxy.' ,
persistent - hint
@ keyup . enter = 'install'
)
v - divider . mb - 4
. overline . pl - 3. mb - 3 Telemetry
v - switch . ml - 3 (
inset
color = 'primary' ,
v - model = 'conf.telemetry' ,
label = 'Allow Telemetry' ,
persistent - hint ,
hint = 'Help Wiki.js developers improve this app with anonymized telemetry.'
)
a . pl - 3 ( style = 'font-size: 12px; letter-spacing: initial;' , href = 'https://docs.requarks.io/telemetry' , target = '_blank' ) Learn more
v - divider . mt - 2
v - card - actions
v - btn ( color = 'primary' , @ click = 'install' , : disabled = 'loading' , x - large , depressed , block )
v - icon ( left ) mdi - check
span Install
v - dialog ( v - model = 'loading' , width = '450' , persistent )
v - card ( color = 'primary' , dark ) . radius - 7
v - card - text . text - center . py - 5
. py - 3 ( style = 'width: 64px; display:inline-block;' )
breeding - rhombus - spinner (
: animation - duration = '2000'
: size = '64'
color = '#FFF'
)
template ( v - if = '!success' )
. subtitle - 1. white -- text Finalizing your installation ...
. caption Just a moment
template ( v - else )
. subtitle - 1. white -- text Installation complete !
. caption Redirecting ...
< / template >
< script >
import _ from 'lodash'
import validate from 'validate.js'
import { BreedingRhombusSpinner } from 'epic-spinners'
export default {
components : {
BreedingRhombusSpinner
} ,
props : {
wikiVersion : {
type : String ,
required : true
}
} ,
data ( ) {
return {
loading : false ,
success : false ,
error : false ,
errorMessage : '' ,
conf : {
adminEmail : '' ,
adminPassword : '' ,
adminPasswordConfirm : '' ,
siteUrl : 'https://wiki.yourdomain.com' ,
telemetry : true
} ,
pwdMode : true ,
pwdConfirmMode : true
}
} ,
mounted ( ) {
_ . delay ( ( ) => {
this . $refs . adminEmailInput . focus ( )
} , 500 )
} ,
methods : {
async install ( ) {
this . error = false
const validationResults = validate ( this . conf , {
adminEmail : {
presence : {
allowEmpty : false
} ,
email : true
} ,
adminPassword : {
presence : {
allowEmpty : false
} ,
length : {
minimum : 6 ,
maximum : 255
}
} ,
adminPasswordConfirm : {
equality : 'adminPassword'
} ,
siteUrl : {
presence : {
allowEmpty : false
} ,
url : {
schemes : [ 'http' , 'https' ] ,
allowLocal : true ,
allowDataUrl : false
} ,
format : {
pattern : '^(?!.*/$).*$' ,
flags : 'i' ,
message : 'must not have a trailing slash'
}
}
} , {
format : 'flat'
} )
if ( validationResults ) {
this . error = true
this . errorMessage = validationResults [ 0 ]
this . $forceUpdate ( )
return
}
this . loading = true
this . success = false
this . $forceUpdate ( )
_ . delay ( async ( ) => {
try {
const resp = await fetch ( '/finalize' , {
method : 'POST' ,
cache : 'no-cache' ,
headers : {
'Content-Type' : 'application/json'
} ,
body : JSON . stringify ( this . conf )
} ) . then ( res => res . json ( ) )
if ( resp . ok === true ) {
_ . delay ( ( ) => {
this . success = true
_ . delay ( ( ) => {
window . location . assign ( '/login' )
} , 3000 )
} , 10000 )
} else {
this . error = true
this . errorMessage = resp . error
this . loading = false
}
} catch ( err ) {
window . alert ( err . message )
}
} , 1000 )
}
}
}
< / script >
< style lang = 'scss' >
. setup {
. v - application -- wrap {
padding - top : 10 vh ;
background - color : # 111 ;
background - image : linear - gradient ( 45 deg , mc ( 'blue' , '100' ) , mc ( 'blue' , '700' ) , mc ( 'indigo' , '900' ) ) ;
background - blend - mode : exclusion ;
& : : before {
content : '' ;
position : absolute ;
left : 0 ;
top : 0 ;
width : 100 % ;
height : 100 vh ;
z - index : 0 ;
background - color : transparent ;
background - image : url ( / s v g / m o t i f - g r i d . s v g ) ! i m p o r t a n t ;
background - size : 100 px ;
background - repeat : repeat ;
animation : bg - anim 100 s linear infinite ;
}
}
@ keyframes bg - anim {
0 % {
background - position : 0 0 ;
}
100 % {
background - position : 100 % 100 % ;
}
}
& - logo {
width : 400 px ;
margin : 2 rem 0 2 rem 0 ;
}
}
< / style >