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.

276 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. search-results
  103. </template>
  104. <script>
  105. import { Diff2Html } from 'diff2html'
  106. import { createPatch } from 'diff'
  107. import { get } from 'vuex-pathify'
  108. import _ from 'lodash'
  109. import historyTrailQuery from 'gql/history/history-trail-query.gql'
  110. export default {
  111. props: {
  112. pageId: {
  113. type: Number,
  114. default: 0
  115. },
  116. locale: {
  117. type: String,
  118. default: 'en'
  119. },
  120. path: {
  121. type: String,
  122. default: 'home'
  123. },
  124. liveContent: {
  125. type: String,
  126. default: ''
  127. }
  128. },
  129. data() {
  130. return {
  131. sourceText: '',
  132. targetText: '',
  133. trail: [],
  134. diffSource: 0,
  135. diffTarget: 0,
  136. offsetPage: 0,
  137. total: 0
  138. }
  139. },
  140. computed: {
  141. darkMode: get('site/dark'),
  142. diffs() {
  143. return createPatch(`/${this.path}`, this.sourceText, this.targetText)
  144. },
  145. diffHTML() {
  146. return Diff2Html.getPrettyHtml(this.diffs, {
  147. inputFormat: 'diff',
  148. showFiles: false,
  149. matching: 'lines',
  150. outputFormat: 'line-by-line'
  151. })
  152. }
  153. },
  154. watch: {
  155. trail(newValue, oldValue) {
  156. if (newValue && newValue.length > 0) {
  157. this.diffTarget = _.get(_.head(newValue), 'versionId', 0)
  158. this.diffSource = _.get(_.nth(newValue, 1), 'versionId', 0)
  159. }
  160. }
  161. },
  162. created () {
  163. this.$store.commit('page/SET_ID', this.id)
  164. this.$store.commit('page/SET_LOCALE', this.locale)
  165. this.$store.commit('page/SET_PATH', this.path)
  166. this.$store.commit('page/SET_MODE', 'history')
  167. this.targetText = this.liveContent
  168. },
  169. methods: {
  170. goLive() {
  171. window.location.assign(`/${this.path}`)
  172. },
  173. setDiffSource(versionId) {
  174. this.diffSource = versionId
  175. },
  176. setDiffTarget(versionId) {
  177. this.diffTarget = versionId
  178. },
  179. loadMore() {
  180. this.offsetPage++
  181. this.$apollo.queries.trail.fetchMore({
  182. variables: {
  183. id: this.pageId,
  184. offsetPage: this.offsetPage,
  185. offsetSize: 25
  186. },
  187. updateQuery: (previousResult, { fetchMoreResult }) => {
  188. return {
  189. pages: {
  190. history: {
  191. total: previousResult.pages.history.total,
  192. trail: [...previousResult.pages.history.trail, ...fetchMoreResult.pages.history.trail],
  193. __typename: previousResult.pages.history.__typename
  194. },
  195. __typename: previousResult.pages.__typename
  196. }
  197. }
  198. }
  199. })
  200. },
  201. trailColor(actionType) {
  202. switch (actionType) {
  203. case 'edit':
  204. return 'primary'
  205. case 'move':
  206. return 'purple'
  207. case 'initial':
  208. return 'teal'
  209. default:
  210. return 'grey'
  211. }
  212. },
  213. trailIcon(actionType) {
  214. switch (actionType) {
  215. case 'edit':
  216. return 'edit'
  217. case 'move':
  218. return 'forward'
  219. case 'initial':
  220. return 'add'
  221. default:
  222. return 'warning'
  223. }
  224. },
  225. trailBgColor(actionType) {
  226. switch (actionType) {
  227. case 'move':
  228. return this.darkMode ? 'purple' : 'purple lighten-5'
  229. case 'initial':
  230. return this.darkMode ? 'teal darken-3' : 'teal lighten-5'
  231. default:
  232. return this.darkMode ? 'grey darken-3' : 'grey lighten-3'
  233. }
  234. }
  235. },
  236. apollo: {
  237. trail: {
  238. query: historyTrailQuery,
  239. variables() {
  240. return {
  241. id: this.pageId,
  242. offsetPage: 0,
  243. offsetSize: 25
  244. }
  245. },
  246. manual: true,
  247. result({ data, loading, networkStatus }) {
  248. this.total = data.pages.history.total
  249. this.trail = data.pages.history.trail
  250. },
  251. watchLoading (isLoading) {
  252. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'history-trail-refresh')
  253. }
  254. }
  255. }
  256. }
  257. </script>
  258. <style lang='scss'>
  259. .history {
  260. &-promptmenu {
  261. border-top: 5px solid mc('blue', '700');
  262. }
  263. }
  264. </style>