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