feat: page history - download version
This commit is contained in:
parent
95f01cdeb8
commit
2ac9131244
@ -4,6 +4,7 @@
|
|||||||
v-content
|
v-content
|
||||||
v-toolbar(color='primary', dark)
|
v-toolbar(color='primary', dark)
|
||||||
.subheading Viewing history of #[strong /{{path}}]
|
.subheading Viewing history of #[strong /{{path}}]
|
||||||
|
template(v-if='$vuetify.breakpoint.mdAndUp')
|
||||||
v-spacer
|
v-spacer
|
||||||
.caption.blue--text.text--lighten-3.mr-4 Trail Length: {{total}}
|
.caption.blue--text.text--lighten-3.mr-4 Trail Length: {{total}}
|
||||||
.caption.blue--text.text--lighten-3 ID: {{pageId}}
|
.caption.blue--text.text--lighten-3 ID: {{pageId}}
|
||||||
@ -42,22 +43,22 @@
|
|||||||
template(v-slot:activator='{ on }')
|
template(v-slot:activator='{ on }')
|
||||||
v-btn.mr-2.radius-4(icon, v-on='on', small, tile): v-icon mdi-dots-horizontal
|
v-btn.mr-2.radius-4(icon, v-on='on', small, tile): v-icon mdi-dots-horizontal
|
||||||
v-list(dense, nav).history-promptmenu
|
v-list(dense, nav).history-promptmenu
|
||||||
v-list-item(@click='setDiffSource(ph.versionId)')
|
v-list-item(@click='setDiffSource(ph.versionId)', :disabled='ph.versionId >= diffTarget')
|
||||||
v-list-item-avatar(size='24'): v-icon mdi-call-made
|
v-list-item-avatar(size='24'): v-avatar A
|
||||||
v-list-item-title Set as Differencing Source (A)
|
v-list-item-title Set as Differencing Source
|
||||||
v-list-item(@click='setDiffTarget(ph.versionId)')
|
v-list-item(@click='setDiffTarget(ph.versionId)', :disabled='ph.versionId <= diffSource')
|
||||||
v-list-item-avatar(size='24'): v-icon mdi-call-received
|
v-list-item-avatar(size='24'): v-avatar B
|
||||||
v-list-item-title Set as Differencing Target (B)
|
v-list-item-title Set as Differencing Target
|
||||||
v-list-item
|
v-list-item(@click='viewSource(ph.versionId)')
|
||||||
v-list-item-avatar(size='24'): v-icon mdi-code-tags
|
v-list-item-avatar(size='24'): v-icon mdi-code-tags
|
||||||
v-list-item-title View Source
|
v-list-item-title View Source
|
||||||
v-list-item
|
v-list-item(@click='download(ph.versionId)')
|
||||||
v-list-item-avatar(size='24'): v-icon mdi-cloud-download-outline
|
v-list-item-avatar(size='24'): v-icon mdi-cloud-download-outline
|
||||||
v-list-item-title Download Version
|
v-list-item-title Download Version
|
||||||
v-list-item
|
v-list-item(@click='restore(ph.versionId)')
|
||||||
v-list-item-avatar(size='24'): v-icon mdi-history
|
v-list-item-avatar(size='24'): v-icon mdi-history
|
||||||
v-list-item-title Restore
|
v-list-item-title Restore
|
||||||
v-list-item
|
v-list-item(@click='branchOff(ph.versionId)')
|
||||||
v-list-item-avatar(size='24'): v-icon mdi-source-branch
|
v-list-item-avatar(size='24'): v-icon mdi-source-branch
|
||||||
v-list-item-title Branch off from here
|
v-list-item-title Branch off from here
|
||||||
v-btn.mr-2.radius-4(
|
v-btn.mr-2.radius-4(
|
||||||
@ -66,7 +67,8 @@
|
|||||||
small
|
small
|
||||||
depressed
|
depressed
|
||||||
tile
|
tile
|
||||||
:class='diffSource === ph.versionId ? `pink white--text` : `grey lighten-2`'
|
:class='diffSource === ph.versionId ? `pink white--text` : ($vuetify.theme.dark ? `grey darken-2` : `grey lighten-2`)'
|
||||||
|
:disabled='ph.versionId >= diffTarget'
|
||||||
): strong A
|
): strong A
|
||||||
v-btn.mr-0.radius-4(
|
v-btn.mr-0.radius-4(
|
||||||
@click='setDiffTarget(ph.versionId)'
|
@click='setDiffTarget(ph.versionId)'
|
||||||
@ -74,13 +76,14 @@
|
|||||||
small
|
small
|
||||||
depressed
|
depressed
|
||||||
tile
|
tile
|
||||||
:class='diffTarget === ph.versionId ? `pink white--text` : `grey lighten-2`'
|
:class='diffTarget === ph.versionId ? `pink white--text` : ($vuetify.theme.dark ? `grey darken-2` : `grey lighten-2`)'
|
||||||
|
:disabled='ph.versionId <= diffSource'
|
||||||
): strong B
|
): strong B
|
||||||
|
|
||||||
v-btn.ma-0.radius-7(
|
v-btn.ma-0.radius-7(
|
||||||
v-if='total > trail.length'
|
v-if='total > trail.length'
|
||||||
block
|
block
|
||||||
color='grey darken-2'
|
color='primary'
|
||||||
@click='loadMore'
|
@click='loadMore'
|
||||||
)
|
)
|
||||||
.caption.white--text Load More...
|
.caption.white--text Load More...
|
||||||
@ -94,16 +97,16 @@
|
|||||||
) End of history trail
|
) End of history trail
|
||||||
|
|
||||||
v-flex(xs12, md8)
|
v-flex(xs12, md8)
|
||||||
v-card.radius-7.mt-8
|
v-card.radius-7(:class='$vuetify.breakpoint.mdAndUp ? `mt-8` : ``')
|
||||||
v-card-text
|
v-card-text
|
||||||
v-card.grey.radius-7(flat, :class='darkMode ? `darken-2` : `lighten-4`')
|
v-card.grey.radius-7(flat, :class='darkMode ? `darken-2` : `lighten-4`')
|
||||||
v-row(no-gutters, align='center')
|
v-row(no-gutters, align='center')
|
||||||
v-col(cols='11')
|
v-col
|
||||||
v-card-text
|
v-card-text
|
||||||
.subheading {{target.title}}
|
.subheading {{target.title}}
|
||||||
.caption {{target.description}}
|
.caption {{target.description}}
|
||||||
v-col.text-right.py-3
|
v-col.text-right.py-3(cols='2', v-if='$vuetify.breakpoint.mdAndUp')
|
||||||
v-btn.mr-3(color='primary', small, dark, outlined, @click='toggleViewMode')
|
v-btn.mr-3(:color='$vuetify.theme.dark ? `white` : `grey darken-3`', small, dark, outlined, @click='toggleViewMode')
|
||||||
v-icon(left) mdi-eye
|
v-icon(left) mdi-eye
|
||||||
.overline View Mode
|
.overline View Mode
|
||||||
v-card.mt-3(light, v-html='diffHTML', flat)
|
v-card.mt-3(light, v-html='diffHTML', flat)
|
||||||
@ -256,6 +259,18 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
return { content: '' }
|
return { content: '' }
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
viewSource (versionId) {
|
||||||
|
window.location.assign(`/s/${this.locale}/${this.path}?v=${versionId}`)
|
||||||
|
},
|
||||||
|
download (versionId) {
|
||||||
|
window.location.assign(`/d/${this.locale}/${this.path}?v=${versionId}`)
|
||||||
|
},
|
||||||
|
restore (versionId) {
|
||||||
|
|
||||||
|
},
|
||||||
|
branchOff (versionId) {
|
||||||
|
|
||||||
},
|
},
|
||||||
toggleViewMode () {
|
toggleViewMode () {
|
||||||
this.viewMode = (this.viewMode === 'line-by-line') ? 'side-by-side' : 'line-by-line'
|
this.viewMode = (this.viewMode === 'line-by-line') ? 'side-by-side' : 'line-by-line'
|
||||||
@ -275,7 +290,7 @@ export default {
|
|||||||
variables: {
|
variables: {
|
||||||
id: this.pageId,
|
id: this.pageId,
|
||||||
offsetPage: this.offsetPage,
|
offsetPage: this.offsetPage,
|
||||||
offsetSize: 25
|
offsetSize: this.$vuetify.breakpoint.mdAndUp ? 25 : 5
|
||||||
},
|
},
|
||||||
updateQuery: (previousResult, { fetchMoreResult }) => {
|
updateQuery: (previousResult, { fetchMoreResult }) => {
|
||||||
return {
|
return {
|
||||||
@ -350,7 +365,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
id: this.pageId,
|
id: this.pageId,
|
||||||
offsetPage: 0,
|
offsetPage: 0,
|
||||||
offsetSize: 25
|
offsetSize: this.$vuetify.breakpoint.mdAndUp ? 25 : 5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
manual: true,
|
manual: true,
|
||||||
|
@ -36,6 +36,49 @@ router.get(['/a', '/a/*'], (req, res, next) => {
|
|||||||
res.render('admin')
|
res.render('admin')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download Page / Version
|
||||||
|
*/
|
||||||
|
router.get(['/d', '/d/*'], async (req, res, next) => {
|
||||||
|
const pageArgs = pageHelper.parsePath(req.path, { stripExt: true })
|
||||||
|
|
||||||
|
const versionId = (req.query.v) ? _.toSafeInteger(req.query.v) : 0
|
||||||
|
|
||||||
|
const page = await WIKI.models.pages.getPageFromDb({
|
||||||
|
path: pageArgs.path,
|
||||||
|
locale: pageArgs.locale,
|
||||||
|
userId: req.user.id,
|
||||||
|
isPrivate: false
|
||||||
|
})
|
||||||
|
|
||||||
|
pageArgs.tags = _.get(page, 'tags', [])
|
||||||
|
|
||||||
|
if (versionId > 0) {
|
||||||
|
if (!WIKI.auth.checkAccess(req.user, ['read:history'], pageArgs)) {
|
||||||
|
_.set(res.locals, 'pageMeta.title', 'Unauthorized')
|
||||||
|
return res.render('unauthorized', { action: 'downloadVersion' })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!WIKI.auth.checkAccess(req.user, ['read:source'], pageArgs)) {
|
||||||
|
_.set(res.locals, 'pageMeta.title', 'Unauthorized')
|
||||||
|
return res.render('unauthorized', { action: 'download' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page) {
|
||||||
|
const fileName = _.last(page.path.split('/')) + '.' + pageHelper.getFileExtension(page.contentType)
|
||||||
|
res.attachment(fileName)
|
||||||
|
if (versionId > 0) {
|
||||||
|
const pageVersion = await WIKI.models.pageHistory.getVersion({ pageId: page.id, versionId })
|
||||||
|
res.send(pageHelper.injectPageMetadata(pageVersion))
|
||||||
|
} else {
|
||||||
|
res.send(pageHelper.injectPageMetadata(page))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(404).end()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create/Edit document
|
* Create/Edit document
|
||||||
*/
|
*/
|
||||||
|
@ -73,11 +73,14 @@ module.exports = {
|
|||||||
['date', page.updatedAt],
|
['date', page.updatedAt],
|
||||||
['tags', page.tags ? page.tags.map(t => t.tag).join(', ') : '']
|
['tags', page.tags ? page.tags.map(t => t.tag).join(', ') : '']
|
||||||
]
|
]
|
||||||
const inject = {
|
switch (page.contentType) {
|
||||||
'markdown': '---\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n---\n\n' + page.content,
|
case 'markdown':
|
||||||
'html': '<!--\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n-->\n\n' + page.content
|
return '---\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n---\n\n' + page.content
|
||||||
|
case 'html':
|
||||||
|
return '<!--\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n-->\n\n' + page.content
|
||||||
|
default:
|
||||||
|
return page.content
|
||||||
}
|
}
|
||||||
return _.get(inject, page.contentType, page.content)
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Check if path is a reserved path
|
* Check if path is a reserved path
|
||||||
|
@ -134,6 +134,7 @@ module.exports = class PageHistory extends Model {
|
|||||||
}).first()
|
}).first()
|
||||||
return {
|
return {
|
||||||
...version,
|
...version,
|
||||||
|
updatedAt: version.createdAt,
|
||||||
tags: []
|
tags: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user