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.

369 lines
13 KiB

  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(
  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. component(:is='activeModal')
  163. </template>
  164. <script>
  165. import _ from 'lodash'
  166. import { sync } from 'vuex-pathify'
  167. import gql from 'graphql-tag'
  168. import editorStore from '../../store/editor'
  169. /* global WIKI */
  170. const titleRegex = /[<>"]/i
  171. WIKI.$store.registerModule('editor', editorStore)
  172. export default {
  173. i18nOptions: { namespaces: 'editor' },
  174. components: {
  175. editorModalMedia: () => import(/* webpackChunkName: "editor", webpackMode: "lazy" */ '../editor/editor-modal-media.vue')
  176. },
  177. data() {
  178. return {
  179. config: {
  180. host: '',
  181. title: '',
  182. description: '',
  183. robots: [],
  184. analyticsService: '',
  185. analyticsId: '',
  186. company: '',
  187. contentLicense: '',
  188. logoUrl: '',
  189. featureAnalytics: false,
  190. featurePageRatings: false,
  191. featurePageComments: false,
  192. featurePersonalWikis: false,
  193. featureTinyPNG: false
  194. },
  195. metaRobots: [
  196. { text: 'Index', value: 'index' },
  197. { text: 'Follow', value: 'follow' },
  198. { text: 'No Index', value: 'noindex' },
  199. { text: 'No Follow', value: 'nofollow' }
  200. ]
  201. }
  202. },
  203. computed: {
  204. siteTitle: sync('site/title'),
  205. logoUrl: sync('site/logoUrl'),
  206. company: sync('site/company'),
  207. contentLicense: sync('site/contentLicense'),
  208. activeModal: sync('editor/activeModal'),
  209. contentLicenses () {
  210. return [
  211. { value: '', text: this.$t('common:license.none') },
  212. { value: 'alr', text: this.$t('common:license.alr') },
  213. { value: 'cc0', text: this.$t('common:license.cc0') },
  214. { value: 'ccby', text: this.$t('common:license.ccby') },
  215. { value: 'ccbysa', text: this.$t('common:license.ccbysa') },
  216. { value: 'ccbynd', text: this.$t('common:license.ccbynd') },
  217. { value: 'ccbync', text: this.$t('common:license.ccbync') },
  218. { value: 'ccbyncsa', text: this.$t('common:license.ccbyncsa') },
  219. { value: 'ccbyncnd', text: this.$t('common:license.ccbyncnd') }
  220. ]
  221. }
  222. },
  223. methods: {
  224. async save () {
  225. const title = _.get(this.config, 'title', '')
  226. if (titleRegex.test(title)) {
  227. this.$store.commit('showNotification', {
  228. style: 'error',
  229. message: this.$t('admin:general.siteTitleInvalidChars'),
  230. icon: 'alert'
  231. })
  232. return
  233. }
  234. try {
  235. await this.$apollo.mutate({
  236. mutation: gql`
  237. mutation (
  238. $host: String!
  239. $title: String!
  240. $description: String!
  241. $robots: [String]!
  242. $analyticsService: String!
  243. $analyticsId: String!
  244. $company: String!
  245. $contentLicense: String!
  246. $logoUrl: String!
  247. $featurePageRatings: Boolean!
  248. $featurePageComments: Boolean!
  249. $featurePersonalWikis: Boolean!
  250. ) {
  251. site {
  252. updateConfig(
  253. host: $host,
  254. title: $title,
  255. description: $description,
  256. robots: $robots,
  257. analyticsService: $analyticsService,
  258. analyticsId: $analyticsId,
  259. company: $company,
  260. contentLicense: $contentLicense,
  261. logoUrl: $logoUrl,
  262. featurePageRatings: $featurePageRatings,
  263. featurePageComments: $featurePageComments,
  264. featurePersonalWikis: $featurePersonalWikis
  265. ) {
  266. responseResult {
  267. succeeded
  268. errorCode
  269. slug
  270. message
  271. }
  272. }
  273. }
  274. }
  275. `,
  276. variables: {
  277. host: _.get(this.config, 'host', ''),
  278. title: _.get(this.config, 'title', ''),
  279. description: _.get(this.config, 'description', ''),
  280. robots: _.get(this.config, 'robots', []),
  281. analyticsService: _.get(this.config, 'analyticsService', ''),
  282. analyticsId: _.get(this.config, 'analyticsId', ''),
  283. company: _.get(this.config, 'company', ''),
  284. contentLicense: _.get(this.config, 'contentLicense', ''),
  285. logoUrl: _.get(this.config, 'logoUrl', ''),
  286. featurePageRatings: _.get(this.config, 'featurePageRatings', false),
  287. featurePageComments: _.get(this.config, 'featurePageComments', false),
  288. featurePersonalWikis: _.get(this.config, 'featurePersonalWikis', false)
  289. },
  290. watchLoading (isLoading) {
  291. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-update')
  292. }
  293. })
  294. this.$store.commit('showNotification', {
  295. style: 'success',
  296. message: this.$t('admin:general.saveSuccess'),
  297. icon: 'check'
  298. })
  299. this.siteTitle = this.config.title
  300. this.company = this.config.company
  301. this.contentLicense = this.config.contentLicense
  302. this.logoUrl = this.config.logoUrl
  303. } catch (err) {
  304. this.$store.commit('pushGraphError', err)
  305. }
  306. },
  307. browseLogo () {
  308. this.$store.set('editor/editorKey', 'common')
  309. this.activeModal = 'editorModalMedia'
  310. },
  311. refreshLogo () {
  312. this.$forceUpdate()
  313. }
  314. },
  315. mounted () {
  316. this.$root.$on('editorInsert', opts => {
  317. this.config.logoUrl = opts.path
  318. })
  319. },
  320. beforeDestroy() {
  321. this.$root.$off('editorInsert')
  322. },
  323. apollo: {
  324. config: {
  325. query: gql`
  326. {
  327. site {
  328. config {
  329. host
  330. title
  331. description
  332. robots
  333. analyticsService
  334. analyticsId
  335. company
  336. contentLicense
  337. logoUrl
  338. featurePageRatings
  339. featurePageComments
  340. featurePersonalWikis
  341. }
  342. }
  343. }
  344. `,
  345. fetchPolicy: 'network-only',
  346. update: (data) => _.cloneDeep(data.site.config),
  347. watchLoading (isLoading) {
  348. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-refresh')
  349. }
  350. }
  351. }
  352. }
  353. </script>
  354. <style lang='scss'>
  355. </style>