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.

288 lines
9.2 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. <template lang="pug">
  2. .editor
  3. nav-header(dense)
  4. template(slot='actions')
  5. v-btn(
  6. outline
  7. color='green'
  8. @click.native.stop='save'
  9. :class='{ "is-icon": $vuetify.breakpoint.mdAndDown }'
  10. )
  11. v-icon(color='green', :left='$vuetify.breakpoint.lgAndUp') check
  12. span.white--text(v-if='$vuetify.breakpoint.lgAndUp') {{ mode === 'create' ? $t('common:actions.create') : $t('common:actions.save') }}
  13. v-btn.mx-0(
  14. outline
  15. color='red'
  16. :class='{ "is-icon": $vuetify.breakpoint.mdAndDown }'
  17. )
  18. v-icon(color='red', :left='$vuetify.breakpoint.lgAndUp') close
  19. span.white--text(v-if='$vuetify.breakpoint.lgAndUp') {{ $t('common:actions.discard') }}
  20. v-btn(
  21. outline
  22. color='blue'
  23. @click.native.stop='openModal(`properties`)'
  24. :class='{ "is-icon": $vuetify.breakpoint.mdAndDown }'
  25. )
  26. v-icon(color='blue', :left='$vuetify.breakpoint.lgAndUp') sort_by_alpha
  27. span.white--text(v-if='$vuetify.breakpoint.lgAndUp') {{ $t('editor:page') }}
  28. v-content
  29. component(:is='currentEditor')
  30. component(:is='currentModal')
  31. v-dialog(v-model='dialogProgress', persistent, max-width='350')
  32. v-card(color='blue darken-3', dark)
  33. v-card-text.text-xs-center.py-4
  34. atom-spinner.is-inline(
  35. :animation-duration='1000'
  36. :size='60'
  37. color='#FFF'
  38. )
  39. .subheading {{ $t('editor:save.processing') }}
  40. .caption.blue--text.text--lighten-3 {{ $t('editor:save.pleaseWait') }}
  41. v-dialog(v-model='dialogEditorSelector', persistent, max-width='550')
  42. v-card(color='blue darken-3', dark)
  43. v-card-text.text-xs-center.py-4
  44. .subheading Which editor do you want to use?
  45. v-container(grid-list-lg, fluid)
  46. v-layout(row, wrap, justify-center)
  47. v-flex(xs4)
  48. v-card(
  49. hover
  50. light
  51. ripple
  52. )
  53. v-card-text.text-xs-center(@click='selectEditor("code")')
  54. v-icon(large, color='primary') code
  55. .body-2.mt-2 Code
  56. v-flex(xs4)
  57. v-card(
  58. hover
  59. light
  60. ripple
  61. )
  62. v-card-text.text-xs-center(@click='selectEditor("markdown")')
  63. v-icon(large, color='primary') list_alt
  64. .body-2.mt-2 Markdown
  65. v-flex(xs4)
  66. v-card.grey(
  67. hover
  68. light
  69. ripple
  70. )
  71. v-card-text.text-xs-center(@click='selectEditor("wysiwyg")')
  72. v-icon(large, color='grey darken-1') web
  73. .body-2.mt-2.grey--text.text--darken-2 Visual Builder
  74. v-snackbar(
  75. :color='notification.style'
  76. bottom,
  77. right,
  78. multi-line,
  79. v-model='notificationState'
  80. )
  81. .text-xs-left
  82. v-icon.mr-3(dark) {{ notification.icon }}
  83. span {{ notification.message }}
  84. </template>
  85. <script>
  86. import _ from 'lodash'
  87. import { get, sync } from 'vuex-pathify'
  88. import { AtomSpinner } from 'epic-spinners'
  89. import createPageMutation from 'gql/editor/create.gql'
  90. import updatePageMutation from 'gql/editor/update.gql'
  91. import editorStore from '@/store/editor'
  92. /* global WIKI */
  93. WIKI.$store.registerModule('editor', editorStore)
  94. export default {
  95. components: {
  96. AtomSpinner,
  97. editorCode: () => import(/* webpackChunkName: "editor-code", webpackMode: "lazy" */ './editor/editor-code.vue'),
  98. editorMarkdown: () => import(/* webpackChunkName: "editor-markdown", webpackMode: "lazy" */ './editor/editor-markdown.vue'),
  99. editorWysiwyg: () => import(/* webpackChunkName: "editor-wysiwyg", webpackMode: "lazy" */ './editor/editor-wysiwyg.vue'),
  100. editorModalProperties: () => import(/* webpackChunkName: "editor", webpackMode: "eager" */ './editor/editor-modal-properties.vue')
  101. },
  102. props: {
  103. locale: {
  104. type: String,
  105. default: 'en'
  106. },
  107. path: {
  108. type: String,
  109. default: 'home'
  110. },
  111. title: {
  112. type: String,
  113. default: 'Untitled Page'
  114. },
  115. description: {
  116. type: String,
  117. default: ''
  118. },
  119. tags: {
  120. type: Array,
  121. default: () => ([])
  122. },
  123. isPublished: {
  124. type: Boolean,
  125. default: false
  126. },
  127. initEditor: {
  128. type: String,
  129. default: null
  130. },
  131. initMode: {
  132. type: String,
  133. default: 'create'
  134. },
  135. initContent: {
  136. type: String,
  137. default: null
  138. }
  139. },
  140. data() {
  141. return {
  142. currentModal: '',
  143. currentEditor: '',
  144. dialogProgress: false,
  145. dialogEditorSelector: false
  146. }
  147. },
  148. computed: {
  149. mode: get('editor/mode'),
  150. notification: get('notification'),
  151. notificationState: sync('notification@isActive')
  152. },
  153. mounted() {
  154. this.$store.set('editor/mode', this.initMode || 'create')
  155. this.$store.set('editor/content', this.initContent ? window.atob(this.initContent) : '# Header\n\nYour content here')
  156. if (this.mode === 'create') {
  157. _.delay(() => {
  158. this.dialogEditorSelector = true
  159. }, 500)
  160. } else {
  161. this.selectEditor(this.initEditor || 'markdown')
  162. }
  163. },
  164. methods: {
  165. selectEditor(name) {
  166. this.currentEditor = `editor${_.startCase(name)}`
  167. this.dialogEditorSelector = false
  168. if (this.mode === 'create') {
  169. _.delay(() => {
  170. this.openModal('properties')
  171. }, 500)
  172. }
  173. },
  174. openModal(name) {
  175. this.currentModal = `editorModal${_.startCase(name)}`
  176. },
  177. closeModal() {
  178. _.delay(() => {
  179. this.currentModal = ``
  180. }, 500)
  181. },
  182. showProgressDialog(textKey) {
  183. this.dialogProgress = true
  184. },
  185. hideProgressDialog() {
  186. this.dialogProgress = false
  187. },
  188. async save() {
  189. this.showProgressDialog('saving')
  190. try {
  191. if (this.$store.get('editor/mode') === 'create') {
  192. // --------------------------------------------
  193. // -> CREATE PAGE
  194. // --------------------------------------------
  195. let resp = await this.$apollo.mutate({
  196. mutation: createPageMutation,
  197. variables: {
  198. content: this.$store.get('editor/content'),
  199. description: this.$store.get('editor/description'),
  200. editor: 'markdown',
  201. locale: this.$store.get('editor/locale'),
  202. isPrivate: false,
  203. isPublished: this.$store.get('editor/isPublished'),
  204. path: this.$store.get('editor/path'),
  205. publishEndDate: this.$store.get('editor/publishEndDate'),
  206. publishStartDate: this.$store.get('editor/publishStartDate'),
  207. tags: this.$store.get('editor/tags'),
  208. title: this.$store.get('editor/title')
  209. }
  210. })
  211. resp = _.get(resp, 'data.pages.create', {})
  212. if (_.get(resp, 'responseResult.succeeded')) {
  213. this.$store.commit('showNotification', {
  214. message: this.$t('editor:save.success'),
  215. style: 'success',
  216. icon: 'check'
  217. })
  218. this.$store.set('editor/id', _.get(resp, 'page.id'))
  219. this.$store.set('editor/mode', 'update')
  220. } else {
  221. throw new Error(_.get(resp, 'responseResult.message'))
  222. }
  223. } else {
  224. // --------------------------------------------
  225. // -> UPDATE EXISTING PAGE
  226. // --------------------------------------------
  227. let resp = await this.$apollo.mutate({
  228. mutation: updatePageMutation,
  229. variables: {
  230. id: this.$store.get('editor/id'),
  231. content: this.$store.get('editor/content'),
  232. description: this.$store.get('editor/description'),
  233. editor: 'markdown',
  234. locale: this.$store.get('editor/locale'),
  235. isPrivate: false,
  236. isPublished: this.$store.get('editor/isPublished'),
  237. path: this.$store.get('editor/path'),
  238. publishEndDate: this.$store.get('editor/publishEndDate'),
  239. publishStartDate: this.$store.get('editor/publishStartDate'),
  240. tags: this.$store.get('editor/tags'),
  241. title: this.$store.get('editor/title')
  242. }
  243. })
  244. resp = _.get(resp, 'data.pages.update', {})
  245. if (_.get(resp, 'responseResult.succeeded')) {
  246. this.$store.commit('showNotification', {
  247. message: this.$t('editor:save.success'),
  248. style: 'success',
  249. icon: 'check'
  250. })
  251. } else {
  252. throw new Error(_.get(resp, 'responseResult.message'))
  253. }
  254. }
  255. } catch (err) {
  256. this.$store.commit('showNotification', {
  257. message: err.message,
  258. style: 'error',
  259. icon: 'warning'
  260. })
  261. }
  262. this.hideProgressDialog()
  263. }
  264. }
  265. }
  266. </script>
  267. <style lang='scss'>
  268. .editor {
  269. background-color: mc('grey', '900');
  270. min-height: 100vh;
  271. }
  272. .atom-spinner.is-inline {
  273. display: inline-block;
  274. }
  275. </style>