2
0

SiteCreateDialog.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <template lang="pug">
  2. q-dialog(ref='dialogRef', @hide='onDialogHide')
  3. q-card(style='min-width: 450px;')
  4. q-card-section.card-header
  5. q-icon(name='img:/_assets/icons/fluent-plus-plus.svg', left, size='sm')
  6. span {{t(`admin.sites.new`)}}
  7. q-form.q-py-sm(ref='createSiteForm')
  8. q-item
  9. blueprint-icon(icon='home')
  10. q-item-section
  11. q-input(
  12. outlined
  13. v-model='state.siteName'
  14. dense
  15. :rules='siteNameValidation'
  16. hide-bottom-space
  17. :label='t(`common.field.name`)'
  18. :aria-label='t(`common.field.name`)'
  19. lazy-rules='ondemand'
  20. autofocus
  21. )
  22. q-item
  23. blueprint-icon.self-start(icon='dns')
  24. q-item-section
  25. q-input(
  26. outlined
  27. v-model='state.siteHostname'
  28. dense
  29. :rules='siteHostnameValidation'
  30. :hint='t(`admin.sites.hostnameHint`)'
  31. hide-bottom-space
  32. :label='t(`admin.sites.hostname`)'
  33. :aria-label='t(`admin.sites.hostname`)'
  34. lazy-rules='ondemand'
  35. )
  36. q-card-actions.card-actions
  37. q-space
  38. q-btn.acrylic-btn(
  39. flat
  40. :label='t(`common.actions.cancel`)'
  41. color='grey'
  42. padding='xs md'
  43. @click='onDialogCancel'
  44. )
  45. q-btn(
  46. unelevated
  47. :label='t(`common.actions.create`)'
  48. color='primary'
  49. padding='xs md'
  50. @click='create'
  51. :loading='state.isLoading'
  52. )
  53. </template>
  54. <script setup>
  55. import gql from 'graphql-tag'
  56. import { useI18n } from 'vue-i18n'
  57. import { useDialogPluginComponent, useQuasar } from 'quasar'
  58. import { reactive, ref } from 'vue'
  59. import { useAdminStore } from '../stores/admin'
  60. // EMITS
  61. defineEmits([
  62. ...useDialogPluginComponent.emits
  63. ])
  64. // QUASAR
  65. const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
  66. const $q = useQuasar()
  67. // STORES
  68. const adminStore = useAdminStore()
  69. // I18N
  70. const { t } = useI18n()
  71. // DATA
  72. const state = reactive({
  73. siteName: '',
  74. siteHostname: 'wiki.example.com',
  75. isLoading: false
  76. })
  77. // REFS
  78. const createSiteForm = ref(null)
  79. // VALIDATION RULES
  80. const siteNameValidation = [
  81. val => val.length > 0 || t('admin.sites.nameMissing'),
  82. val => /^[^<>"]+$/.test(val) || t('admin.sites.nameInvalidChars')
  83. ]
  84. const siteHostnameValidation = [
  85. val => val.length > 0 || t('admin.sites.hostnameMissing'),
  86. val => /^(\\*)|([a-z0-9\-.:]+)$/.test(val) || t('admin.sites.hostnameInvalidChars')
  87. ]
  88. // METHODS
  89. async function create () {
  90. state.isLoading = true
  91. try {
  92. const isFormValid = await createSiteForm.value.validate(true)
  93. if (!isFormValid) {
  94. throw new Error(t('admin.sites.createInvalidData'))
  95. }
  96. const resp = await APOLLO_CLIENT.mutate({
  97. mutation: gql`
  98. mutation createSite (
  99. $hostname: String!
  100. $title: String!
  101. ) {
  102. createSite(
  103. hostname: $hostname
  104. title: $title
  105. ) {
  106. operation {
  107. succeeded
  108. message
  109. }
  110. }
  111. }
  112. `,
  113. variables: {
  114. hostname: state.siteHostname,
  115. title: state.siteName
  116. }
  117. })
  118. if (resp?.data?.createSite?.operation?.succeeded) {
  119. $q.notify({
  120. type: 'positive',
  121. message: t('admin.sites.createSuccess')
  122. })
  123. await adminStore.fetchSites()
  124. onDialogOK()
  125. } else {
  126. throw new Error(resp?.data?.createSite?.operation?.message || 'An unexpected error occured.')
  127. }
  128. } catch (err) {
  129. $q.notify({
  130. type: 'negative',
  131. message: err.message
  132. })
  133. }
  134. state.isLoading = false
  135. }
  136. </script>