admin-general.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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='/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-spacer
  114. v-chip(label, color='white', small).indigo--text coming soon
  115. v-card-text
  116. v-switch(
  117. inset
  118. label='Asset Image Optimization'
  119. color='indigo'
  120. v-model='config.featureTinyPNG'
  121. persistent-hint
  122. hint='Image optimization tool to reduce filesize and bandwidth costs.'
  123. disabled
  124. )
  125. v-text-field.mt-3(
  126. outlined
  127. label='TinyPNG API Key'
  128. :counter='255'
  129. v-model='config.description'
  130. prepend-icon='mdi-subdirectory-arrow-right'
  131. hint='Get your API key at https://tinypng.com/developers'
  132. persistent-hint
  133. disabled
  134. )
  135. v-divider.mt-3
  136. v-switch(
  137. inset
  138. label='Page Ratings'
  139. color='indigo'
  140. v-model='config.featurePageRatings'
  141. persistent-hint
  142. hint='Allow users to rate pages.'
  143. disabled
  144. )
  145. v-divider.mt-3
  146. v-switch(
  147. inset
  148. label='Page Comments'
  149. color='indigo'
  150. v-model='config.featurePageComments'
  151. persistent-hint
  152. hint='Allow users to leave comments on pages.'
  153. disabled
  154. )
  155. v-divider.mt-3
  156. v-switch(
  157. inset
  158. label='Personal Wikis'
  159. color='indigo'
  160. v-model='config.featurePersonalWikis'
  161. persistent-hint
  162. hint='Allow users to have their own personal wiki.'
  163. disabled
  164. )
  165. component(:is='activeModal')
  166. </template>
  167. <script>
  168. import _ from 'lodash'
  169. import { sync } from 'vuex-pathify'
  170. import gql from 'graphql-tag'
  171. import editorStore from '../../store/editor'
  172. /* global WIKI */
  173. WIKI.$store.registerModule('editor', editorStore)
  174. export default {
  175. i18nOptions: { namespaces: 'editor' },
  176. components: {
  177. editorModalMedia: () => import(/* webpackChunkName: "editor", webpackMode: "lazy" */ '../editor/editor-modal-media.vue')
  178. },
  179. data() {
  180. return {
  181. analyticsServices: [
  182. { text: 'None', value: '' },
  183. { text: 'Elasticsearch APM RUM', value: 'elk' },
  184. { text: 'Google Analytics', value: 'ga' },
  185. { text: 'Google Tag Manager', value: 'gtm' }
  186. ],
  187. config: {
  188. host: '',
  189. title: '',
  190. description: '',
  191. robots: [],
  192. analyticsService: '',
  193. analyticsId: '',
  194. company: '',
  195. contentLicense: '',
  196. logoUrl: '',
  197. featureAnalytics: false,
  198. featurePageRatings: false,
  199. featurePageComments: false,
  200. featurePersonalWikis: false,
  201. featureTinyPNG: false
  202. },
  203. metaRobots: [
  204. { text: 'Index', value: 'index' },
  205. { text: 'Follow', value: 'follow' },
  206. { text: 'No Index', value: 'noindex' },
  207. { text: 'No Follow', value: 'nofollow' }
  208. ]
  209. }
  210. },
  211. computed: {
  212. siteTitle: sync('site/title'),
  213. logoUrl: sync('site/logoUrl'),
  214. company: sync('site/company'),
  215. contentLicense: sync('site/contentLicense'),
  216. activeModal: sync('editor/activeModal'),
  217. contentLicenses () {
  218. return [
  219. { value: '', text: this.$t('common:license.none') },
  220. { value: 'alr', text: this.$t('common:license.alr') },
  221. { value: 'cc0', text: this.$t('common:license.cc0') },
  222. { value: 'ccby', text: this.$t('common:license.ccby') },
  223. { value: 'ccbysa', text: this.$t('common:license.ccbysa') },
  224. { value: 'ccbynd', text: this.$t('common:license.ccbynd') },
  225. { value: 'ccbync', text: this.$t('common:license.ccbync') },
  226. { value: 'ccbyncsa', text: this.$t('common:license.ccbyncsa') },
  227. { value: 'ccbyncnd', text: this.$t('common:license.ccbyncnd') }
  228. ]
  229. }
  230. },
  231. methods: {
  232. async save () {
  233. try {
  234. await this.$apollo.mutate({
  235. mutation: gql`
  236. mutation (
  237. $host: String!
  238. $title: String!
  239. $description: String!
  240. $robots: [String]!
  241. $analyticsService: String!
  242. $analyticsId: String!
  243. $company: String!
  244. $contentLicense: String!
  245. $logoUrl: String!
  246. $featurePageRatings: Boolean!
  247. $featurePageComments: Boolean!
  248. $featurePersonalWikis: Boolean!
  249. ) {
  250. site {
  251. updateConfig(
  252. host: $host,
  253. title: $title,
  254. description: $description,
  255. robots: $robots,
  256. analyticsService: $analyticsService,
  257. analyticsId: $analyticsId,
  258. company: $company,
  259. contentLicense: $contentLicense,
  260. logoUrl: $logoUrl,
  261. featurePageRatings: $featurePageRatings,
  262. featurePageComments: $featurePageComments,
  263. featurePersonalWikis: $featurePersonalWikis
  264. ) {
  265. responseResult {
  266. succeeded
  267. errorCode
  268. slug
  269. message
  270. }
  271. }
  272. }
  273. }
  274. `,
  275. variables: {
  276. host: _.get(this.config, 'host', ''),
  277. title: _.get(this.config, 'title', ''),
  278. description: _.get(this.config, 'description', ''),
  279. robots: _.get(this.config, 'robots', []),
  280. analyticsService: _.get(this.config, 'analyticsService', ''),
  281. analyticsId: _.get(this.config, 'analyticsId', ''),
  282. company: _.get(this.config, 'company', ''),
  283. contentLicense: _.get(this.config, 'contentLicense', ''),
  284. logoUrl: _.get(this.config, 'logoUrl', ''),
  285. featurePageRatings: _.get(this.config, 'featurePageRatings', false),
  286. featurePageComments: _.get(this.config, 'featurePageComments', false),
  287. featurePersonalWikis: _.get(this.config, 'featurePersonalWikis', false)
  288. },
  289. watchLoading (isLoading) {
  290. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-update')
  291. }
  292. })
  293. this.$store.commit('showNotification', {
  294. style: 'success',
  295. message: 'Configuration saved successfully.',
  296. icon: 'check'
  297. })
  298. this.siteTitle = this.config.title
  299. this.company = this.config.company
  300. this.contentLicense = this.config.contentLicense
  301. this.logoUrl = this.config.logoUrl
  302. } catch (err) {
  303. this.$store.commit('pushGraphError', err)
  304. }
  305. },
  306. browseLogo () {
  307. this.$store.set('editor/editorKey', 'common')
  308. this.activeModal = 'editorModalMedia'
  309. },
  310. refreshLogo () {
  311. this.$forceUpdate()
  312. }
  313. },
  314. mounted () {
  315. this.$root.$on('editorInsert', opts => {
  316. this.config.logoUrl = opts.path
  317. })
  318. },
  319. beforeDestroy() {
  320. this.$root.$off('editorInsert')
  321. },
  322. apollo: {
  323. config: {
  324. query: gql`
  325. {
  326. site {
  327. config {
  328. host
  329. title
  330. description
  331. robots
  332. analyticsService
  333. analyticsId
  334. company
  335. contentLicense
  336. logoUrl
  337. featurePageRatings
  338. featurePageComments
  339. featurePersonalWikis
  340. }
  341. }
  342. }
  343. `,
  344. fetchPolicy: 'network-only',
  345. update: (data) => _.cloneDeep(data.site.config),
  346. watchLoading (isLoading) {
  347. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-refresh')
  348. }
  349. }
  350. }
  351. }
  352. </script>
  353. <style lang='scss'>
  354. </style>