LocationEditor.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <script setup lang="ts">
  2. import type { NgxConfig, NgxLocation } from '@/api/ngx'
  3. import CodeEditor from '@/components/CodeEditor'
  4. import { CopyOutlined, DeleteOutlined, HolderOutlined } from '@ant-design/icons-vue'
  5. import _ from 'lodash'
  6. import Draggable from 'vuedraggable'
  7. const props = defineProps<{
  8. locations?: NgxLocation[]
  9. readonly?: boolean
  10. currentServerIndex?: number
  11. }>()
  12. const ngx_config = inject('ngx_config') as NgxConfig
  13. const location = reactive({
  14. comments: '',
  15. path: '',
  16. content: '',
  17. })
  18. const adding = ref(false)
  19. function add() {
  20. adding.value = true
  21. location.comments = ''
  22. location.path = ''
  23. location.content = ''
  24. }
  25. function save() {
  26. adding.value = false
  27. ngx_config.servers[props.currentServerIndex!].locations?.push({
  28. ...location,
  29. })
  30. }
  31. function remove(index: number) {
  32. ngx_config.servers[props.currentServerIndex!].locations?.splice(index, 1)
  33. }
  34. function duplicate(index: number) {
  35. const loc = ngx_config.servers[props.currentServerIndex!].locations![index]
  36. ngx_config.servers[props.currentServerIndex!].locations?.splice(index, 0, _.cloneDeep(loc))
  37. }
  38. </script>
  39. <template>
  40. <h3>{{ $gettext('Locations') }}</h3>
  41. <AEmpty v-if="locations && locations?.length === 0" />
  42. <Draggable
  43. v-else
  44. :list="locations"
  45. item-key="name"
  46. class="list-group"
  47. ghost-class="ghost"
  48. handle=".ant-collapse-header"
  49. >
  50. <template #item="{ element: v, index }">
  51. <ACollapse
  52. :bordered="false"
  53. collapsible="header"
  54. >
  55. <ACollapsePanel>
  56. <template #header>
  57. <HolderOutlined />
  58. {{ $gettext('Location') }}
  59. {{ v.path }}
  60. </template>
  61. <template
  62. v-if="!readonly"
  63. #extra
  64. >
  65. <ASpace>
  66. <AButton
  67. type="text"
  68. size="small"
  69. @click="() => duplicate(index)"
  70. >
  71. <template #icon>
  72. <CopyOutlined style="font-size: 14px;" />
  73. </template>
  74. </AButton>
  75. <APopconfirm
  76. :title="$gettext('Are you sure you want to remove this location?')"
  77. :ok-text="$gettext('Yes')"
  78. :cancel-text="$gettext('No')"
  79. @confirm="remove(index)"
  80. >
  81. <AButton
  82. type="text"
  83. size="small"
  84. >
  85. <template #icon>
  86. <DeleteOutlined style="font-size: 14px;" />
  87. </template>
  88. </AButton>
  89. </APopconfirm>
  90. </ASpace>
  91. </template>
  92. <AForm layout="vertical">
  93. <AFormItem :label="$gettext('Comments')">
  94. <ATextarea
  95. v-model:value="v.comments"
  96. :bordered="false"
  97. />
  98. </AFormItem>
  99. <AFormItem :label="$gettext('Path')">
  100. <AInput
  101. v-model:value="v.path"
  102. addon-before="location"
  103. />
  104. </AFormItem>
  105. <AFormItem :label="$gettext('Content')">
  106. <CodeEditor
  107. v-model:content="v.content"
  108. default-height="200px"
  109. style="width: 100%;"
  110. />
  111. </AFormItem>
  112. </AForm>
  113. </ACollapsePanel>
  114. </ACollapse>
  115. </template>
  116. </Draggable>
  117. <AModal
  118. v-model:open="adding"
  119. :title="$gettext('Add Location')"
  120. @ok="save"
  121. >
  122. <AForm layout="vertical">
  123. <AFormItem :label="$gettext('Comments')">
  124. <ATextarea v-model:value="location.comments" />
  125. </AFormItem>
  126. <AFormItem :label="$gettext('Path')">
  127. <AInput
  128. v-model:value="location.path"
  129. addon-before="location"
  130. />
  131. </AFormItem>
  132. <AFormItem :label="$gettext('Content')">
  133. <CodeEditor
  134. v-model:content="location.content"
  135. default-height="200px"
  136. />
  137. </AFormItem>
  138. </AForm>
  139. </AModal>
  140. <div v-if="!readonly">
  141. <AButton
  142. block
  143. @click="add"
  144. >
  145. {{ $gettext('Add Location') }}
  146. </AButton>
  147. </div>
  148. </template>
  149. <style lang="less" scoped>
  150. .ant-collapse {
  151. margin: 10px 0;
  152. }
  153. .ant-collapse-item {
  154. border: 0 !important;
  155. }
  156. .ant-collapse-header {
  157. align-items: center;
  158. }
  159. :deep(.ant-collapse-header-text) {
  160. max-width: calc(90% - 56px);
  161. }
  162. </style>