2
0

admin-general.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  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-text-field.mt-3(
  87. outlined
  88. :label='$t(`admin:general.footerOverride`)'
  89. v-model='config.footerOverride'
  90. prepend-icon='mdi-page-layout-footer'
  91. persistent-hint
  92. :hint='$t(`admin:general.footerOverrideHint`)'
  93. )
  94. v-divider
  95. .overline.grey--text.pa-4 SEO
  96. .px-3.pb-3
  97. v-text-field(
  98. outlined
  99. :label='$t(`admin:general.siteDescription`)'
  100. :counter='255'
  101. v-model='config.description'
  102. prepend-icon='mdi-compass'
  103. :hint='$t(`admin:general.siteDescriptionHint`)'
  104. persistent-hint
  105. )
  106. v-select.mt-3(
  107. outlined
  108. :label='$t(`admin:general.metaRobots`)'
  109. multiple
  110. :items='metaRobots'
  111. v-model='config.robots'
  112. prepend-icon='mdi-compass'
  113. :return-object='false'
  114. :hint='$t(`admin:general.metaRobotsHint`)'
  115. persistent-hint
  116. )
  117. v-flex(lg6 xs12)
  118. v-card.animated.fadeInUp.wait-p4s
  119. v-toolbar(color='indigo', dark, dense, flat)
  120. v-toolbar-title.subtitle-1 Features
  121. v-card-text
  122. //- v-switch(
  123. //- inset
  124. //- label='Asset Image Optimization'
  125. //- color='indigo'
  126. //- v-model='config.featureTinyPNG'
  127. //- persistent-hint
  128. //- hint='Image optimization tool to reduce filesize and bandwidth costs.'
  129. //- disabled
  130. //- )
  131. //- v-text-field.mt-3(
  132. //- outlined
  133. //- label='TinyPNG API Key'
  134. //- :counter='255'
  135. //- v-model='config.description'
  136. //- prepend-icon='mdi-subdirectory-arrow-right'
  137. //- hint='Get your API key at https://tinypng.com/developers'
  138. //- persistent-hint
  139. //- disabled
  140. //- )
  141. //- v-divider.mt-3
  142. //- v-switch(
  143. //- inset
  144. //- label='Page Ratings'
  145. //- color='indigo'
  146. //- v-model='config.featurePageRatings'
  147. //- persistent-hint
  148. //- hint='Allow users to rate pages.'
  149. //- disabled
  150. //- )
  151. //- v-divider.mt-3
  152. v-switch.mt-0(
  153. inset
  154. label='Comments'
  155. color='indigo'
  156. v-model='config.featurePageComments'
  157. persistent-hint
  158. hint='Allow users to leave comments on pages.'
  159. )
  160. //- v-divider.mt-3
  161. //- v-switch(
  162. //- inset
  163. //- label='Personal Wikis'
  164. //- color='indigo'
  165. //- v-model='config.featurePersonalWikis'
  166. //- persistent-hint
  167. //- hint='Allow users to have their own personal wiki.'
  168. //- disabled
  169. //- )
  170. v-card.mt-5.animated.fadeInUp.wait-p6s
  171. v-toolbar(color='primary', dark, dense, flat)
  172. v-toolbar-title.subtitle-1 URL Handling
  173. v-card-text
  174. v-text-field(
  175. outlined
  176. :label='$t(`admin:general.pageExtensions`)'
  177. v-model='config.pageExtensions'
  178. prepend-icon='mdi-format-text-wrapping-overflow'
  179. :hint='$t(`admin:general.pageExtensionsHint`)'
  180. persistent-hint
  181. )
  182. v-card.mt-5.animated.fadeInUp.wait-p7s
  183. v-toolbar(color='primary', dark, dense, flat)
  184. v-toolbar-title.subtitle-1 {{$t('admin:general.editShortcuts')}}
  185. v-card-text
  186. v-switch.mt-0(
  187. inset
  188. :label='$t(`admin:general.editFab`)'
  189. color='primary'
  190. v-model='config.editFab'
  191. persistent-hint
  192. :hint='$t(`admin:general.editFabHint`)'
  193. )
  194. v-divider
  195. .overline.grey--text.pa-4 {{$t('admin:general.editMenuBar')}}
  196. .px-3.pb-3
  197. v-switch.mt-0.ml-1(
  198. inset
  199. :label='$t(`admin:general.displayEditMenuBar`)'
  200. color='primary'
  201. v-model='config.editMenuBar'
  202. persistent-hint
  203. :hint='$t(`admin:general.displayEditMenuBarHint`)'
  204. )
  205. v-switch.mt-4.ml-1(
  206. v-if='config.editMenuBar'
  207. inset
  208. :label='$t(`admin:general.displayEditMenuBtn`)'
  209. color='primary'
  210. v-model='config.editMenuBtn'
  211. persistent-hint
  212. :hint='$t(`admin:general.displayEditMenuBtnHint`)'
  213. )
  214. v-switch.mt-4.ml-1(
  215. v-if='config.editMenuBar'
  216. inset
  217. :label='$t(`admin:general.displayEditMenuExternalBtn`)'
  218. color='primary'
  219. v-model='config.editMenuExternalBtn'
  220. persistent-hint
  221. :hint='$t(`admin:general.displayEditMenuExternalBtnHint`)'
  222. )
  223. template(v-if='config.editMenuBar && config.editMenuExternalBtn')
  224. v-divider
  225. .overline.grey--text.pa-4 External Edit Button
  226. .px-3.pb-3
  227. v-text-field(
  228. outlined
  229. :label='$t(`admin:general.editMenuExternalName`)'
  230. v-model='config.editMenuExternalName'
  231. prepend-icon='mdi-format-title'
  232. :hint='$t(`admin:general.editMenuExternalNameHint`)'
  233. persistent-hint
  234. )
  235. v-text-field.mt-3(
  236. outlined
  237. :label='$t(`admin:general.editMenuExternalIcon`)'
  238. v-model='config.editMenuExternalIcon'
  239. prepend-icon='mdi-dice-5'
  240. :hint='$t(`admin:general.editMenuExternalIconHint`)'
  241. persistent-hint
  242. )
  243. v-text-field.mt-3(
  244. outlined
  245. :label='$t(`admin:general.editMenuExternalUrl`)'
  246. v-model='config.editMenuExternalUrl'
  247. prepend-icon='mdi-near-me'
  248. :hint='$t(`admin:general.editMenuExternalUrlHint`)'
  249. persistent-hint
  250. )
  251. component(:is='activeModal')
  252. </template>
  253. <script>
  254. import _ from 'lodash'
  255. import { sync } from 'vuex-pathify'
  256. import gql from 'graphql-tag'
  257. import editorStore from '../../store/editor'
  258. /* global WIKI */
  259. const titleRegex = /[<>"]/i
  260. WIKI.$store.registerModule('editor', editorStore)
  261. export default {
  262. i18nOptions: { namespaces: 'editor' },
  263. components: {
  264. editorModalMedia: () => import(/* webpackChunkName: "editor", webpackMode: "lazy" */ '../editor/editor-modal-media.vue')
  265. },
  266. data() {
  267. return {
  268. config: {
  269. host: '',
  270. title: '',
  271. description: '',
  272. robots: [],
  273. analyticsService: '',
  274. analyticsId: '',
  275. company: '',
  276. contentLicense: '',
  277. footerOverride: '',
  278. logoUrl: '',
  279. featureAnalytics: false,
  280. featurePageRatings: false,
  281. featurePageComments: false,
  282. featurePersonalWikis: false,
  283. featureTinyPNG: false,
  284. pageExtensions: '',
  285. editFab: false,
  286. editMenuBar: false,
  287. editMenuBtn: false,
  288. editMenuExternalBtn: false,
  289. editMenuExternalName: '',
  290. editMenuExternalIcon: '',
  291. editMenuExternalUrl: ''
  292. },
  293. metaRobots: [
  294. { text: 'Index', value: 'index' },
  295. { text: 'Follow', value: 'follow' },
  296. { text: 'No Index', value: 'noindex' },
  297. { text: 'No Follow', value: 'nofollow' }
  298. ]
  299. }
  300. },
  301. computed: {
  302. siteTitle: sync('site/title'),
  303. logoUrl: sync('site/logoUrl'),
  304. company: sync('site/company'),
  305. contentLicense: sync('site/contentLicense'),
  306. footerOverride: sync('site/footerOverride'),
  307. activeModal: sync('editor/activeModal'),
  308. contentLicenses () {
  309. return [
  310. { value: '', text: this.$t('common:license.none') },
  311. { value: 'alr', text: this.$t('common:license.alr') },
  312. { value: 'cc0', text: this.$t('common:license.cc0') },
  313. { value: 'ccby', text: this.$t('common:license.ccby') },
  314. { value: 'ccbysa', text: this.$t('common:license.ccbysa') },
  315. { value: 'ccbynd', text: this.$t('common:license.ccbynd') },
  316. { value: 'ccbync', text: this.$t('common:license.ccbync') },
  317. { value: 'ccbyncsa', text: this.$t('common:license.ccbyncsa') },
  318. { value: 'ccbyncnd', text: this.$t('common:license.ccbyncnd') }
  319. ]
  320. }
  321. },
  322. methods: {
  323. async save () {
  324. const title = _.get(this.config, 'title', '')
  325. if (titleRegex.test(title)) {
  326. this.$store.commit('showNotification', {
  327. style: 'error',
  328. message: this.$t('admin:general.siteTitleInvalidChars'),
  329. icon: 'alert'
  330. })
  331. return
  332. }
  333. try {
  334. await this.$apollo.mutate({
  335. mutation: gql`
  336. mutation (
  337. $host: String
  338. $title: String
  339. $description: String
  340. $robots: [String]
  341. $analyticsService: String
  342. $analyticsId: String
  343. $company: String
  344. $contentLicense: String
  345. $footerOverride: String
  346. $logoUrl: String
  347. $pageExtensions: String
  348. $featurePageRatings: Boolean
  349. $featurePageComments: Boolean
  350. $featurePersonalWikis: Boolean
  351. $editFab: Boolean
  352. $editMenuBar: Boolean
  353. $editMenuBtn: Boolean
  354. $editMenuExternalBtn: Boolean
  355. $editMenuExternalName: String
  356. $editMenuExternalIcon: String
  357. $editMenuExternalUrl: String
  358. ) {
  359. site {
  360. updateConfig(
  361. host: $host
  362. title: $title
  363. description: $description
  364. robots: $robots
  365. analyticsService: $analyticsService
  366. analyticsId: $analyticsId
  367. company: $company
  368. contentLicense: $contentLicense
  369. footerOverride: $footerOverride
  370. logoUrl: $logoUrl
  371. pageExtensions: $pageExtensions
  372. featurePageRatings: $featurePageRatings
  373. featurePageComments: $featurePageComments
  374. featurePersonalWikis: $featurePersonalWikis
  375. editFab: $editFab
  376. editMenuBar: $editMenuBar
  377. editMenuBtn: $editMenuBtn
  378. editMenuExternalBtn: $editMenuExternalBtn
  379. editMenuExternalName: $editMenuExternalName
  380. editMenuExternalIcon: $editMenuExternalIcon
  381. editMenuExternalUrl: $editMenuExternalUrl
  382. ) {
  383. responseResult {
  384. succeeded
  385. errorCode
  386. slug
  387. message
  388. }
  389. }
  390. }
  391. }
  392. `,
  393. variables: {
  394. host: _.get(this.config, 'host', ''),
  395. title: _.get(this.config, 'title', ''),
  396. description: _.get(this.config, 'description', ''),
  397. robots: _.get(this.config, 'robots', []),
  398. analyticsService: _.get(this.config, 'analyticsService', ''),
  399. analyticsId: _.get(this.config, 'analyticsId', ''),
  400. company: _.get(this.config, 'company', ''),
  401. contentLicense: _.get(this.config, 'contentLicense', ''),
  402. footerOverride: _.get(this.config, 'footerOverride', ''),
  403. logoUrl: _.get(this.config, 'logoUrl', ''),
  404. pageExtensions: _.get(this.config, 'pageExtensions', ''),
  405. featurePageRatings: _.get(this.config, 'featurePageRatings', false),
  406. featurePageComments: _.get(this.config, 'featurePageComments', false),
  407. featurePersonalWikis: _.get(this.config, 'featurePersonalWikis', false),
  408. editFab: _.get(this.config, 'editFab', false),
  409. editMenuBar: _.get(this.config, 'editMenuBar', false),
  410. editMenuBtn: _.get(this.config, 'editMenuBtn', false),
  411. editMenuExternalBtn: _.get(this.config, 'editMenuExternalBtn', false),
  412. editMenuExternalName: _.get(this.config, 'editMenuExternalName', ''),
  413. editMenuExternalIcon: _.get(this.config, 'editMenuExternalIcon', ''),
  414. editMenuExternalUrl: _.get(this.config, 'editMenuExternalUrl', '')
  415. },
  416. watchLoading (isLoading) {
  417. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-update')
  418. }
  419. })
  420. this.$store.commit('showNotification', {
  421. style: 'success',
  422. message: this.$t('admin:general.saveSuccess'),
  423. icon: 'check'
  424. })
  425. this.siteTitle = this.config.title
  426. this.company = this.config.company
  427. this.contentLicense = this.config.contentLicense
  428. this.footerOverride = this.config.footerOverride
  429. this.logoUrl = this.config.logoUrl
  430. } catch (err) {
  431. this.$store.commit('pushGraphError', err)
  432. }
  433. },
  434. browseLogo () {
  435. this.$store.set('editor/editorKey', 'common')
  436. this.activeModal = 'editorModalMedia'
  437. },
  438. refreshLogo () {
  439. this.$forceUpdate()
  440. }
  441. },
  442. mounted () {
  443. this.$root.$on('editorInsert', opts => {
  444. this.config.logoUrl = opts.path
  445. })
  446. },
  447. beforeDestroy() {
  448. this.$root.$off('editorInsert')
  449. },
  450. apollo: {
  451. config: {
  452. query: gql`
  453. {
  454. site {
  455. config {
  456. host
  457. title
  458. description
  459. robots
  460. analyticsService
  461. analyticsId
  462. company
  463. contentLicense
  464. footerOverride
  465. logoUrl
  466. pageExtensions
  467. featurePageRatings
  468. featurePageComments
  469. featurePersonalWikis
  470. editFab
  471. editMenuBar
  472. editMenuBtn
  473. editMenuExternalBtn
  474. editMenuExternalName
  475. editMenuExternalIcon
  476. editMenuExternalUrl
  477. }
  478. }
  479. }
  480. `,
  481. fetchPolicy: 'network-only',
  482. update: (data) => _.cloneDeep(data.site.config),
  483. watchLoading (isLoading) {
  484. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-refresh')
  485. }
  486. }
  487. }
  488. }
  489. </script>
  490. <style lang='scss'>
  491. </style>