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.

300 lines
11 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-globe-earth.svg', alt='Locale', style='width: 80px;')
  7. .admin-header-title
  8. .headline.primary--text.animated.fadeInLeft {{ $t('admin:locale.title') }}
  9. .subtitle-1.grey--text.animated.fadeInLeft.wait-p4s {{ $t('admin:locale.subtitle') }}
  10. v-spacer
  11. v-btn.animated.fadeInDown(color='success', depressed, @click='save', large, :loading='loading')
  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-card.wiki-form.animated.fadeInUp
  18. v-toolbar(color='primary', dark, dense, flat)
  19. v-toolbar-title.subtitle-1 {{ $t('admin:locale.settings') }}
  20. v-card-text
  21. v-select(
  22. outlined
  23. :items='installedLocales'
  24. prepend-icon='mdi-web'
  25. v-model='selectedLocale'
  26. item-value='code'
  27. item-text='nativeName'
  28. :label='namespacing ? $t("admin:locale.base.labelWithNS") : $t("admin:locale.base.label")'
  29. persistent-hint
  30. :hint='$t("admin:locale.base.hint")'
  31. )
  32. template(slot='item', slot-scope='data')
  33. template(v-if='typeof data.item !== "object"')
  34. v-list-item-content(v-text='data.item')
  35. template(v-else)
  36. v-list-item-avatar
  37. v-avatar.blue.white--text(tile, size='40', v-html='data.item.code.toUpperCase()')
  38. v-list-item-content
  39. v-list-item-title(v-html='data.item.name')
  40. v-list-item-subtitle(v-html='data.item.nativeName')
  41. v-divider.mt-3
  42. v-switch(
  43. inset
  44. v-model='autoUpdate'
  45. :label='$t("admin:locale.autoUpdate.label")'
  46. color='primary'
  47. persistent-hint
  48. :hint='namespacing ? $t("admin:locale.autoUpdate.hintWithNS") : $t("admin:locale.autoUpdate.hint")'
  49. )
  50. v-card.wiki-form.mt-3.animated.fadeInUp.wait-p2s
  51. v-toolbar(color='primary', dark, dense, flat)
  52. v-toolbar-title.subtitle-1 {{ $t('admin:locale.namespacing') }}
  53. v-card-text
  54. v-switch(
  55. inset
  56. v-model='namespacing'
  57. :label='$t("admin:locale.namespaces.label")'
  58. color='primary'
  59. persistent-hint
  60. :hint='$t("admin:locale.namespaces.hint")'
  61. )
  62. v-alert.mt-3(
  63. outlined
  64. color='orange'
  65. :value='true'
  66. icon='mdi-alert'
  67. )
  68. span {{ $t('admin:locale.namespacingPrefixWarning.title', { langCode: selectedLocale }) }}
  69. .caption.grey--text {{ $t('admin:locale.namespacingPrefixWarning.subtitle') }}
  70. v-divider.mt-3.mb-4
  71. v-select(
  72. outlined
  73. :disabled='!namespacing'
  74. :items='installedLocales'
  75. prepend-icon='mdi-web'
  76. multiple
  77. chips
  78. deletable-chips
  79. v-model='namespaces'
  80. item-value='code'
  81. item-text='name'
  82. :label='$t("admin:locale.activeNamespaces.label")'
  83. persistent-hint
  84. small-chips
  85. :hint='$t("admin:locale.activeNamespaces.hint")'
  86. )
  87. template(slot='item', slot-scope='data')
  88. template(v-if='typeof data.item !== "object"')
  89. v-list-item-content(v-text='data.item')
  90. template(v-else)
  91. v-list-item-avatar
  92. v-avatar.blue.white--text(tile, size='40', v-html='data.item.code.toUpperCase()')
  93. v-list-item-content
  94. v-list-item-title(v-html='data.item.name')
  95. v-list-item-subtitle(v-html='data.item.nativeName')
  96. v-list-item-action
  97. v-checkbox(:input-value='data.attrs.inputValue', color='primary', value)
  98. v-flex(lg6 xs12)
  99. v-card.animated.fadeInUp.wait-p4s
  100. v-toolbar(color='teal', dark, dense, flat)
  101. v-toolbar-title.subtitle-1 {{ $t('admin:locale.downloadTitle') }}
  102. v-data-table(
  103. :headers='headers',
  104. :items='locales',
  105. hide-default-footer,
  106. item-key='code',
  107. :items-per-page='1000'
  108. )
  109. template(v-slot:item.code='{ item }')
  110. v-chip.white--text(label, color='teal', small) {{item.code}}
  111. template(v-slot:item.name='{ item }')
  112. strong {{item.name}}
  113. template(v-slot:item.isRTL='{ item }')
  114. v-icon(v-if='item.isRTL') mdi-check
  115. template(v-slot:item.availability='{ item }')
  116. .d-flex.align-center.pl-4
  117. v-progress-circular(:value='item.availability', width='2', size='20', :color='item.availability <= 33 ? `red` : (item.availability <= 66) ? `orange` : `green`')
  118. .caption.mx-2(:class='item.availability <= 33 ? `red--text` : (item.availability <= 66) ? `orange--text` : `green--text`') {{item.availability}}%
  119. template(v-slot:item.isInstalled='{ item }')
  120. v-progress-circular(v-if='item.isDownloading', indeterminate, color='blue', size='20', :width='2')
  121. v-btn(v-else-if='item.isInstalled && item.installDate < item.updatedAt', icon, small, @click='download(item)')
  122. v-icon.blue--text mdi-cached
  123. v-btn(v-else-if='item.isInstalled', icon, small, @click='download(item)')
  124. v-icon.green--text mdi-check-bold
  125. v-btn(v-else, icon, small, @click='download(item)')
  126. v-icon.grey--text mdi-cloud-download
  127. v-card.wiki-form.mt-3.animated.fadeInUp.wait-p5s
  128. v-toolbar(color='teal', dark, dense, flat)
  129. v-toolbar-title.subtitle-1 {{ $t('admin:locale.sideload') }}
  130. v-spacer
  131. v-chip(label, color='white', small).teal--text coming soon
  132. v-card-text
  133. div {{ $t('admin:locale.sideloadHelp') }}
  134. v-btn.ml-0.mt-3(color='teal', disabled) {{ $t('common:actions.browse') }}
  135. </template>
  136. <script>
  137. import _ from 'lodash'
  138. /* global WIKI */
  139. import localesQuery from 'gql/admin/locale/locale-query-list.gql'
  140. import localesDownloadMutation from 'gql/admin/locale/locale-mutation-download.gql'
  141. import localesSaveMutation from 'gql/admin/locale/locale-mutation-save.gql'
  142. export default {
  143. data() {
  144. return {
  145. loading: false,
  146. locales: [],
  147. selectedLocale: 'en',
  148. autoUpdate: false,
  149. namespacing: false,
  150. namespaces: []
  151. }
  152. },
  153. computed: {
  154. installedLocales() {
  155. return _.filter(this.locales, ['isInstalled', true])
  156. },
  157. headers() {
  158. return [
  159. {
  160. text: this.$t('admin:locale.code'),
  161. align: 'left',
  162. value: 'code',
  163. width: 90
  164. },
  165. {
  166. text: this.$t('admin:locale.name'),
  167. align: 'left',
  168. value: 'name'
  169. },
  170. {
  171. text: this.$t('admin:locale.nativeName'),
  172. align: 'left',
  173. value: 'nativeName'
  174. },
  175. {
  176. text: this.$t('admin:locale.rtl'),
  177. align: 'center',
  178. value: 'isRTL',
  179. sortable: false,
  180. width: 10
  181. },
  182. {
  183. text: this.$t('admin:locale.availability'),
  184. align: 'center',
  185. value: 'availability',
  186. sortable: false,
  187. width: 120
  188. },
  189. {
  190. text: this.$t('admin:locale.download'),
  191. align: 'center',
  192. value: 'isInstalled',
  193. sortable: false,
  194. width: 100
  195. }
  196. ]
  197. }
  198. },
  199. methods: {
  200. async download(lc) {
  201. lc.isDownloading = true
  202. const respRaw = await this.$apollo.mutate({
  203. mutation: localesDownloadMutation,
  204. variables: {
  205. locale: lc.code
  206. }
  207. })
  208. const resp = _.get(respRaw, 'data.localization.downloadLocale.responseResult', {})
  209. if (resp.succeeded) {
  210. lc.isDownloading = false
  211. lc.isInstalled = true
  212. lc.updatedAt = new Date().toISOString()
  213. lc.installDate = lc.updatedAt
  214. this.$store.commit('showNotification', {
  215. message: `Locale ${lc.name} has been installed successfully.`,
  216. style: 'success',
  217. icon: 'get_app'
  218. })
  219. } else {
  220. this.$store.commit('showNotification', {
  221. message: `Error: ${resp.message}`,
  222. style: 'error',
  223. icon: 'warning'
  224. })
  225. }
  226. this.isDownloading = false
  227. },
  228. async save() {
  229. this.loading = true
  230. const respRaw = await this.$apollo.mutate({
  231. mutation: localesSaveMutation,
  232. variables: {
  233. locale: this.selectedLocale,
  234. autoUpdate: this.autoUpdate,
  235. namespacing: this.namespacing,
  236. namespaces: this.namespaces
  237. }
  238. })
  239. const resp = _.get(respRaw, 'data.localization.updateLocale.responseResult', {})
  240. if (resp.succeeded) {
  241. // Change UI language
  242. WIKI.$i18n.i18next.changeLanguage(this.selectedLocale)
  243. WIKI.$moment.locale(this.selectedLocale)
  244. // Check for RTL
  245. const curLocale = _.find(this.locales, ['code', this.selectedLocale])
  246. this.$vuetify.rtl = curLocale && curLocale.isRTL
  247. this.$store.commit('showNotification', {
  248. message: 'Locale settings updated successfully.',
  249. style: 'success',
  250. icon: 'check'
  251. })
  252. _.delay(() => {
  253. window.location.reload(true)
  254. }, 1000)
  255. } else {
  256. this.$store.commit('showNotification', {
  257. message: `Error: ${resp.message}`,
  258. style: 'error',
  259. icon: 'warning'
  260. })
  261. }
  262. this.loading = false
  263. }
  264. },
  265. apollo: {
  266. locales: {
  267. query: localesQuery,
  268. fetchPolicy: 'network-only',
  269. update: (data) => data.localization.locales.map(lc => ({ ...lc, isDownloading: false })),
  270. watchLoading (isLoading) {
  271. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-locale-refresh')
  272. }
  273. },
  274. selectedLocale: {
  275. query: localesQuery,
  276. update: (data) => data.localization.config.locale
  277. },
  278. autoUpdate: {
  279. query: localesQuery,
  280. update: (data) => data.localization.config.autoUpdate
  281. },
  282. namespacing: {
  283. query: localesQuery,
  284. update: (data) => data.localization.config.namespacing
  285. },
  286. namespaces: {
  287. query: localesQuery,
  288. update: (data) => data.localization.config.namespaces
  289. }
  290. }
  291. }
  292. </script>