2
0

admin-general.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <template lang='pug'>
  2. v-container(fluid, grid-list-lg)
  3. v-layout(row wrap)
  4. v-flex(xs12)
  5. .admin-header
  6. img.animated.fadeInUp(src='/_assets/svg/icon-categorize.svg', alt='General', style='width: 80px;')
  7. .admin-header-title
  8. .headline.primary--text.animated.fadeInLeft {{ $t('admin:general.title') }}
  9. .subtitle-1.grey--text.animated.fadeInLeft {{ $t('admin:general.subtitle') }}
  10. v-spacer
  11. v-btn.animated.fadeInDown(color='success', depressed, @click='save', large)
  12. v-icon(left) mdi-check
  13. span {{$t('common:actions.apply')}}
  14. v-form.pt-3
  15. v-layout(row wrap)
  16. v-flex(lg6 xs12)
  17. v-form
  18. v-card.animated.fadeInUp
  19. v-toolbar(color='primary', dark, dense, flat)
  20. v-toolbar-title.subtitle-1 {{ $t('admin:general.siteInfo') }}
  21. .overline.grey--text.pa-4 {{$t('admin:general.general')}}
  22. .px-3.pb-3
  23. v-text-field(
  24. outlined
  25. :label='$t(`admin:general.siteUrl`)'
  26. required
  27. :counter='255'
  28. v-model='config.host'
  29. prepend-icon='mdi-label-variant-outline'
  30. :hint='$t(`admin:general.siteUrlHint`)'
  31. persistent-hint
  32. )
  33. v-text-field.mt-3(
  34. outlined
  35. :label='$t(`admin:general.siteTitle`)'
  36. required
  37. :counter='50'
  38. v-model='config.title'
  39. prepend-icon='mdi-earth'
  40. :hint='$t(`admin:general.siteTitleHint`)'
  41. persistent-hint
  42. )
  43. v-divider
  44. .overline.grey--text.pa-4 {{$t('admin:general.logo')}}
  45. .pt-2.pb-7.pl-10.pr-3
  46. .d-flex.align-center
  47. v-avatar(size='100', tile)
  48. v-img(
  49. :src='config.logoUrl'
  50. lazy-src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNcWQ8AAdcBKrJda2oAAAAASUVORK5CYII='
  51. aspect-ratio='1'
  52. )
  53. .ml-4(style='flex: 1 1 auto;')
  54. v-text-field(
  55. outlined
  56. :label='$t(`admin:general.logoUrl`)'
  57. v-model='config.logoUrl'
  58. :hint='$t(`admin:general.logoUrlHint`)'
  59. persistent-hint
  60. append-icon='mdi-folder-image'
  61. @click:append='browseLogo'
  62. @keyup.enter='refreshLogo'
  63. )
  64. v-divider
  65. .overline.grey--text.pa-4 {{$t('admin:general.footerCopyright')}}
  66. .px-3.pb-3
  67. v-text-field(
  68. outlined
  69. :label='$t(`admin:general.companyName`)'
  70. v-model='config.company'
  71. :counter='255'
  72. prepend-icon='mdi-domain'
  73. persistent-hint
  74. :hint='$t(`admin:general.companyNameHint`)'
  75. )
  76. v-select.mt-3(
  77. outlined
  78. :label='$t(`admin:general.contentLicense`)'
  79. :items='contentLicenses'
  80. v-model='config.contentLicense'
  81. prepend-icon='mdi-creative-commons'
  82. :return-object='false'
  83. :hint='$t(`admin:general.contentLicenseHint`)'
  84. persistent-hint
  85. )
  86. v-divider
  87. .overline.grey--text.pa-4 SEO
  88. .px-3.pb-3
  89. v-text-field(
  90. outlined
  91. :label='$t(`admin:general.siteDescription`)'
  92. :counter='255'
  93. v-model='config.description'
  94. prepend-icon='mdi-compass'
  95. :hint='$t(`admin:general.siteDescriptionHint`)'
  96. persistent-hint
  97. )
  98. v-select.mt-3(
  99. outlined
  100. :label='$t(`admin:general.metaRobots`)'
  101. multiple
  102. :items='metaRobots'
  103. v-model='config.robots'
  104. prepend-icon='mdi-compass'
  105. :return-object='false'
  106. :hint='$t(`admin:general.metaRobotsHint`)'
  107. persistent-hint
  108. )
  109. v-flex(lg6 xs12)
  110. v-card.animated.fadeInUp.wait-p4s
  111. v-toolbar(color='indigo', dark, dense, flat)
  112. v-toolbar-title.subtitle-1 Features
  113. v-card-text
  114. //- v-switch(
  115. //- inset
  116. //- label='Asset Image Optimization'
  117. //- color='indigo'
  118. //- v-model='config.featureTinyPNG'
  119. //- persistent-hint
  120. //- hint='Image optimization tool to reduce filesize and bandwidth costs.'
  121. //- disabled
  122. //- )
  123. //- v-text-field.mt-3(
  124. //- outlined
  125. //- label='TinyPNG API Key'
  126. //- :counter='255'
  127. //- v-model='config.description'
  128. //- prepend-icon='mdi-subdirectory-arrow-right'
  129. //- hint='Get your API key at https://tinypng.com/developers'
  130. //- persistent-hint
  131. //- disabled
  132. //- )
  133. //- v-divider.mt-3
  134. //- v-switch(
  135. //- inset
  136. //- label='Page Ratings'
  137. //- color='indigo'
  138. //- v-model='config.featurePageRatings'
  139. //- persistent-hint
  140. //- hint='Allow users to rate pages.'
  141. //- disabled
  142. //- )
  143. //- v-divider.mt-3
  144. v-switch.mt-0(
  145. inset
  146. label='Comments'
  147. color='indigo'
  148. v-model='config.featurePageComments'
  149. persistent-hint
  150. hint='Allow users to leave comments on pages.'
  151. )
  152. //- v-divider.mt-3
  153. //- v-switch(
  154. //- inset
  155. //- label='Personal Wikis'
  156. //- color='indigo'
  157. //- v-model='config.featurePersonalWikis'
  158. //- persistent-hint
  159. //- hint='Allow users to have their own personal wiki.'
  160. //- disabled
  161. //- )
  162. v-card.mt-5.animated.fadeInUp.wait-p6s
  163. v-toolbar(color='primary', dark, dense, flat)
  164. v-toolbar-title.subtitle-1 URL Handling
  165. v-card-text
  166. v-text-field(
  167. outlined
  168. :label='$t(`admin:general.pageExtensions`)'
  169. v-model='config.pageExtensions'
  170. prepend-icon='mdi-format-text-wrapping-overflow'
  171. :hint='$t(`admin:general.pageExtensionsHint`)'
  172. persistent-hint
  173. )
  174. v-card.mt-5.animated.fadeInUp.wait-p7s
  175. v-toolbar(color='primary', dark, dense, flat)
  176. v-toolbar-title.subtitle-1 {{$t('admin:general.editShortcuts')}}
  177. v-card-text
  178. v-switch.mt-0(
  179. inset
  180. :label='$t(`admin:general.editFab`)'
  181. color='primary'
  182. v-model='config.editFab'
  183. persistent-hint
  184. :hint='$t(`admin:general.editFabHint`)'
  185. )
  186. v-divider
  187. .overline.grey--text.pa-4 {{$t('admin:general.editMenuBar')}}
  188. .px-3.pb-3
  189. v-switch.mt-0.ml-1(
  190. inset
  191. :label='$t(`admin:general.displayEditMenuBar`)'
  192. color='primary'
  193. v-model='config.editMenuBar'
  194. persistent-hint
  195. :hint='$t(`admin:general.displayEditMenuBarHint`)'
  196. )
  197. v-switch.mt-4.ml-1(
  198. v-if='config.editMenuBar'
  199. inset
  200. :label='$t(`admin:general.displayEditMenuBtn`)'
  201. color='primary'
  202. v-model='config.editMenuBtn'
  203. persistent-hint
  204. :hint='$t(`admin:general.displayEditMenuBtnHint`)'
  205. )
  206. v-switch.mt-4.ml-1(
  207. v-if='config.editMenuBar'
  208. inset
  209. :label='$t(`admin:general.displayEditMenuExternalBtn`)'
  210. color='primary'
  211. v-model='config.editMenuExternalBtn'
  212. persistent-hint
  213. :hint='$t(`admin:general.displayEditMenuExternalBtnHint`)'
  214. )
  215. template(v-if='config.editMenuBar && config.editMenuExternalBtn')
  216. v-divider
  217. .overline.grey--text.pa-4 External Edit Button
  218. .px-3.pb-3
  219. v-text-field(
  220. outlined
  221. :label='$t(`admin:general.editMenuExternalName`)'
  222. v-model='config.editMenuExternalName'
  223. prepend-icon='mdi-format-title'
  224. :hint='$t(`admin:general.editMenuExternalNameHint`)'
  225. persistent-hint
  226. )
  227. v-text-field.mt-3(
  228. outlined
  229. :label='$t(`admin:general.editMenuExternalIcon`)'
  230. v-model='config.editMenuExternalIcon'
  231. prepend-icon='mdi-dice-5'
  232. :hint='$t(`admin:general.editMenuExternalIconHint`)'
  233. persistent-hint
  234. )
  235. v-text-field.mt-3(
  236. outlined
  237. :label='$t(`admin:general.editMenuExternalUrl`)'
  238. v-model='config.editMenuExternalUrl'
  239. prepend-icon='mdi-near-me'
  240. :hint='$t(`admin:general.editMenuExternalUrlHint`)'
  241. persistent-hint
  242. )
  243. component(:is='activeModal')
  244. </template>
  245. <script>
  246. import _ from 'lodash'
  247. import { sync } from 'vuex-pathify'
  248. import gql from 'graphql-tag'
  249. import editorStore from '../../store/editor'
  250. /* global WIKI */
  251. const titleRegex = /[<>"]/i
  252. WIKI.$store.registerModule('editor', editorStore)
  253. export default {
  254. i18nOptions: { namespaces: 'editor' },
  255. components: {
  256. editorModalMedia: () => import(/* webpackChunkName: "editor", webpackMode: "lazy" */ '../editor/editor-modal-media.vue')
  257. },
  258. data() {
  259. return {
  260. config: {
  261. host: '',
  262. title: '',
  263. description: '',
  264. robots: [],
  265. analyticsService: '',
  266. analyticsId: '',
  267. company: '',
  268. contentLicense: '',
  269. logoUrl: '',
  270. featureAnalytics: false,
  271. featurePageRatings: false,
  272. featurePageComments: false,
  273. featurePersonalWikis: false,
  274. featureTinyPNG: false,
  275. pageExtensions: '',
  276. editFab: false,
  277. editMenuBar: false,
  278. editMenuBtn: false,
  279. editMenuExternalBtn: false,
  280. editMenuExternalName: '',
  281. editMenuExternalIcon: '',
  282. editMenuExternalUrl: ''
  283. },
  284. metaRobots: [
  285. { text: 'Index', value: 'index' },
  286. { text: 'Follow', value: 'follow' },
  287. { text: 'No Index', value: 'noindex' },
  288. { text: 'No Follow', value: 'nofollow' }
  289. ]
  290. }
  291. },
  292. computed: {
  293. siteTitle: sync('site/title'),
  294. logoUrl: sync('site/logoUrl'),
  295. company: sync('site/company'),
  296. contentLicense: sync('site/contentLicense'),
  297. activeModal: sync('editor/activeModal'),
  298. contentLicenses () {
  299. return [
  300. { value: '', text: this.$t('common:license.none') },
  301. { value: 'alr', text: this.$t('common:license.alr') },
  302. { value: 'cc0', text: this.$t('common:license.cc0') },
  303. { value: 'ccby', text: this.$t('common:license.ccby') },
  304. { value: 'ccbysa', text: this.$t('common:license.ccbysa') },
  305. { value: 'ccbynd', text: this.$t('common:license.ccbynd') },
  306. { value: 'ccbync', text: this.$t('common:license.ccbync') },
  307. { value: 'ccbyncsa', text: this.$t('common:license.ccbyncsa') },
  308. { value: 'ccbyncnd', text: this.$t('common:license.ccbyncnd') }
  309. ]
  310. }
  311. },
  312. methods: {
  313. async save () {
  314. const title = _.get(this.config, 'title', '')
  315. if (titleRegex.test(title)) {
  316. this.$store.commit('showNotification', {
  317. style: 'error',
  318. message: this.$t('admin:general.siteTitleInvalidChars'),
  319. icon: 'alert'
  320. })
  321. return
  322. }
  323. try {
  324. await this.$apollo.mutate({
  325. mutation: gql`
  326. mutation (
  327. $host: String
  328. $title: String
  329. $description: String
  330. $robots: [String]
  331. $analyticsService: String
  332. $analyticsId: String
  333. $company: String
  334. $contentLicense: String
  335. $logoUrl: String
  336. $pageExtensions: String
  337. $featurePageRatings: Boolean
  338. $featurePageComments: Boolean
  339. $featurePersonalWikis: Boolean
  340. $editFab: Boolean
  341. $editMenuBar: Boolean
  342. $editMenuBtn: Boolean
  343. $editMenuExternalBtn: Boolean
  344. $editMenuExternalName: String
  345. $editMenuExternalIcon: String
  346. $editMenuExternalUrl: String
  347. ) {
  348. site {
  349. updateConfig(
  350. host: $host
  351. title: $title
  352. description: $description
  353. robots: $robots
  354. analyticsService: $analyticsService
  355. analyticsId: $analyticsId
  356. company: $company
  357. contentLicense: $contentLicense
  358. logoUrl: $logoUrl
  359. pageExtensions: $pageExtensions
  360. featurePageRatings: $featurePageRatings
  361. featurePageComments: $featurePageComments
  362. featurePersonalWikis: $featurePersonalWikis
  363. editFab: $editFab
  364. editMenuBar: $editMenuBar
  365. editMenuBtn: $editMenuBtn
  366. editMenuExternalBtn: $editMenuExternalBtn
  367. editMenuExternalName: $editMenuExternalName
  368. editMenuExternalIcon: $editMenuExternalIcon
  369. editMenuExternalUrl: $editMenuExternalUrl
  370. ) {
  371. responseResult {
  372. succeeded
  373. errorCode
  374. slug
  375. message
  376. }
  377. }
  378. }
  379. }
  380. `,
  381. variables: {
  382. host: _.get(this.config, 'host', ''),
  383. title: _.get(this.config, 'title', ''),
  384. description: _.get(this.config, 'description', ''),
  385. robots: _.get(this.config, 'robots', []),
  386. analyticsService: _.get(this.config, 'analyticsService', ''),
  387. analyticsId: _.get(this.config, 'analyticsId', ''),
  388. company: _.get(this.config, 'company', ''),
  389. contentLicense: _.get(this.config, 'contentLicense', ''),
  390. logoUrl: _.get(this.config, 'logoUrl', ''),
  391. pageExtensions: _.get(this.config, 'pageExtensions', ''),
  392. featurePageRatings: _.get(this.config, 'featurePageRatings', false),
  393. featurePageComments: _.get(this.config, 'featurePageComments', false),
  394. featurePersonalWikis: _.get(this.config, 'featurePersonalWikis', false),
  395. editFab: _.get(this.config, 'editFab', false),
  396. editMenuBar: _.get(this.config, 'editMenuBar', false),
  397. editMenuBtn: _.get(this.config, 'editMenuBtn', false),
  398. editMenuExternalBtn: _.get(this.config, 'editMenuExternalBtn', false),
  399. editMenuExternalName: _.get(this.config, 'editMenuExternalName', ''),
  400. editMenuExternalIcon: _.get(this.config, 'editMenuExternalIcon', ''),
  401. editMenuExternalUrl: _.get(this.config, 'editMenuExternalUrl', '')
  402. },
  403. watchLoading (isLoading) {
  404. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-update')
  405. }
  406. })
  407. this.$store.commit('showNotification', {
  408. style: 'success',
  409. message: this.$t('admin:general.saveSuccess'),
  410. icon: 'check'
  411. })
  412. this.siteTitle = this.config.title
  413. this.company = this.config.company
  414. this.contentLicense = this.config.contentLicense
  415. this.logoUrl = this.config.logoUrl
  416. } catch (err) {
  417. this.$store.commit('pushGraphError', err)
  418. }
  419. },
  420. browseLogo () {
  421. this.$store.set('editor/editorKey', 'common')
  422. this.activeModal = 'editorModalMedia'
  423. },
  424. refreshLogo () {
  425. this.$forceUpdate()
  426. }
  427. },
  428. mounted () {
  429. this.$root.$on('editorInsert', opts => {
  430. this.config.logoUrl = opts.path
  431. })
  432. },
  433. beforeDestroy() {
  434. this.$root.$off('editorInsert')
  435. },
  436. apollo: {
  437. config: {
  438. query: gql`
  439. {
  440. site {
  441. config {
  442. host
  443. title
  444. description
  445. robots
  446. analyticsService
  447. analyticsId
  448. company
  449. contentLicense
  450. logoUrl
  451. pageExtensions
  452. featurePageRatings
  453. featurePageComments
  454. featurePersonalWikis
  455. editFab
  456. editMenuBar
  457. editMenuBtn
  458. editMenuExternalBtn
  459. editMenuExternalName
  460. editMenuExternalIcon
  461. editMenuExternalUrl
  462. }
  463. }
  464. }
  465. `,
  466. fetchPolicy: 'network-only',
  467. update: (data) => _.cloneDeep(data.site.config),
  468. watchLoading (isLoading) {
  469. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-refresh')
  470. }
  471. }
  472. }
  473. }
  474. </script>
  475. <style lang='scss'>
  476. </style>