You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
8.5 KiB

  1. <template lang='pug'>
  2. v-app(:dark='darkMode').history
  3. nav-header
  4. v-content
  5. v-toolbar(color='primary', dark)
  6. .subheading Viewing history of page #[strong /{{path}}]
  7. v-spacer
  8. .caption.blue--text.text--lighten-3.mr-4 Trail Length: {{total}}
  9. .caption.blue--text.text--lighten-3 ID: {{pageId}}
  10. v-btn.ml-4(depressed, color='blue darken-1', @click='goLive') Return to Live Version
  11. v-container(fluid, grid-list-xl)
  12. v-layout(row, wrap)
  13. v-flex(xs4)
  14. v-chip.ma-0(
  15. label
  16. small
  17. :color='darkMode ? `grey darken-2` : `grey lighten-2`'
  18. :class='darkMode ? `grey--text text--lighten-2` : `grey--text text--darken-2`'
  19. )
  20. span Live
  21. v-timeline(
  22. dense
  23. )
  24. v-timeline-item.pb-2(
  25. v-for='(ph, idx) in trail'
  26. :key='ph.versionId'
  27. :small='ph.actionType === `edit`'
  28. fill-dot
  29. :color='trailColor(ph.actionType)'
  30. :icon='trailIcon(ph.actionType)'
  31. :class='idx >= trail.length - 1 ? `pb-4` : `pb-2`'
  32. )
  33. v-card.radius-7(flat, :class='trailBgColor(ph.actionType)')
  34. v-toolbar(flat, :color='trailBgColor(ph.actionType)', height='40')
  35. v-chip.ml-0.mr-3(
  36. v-if='diffSource === ph.versionId'
  37. small
  38. color='pink'
  39. label
  40. )
  41. .caption.white--text Source
  42. v-chip.ml-0.mr-3(
  43. v-if='diffTarget === ph.versionId'
  44. small
  45. color='pink'
  46. label
  47. )
  48. .caption.white--text Target
  49. .caption(v-if='ph.actionType === `edit`') Edited by #[strong {{ ph.authorName }}]
  50. .caption(v-else-if='ph.actionType === `move`') Moved from #[strong {{ph.valueBefore}}] to #[strong {{ph.valueAfter}}] by #[strong {{ ph.authorName }}]
  51. .caption(v-else-if='ph.actionType === `initial`') Created by #[strong {{ ph.authorName }}]
  52. .caption(v-else) Unknown Action by #[strong {{ ph.authorName }}]
  53. v-spacer
  54. .caption.mr-3 {{ ph.createdAt | moment('calendar') }}
  55. v-menu(offset-x, left)
  56. template(v-slot:activator='{ on }')
  57. v-btn.mr-0(icon, v-on='on', small, tile): v-icon mdi-dots-horizontal
  58. v-list(dense, nav).history-promptmenu
  59. v-list-item(@click='setDiffTarget(ph.versionId)')
  60. v-list-item-avatar(size='24'): v-icon mdi-call-received
  61. v-list-item-title Set as Differencing Target
  62. v-list-item(@click='setDiffSource(ph.versionId)')
  63. v-list-item-avatar(size='24'): v-icon mdi-call-made
  64. v-list-item-title Set as Differencing Source
  65. v-list-item
  66. v-list-item-avatar(size='24'): v-icon mdi-code-tags
  67. v-list-item-title View Source
  68. v-list-item
  69. v-list-item-avatar(size='24'): v-icon mdi-cloud-download-outline
  70. v-list-item-title Download Version
  71. v-list-item
  72. v-list-item-avatar(size='24'): v-icon mdi-history
  73. v-list-item-title Restore
  74. v-list-item
  75. v-list-item-avatar(size='24'): v-icon mdi-source-branch
  76. v-list-item-title Branch off from here
  77. v-btn.ma-0.radius-7(
  78. v-if='total > trail.length'
  79. block
  80. color='grey darken-2'
  81. @click='loadMore'
  82. )
  83. .caption.white--text Load More...
  84. v-chip.ma-0(
  85. v-else
  86. label
  87. small
  88. :color='darkMode ? `grey darken-2` : `grey lighten-2`'
  89. :class='darkMode ? `grey--text text--lighten-2` : `grey--text text--darken-2`'
  90. ) End of history trail
  91. v-flex(xs8)
  92. v-card.radius-7
  93. v-card-text
  94. v-card.grey.radius-7(flat, :class='darkMode ? `darken-2` : `lighten-4`')
  95. v-card-text
  96. .subheading Page Title
  97. .caption Some page description
  98. v-card.mt-3(light, v-html='diffHTML')
  99. nav-footer
  100. notify
  101. search-results
  102. </template>
  103. <script>
  104. import { Diff2Html } from 'diff2html'
  105. import { createPatch } from 'diff'
  106. import { get } from 'vuex-pathify'
  107. import _ from 'lodash'
  108. import historyTrailQuery from 'gql/history/history-trail-query.gql'
  109. export default {
  110. props: {
  111. pageId: {
  112. type: Number,
  113. default: 0
  114. },
  115. locale: {
  116. type: String,
  117. default: 'en'
  118. },
  119. path: {
  120. type: String,
  121. default: 'home'
  122. },
  123. liveContent: {
  124. type: String,
  125. default: ''
  126. }
  127. },
  128. data() {
  129. return {
  130. sourceText: '',
  131. targetText: '',
  132. trail: [],
  133. diffSource: 0,
  134. diffTarget: 0,
  135. offsetPage: 0,
  136. total: 0
  137. }
  138. },
  139. computed: {
  140. darkMode: get('site/dark'),
  141. diffs() {
  142. return createPatch(`/${this.path}`, this.sourceText, this.targetText)
  143. },
  144. diffHTML() {
  145. return Diff2Html.getPrettyHtml(this.diffs, {
  146. inputFormat: 'diff',
  147. showFiles: false,
  148. matching: 'lines',
  149. outputFormat: 'line-by-line'
  150. })
  151. }
  152. },
  153. watch: {
  154. trail(newValue, oldValue) {
  155. if (newValue && newValue.length > 0) {
  156. this.diffTarget = _.get(_.head(newValue), 'versionId', 0)
  157. this.diffSource = _.get(_.nth(newValue, 1), 'versionId', 0)
  158. }
  159. }
  160. },
  161. created () {
  162. this.$store.commit('page/SET_ID', this.id)
  163. this.$store.commit('page/SET_LOCALE', this.locale)
  164. this.$store.commit('page/SET_PATH', this.path)
  165. this.$store.commit('page/SET_MODE', 'history')
  166. this.targetText = this.liveContent
  167. },
  168. methods: {
  169. goLive() {
  170. window.location.assign(`/${this.path}`)
  171. },
  172. setDiffSource(versionId) {
  173. this.diffSource = versionId
  174. },
  175. setDiffTarget(versionId) {
  176. this.diffTarget = versionId
  177. },
  178. loadMore() {
  179. this.offsetPage++
  180. this.$apollo.queries.trail.fetchMore({
  181. variables: {
  182. id: this.pageId,
  183. offsetPage: this.offsetPage,
  184. offsetSize: 25
  185. },
  186. updateQuery: (previousResult, { fetchMoreResult }) => {
  187. return {
  188. pages: {
  189. history: {
  190. total: previousResult.pages.history.total,
  191. trail: [...previousResult.pages.history.trail, ...fetchMoreResult.pages.history.trail],
  192. __typename: previousResult.pages.history.__typename
  193. },
  194. __typename: previousResult.pages.__typename
  195. }
  196. }
  197. }
  198. })
  199. },
  200. trailColor(actionType) {
  201. switch (actionType) {
  202. case 'edit':
  203. return 'primary'
  204. case 'move':
  205. return 'purple'
  206. case 'initial':
  207. return 'teal'
  208. default:
  209. return 'grey'
  210. }
  211. },
  212. trailIcon(actionType) {
  213. switch (actionType) {
  214. case 'edit':
  215. return 'mdi-pencil'
  216. case 'move':
  217. return 'forward'
  218. case 'initial':
  219. return 'mdi-plus'
  220. default:
  221. return 'warning'
  222. }
  223. },
  224. trailBgColor(actionType) {
  225. switch (actionType) {
  226. case 'move':
  227. return this.darkMode ? 'purple' : 'purple lighten-5'
  228. case 'initial':
  229. return this.darkMode ? 'teal darken-3' : 'teal lighten-5'
  230. default:
  231. return this.darkMode ? 'grey darken-3' : 'grey lighten-3'
  232. }
  233. }
  234. },
  235. apollo: {
  236. trail: {
  237. query: historyTrailQuery,
  238. variables() {
  239. return {
  240. id: this.pageId,
  241. offsetPage: 0,
  242. offsetSize: 25
  243. }
  244. },
  245. manual: true,
  246. result({ data, loading, networkStatus }) {
  247. this.total = data.pages.history.total
  248. this.trail = data.pages.history.trail
  249. },
  250. watchLoading (isLoading) {
  251. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'history-trail-refresh')
  252. }
  253. }
  254. }
  255. }
  256. </script>
  257. <style lang='scss'>
  258. .history {
  259. &-promptmenu {
  260. border-top: 5px solid mc('blue', '700');
  261. }
  262. }
  263. </style>