EditWebhook.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <template>
  2. <div class="mb-2 mt-4">
  3. <ui-textarea
  4. :model-value="data.description"
  5. :placeholder="t('common.description')"
  6. class="w-full mb-2"
  7. @change="updateData({ description: $event })"
  8. />
  9. <ui-select
  10. :model-value="data.method || 'POST'"
  11. :label="t('workflow.blocks.webhook.method')"
  12. class="mb-2 w-full"
  13. @change="updateMethod"
  14. >
  15. <option v-for="method in methods" :key="method" :value="method">
  16. {{ method }}
  17. </option>
  18. </ui-select>
  19. <edit-autocomplete class="mb-2">
  20. <ui-textarea
  21. :model-value="data.url"
  22. :label="`${t('workflow.blocks.webhook.url')}*`"
  23. placeholder="http://api.example.com"
  24. class="w-full"
  25. rows="1"
  26. autocomplete="off"
  27. required
  28. type="url"
  29. @change="updateData({ url: $event })"
  30. />
  31. </edit-autocomplete>
  32. <ui-select
  33. :model-value="data.contentType"
  34. :label="t('workflow.blocks.webhook.contentType')"
  35. class="mb-2 w-full"
  36. @change="updateData({ contentType: $event })"
  37. >
  38. <option
  39. v-for="type in contentTypes"
  40. :key="type.value"
  41. :value="type.value"
  42. >
  43. {{ type.name }}
  44. </option>
  45. </ui-select>
  46. <ui-input
  47. :model-value="data.timeout"
  48. :label="t('workflow.blocks.webhook.timeout.placeholder')"
  49. :title="t('workflow.blocks.webhook.timeout.title')"
  50. class="mb-2 w-full"
  51. type="number"
  52. @change="updateData({ timeout: +$event })"
  53. />
  54. <ui-tabs v-model="activeTab" fill>
  55. <ui-tab value="headers">
  56. {{ t('workflow.blocks.webhook.tabs.headers') }}
  57. </ui-tab>
  58. <ui-tab v-if="!notHaveBody.includes(data.method)" value="body">
  59. {{ t('workflow.blocks.webhook.tabs.body') }}
  60. </ui-tab>
  61. <ui-tab value="response">
  62. {{ t('workflow.blocks.webhook.tabs.response') }}
  63. </ui-tab>
  64. </ui-tabs>
  65. <ui-tab-panels v-model="activeTab">
  66. <ui-tab-panel
  67. value="headers"
  68. class="grid grid-cols-7 justify-items-center mt-4 gap-2"
  69. >
  70. <template v-for="(items, index) in headers" :key="index">
  71. <ui-input
  72. v-model="items.name"
  73. :title="items.name"
  74. :placeholder="`Header ${index + 1}`"
  75. type="text"
  76. class="col-span-3"
  77. />
  78. <ui-input
  79. v-model="items.value"
  80. :title="items.value"
  81. placeholder="Value"
  82. type="text"
  83. class="col-span-3"
  84. />
  85. <button @click="removeHeader(index)">
  86. <v-remixicon name="riCloseCircleLine" size="20" />
  87. </button>
  88. </template>
  89. <ui-button class="col-span-4 mt-4 block w-full" @click="addHeader">
  90. <span> {{ t('workflow.blocks.webhook.buttons.header') }} </span>
  91. </ui-button>
  92. </ui-tab-panel>
  93. <ui-tab-panel value="body" class="mt-4">
  94. <pre
  95. v-if="!showBodyModal"
  96. class="rounded-lg text-gray-200 p-4 max-h-80 bg-gray-900 overflow-auto"
  97. @click="showBodyModal = true"
  98. v-text="data.body"
  99. />
  100. </ui-tab-panel>
  101. <ui-tab-panel value="response" class="mt-2">
  102. <ui-select
  103. :model-value="data.responseType"
  104. label="Response type"
  105. class="w-full"
  106. @change="updateData({ responseType: $event })"
  107. >
  108. <option value="json">JSON</option>
  109. <option value="text">Text</option>
  110. <option value="base64">Base64</option>
  111. </ui-select>
  112. <ui-input
  113. v-if="data.responseType === 'json'"
  114. :model-value="data.dataPath"
  115. placeholder="path.to.data"
  116. label="Data path"
  117. class="w-full mt-2"
  118. @change="updateData({ dataPath: $event })"
  119. />
  120. <insert-workflow-data
  121. :data="data"
  122. :columns="[{ name: '[Assign columns]', id: '$assignColumns' }]"
  123. variables
  124. @update="updateData"
  125. />
  126. </ui-tab-panel>
  127. </ui-tab-panels>
  128. <ui-modal
  129. v-model="showBodyModal"
  130. content-class="max-w-3xl"
  131. :title="t('workflow.blocks.webhook.tabs.body')"
  132. >
  133. <shared-codemirror
  134. :model-value="data.body"
  135. lang="json"
  136. style="height: calc(100vh - 10rem)"
  137. @change="updateData({ body: $event })"
  138. />
  139. <div class="mt-3">
  140. <a
  141. href="https://docs.automa.site/workflow/expressions.html"
  142. rel="noopener"
  143. class="border-b text-primary"
  144. target="_blank"
  145. >
  146. {{ t('message.useDynamicData') }}
  147. </a>
  148. </div>
  149. </ui-modal>
  150. </div>
  151. </template>
  152. <script setup>
  153. import { ref, watch, defineAsyncComponent } from 'vue';
  154. import { useI18n } from 'vue-i18n';
  155. import { contentTypes } from '@/utils/shared';
  156. import InsertWorkflowData from './InsertWorkflowData.vue';
  157. import EditAutocomplete from './EditAutocomplete.vue';
  158. const SharedCodemirror = defineAsyncComponent(() =>
  159. import('@/components/newtab/shared/SharedCodemirror.vue')
  160. );
  161. const props = defineProps({
  162. data: {
  163. type: Object,
  164. default: () => ({}),
  165. },
  166. });
  167. const emit = defineEmits(['update:data']);
  168. const { t } = useI18n();
  169. const methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
  170. const notHaveBody = ['GET', 'DELETE'];
  171. const activeTab = ref('headers');
  172. const showBodyModal = ref(false);
  173. const headers = ref(JSON.parse(JSON.stringify(props.data.headers)));
  174. function updateData(value) {
  175. emit('update:data', { ...props.data, ...value });
  176. }
  177. function removeHeader(index) {
  178. headers.value.splice(index, 1);
  179. }
  180. function addHeader() {
  181. headers.value.push({ name: '', value: '' });
  182. }
  183. function updateMethod(method) {
  184. if (notHaveBody.includes(method) && activeTab.value === 'body') {
  185. activeTab.value = 'headers';
  186. }
  187. updateData({ method });
  188. }
  189. watch(
  190. headers,
  191. (value) => {
  192. updateData({ headers: value });
  193. },
  194. { deep: true }
  195. );
  196. </script>
  197. <style scoped>
  198. code {
  199. @apply bg-gray-900 text-sm text-white p-1 rounded-md;
  200. }
  201. </style>