Browse Source

feat: History page - List previous commits

pull/89/head
NGPixel 7 years ago
parent
commit
a748b3a4eb
10 changed files with 132 additions and 6 deletions
  1. 3
      .build/.deployexclude
  2. 3
      client/js/app.js
  3. 11
      client/js/pages/history.js
  4. 22
      client/scss/components/sidebar.scss
  5. 21
      server/controllers/pages.js
  6. 12
      server/libs/entries.js
  7. 24
      server/libs/git.js
  8. 1
      server/views/pages/admin/settings.pug
  9. 35
      server/views/pages/history.pug
  10. 6
      server/views/pages/view.pug

3
.build/.deployexclude

@ -1,5 +1,4 @@
client/js
client/scss
client
coverage
data
logs

3
client/js/app.js

@ -19,7 +19,7 @@ $(() => {
offset: -50
})
$('.stickyscroll').sticky({ topSpacing: 15 })
$('.stickyscroll').sticky({ topSpacing: 15, bottomSpacing: 75 })
// ====================================
// Notifications
@ -58,5 +58,6 @@ $(() => {
require('./pages/create.js')(alerts, socket)
require('./pages/edit.js')(alerts, socket)
require('./pages/source.js')(alerts)
require('./pages/history.js')(alerts)
require('./pages/admin.js')(alerts)
})

11
client/js/pages/history.js

@ -0,0 +1,11 @@
'use strict'
import $ from 'jquery'
module.exports = (alerts) => {
if ($('#page-type-history').length) {
let currentBasePath = ($('#page-type-history').data('entrypath') !== 'home') ? $('#page-type-history').data('entrypath') : ''
}
}

22
client/scss/components/sidebar.scss

@ -45,6 +45,21 @@
transition: all .4s ease;
line-height: 14px;
&.is-multiline {
flex-wrap: wrap;
}
&.is-active {
border-left: 5px solid mc('blue', '500');
color: mc('blue', '300');
padding-left: 15px;
.is-small {
color: mc('blue', '500');
}
}
i {
margin-right: 7px;
color: mc('blue-grey', '300');
@ -55,6 +70,13 @@
text-decoration: none;
}
.is-small {
flex: 1 0 100%;
display: block;
font-size: 11px;
color: rgba(255,255,255,.5)
}
}
> ul {

21
server/controllers/pages.js

@ -179,6 +179,27 @@ router.get('/source/*', (req, res, next) => {
})
})
/**
* View history of a document
*/
router.get('/hist/*', (req, res, next) => {
let safePath = entryHelper.parsePath(_.replace(req.path, '/hist', ''))
entries.getHistory(safePath).then((pageData) => {
if (pageData) {
res.render('pages/history', { pageData })
} else {
throw new Error('Invalid page path.')
}
return true
}).catch((err) => {
res.render('error', {
message: err.message,
error: {}
})
})
})
/**
* View document
*/

12
server/libs/entries.js

@ -402,5 +402,17 @@ module.exports = {
return rights.checkRole('/' + r._id, usr.rights, 'read')
})
})
},
getHistory (entryPath) {
return db.Entry.findOne({ _id: entryPath, isEntry: true }).then(entry => {
if (!entry) { return false }
return git.getHistory(entryPath).then(history => {
return {
meta: entry,
history
}
})
})
}
}

24
server/libs/git.js

@ -253,6 +253,30 @@ module.exports = {
if (_.includes(err.stdout, 'nothing to commit')) { return true }
})
})
},
getHistory (entryPath) {
let self = this
let gitFilePath = entryPath + '.md'
return self._git.exec('log', ['-n', '25', '--format=format:%H %h %cI %cE %cN', '--', gitFilePath]).then((cProc) => {
let out = cProc.stdout.toString()
if (_.includes(out, 'fatal')) {
let errorMsg = _.capitalize(_.head(_.split(_.replace(out, 'fatal: ', ''), ',')))
throw new Error(errorMsg)
}
let hist = _.chain(out).split('\n').map(h => {
let hParts = h.split(' ', 4)
return {
commit: hParts[0],
commitAbbr: hParts[1],
date: hParts[2],
email: hParts[3],
name: hParts[4]
}
}).value()
return hist
})
}
}

1
server/views/pages/admin/settings.pug

@ -7,6 +7,7 @@ block adminContent
h2.subtitle Manage site configuration
.form-sections
section
img(src='/images/logo.png', style={width:'200px', float:'right'})
label.label System Version
.section-block
p Current Version: #[strong= sysversion.current]

35
server/views/pages/history.pug

@ -0,0 +1,35 @@
extends ../layout.pug
block rootNavRight
i.nav-item#notifload
.nav-item
a.button(href='/' + pageData.meta._id)
i.icon-circle-check
span View Latest
block content
#page-type-history.page-type-container(data-entrypath=pageData.meta._id)
.container.is-fluid.has-mkcontent
.columns.is-gapless
.column.is-narrow.is-hidden-touch.sidebar
aside.stickyscroll
.sidebar-label
span Past versions
ul.sidebar-menu
each item, index in pageData.history
- var itemDate = moment(item.date)
li: a.is-multiline(class={ 'is-active': index < 1 }, href='', title=itemDate.format('LLLL'))
span= itemDate.calendar(null, { sameElse: 'llll'})
span.is-small= item.commitAbbr
.column
.hero
h1.title#title= pageData.meta.title
if pageData.meta.subtitle
h2.subtitle= pageData.meta.subtitle
.content.mkcontent
!= pageData.html

6
server/views/pages/view.pug

@ -18,9 +18,9 @@ block rootNavRight
a.button.is-outlined(href='/source/' + pageData.meta.path)
i.icon-loader
span Source
a.button.is-outlined(href='/diff/' + pageData.meta.path)
i.icon-flow-merge
span Diff
a.button.is-outlined(href='/hist/' + pageData.meta.path)
i.icon-clock
span History
if rights.write
a.button(href='/edit/' + pageData.meta.path)
i.icon-document-text

Loading…
Cancel
Save