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.

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