diff --git a/client/js/pages/all.js b/client/js/pages/all.js index 4819f5c2..18690f89 100644 --- a/client/js/pages/all.js +++ b/client/js/pages/all.js @@ -20,9 +20,9 @@ module.exports = (alerts, socket) => { Vue.nextTick(() => { socket.emit('treeFetch', { basePath }, (data) => { if (self.tree.length > 0) { - let curTree = _.last(self.tree) - curTree.hasChildren = true - _.find(curTree.pages, { _id: basePath }).isActive = true + let branch = _.last(self.tree) + branch.hasChildren = true + _.find(branch.pages, { _id: basePath }).isActive = true } self.tree.push({ hasChildren: false, @@ -34,6 +34,32 @@ module.exports = (alerts, socket) => { }, goto: function (entryPath) { window.location.assign(rootUrl + entryPath) + }, + unfold: function (entryPath) { + let self = this + let lastIndex = 0 + _.forEach(self.tree, branch => { + lastIndex++ + if (_.find(branch.pages, { _id: entryPath }) !== undefined) { + return false + } + }) + self.tree = _.slice(self.tree, 0, lastIndex) + let branch = _.last(self.tree) + branch.hasChildren = false + branch.pages.forEach(page => { + page.isActive = false + }) + }, + mainAction: function (page) { + let self = this + if (page.isActive) { + self.unfold(page._id) + } else if (page.isDirectory) { + self.fetch(page._id) + } else { + self.goto(page._id) + } } }, mounted: function () { diff --git a/client/scss/components/collapsable-nav.scss b/client/scss/components/collapsable-nav.scss index 614108c9..0629776d 100644 --- a/client/scss/components/collapsable-nav.scss +++ b/client/scss/components/collapsable-nav.scss @@ -58,6 +58,11 @@ a { height: 50px; + + &:nth-child(2) { + display: none; + } + } } @@ -65,7 +70,8 @@ a { display: flex; - height: 40px; + flex: 1 1 auto; + min-height: 40px; width: 100%; align-items: center; padding: 0 15px; @@ -74,9 +80,9 @@ transition: all .4s ease; background-color: rgba(0,0,0,0); - i { - font-size: 14px; - margin-right: 10px; + &.is-pagelink { + flex: 0 1 70px; + justify-content: center; } &:hover { @@ -84,6 +90,20 @@ text-decoration: none; } + i { + font-size: 14px; + + &:first-of-type { + margin-right: 10px; + } + + } + + span { + display: block; + padding: 5px 0; + } + } } diff --git a/libs/entries.js b/libs/entries.js index daf23229..eb976370 100644 --- a/libs/entries.js +++ b/libs/entries.js @@ -310,20 +310,15 @@ module.exports = { subtitle: content.meta.subtitle || '', parentTitle: content.parent.title || '', parentPath: parentPath, - isDirectory: false + isDirectory: false, + isEntry: true }, { new: true, upsert: true }) }).then(result => { - return db.Entry.distinct('parentPath', { parentPath: { $ne: '' } }).then(allPaths => { - if (allPaths.length > 0) { - return db.Entry.updateMany({ _id: { $in: allPaths } }, { $set: { isDirectory: true } }).then(() => { - return result - }) - } else { - return result - } + return self.updateTreeInfo().then(() => { + return result }) }).catch(err => { winston.error(err) @@ -331,6 +326,28 @@ module.exports = { }) }, + /** + * Update tree info for all directory and parent entries + * + * @returns {Promise} Promise of the operation + */ + updateTreeInfo () { + return db.Entry.distinct('parentPath', { parentPath: { $ne: '' } }).then(allPaths => { + if (allPaths.length > 0) { + return Promise.map(allPaths, pathItem => { + let parentPath = _.chain(pathItem).split('/').initial().join('/').value() + let guessedTitle = _.chain(pathItem).split('/').last().startCase().value() + return db.Entry.update({ _id: pathItem }, { + $set: { isDirectory: true }, + $setOnInsert: { isEntry: false, title: guessedTitle, parentPath } + }, { upsert: true }) + }) + } else { + return true + } + }) + }, + /** * Create a new document * @@ -428,6 +445,6 @@ module.exports = { * @return {Promise} List of entries */ getFromTree (basePath) { - return db.Entry.find({ parentPath: basePath }) + return db.Entry.find({ parentPath: basePath }, 'title parentPath isDirectory isEntry').sort({ title: 'asc' }) } } diff --git a/models/entry.js b/models/entry.js index 80edcab2..6740f722 100644 --- a/models/entry.js +++ b/models/entry.js @@ -28,6 +28,10 @@ var entrySchema = Mongoose.Schema({ isDirectory: { type: Boolean, default: false + }, + isEntry: { + type: Boolean, + default: false } }, { timestamps: {} diff --git a/npm/package.json b/npm/package.json index 792a4650..57907b8b 100644 --- a/npm/package.json +++ b/npm/package.json @@ -1,6 +1,6 @@ { "name": "wiki.js", - "version": "1.0.0-beta.10", + "version": "1.0.0-beta.11", "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown", "main": "install.js", "scripts": { diff --git a/package.json b/package.json index 30f2e2cd..dc005c6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wiki", - "version": "1.0.0-beta.10", + "version": "1.0.0-beta.11", "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown", "main": "server.js", "scripts": { diff --git a/views/pages/all.pug b/views/pages/all.pug index 220ef911..fff7daeb 100644 --- a/views/pages/all.pug +++ b/views/pages/all.pug @@ -28,10 +28,13 @@ block content span Login ul.collapsable-nav(v-for='treeItem in tree', :class='{ "has-children": treeItem.hasChildren }', v-cloak) li(v-for='page in treeItem.pages', :class='{ "is-active": page.isActive }') - a(v-on:click='(page.isDirectory) ? fetch(page._id) : goto(page._id)') + a(v-on:click='mainAction(page)') template(v-if='page._id !== "home"') i(:class='{ "icon-folder2": page.isDirectory, "icon-file-text-o": !page.isDirectory }') span {{ page.title }} template(v-else) i.icon-home span Home + a.is-pagelink(v-if='page.isDirectory && page.isEntry', v-on:click='goto(page._id)') + i.icon-file-text-o + i.icon-arrow-right2