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.
wiki/client/components/editor/editor-modal-conflict.vue

223 lines
7.1 KiB

<template lang='pug'>
v-card.editor-modal-conflict.animated.fadeIn(flat, tile)
.pa-4
v-toolbar.radius-7(flat, color='indigo', style='border-bottom-left-radius: 0; border-bottom-right-radius: 0;', dark)
v-icon.mr-3 mdi-merge
.subtitle-1 {{$t('editor:conflict.title')}}
v-spacer
v-btn(outlined, color='white', @click='useLocal', :title='$t(`editor:conflict.useLocalHint`)')
v-icon(left) mdi-alpha-l-box
span {{$t('editor:conflict.useLocal')}}
v-dialog(
v-model='isRemoteConfirmDiagShown'
width='500'
)
template(v-slot:activator='{ on }')
v-btn.ml-3(outlined, color='white', v-on='on', :title='$t(`editor:conflict.useRemoteHint`)')
v-icon(left) mdi-alpha-r-box
span {{$t('editor:conflict.useRemote')}}
v-card
.dialog-header.is-short.is-indigo
v-icon.mr-3(color='white') mdi-alpha-r-box
span {{$t('editor:conflict.overwrite.title')}}
v-card-text.pa-4
i18next.body-2(tag='div', path='editor:conflict.overwrite.description')
strong(place='refEditsLost') {{$t('editor:conflict.overwrite.editsLost')}}
v-card-chin
v-spacer
v-btn(outlined, color='indigo', @click='isRemoteConfirmDiagShown = false')
v-icon(left) mdi-close
span {{$t('common:actions.cancel')}}
v-btn(@click='useRemote', color='indigo', dark)
v-icon(left) mdi-check
span {{$t('common:actions.confirm')}}
v-divider.mx-3(vertical)
v-btn(outlined, color='indigo lighten-4', @click='close')
v-icon(left) mdi-close
span {{$t('common:actions.cancel')}}
v-row.indigo.darken-1.body-2(no-gutters)
v-col.pa-4
v-icon.mr-3(color='white') mdi-alpha-l-box
i18next.white--text(tag='span', path='editor:conflict.localVersion')
em.indigo--text.text--lighten-4(place='refEditable') {{$t('editor:conflict.editable')}}
v-divider(vertical)
v-col.pa-4
v-icon.mr-3(color='white') mdi-alpha-r-box
i18next.white--text(tag='span', path='editor:conflict.remoteVersion')
em.indigo--text.text--lighten-4(place='refReadOnly') {{$t('editor:conflict.readonly')}}
v-row.grey.lighten-2.body-2(no-gutters)
v-col.px-4.py-2
i18next.grey--text.text--darken-2(tag='em', path='editor:conflict.leftPanelInfo')
span(place='date', :title='$options.filters.moment(checkoutDateActive, `LLL`)') {{ checkoutDateActive | moment('from') }}
v-divider(vertical)
v-col.px-4.py-2
i18next.grey--text.text--darken-2(tag='em', path='editor:conflict.rightPanelInfo')
strong(place='authorName') {{latest.authorName}}
span(place='date', :title='$options.filters.moment(latest.updatedAt, `LLL`)') {{ latest.updatedAt | moment('from') }}
v-row.grey.lighten-3.grey--text.text--darken-3(no-gutters)
v-col.pa-4
.body-2
strong.indigo--text {{$t('editor:conflict.pageTitle')}}
strong.pl-2 {{title}}
.caption
strong.indigo--text {{$t('editor:conflict.pageDescription')}}
span.pl-2 {{description}}
v-divider(vertical, light)
v-col.pa-4
.body-2
strong.indigo--text {{$t('editor:conflict.pageTitle')}}
strong.pl-2 {{latest.title}}
.caption
strong.indigo--text {{$t('editor:conflict.pageDescription')}}
span.pl-2 {{latest.description}}
v-card.radius-7(:light='!$vuetify.theme.dark', :dark='$vuetify.theme.dark')
div(ref='cm')
</template>
<script>
import _ from 'lodash'
import gql from 'graphql-tag'
import { sync, get } from 'vuex-pathify'
/* global siteConfig */
// ========================================
// IMPORTS
// ========================================
import '../../libs/codemirror-merge/diff-match-patch.js'
// Code Mirror
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
// Language
import 'codemirror/mode/markdown/markdown.js'
import 'codemirror/mode/htmlmixed/htmlmixed.js'
// Addons
import 'codemirror/addon/selection/active-line.js'
import 'codemirror/addon/merge/merge.js'
import 'codemirror/addon/merge/merge.css'
export default {
data() {
return {
cm: null,
latest: {
title: '',
description: '',
updatedAt: '',
authorName: ''
},
isRemoteConfirmDiagShown: false
}
},
computed: {
editorKey: get('editor/editorKey'),
activeModal: sync('editor/activeModal'),
pageId: get('page/id'),
title: get('page/title'),
description: get('page/description'),
updatedAt: get('page/updatedAt'),
checkoutDateActive: sync('editor/checkoutDateActive')
},
methods: {
close () {
this.isRemoteConfirmDiagShown = false
this.activeModal = ''
},
overwriteAndClose() {
this.checkoutDateActive = this.latest.updatedAt
this.$root.$emit('overwriteEditorContent')
this.$root.$emit('resetEditorConflict')
this.close()
},
useLocal () {
this.$store.set('editor/content', this.cm.edit.getValue())
this.overwriteAndClose()
},
useRemote () {
this.$store.set('editor/content', this.latest.content)
this.overwriteAndClose()
}
},
async mounted () {
let textMode = 'text/html'
switch (this.editorKey) {
case 'markdown':
textMode = 'text/markdown'
break
}
let resp = await this.$apollo.query({
query: gql`
query ($id: Int!) {
pages {
conflictLatest(id: $id) {
id
authorId
authorName
content
createdAt
description
isPublished
locale
path
tags
title
updatedAt
}
}
}
`,
fetchPolicy: 'network-only',
variables: {
id: this.$store.get('page/id')
}
})
resp = _.get(resp, 'data.pages.conflictLatest', false)
if (!resp) {
return this.$store.commit('showNotification', {
message: 'Failed to fetch latest version.',
style: 'warning',
icon: 'warning'
})
}
this.latest = resp
this.cm = CodeMirror.MergeView(this.$refs.cm, {
value: this.$store.get('editor/content'),
orig: resp.content,
tabSize: 2,
mode: textMode,
lineNumbers: true,
lineWrapping: true,
connect: null,
highlightDifferences: true,
styleActiveLine: true,
collapseIdentical: true,
direction: siteConfig.rtl ? 'rtl' : 'ltr'
})
this.cm.rightOriginal().setSize(null, 'calc(100vh - 265px)')
this.cm.editor().setSize(null, 'calc(100vh - 265px)')
this.cm.wrap.style.height = 'calc(100vh - 265px)'
}
}
</script>
<style lang='scss'>
.editor-modal-conflict {
position: fixed !important;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, .9) !important;
overflow: auto;
}
</style>