feat: history version diff

This commit is contained in:
NGPixel 2020-02-23 23:53:27 -05:00 committed by Nicolas Giard
parent 27ff329d16
commit 95f01cdeb8
5 changed files with 175 additions and 40 deletions

View File

@ -3,7 +3,7 @@
nav-header nav-header
v-content v-content
v-toolbar(color='primary', dark) v-toolbar(color='primary', dark)
.subheading Viewing history of page #[strong /{{path}}] .subheading Viewing history of #[strong /{{path}}]
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,12 +42,12 @@
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='setDiffTarget(ph.versionId)')
v-list-item-avatar(size='24'): v-icon mdi-call-received
v-list-item-title Set as Differencing Target (B)
v-list-item(@click='setDiffSource(ph.versionId)') v-list-item(@click='setDiffSource(ph.versionId)')
v-list-item-avatar(size='24'): v-icon mdi-call-made v-list-item-avatar(size='24'): v-icon mdi-call-made
v-list-item-title Set as Differencing Source (A) v-list-item-title Set as Differencing Source (A)
v-list-item(@click='setDiffTarget(ph.versionId)')
v-list-item-avatar(size='24'): v-icon mdi-call-received
v-list-item-title Set as Differencing Target (B)
v-list-item v-list-item
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
@ -94,7 +94,7 @@
) End of history trail ) End of history trail
v-flex(xs12, md8) v-flex(xs12, md8)
v-card.radius-7 v-card.radius-7.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')
@ -118,8 +118,7 @@ import * as Diff2Html from 'diff2html'
import { createPatch } from 'diff' import { createPatch } from 'diff'
import { get } from 'vuex-pathify' import { get } from 'vuex-pathify'
import _ from 'lodash' import _ from 'lodash'
import gql from 'graphql-tag'
import historyTrailQuery from 'gql/history/history-trail-query.gql'
export default { export default {
props: { props: {
@ -140,14 +139,16 @@ export default {
default: '' default: ''
} }
}, },
data() { data () {
return { return {
source: { source: {
versionId: 0,
content: '', content: '',
title: '', title: '',
description: '' description: ''
}, },
target: { target: {
versionId: 0,
content: '', content: '',
title: '', title: '',
description: '' description: ''
@ -157,15 +158,16 @@ export default {
diffTarget: 0, diffTarget: 0,
offsetPage: 0, offsetPage: 0,
total: 0, total: 0,
viewMode: 'line-by-line' viewMode: 'line-by-line',
cache: []
} }
}, },
computed: { computed: {
darkMode: get('site/dark'), darkMode: get('site/dark'),
diffs() { diffs () {
return createPatch(`/${this.path}`, this.source.content, this.target.content) return createPatch(`/${this.path}`, this.source.content, this.target.content)
}, },
diffHTML() { diffHTML () {
return Diff2Html.html(this.diffs, { return Diff2Html.html(this.diffs, {
inputFormat: 'diff', inputFormat: 'diff',
drawFileList: false, drawFileList: false,
@ -175,11 +177,31 @@ export default {
} }
}, },
watch: { watch: {
trail(newValue, oldValue) { trail (newValue, oldValue) {
if (newValue && newValue.length > 0) { if (newValue && newValue.length > 0) {
this.diffTarget = _.get(_.head(newValue), 'versionId', 0) this.diffTarget = _.get(_.head(newValue), 'versionId', 0)
this.diffSource = _.get(_.nth(newValue, 1), 'versionId', 0) this.diffSource = _.get(_.nth(newValue, 1), 'versionId', 0)
} }
},
async diffSource (newValue, oldValue) {
if (this.diffSource !== this.source.versionId) {
const page = _.find(this.cache, { versionId: newValue })
if (page) {
this.source = page
} else {
this.source = await this.loadVersion(newValue)
}
}
},
async diffTarget (newValue, oldValue) {
if (this.diffTarget !== this.target.versionId) {
const page = _.find(this.cache, { versionId: newValue })
if (page) {
this.target = page
} else {
this.target = await this.loadVersion(newValue)
}
}
} }
}, },
created () { created () {
@ -192,19 +214,62 @@ export default {
this.target.content = this.liveContent this.target.content = this.liveContent
}, },
methods: { methods: {
async loadVersion (versionId) {
this.$store.commit(`loadingStart`, 'history-version-' + versionId)
const resp = await this.$apollo.query({
query: gql`
query ($pageId: Int!, $versionId: Int!) {
pages {
version (pageId: $pageId, versionId: $versionId) {
action
authorId
authorName
content
contentType
createdAt
description
editor
isPrivate
isPublished
locale
pageId
path
publishEndDate
publishStartDate
tags
title
versionId
}
}
}
`,
variables: {
versionId,
pageId: this.pageId
}
})
this.$store.commit(`loadingStop`, 'history-version-' + versionId)
const page = _.get(resp, 'data.pages.version', null)
if (page) {
this.cache.push(page)
return page
} else {
return { content: '' }
}
},
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'
}, },
goLive() { goLive () {
window.location.assign(`/${this.path}`) window.location.assign(`/${this.path}`)
}, },
setDiffSource(versionId) { setDiffSource (versionId) {
this.diffSource = versionId this.diffSource = versionId
}, },
setDiffTarget(versionId) { setDiffTarget (versionId) {
this.diffTarget = versionId this.diffTarget = versionId
}, },
loadMore() { loadMore () {
this.offsetPage++ this.offsetPage++
this.$apollo.queries.trail.fetchMore({ this.$apollo.queries.trail.fetchMore({
variables: { variables: {
@ -226,7 +291,7 @@ export default {
} }
}) })
}, },
trailColor(actionType) { trailColor (actionType) {
switch (actionType) { switch (actionType) {
case 'edit': case 'edit':
return 'primary' return 'primary'
@ -238,7 +303,7 @@ export default {
return 'grey' return 'grey'
} }
}, },
trailIcon(actionType) { trailIcon (actionType) {
switch (actionType) { switch (actionType) {
case 'edit': case 'edit':
return '' // 'mdi-pencil' return '' // 'mdi-pencil'
@ -250,7 +315,7 @@ export default {
return 'warning' return 'warning'
} }
}, },
trailBgColor(actionType) { trailBgColor (actionType) {
switch (actionType) { switch (actionType) {
case 'move': case 'move':
return this.darkMode ? 'purple' : 'purple lighten-5' return this.darkMode ? 'purple' : 'purple lighten-5'
@ -263,8 +328,25 @@ export default {
}, },
apollo: { apollo: {
trail: { trail: {
query: historyTrailQuery, query: gql`
variables() { query($id: Int!, $offsetPage: Int, $offsetSize: Int) {
pages {
history(id:$id, offsetPage:$offsetPage, offsetSize:$offsetSize) {
trail {
versionId
authorId
authorName
actionType
valueBefore
valueAfter
createdAt
}
total
}
}
}
`,
variables () {
return { return {
id: this.pageId, id: this.pageId,
offsetPage: 0, offsetPage: 0,
@ -272,7 +354,7 @@ export default {
} }
}, },
manual: true, manual: true,
result({ data, loading, networkStatus }) { result ({ data, loading, networkStatus }) {
this.total = data.pages.history.total this.total = data.pages.history.total
this.trail = data.pages.history.trail this.trail = data.pages.history.trail
}, },

View File

@ -1,16 +0,0 @@
query($id: Int!, $offsetPage: Int, $offsetSize: Int) {
pages {
history(id:$id, offsetPage:$offsetPage, offsetSize:$offsetSize) {
trail {
versionId
authorId
authorName
actionType
valueBefore
valueAfter
createdAt
}
total
}
}
}

View File

@ -21,6 +21,15 @@ module.exports = {
offsetSize: args.offsetSize || 100 offsetSize: args.offsetSize || 100
}) })
}, },
/**
* PAGE VERSION
*/
async version(obj, args, context, info) {
return WIKI.models.pageHistory.getVersion({
pageId: args.pageId,
versionId: args.versionId
})
},
/** /**
* SEARCH PAGES * SEARCH PAGES
*/ */

View File

@ -19,7 +19,12 @@ type PageQuery {
id: Int! id: Int!
offsetPage: Int offsetPage: Int
offsetSize: Int offsetSize: Int
): PageHistoryResult @auth(requires: ["manage:system", "read:pages"]) ): PageHistoryResult @auth(requires: ["manage:system", "read:history"])
version(
pageId: Int!
versionId: Int!
): PageVersion @auth(requires: ["manage:system", "read:history"])
search( search(
query: String! query: String!
@ -150,7 +155,7 @@ type Page {
isPublished: Boolean! isPublished: Boolean!
privateNS: String privateNS: String
publishStartDate: Date! publishStartDate: Date!
publishEndDate: String! publishEndDate: Date!
tags: [PageTag]! tags: [PageTag]!
content: String! content: String!
render: String render: String
@ -186,6 +191,27 @@ type PageHistory {
createdAt: Date! createdAt: Date!
} }
type PageVersion {
action: String!
authorId: String!
authorName: String!
content: String!
contentType: String!
createdAt: Date!
description: String!
editor: String!
isPrivate: Boolean!
isPublished: Boolean!
locale: String!
pageId: Int!
path: String!
publishEndDate: Date!
publishStartDate: Date!
tags: [String]!
title: String!
versionId: Int!
}
type PageHistoryResult { type PageHistoryResult {
trail: [PageHistory] trail: [PageHistory]
total: Int! total: Int!

View File

@ -104,6 +104,40 @@ module.exports = class PageHistory extends Model {
}) })
} }
static async getVersion({ pageId, versionId }) {
const version = await WIKI.models.pageHistory.query()
.column([
'pageHistory.path',
'pageHistory.title',
'pageHistory.description',
'pageHistory.isPrivate',
'pageHistory.isPublished',
'pageHistory.publishStartDate',
'pageHistory.publishEndDate',
'pageHistory.content',
'pageHistory.contentType',
'pageHistory.createdAt',
'pageHistory.action',
'pageHistory.authorId',
'pageHistory.pageId',
{
versionId: 'pageHistory.id',
editor: 'pageHistory.editorKey',
locale: 'pageHistory.localeCode',
authorName: 'author.name'
}
])
.joinRelated('author')
.where({
'pageHistory.id': versionId,
'pageHistory.pageId': pageId
}).first()
return {
...version,
tags: []
}
}
static async getHistory({ pageId, offsetPage = 0, offsetSize = 100 }) { static async getHistory({ pageId, offsetPage = 0, offsetSize = 100 }) {
const history = await WIKI.models.pageHistory.query() const history = await WIKI.models.pageHistory.query()
.column([ .column([