admin-storage.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <template lang='pug'>
  2. v-card(tile, :color='$vuetify.dark ? "grey darken-4" : "grey lighten-5"')
  3. .pa-3.pt-4
  4. .admin-header-icon: v-icon(size='80', color='grey lighten-2') storage
  5. .headline.primary--text Storage
  6. .subheading.grey--text Set backup and sync targets for your content
  7. v-tabs(:color='$vuetify.dark ? "primary" : "grey lighten-4"', fixed-tabs, :slider-color='$vuetify.dark ? "white" : "primary"', show-arrows)
  8. v-tab(key='settings'): v-icon settings
  9. v-tab(v-for='tgt in activeTargets', :key='tgt.key') {{ tgt.title }}
  10. v-tab-item(key='settings', :transition='false', :reverse-transition='false')
  11. v-card.pa-3(flat, tile)
  12. .body-2.grey--text.text--darken-1 Select which storage targets to enable:
  13. .caption.grey--text.pb-2 Some storage targets require additional configuration in their dedicated tab (when selected).
  14. v-form
  15. v-checkbox.my-0(
  16. v-for='tgt in targets'
  17. v-model='tgt.isEnabled'
  18. :key='tgt.key'
  19. :label='tgt.title'
  20. color='primary'
  21. hide-details
  22. )
  23. v-tab-item(v-for='(tgt, n) in activeTargets', :key='tgt.key', :transition='false', :reverse-transition='false')
  24. v-card.pa-3(flat, tile)
  25. v-form
  26. .targetlogo
  27. img(:src='tgt.logo', :alt='tgt.title')
  28. v-subheader.pl-0 {{tgt.title}}
  29. .caption {{tgt.description}}
  30. .caption: a(:href='tgt.website') {{tgt.website}}
  31. v-divider.mt-3
  32. v-subheader.pl-0 Target Configuration
  33. .body-1.ml-3(v-if='!tgt.config || tgt.config.length < 1') This storage target has no configuration options you can modify.
  34. template(v-else, v-for='cfg in tgt.config')
  35. v-select(
  36. v-if='cfg.value.type === "string" && cfg.value.enum'
  37. outline
  38. background-color='grey lighten-2'
  39. :items='cfg.value.enum'
  40. :key='cfg.key'
  41. :label='cfg.value.title'
  42. v-model='cfg.value.value'
  43. prepend-icon='settings_applications'
  44. :hint='cfg.value.hint ? cfg.value.hint : ""'
  45. persistent-hint
  46. :class='cfg.value.hint ? "mb-2" : ""'
  47. )
  48. v-switch(
  49. v-else-if='cfg.value.type === "boolean"'
  50. :key='cfg.key'
  51. :label='cfg.value.title'
  52. v-model='cfg.value.value'
  53. color='primary'
  54. prepend-icon='settings_applications'
  55. :hint='cfg.value.hint ? cfg.value.hint : ""'
  56. persistent-hint
  57. )
  58. v-text-field(
  59. v-else
  60. outline
  61. background-color='grey lighten-2'
  62. :key='cfg.key'
  63. :label='cfg.value.title'
  64. v-model='cfg.value.value'
  65. prepend-icon='settings_applications'
  66. :hint='cfg.value.hint ? cfg.value.hint : ""'
  67. persistent-hint
  68. :class='cfg.value.hint ? "mb-2" : ""'
  69. )
  70. v-divider.mt-3
  71. v-subheader.pl-0 Sync Direction
  72. .body-1.ml-3 Choose how content synchronization is handled for this storage target.
  73. .pr-3.pt-3
  74. v-radio-group.ml-3.py-0(v-model='tgt.mode')
  75. v-radio(
  76. label='Bi-directional'
  77. color='primary'
  78. value='sync'
  79. )
  80. v-radio(
  81. label='Push to target'
  82. color='primary'
  83. value='push'
  84. )
  85. v-radio(
  86. label='Pull from target'
  87. color='primary'
  88. value='pull'
  89. )
  90. .body-1.ml-3
  91. strong Bi-directional
  92. .pb-3 In bi-directional mode, content is first pulled from the storage target. Any newer content overwrites local content. New content since last sync is then pushed to the storage target, overwriting any content on target if present.
  93. strong Push to target
  94. .pb-3 Content is always pushed to the storage target, overwriting any existing content. This is the default and safest choice for backup scenarios.
  95. strong Pull from target
  96. .pb-3 Content is always pulled from the storage target, overwriting any local content which already exists. This choice is usually reserved for single-use content import. Caution with this option as any local content will always be overwritten!
  97. v-card-chin
  98. v-btn(color='primary', @click='save')
  99. v-icon(left) chevron_right
  100. span Apply Configuration
  101. v-spacer
  102. v-btn(icon, @click='refresh')
  103. v-icon.grey--text refresh
  104. </template>
  105. <script>
  106. import _ from 'lodash'
  107. import targetsQuery from 'gql/admin/storage/storage-query-targets.gql'
  108. import targetsSaveMutation from 'gql/admin/storage/storage-mutation-save-targets.gql'
  109. export default {
  110. filters: {
  111. startCase(val) { return _.startCase(val) }
  112. },
  113. data() {
  114. return {
  115. targets: []
  116. }
  117. },
  118. computed: {
  119. activeTargets() {
  120. return _.filter(this.targets, 'isEnabled')
  121. }
  122. },
  123. methods: {
  124. async refresh() {
  125. await this.$apollo.queries.targets.refetch()
  126. this.$store.commit('showNotification', {
  127. message: 'List of storage targets has been refreshed.',
  128. style: 'success',
  129. icon: 'cached'
  130. })
  131. },
  132. async save() {
  133. this.$store.commit(`loadingStart`, 'admin-storage-savetargets')
  134. await this.$apollo.mutate({
  135. mutation: targetsSaveMutation,
  136. variables: {
  137. targets: this.targets.map(tgt => _.pick(tgt, [
  138. 'isEnabled',
  139. 'key',
  140. 'config',
  141. 'mode'
  142. ])).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: cfg.value.value}))}))
  143. }
  144. })
  145. this.$store.commit('showNotification', {
  146. message: 'Storage configuration saved successfully.',
  147. style: 'success',
  148. icon: 'check'
  149. })
  150. this.$store.commit(`loadingStop`, 'admin-storage-savetargets')
  151. }
  152. },
  153. apollo: {
  154. targets: {
  155. query: targetsQuery,
  156. fetchPolicy: 'network-only',
  157. update: (data) => _.cloneDeep(data.storage.targets).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: JSON.parse(cfg.value)}))})),
  158. watchLoading (isLoading) {
  159. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-storage-refresh')
  160. }
  161. }
  162. }
  163. }
  164. </script>
  165. <style lang='scss' scoped>
  166. .targetlogo {
  167. width: 250px;
  168. height: 85px;
  169. float:right;
  170. display: flex;
  171. justify-content: flex-end;
  172. align-items: center;
  173. img {
  174. max-width: 100%;
  175. max-height: 50px;
  176. }
  177. }
  178. </style>