SiteStatusSegmented.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <script setup lang="ts">
  2. import site from '@/api/site'
  3. import { ConfigStatus } from '@/constants'
  4. import { message, Modal } from 'ant-design-vue'
  5. /**
  6. * Component props interface
  7. */
  8. interface Props {
  9. /**
  10. * The name of the site configuration
  11. */
  12. siteName: string
  13. /**
  14. * Whether the site is enabled
  15. */
  16. enabled: boolean
  17. }
  18. // Define props with TypeScript
  19. const props = defineProps<Props>()
  20. // Define event for status change notification
  21. const emit = defineEmits<{
  22. statusChanged: [{ status: string, enabled: boolean }]
  23. }>()
  24. // Use defineModel for v-model binding
  25. const status = defineModel<string>({
  26. default: ConfigStatus.Disabled,
  27. })
  28. const [modal, ContextHolder] = Modal.useModal()
  29. /**
  30. * Enable the site
  31. */
  32. function enable() {
  33. site.enable(props.siteName).then(() => {
  34. message.success($gettext('Enabled successfully'))
  35. status.value = ConfigStatus.Enabled
  36. emit('statusChanged', {
  37. status: ConfigStatus.Enabled,
  38. enabled: true,
  39. })
  40. }).catch(r => {
  41. message.error($gettext('Failed to enable %{msg}', { msg: r.message ?? '' }), 10)
  42. })
  43. }
  44. /**
  45. * Disable the site
  46. */
  47. function disable() {
  48. site.disable(props.siteName).then(() => {
  49. message.success($gettext('Disabled successfully'))
  50. status.value = ConfigStatus.Disabled
  51. emit('statusChanged', {
  52. status: ConfigStatus.Disabled,
  53. enabled: false,
  54. })
  55. }).catch(r => {
  56. message.error($gettext('Failed to disable %{msg}', { msg: r.message ?? '' }))
  57. })
  58. }
  59. /**
  60. * Enable maintenance mode for the site
  61. */
  62. function enableMaintenance() {
  63. site.enableMaintenance(props.siteName).then(() => {
  64. message.success($gettext('Maintenance mode enabled successfully'))
  65. status.value = ConfigStatus.Maintenance
  66. emit('statusChanged', {
  67. status: ConfigStatus.Maintenance,
  68. enabled: true,
  69. })
  70. }).catch(r => {
  71. message.error($gettext('Failed to enable maintenance mode %{msg}', { msg: r.message ?? '' }))
  72. })
  73. }
  74. /**
  75. * Disable maintenance mode for the site
  76. */
  77. function disableMaintenance() {
  78. site.enable(props.siteName).then(() => {
  79. message.success($gettext('Maintenance mode disabled successfully'))
  80. status.value = ConfigStatus.Enabled
  81. emit('statusChanged', {
  82. status: ConfigStatus.Enabled,
  83. enabled: true,
  84. })
  85. }).catch(r => {
  86. message.error($gettext('Failed to disable maintenance mode %{msg}', { msg: r.message ?? '' }))
  87. })
  88. }
  89. /**
  90. * Handle status change from segmented control
  91. */
  92. function onChangeStatus(value: string | number) {
  93. const statusValue = value as string
  94. if (statusValue === status.value) {
  95. return
  96. }
  97. // Save original status to restore if user cancels
  98. const originalStatus = status.value
  99. const statusMap = {
  100. [ConfigStatus.Enabled]: $gettext('enable'),
  101. [ConfigStatus.Disabled]: $gettext('disable'),
  102. [ConfigStatus.Maintenance]: $gettext('set to maintenance mode'),
  103. }
  104. modal.confirm({
  105. title: $gettext('Do you want to %{action} this site?', { action: statusMap[statusValue] }),
  106. mask: false,
  107. centered: true,
  108. okText: $gettext('OK'),
  109. cancelText: $gettext('Cancel'),
  110. async onOk() {
  111. if (statusValue === ConfigStatus.Enabled) {
  112. if (status.value === ConfigStatus.Maintenance) {
  113. disableMaintenance()
  114. }
  115. else {
  116. enable()
  117. }
  118. }
  119. else if (statusValue === ConfigStatus.Disabled) {
  120. disable()
  121. }
  122. else if (statusValue === ConfigStatus.Maintenance) {
  123. enableMaintenance()
  124. }
  125. },
  126. onCancel() {
  127. // Restore original status if user cancels
  128. status.value = originalStatus
  129. },
  130. })
  131. }
  132. </script>
  133. <template>
  134. <div class="site-status-segmented">
  135. <ContextHolder />
  136. <ASegmented
  137. v-model:value="status"
  138. :options="[
  139. {
  140. value: ConfigStatus.Enabled,
  141. label: $gettext('Enabled'),
  142. },
  143. {
  144. value: ConfigStatus.Disabled,
  145. label: $gettext('Disabled'),
  146. },
  147. {
  148. value: ConfigStatus.Maintenance,
  149. label: $gettext('Maintenance'),
  150. },
  151. ]"
  152. @change="onChangeStatus"
  153. />
  154. </div>
  155. </template>
  156. <style scoped>
  157. .site-status-segmented {
  158. display: flex;
  159. align-items: center;
  160. justify-content: flex-start;
  161. }
  162. :deep(.ant-segmented-item:nth-child(1).ant-segmented-item-selected) {
  163. background: #1890ff;
  164. color: white;
  165. }
  166. :deep(.ant-segmented-item:nth-child(2).ant-segmented-item-selected) {
  167. background: #ff4d4f;
  168. color: white;
  169. }
  170. :deep(.ant-segmented-item:nth-child(3).ant-segmented-item-selected) {
  171. background: #faad14;
  172. color: white;
  173. }
  174. :deep(.ant-segmented-item-selected) {
  175. border-radius: 6px;
  176. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  177. transition: all 0.3s ease;
  178. }
  179. </style>