history.vue 8.52 KB
Newer Older
1 2 3 4 5 6 7
<template lang='pug'>
  v-app(:dark='darkMode').history
    nav-header
    v-content
      v-toolbar(color='primary', dark)
        .subheading Viewing history of page #[strong /{{path}}]
        v-spacer
8 9
        .caption.blue--text.text--lighten-3.mr-4 Trail Length: {{total}}
        .caption.blue--text.text--lighten-3 ID: {{pageId}}
10 11 12
        v-btn.ml-4(depressed, color='blue darken-1', @click='goLive') Return to Live Version
      v-container(fluid, grid-list-xl)
        v-layout(row, wrap)
13
          v-flex(xs4)
14
            v-chip.ma-0(
15 16
              label
              small
17 18
              :color='darkMode ? `grey darken-2` : `grey lighten-2`'
              :class='darkMode ? `grey--text text--lighten-2` : `grey--text text--darken-2`'
19 20 21 22 23
              )
              span Live
            v-timeline(
              dense
              )
24 25
              v-timeline-item.pb-2(
                v-for='(ph, idx) in trail'
26 27
                :key='ph.versionId'
                :small='ph.actionType === `edit`'
28
                fill-dot
29 30
                :color='trailColor(ph.actionType)'
                :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 36 37 38
                    v-chip.ml-0.mr-3(
                      v-if='diffSource === ph.versionId'
                      small
                      color='pink'
Nick's avatar
Nick committed
39
                      label
40 41 42 43 44 45
                      )
                      .caption.white--text Source
                    v-chip.ml-0.mr-3(
                      v-if='diffTarget === ph.versionId'
                      small
                      color='pink'
Nick's avatar
Nick committed
46
                      label
47 48
                      )
                      .caption.white--text Target
49 50 51 52
                    .caption(v-if='ph.actionType === `edit`') Edited by #[strong {{ ph.authorName }}]
                    .caption(v-else-if='ph.actionType === `move`') Moved from #[strong {{ph.valueBefore}}] to #[strong {{ph.valueAfter}}] by #[strong {{ ph.authorName }}]
                    .caption(v-else-if='ph.actionType === `initial`') Created by #[strong {{ ph.authorName }}]
                    .caption(v-else) Unknown Action by #[strong {{ ph.authorName }}]
53
                    v-spacer
Nick's avatar
Nick committed
54
                    .caption.mr-3 {{ ph.createdAt | moment('calendar') }}
55
                    v-menu(offset-x, left)
Nick's avatar
Nick committed
56 57 58
                      template(v-slot:activator='{ on }')
                        v-btn.mr-0(icon, v-on='on', small, tile): v-icon mdi-dots-horizontal
                      v-list(dense, nav).history-promptmenu
59
                        v-list-item(@click='setDiffTarget(ph.versionId)')
Nick's avatar
Nick committed
60
                          v-list-item-avatar(size='24'): v-icon mdi-call-received
61 62
                          v-list-item-title Set as Differencing Target
                        v-list-item(@click='setDiffSource(ph.versionId)')
Nick's avatar
Nick committed
63
                          v-list-item-avatar(size='24'): v-icon mdi-call-made
64 65
                          v-list-item-title Set as Differencing Source
                        v-list-item
Nick's avatar
Nick committed
66
                          v-list-item-avatar(size='24'): v-icon mdi-code-tags
67 68
                          v-list-item-title View Source
                        v-list-item
Nick's avatar
Nick committed
69
                          v-list-item-avatar(size='24'): v-icon mdi-cloud-download-outline
70 71
                          v-list-item-title Download Version
                        v-list-item
Nick's avatar
Nick committed
72
                          v-list-item-avatar(size='24'): v-icon mdi-history
73 74
                          v-list-item-title Restore
                        v-list-item
Nick's avatar
Nick committed
75
                          v-list-item-avatar(size='24'): v-icon mdi-source-branch
76
                          v-list-item-title Branch off from here
77

78 79 80 81 82 83 84 85 86 87
            v-btn.ma-0.radius-7(
              v-if='total > trail.length'
              block
              color='grey darken-2'
              @click='loadMore'
              )
              .caption.white--text Load More...

            v-chip.ma-0(
              v-else
88 89
              label
              small
90 91
              :color='darkMode ? `grey darken-2` : `grey lighten-2`'
              :class='darkMode ? `grey--text text--lighten-2` : `grey--text text--darken-2`'
92
              ) End of history trail
93

94
          v-flex(xs8)
95 96
            v-card.radius-7
              v-card-text
97
                v-card.grey.radius-7(flat, :class='darkMode ? `darken-2` : `lighten-4`')
98 99 100
                  v-card-text
                    .subheading Page Title
                    .caption Some page description
101
                v-card.mt-3(light, v-html='diffHTML')
102 103

    nav-footer
104
    notify
105
    search-results
106 107 108
</template>

<script>
109 110
import { Diff2Html } from 'diff2html'
import { createPatch } from 'diff'
111
import { get } from 'vuex-pathify'
112 113 114 115
import _ from 'lodash'

import historyTrailQuery from 'gql/history/history-trail-query.gql'

116 117
export default {
  props: {
118
    pageId: {
119 120 121 122 123 124 125 126 127 128
      type: Number,
      default: 0
    },
    locale: {
      type: String,
      default: 'en'
    },
    path: {
      type: String,
      default: 'home'
129 130 131 132
    },
    liveContent: {
      type: String,
      default: ''
133 134 135
    }
  },
  data() {
136 137 138 139 140 141
    return {
      sourceText: '',
      targetText: '',
      trail: [],
      diffSource: 0,
      diffTarget: 0,
142 143
      offsetPage: 0,
      total: 0
144
    }
145 146
  },
  computed: {
147
    darkMode: get('site/dark'),
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
    diffs() {
      return createPatch(`/${this.path}`, this.sourceText, this.targetText)
    },
    diffHTML() {
      return Diff2Html.getPrettyHtml(this.diffs, {
        inputFormat: 'diff',
        showFiles: false,
        matching: 'lines',
        outputFormat: 'line-by-line'
      })
    }
  },
  watch: {
    trail(newValue, oldValue) {
      if (newValue && newValue.length > 0) {
        this.diffTarget = _.get(_.head(newValue), 'versionId', 0)
        this.diffSource = _.get(_.nth(newValue, 1), 'versionId', 0)
      }
    }
167 168 169 170 171
  },
  created () {
    this.$store.commit('page/SET_ID', this.id)
    this.$store.commit('page/SET_LOCALE', this.locale)
    this.$store.commit('page/SET_PATH', this.path)
172 173

    this.$store.commit('page/SET_MODE', 'history')
174 175

    this.targetText = this.liveContent
176 177 178 179
  },
  methods: {
    goLive() {
      window.location.assign(`/${this.path}`)
180 181 182 183 184 185 186
    },
    setDiffSource(versionId) {
      this.diffSource = versionId
    },
    setDiffTarget(versionId) {
      this.diffTarget = versionId
    },
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
    loadMore() {
      this.offsetPage++
      this.$apollo.queries.trail.fetchMore({
        variables: {
          id: this.pageId,
          offsetPage: this.offsetPage,
          offsetSize: 25
        },
        updateQuery: (previousResult, { fetchMoreResult }) => {
          return {
            pages: {
              history: {
                total: previousResult.pages.history.total,
                trail: [...previousResult.pages.history.trail, ...fetchMoreResult.pages.history.trail],
                __typename: previousResult.pages.history.__typename
              },
              __typename: previousResult.pages.__typename
            }
          }
        }
      })
    },
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
    trailColor(actionType) {
      switch (actionType) {
        case 'edit':
          return 'primary'
        case 'move':
          return 'purple'
        case 'initial':
          return 'teal'
        default:
          return 'grey'
      }
    },
    trailIcon(actionType) {
      switch (actionType) {
        case 'edit':
Nick's avatar
Nick committed
224
          return 'mdi-pencil'
225 226 227
        case 'move':
          return 'forward'
        case 'initial':
Nick's avatar
Nick committed
228
          return 'mdi-plus'
229 230 231 232 233 234 235
        default:
          return 'warning'
      }
    },
    trailBgColor(actionType) {
      switch (actionType) {
        case 'move':
236
          return this.darkMode ? 'purple' : 'purple lighten-5'
237
        case 'initial':
238
          return this.darkMode ? 'teal darken-3' : 'teal lighten-5'
239
        default:
240
          return this.darkMode ? 'grey darken-3' : 'grey lighten-3'
241 242 243 244 245 246 247 248 249
      }
    }
  },
  apollo: {
    trail: {
      query: historyTrailQuery,
      variables() {
        return {
          id: this.pageId,
250 251
          offsetPage: 0,
          offsetSize: 25
252 253
        }
      },
254 255 256 257 258
      manual: true,
      result({ data, loading, networkStatus }) {
        this.total = data.pages.history.total
        this.trail = data.pages.history.trail
      },
259 260 261
      watchLoading (isLoading) {
        this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'history-trail-refresh')
      }
262 263 264 265 266 267 268
    }
  }
}
</script>

<style lang='scss'>

269 270 271 272 273 274
.history {
  &-promptmenu {
    border-top: 5px solid mc('blue', '700');
  }
}

275
</style>