AdminWebhooks.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <template lang='pug'>
  2. q-page.admin-webhooks
  3. .row.q-pa-md.items-center
  4. .col-auto
  5. img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-lightning-bolt.svg')
  6. .col.q-pl-md
  7. .text-h5.text-primary.animated.fadeInLeft {{ t('admin.webhooks.title') }}
  8. .text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ t('admin.webhooks.subtitle') }}
  9. .col-auto
  10. q-btn.q-mr-sm.acrylic-btn(
  11. icon='las la-question-circle'
  12. flat
  13. color='grey'
  14. :aria-label='t(`common.actions.viewDocs`)'
  15. :href='siteStore.docsBase + `/system/webhooks`'
  16. target='_blank'
  17. type='a'
  18. )
  19. q-tooltip {{ t(`common.actions.viewDocs`) }}
  20. q-btn.acrylic-btn.q-mr-sm(
  21. icon='las la-redo-alt'
  22. flat
  23. color='secondary'
  24. :loading='state.loading > 0'
  25. :aria-label='t(`common.actions.refresh`)'
  26. @click='load'
  27. )
  28. q-tooltip {{ t(`common.actions.refresh`) }}
  29. q-btn(
  30. unelevated
  31. icon='las la-plus'
  32. :label='t(`admin.webhooks.new`)'
  33. color='primary'
  34. @click='createHook'
  35. )
  36. q-separator(inset)
  37. .row.q-pa-md.q-col-gutter-md
  38. .col-12(v-if='state.hooks.length < 1')
  39. q-card.rounded-borders(
  40. flat
  41. :class='$q.dark.isActive ? `bg-dark-5 text-white` : `bg-grey-3 text-dark`'
  42. )
  43. q-card-section.items-center(horizontal)
  44. q-card-section.col-auto.q-pr-none
  45. q-icon(name='las la-info-circle', size='sm')
  46. q-card-section.text-caption {{ t('admin.webhooks.none') }}
  47. .col-12(v-else)
  48. q-card
  49. q-list(separator)
  50. q-item(v-for='hook of state.hooks', :key='hook.id')
  51. q-item-section(side)
  52. q-icon(name='las la-bolt', color='primary')
  53. q-item-section
  54. q-item-label {{hook.name}}
  55. q-item-label(caption) {{hook.url}}
  56. q-item-section(side, style='flex-direction: row; align-items: center;')
  57. template(v-if='hook.state === `pending`')
  58. q-spinner-clock.q-mr-sm(
  59. color='indigo'
  60. size='xs'
  61. )
  62. .text-caption.text-indigo {{t('admin.webhooks.statePending')}}
  63. q-tooltip(anchor='center left', self='center right') {{t('admin.webhooks.statePendingHint')}}
  64. template(v-else-if='hook.state === `success`')
  65. q-spinner-infinity.q-mr-sm(
  66. color='positive'
  67. size='xs'
  68. )
  69. .text-caption.text-positive {{t('admin.webhooks.stateSuccess')}}
  70. q-tooltip(anchor='center left', self='center right') {{t('admin.webhooks.stateSuccessHint')}}
  71. template(v-else-if='hook.state === `error`')
  72. q-icon.q-mr-sm(
  73. color='negative'
  74. size='xs'
  75. name='las la-exclamation-triangle'
  76. )
  77. .text-caption.text-negative {{t('admin.webhooks.stateError')}}
  78. q-tooltip(anchor='center left', self='center right') {{t('admin.webhooks.stateErrorHint')}}
  79. q-separator.q-ml-md(vertical)
  80. q-item-section(side, style='flex-direction: row; align-items: center;')
  81. q-btn.acrylic-btn.q-mr-sm(
  82. color='indigo'
  83. icon='las la-pen'
  84. label='Edit'
  85. flat
  86. no-caps
  87. @click='editHook(hook.id)'
  88. )
  89. q-btn.acrylic-btn(
  90. color='red'
  91. icon='las la-trash'
  92. flat
  93. @click='deleteHook(hook)'
  94. )
  95. </template>
  96. <script setup>
  97. import { cloneDeep } from 'lodash-es'
  98. import gql from 'graphql-tag'
  99. import { useI18n } from 'vue-i18n'
  100. import { useMeta, useQuasar } from 'quasar'
  101. import { onMounted, reactive } from 'vue'
  102. import { useSiteStore } from '@/stores/site'
  103. import WebhookEditDialog from '@/components/WebhookEditDialog.vue'
  104. import WebhookDeleteDialog from '@/components/WebhookDeleteDialog.vue'
  105. // QUASAR
  106. const $q = useQuasar()
  107. // STORES
  108. const siteStore = useSiteStore()
  109. // I18N
  110. const { t } = useI18n()
  111. // META
  112. useMeta({
  113. title: t('admin.webhooks.title')
  114. })
  115. // DATA
  116. const state = reactive({
  117. hooks: [],
  118. loading: 0
  119. })
  120. // METHODS
  121. async function load () {
  122. state.loading++
  123. $q.loading.show()
  124. const resp = await APOLLO_CLIENT.query({
  125. query: gql`
  126. query getHooks {
  127. hooks {
  128. id
  129. name
  130. url
  131. state
  132. }
  133. }
  134. `,
  135. fetchPolicy: 'network-only'
  136. })
  137. state.hooks = cloneDeep(resp?.data?.hooks) ?? []
  138. $q.loading.hide()
  139. state.loading--
  140. }
  141. function createHook () {
  142. $q.dialog({
  143. component: WebhookEditDialog,
  144. componentProps: {
  145. hookId: null
  146. }
  147. }).onOk(() => {
  148. load()
  149. })
  150. }
  151. function editHook (id) {
  152. $q.dialog({
  153. component: WebhookEditDialog,
  154. componentProps: {
  155. hookId: id
  156. }
  157. }).onOk(() => {
  158. load()
  159. })
  160. }
  161. function deleteHook (hook) {
  162. $q.dialog({
  163. component: WebhookDeleteDialog,
  164. componentProps: {
  165. hook
  166. }
  167. }).onOk(() => {
  168. load()
  169. })
  170. }
  171. // MOUNTED
  172. onMounted(() => {
  173. load()
  174. })
  175. </script>
  176. <style lang='scss'>
  177. </style>