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.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. </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 'edit'
  216. case 'move':
  217. return 'forward'
  218. case 'initial':
  219. return 'add'
  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>