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.

267 lines
9.3 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-process.svg', alt='Rendering', style='width: 80px;')
  7. .admin-header-title
  8. .headline.primary--text.animated.fadeInLeft {{ $t('admin:rendering.title') }}
  9. .subtitle-1.grey--text.animated.fadeInLeft.wait-p4s {{ $t('admin:rendering.subtitle') }}
  10. v-spacer
  11. v-btn.animated.fadeInDown.wait-p3s(icon, outlined, color='grey', href='https://docs.requarks.io/rendering', target='_blank')
  12. v-icon mdi-help-circle
  13. v-btn.mx-3.animated.fadeInDown.wait-p2s(icon, outlined, color='grey', @click='refresh')
  14. v-icon mdi-refresh
  15. v-btn.animated.fadeInDown(color='success', @click='save', depressed, large)
  16. v-icon(left) mdi-check
  17. span {{$t('common:actions.apply')}}
  18. v-flex.animated.fadeInUp(lg3, xs12)
  19. v-toolbar(
  20. color='blue darken-2'
  21. dense
  22. flat
  23. dark
  24. )
  25. .subtitle-1 Pipeline
  26. v-expansion-panels.adm-rendering-pipeline(
  27. v-model='selectedCore'
  28. accordion
  29. mandatory
  30. )
  31. v-expansion-panel(
  32. v-for='core in renderers'
  33. :key='core.key'
  34. )
  35. v-expansion-panel-header(
  36. hide-actions
  37. ripple
  38. )
  39. v-toolbar(
  40. color='blue'
  41. dense
  42. dark
  43. flat
  44. )
  45. v-spacer
  46. .body-2 {{core.input}}
  47. v-icon.mx-2 mdi-arrow-right-circle
  48. .caption {{core.output}}
  49. v-spacer
  50. v-expansion-panel-content
  51. v-list.py-0(two-line, dense)
  52. template(v-for='(rdr, n) in core.children')
  53. v-list-item(
  54. :key='rdr.key'
  55. @click='selectRenderer(rdr.key)'
  56. :class='currentRenderer.key === rdr.key ? ($vuetify.theme.dark ? `grey darken-4-l4` : `blue lighten-5`) : ``'
  57. )
  58. v-list-item-avatar(size='24', tile)
  59. v-icon(:color='currentRenderer.key === rdr.key ? "primary" : "grey"') {{rdr.icon}}
  60. v-list-item-content
  61. v-list-item-title {{rdr.title}}
  62. v-list-item-subtitle: .caption {{rdr.description}}
  63. v-list-item-avatar(size='24')
  64. status-indicator(v-if='rdr.isEnabled', positive, pulse)
  65. status-indicator(v-else, negative, pulse)
  66. v-divider.my-0(v-if='n < core.children.length - 1')
  67. v-flex(lg9, xs12)
  68. v-card.wiki-form.animated.fadeInUp
  69. v-toolbar(
  70. color='indigo'
  71. dark
  72. flat
  73. dense
  74. )
  75. v-icon.mr-2 {{currentRenderer.icon}}
  76. .subtitle-1 {{currentRenderer.title}}
  77. v-spacer
  78. v-switch(
  79. dark
  80. color='white'
  81. label='Enabled'
  82. v-model='currentRenderer.isEnabled'
  83. hide-details
  84. inset
  85. )
  86. v-card-text.py-2.pl-4
  87. .body-2.pt-3 {{currentRenderer.description}}
  88. .body-2.pt-1.pb-5: a(href='https://docs.requarks.io/en/rendering', target='_blank') Documentation
  89. i18next.body-2(path='admin:auth.strategyState', tag='div', v-if='currentRenderer.isEnabled')
  90. v-chip(color='green', small, dark, label, place='state') {{$t('admin:auth.strategyStateActive')}}
  91. span(v-if='selectedCore === `local`', place='locked') {{$t('admin:auth.strategyStateLocked')}}
  92. span(v-else, place='locked', v-text='')
  93. i18next.body-2(path='admin:auth.strategyState', tag='div', v-else)
  94. v-chip(color='red', small, dark, label, place='state') {{$t('admin:auth.strategyStateInactive')}}
  95. v-divider.mt-3
  96. v-card-text.pb-4.pt-2.pl-4
  97. .overline.my-5 Rendering Module Configuration
  98. .body-2.ml-3(v-if='!currentRenderer.config || currentRenderer.config.length < 1'): em This rendering module has no configuration options you can modify.
  99. template(v-else, v-for='(cfg, idx) in currentRenderer.config')
  100. v-select(
  101. v-if='cfg.value.type === "string" && cfg.value.enum'
  102. outlined
  103. :items='cfg.value.enum'
  104. :key='cfg.key'
  105. :label='cfg.value.title'
  106. v-model='cfg.value.value'
  107. :hint='cfg.value.hint ? cfg.value.hint : ""'
  108. persistent-hint
  109. :class='cfg.value.hint ? "mb-2" : ""'
  110. color='indigo'
  111. )
  112. v-switch(
  113. v-else-if='cfg.value.type === "boolean"'
  114. :key='cfg.key'
  115. :label='cfg.value.title'
  116. v-model='cfg.value.value'
  117. color='indigo'
  118. :hint='cfg.value.hint ? cfg.value.hint : ""'
  119. persistent-hint
  120. inset
  121. )
  122. v-text-field(
  123. v-else
  124. outlined
  125. :key='cfg.key'
  126. :label='cfg.value.title'
  127. v-model='cfg.value.value'
  128. :hint='cfg.value.hint ? cfg.value.hint : ""'
  129. persistent-hint
  130. :class='cfg.value.hint ? "mb-2" : ""'
  131. color='indigo'
  132. )
  133. v-divider.my-5(v-if='idx < currentRenderer.config.length - 1')
  134. v-card-chin
  135. v-spacer
  136. .caption.pr-3.grey--text Module: {{ currentRenderer.key }}
  137. </template>
  138. <script>
  139. import _ from 'lodash'
  140. import { DepGraph } from 'dependency-graph'
  141. import { StatusIndicator } from 'vue-status-indicator'
  142. import renderersQuery from 'gql/admin/rendering/rendering-query-renderers.gql'
  143. import renderersSaveMutation from 'gql/admin/rendering/rendering-mutation-save-renderers.gql'
  144. export default {
  145. components: {
  146. StatusIndicator
  147. },
  148. data() {
  149. return {
  150. selectedCore: -1,
  151. renderers: [],
  152. currentRenderer: {}
  153. }
  154. },
  155. watch: {
  156. renderers(newValue, oldValue) {
  157. _.delay(() => {
  158. this.selectedCore = _.findIndex(newValue, ['key', 'markdownCore'])
  159. this.selectRenderer('markdownCore')
  160. }, 500)
  161. }
  162. },
  163. methods: {
  164. selectRenderer (key) {
  165. this.renderers.map(rdr => {
  166. if (_.some(rdr.children, ['key', key])) {
  167. this.currentRenderer = _.find(rdr.children, ['key', key])
  168. }
  169. })
  170. },
  171. async refresh () {
  172. await this.$apollo.queries.renderers.refetch()
  173. this.$store.commit('showNotification', {
  174. message: 'Rendering active configuration has been reloaded.',
  175. style: 'success',
  176. icon: 'cached'
  177. })
  178. },
  179. async save () {
  180. this.$store.commit(`loadingStart`, 'admin-rendering-saverenderers')
  181. await this.$apollo.mutate({
  182. mutation: renderersSaveMutation,
  183. variables: {
  184. renderers: _.reduce(this.renderers, (result, core) => {
  185. result = _.concat(result, core.children.map(rd => ({
  186. key: rd.key,
  187. isEnabled: rd.isEnabled,
  188. config: rd.config.map(cfg => ({ key: cfg.key, value: JSON.stringify({ v: cfg.value.value }) }))
  189. })))
  190. return result
  191. }, [])
  192. }
  193. })
  194. this.$store.commit('showNotification', {
  195. message: 'Rendering configuration saved successfully.',
  196. style: 'success',
  197. icon: 'check'
  198. })
  199. this.$store.commit(`loadingStop`, 'admin-rendering-saverenderers')
  200. }
  201. },
  202. apollo: {
  203. renderers: {
  204. query: renderersQuery,
  205. fetchPolicy: 'network-only',
  206. update: (data) => {
  207. let renderers = _.cloneDeep(data.rendering.renderers).map(str => ({
  208. ...str,
  209. config: _.sortBy(str.config.map(cfg => ({
  210. ...cfg,
  211. value: JSON.parse(cfg.value)
  212. })), [t => t.value.order])
  213. }))
  214. // Build tree
  215. const graph = new DepGraph({ circular: true })
  216. const rawCores = _.filter(renderers, ['dependsOn', null]).map(core => {
  217. core.children = _.concat([_.cloneDeep(core)], _.filter(renderers, ['dependsOn', core.key]))
  218. return core
  219. })
  220. // Build dependency graph
  221. rawCores.map(core => { graph.addNode(core.key) })
  222. rawCores.map(core => {
  223. rawCores.map(coreTarget => {
  224. if (core.key !== coreTarget.key) {
  225. if (core.output === coreTarget.input) {
  226. graph.addDependency(core.key, coreTarget.key)
  227. }
  228. }
  229. })
  230. })
  231. // Reorder cores in reverse dependency order
  232. let orderedCores = []
  233. _.reverse(graph.overallOrder()).map(coreKey => {
  234. orderedCores.push(_.find(rawCores, ['key', coreKey]))
  235. })
  236. return orderedCores
  237. },
  238. watchLoading (isLoading) {
  239. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-rendering-refresh')
  240. }
  241. }
  242. }
  243. }
  244. </script>
  245. <style lang='scss'>
  246. .adm-rendering-pipeline {
  247. .v-expansion-panel--active .v-expansion-panel-header {
  248. min-height: 0;
  249. }
  250. .v-expansion-panel-header {
  251. padding: 0;
  252. margin-top: 1px;
  253. }
  254. .v-expansion-panel-content__wrap {
  255. padding: 0;
  256. }
  257. }
  258. </style>