Commit bb456184 authored by NGPixel's avatar NGPixel

Setup wizard - all UI steps

parent 04be7eba
......@@ -18,6 +18,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- 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 results are no longer duplicated upon article update
- UI: Missing icons on login page
......
......@@ -49,38 +49,41 @@ var Cron = require('cron').CronJob
// Start Cron
// ----------------------------------------
var job
var jobIsBusy = false
var jobUplWatchStarted = false
var job = new Cron({
cronTime: '0 */5 * * * *',
onTick: () => {
// Make sure we don't start two concurrent jobs
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)')
return
}
winston.info('[AGENT] Running all jobs...')
jobIsBusy = true
db.onReady.then(() => {
return db.Entry.remove({})
}).then(() => {
job = new Cron({
cronTime: '0 */5 * * * *',
onTick: () => {
// Make sure we don't start two concurrent jobs
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)')
return
}
winston.info('[AGENT] Running all jobs...')
jobIsBusy = true
// Prepare async job collector
// Prepare async job collector
let jobs = []
let repoPath = path.resolve(ROOTPATH, appconfig.paths.repo)
let dataPath = path.resolve(ROOTPATH, appconfig.paths.data)
let uploadsTempPath = path.join(dataPath, 'temp-upload')
let jobs = []
let repoPath = path.resolve(ROOTPATH, appconfig.paths.repo)
let dataPath = path.resolve(ROOTPATH, appconfig.paths.data)
let uploadsTempPath = path.join(dataPath, 'temp-upload')
// ----------------------------------------
// REGULAR JOBS
// ----------------------------------------
// ----------------------------------------
// REGULAR JOBS
// ----------------------------------------
//* ****************************************
// -> Sync with Git remote
//* ****************************************
//* ****************************************
// -> Sync with Git remote
//* ****************************************
jobs.push(git.onReady.then(() => {
return git.resync().then(() => {
jobs.push(git.resync().then(() => {
// -> Stream all documents
let cacheJobs = []
......@@ -131,55 +134,56 @@ var job = new Cron({
})
return jobCbStreamDocs
})
}))
//* ****************************************
// -> Clear failed temporary upload files
//* ****************************************
jobs.push(
fs.readdirAsync(uploadsTempPath).then((ls) => {
let fifteenAgo = moment().subtract(15, 'minutes')
return Promise.map(ls, (f) => {
return fs.statAsync(path.join(uploadsTempPath, f)).then((s) => { return { filename: f, stat: s } })
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
return Promise.map(arrFiles, (f) => {
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
return fs.unlinkAsync(path.join(uploadsTempPath, f.filename))
} else {
return true
}
}))
//* ****************************************
// -> Clear failed temporary upload files
//* ****************************************
jobs.push(
fs.readdirAsync(uploadsTempPath).then((ls) => {
let fifteenAgo = moment().subtract(15, 'minutes')
return Promise.map(ls, (f) => {
return fs.statAsync(path.join(uploadsTempPath, f)).then((s) => { return { filename: f, stat: s } })
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
return Promise.map(arrFiles, (f) => {
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
return fs.unlinkAsync(path.join(uploadsTempPath, f.filename))
} else {
return true
}
})
})
})
})
)
)
// ----------------------------------------
// Run
// ----------------------------------------
// ----------------------------------------
// Run
// ----------------------------------------
Promise.all(jobs).then(() => {
winston.info('[AGENT] All jobs completed successfully! Going to sleep for now.')
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()
})
}
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
})
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:
name: Wiki
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
# ---------------------------------
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(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}}})});
\ No newline at end of file
"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){}}})});
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -93,6 +93,7 @@ if ($('#mk-editor').length === 1) {
mdeModalOpenState = true;
$('#modal-editor-link').slideToggle();
} */
window.alert('Coming soon!')
},
className: 'icon-link2',
title: 'Insert Link'
......@@ -163,6 +164,7 @@ if ($('#mk-editor').length === 1) {
{
name: 'table',
action: (editor) => {
window.alert('Coming soon!')
// todo
},
className: 'icon-table',
......
'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 ($) {
new Vue({ // eslint-disable-line no-new
el: 'main',
data: {
loading: false,
state: 'considerations',
state: 'welcome',
syscheck: {
ok: false,
error: '',
results: []
},
dbcheck: {
ok: false,
error: ''
},
gitcheck: {
ok: false,
error: ''
},
final: {
ok: false,
error: '',
results: []
},
conf: {
title: 'Wiki',
host: '',
host: 'http://',
port: 80,
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: {
https: false,
......@@ -26,6 +65,44 @@ jQuery(document).ready(function ($) {
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: {
proceedToWelcome: function (ev) {
this.state = 'welcome'
......@@ -58,8 +135,12 @@ jQuery(document).ready(function ($) {
}, 1000)
},
proceedToGeneral: function (ev) {
this.state = 'general'
this.loading = false
let self = this
self.state = 'general'
self.loading = false
self.$nextTick(() => {
self.$validator.validateAll('general')
})
},
proceedToConsiderations: function (ev) {
this.considerations = {
......@@ -71,8 +152,115 @@ jQuery(document).ready(function ($) {
this.loading = false
},
proceedToDb: function (ev) {
this.state = 'db'
this.loading = false
let self = this
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) {
let pageEntryPath = $('#page-type-edit').data('entrypath') // eslint-disable-line no-unused-vars
// let pageCleanExit = false
// -> Discard
......@@ -9,6 +10,10 @@ if ($('#page-type-edit').length) {
$('#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 */
//=include ../components/editor.js
/* eslint-enable spaced-comment */
......
.editor-toolbar {
z-index: 2;
background-color: rgba(0,0,0,0.75);
background-color: mc('indigo', '900');
border: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
opacity: 1;
position: fixed;
top: 51px;
top: 50px;
left: 0;
width: 100%;
......@@ -90,7 +90,7 @@
}
}
......@@ -98,7 +98,7 @@
display: flex;
flex-wrap: wrap;
align-items: flex-start;
overflow: auto;
overflow-x: hidden;
......@@ -140,7 +140,7 @@
> span {
font-size: 12px;
> strong {
text-overflow: ellipsis;
white-space: nowrap;
......@@ -358,4 +358,4 @@
left: 0;
bottom: 0;
right: 0;
}
\ No newline at end of file
}
......@@ -53,3 +53,24 @@ i.icon-warning-outline {
max-height: 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;
}
}
......@@ -15,8 +15,11 @@ module.exports = (port, spinner) => {
const http = require('http')
const path = require('path')
const Promise = require('bluebird')
const fs = require('fs-extra')
const yaml = require('js-yaml')
const _ = require('lodash')
// ----------------------------------------
// Define Express App
// ----------------------------------------
......@@ -48,9 +51,20 @@ module.exports = (port, spinner) => {
// ----------------------------------------
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) => {
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
// ----------------------------------------
......
......@@ -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/vee-validate/dist/vee-validate.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',
......
......@@ -152,7 +152,7 @@ module.exports = {
return false
}
}).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,
title: content.meta.title || content.entryPath,
subtitle: content.meta.subtitle || '',
parent: content.parent.title || '',
content: content.text || ''
parent: content.parent.title || ''
}, {
new: true,
upsert: true
......@@ -396,60 +395,5 @@ module.exports = {
return fs.readFileAsync(path.join(ROOTPATH, 'client/content/create.md'), 'utf8').then((contents) => {
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) {
return jimp.read(sourcePath).then(img => {
return img.cover(150, 150)
.background(0xFFFFFFFF)
.opaque()
.rgba(false)
return img
.contain(150, 150)
.write(destPath)
})
},
......
......@@ -21,10 +21,6 @@ var entrySchema = Mongoose.Schema({
parent: {
type: String,
default: ''
},
content: {
type: String,
default: ''
}
},
......@@ -32,19 +28,4 @@ var entrySchema = Mongoose.Schema({
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)
......@@ -41,7 +41,7 @@
"bcryptjs-then": "^1.0.1",
"bluebird": "^3.4.7",
"body-parser": "^1.17.1",
"bunyan": "^1.8.8",
"bunyan": "^1.8.9",
"cheerio": "^0.22.0",
"child-process-promise": "^2.2.0",
"chokidar": "^1.6.0",
......@@ -51,21 +51,22 @@
"connect-mongo": "^1.3.2",
"cookie-parser": "^1.4.3",
"cron": "^1.2.1",
"execa": "^0.6.3",
"express": "^4.15.2",
"express-brute": "^1.0.0",
"express-brute-mongoose": "0.0.7",
"express-session": "^1.15.1",
"file-type": "^4.0.0",
"filesize.js": "^1.0.2",
"follow-redirects": "^1.2.1",
"fs-extra": "^2.0.0",
"follow-redirects": "^1.2.3",
"fs-extra": "^2.1.2",
"git-wrapper2-promise": "^0.2.9",
"highlight.js": "^9.9.0",
"i18next": "^7.1.1",
"i18next-express-middleware": "^1.0.2",
"i18next": "^7.1.3",
"i18next-express-middleware": "^1.0.3",
"i18next-node-fs-backend": "^0.1.3",
"image-size": "^0.5.1",
"jimp": "github:NGPixel/jimp",
"jimp": "github:ngpixel/jimp",
"js-yaml": "^3.8.1",
"klaw": "^1.3.1",
"levelup": "^1.3.5",
......@@ -80,12 +81,13 @@
"markdown-it-footnote": "^3.0.1",
"markdown-it-task-lists": "^1.4.1",
"memdown": "^1.2.4",
"mime-types": "^2.1.13",
"moment": "^2.17.1",
"mime-types": "^2.1.15",
"moment": "^2.18.1",
"moment-timezone": "^0.5.11",
"mongoose": "^4.8.5",
"mongodb": "^2.2.25",
"mongoose": "^4.9.1",
"multer": "^1.2.1",
"ora": "^1.1.0",
"ora": "^1.2.0",
"passport": "^0.3.2",
"passport-local": "^1.0.0",
"passport.socketio": "^3.7.0",
......@@ -94,11 +96,11 @@
"read-chunk": "^2.0.0",
"remove-markdown": "^0.1.0",
"requarks-core": "^0.2.2",
"request": "^2.80.0",
"search-index-adder": "github:NGPixel/search-index-adder",
"search-index-searcher": "github:NGPixel/search-index-searcher",
"request": "^2.81.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",
"serve-favicon": "^2.4.2",
"simplemde": "^1.11.2",
"socket.io": "^1.7.3",
"sticky-js": "^1.0.7",
......@@ -112,16 +114,16 @@
},
"devDependencies": {
"ace-builds": "^1.2.6",
"babel-preset-es2015": "^6.16.0",
"babel-preset-es2015": "^6.24.0",
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"codacy-coverage": "^2.0.0",
"eslint": "^3.16.1",
"eslint": "^3.18.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^2.1.1",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-clean-css": "^3.0.3",
"gulp-clean-css": "^3.0.4",
"gulp-concat": "^2.6.1",
"gulp-gzip": "^1.4.0",
"gulp-include": "^2.3.1",
......@@ -129,12 +131,12 @@
"gulp-plumber": "^1.1.0",
"gulp-sass": "^3.0.0",
"gulp-tar": "^1.9.0",
"gulp-uglify": "^2.0.0",
"gulp-uglify": "^2.1.2",
"gulp-watch": "^4.3.11",
"gulp-zip": "^4.0.0",
"istanbul": "^0.4.5",
"jquery": "^3.1.1",
"jquery-contextmenu": "^2.4.3",
"jquery": "^3.2.1",
"jquery-contextmenu": "^2.4.4",
"jquery-simple-upload": "^1.0.0",
"jquery-smooth-scroll": "^2.0.0",
"merge-stream": "^1.0.1",
......@@ -144,10 +146,11 @@
"pug-lint": "^2.4.0",
"run-sequence": "^1.2.2",
"snyk": "^1.25.1",
"standard": "^9.0.0",
"standard": "^9.0.2",
"sticky-js": "^1.1.9",
"twemoji-awesome": "^1.0.4",
"vue": "^2.2.1"
"vee-validate": "^2.0.0-beta.25",
"vue": "^2.2.5"
},
"standard": {
"globals": [
......
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