/
wax_boy
/
semaphore_custom
Обзор
Документация
Войти
/
wax_boy
/
semaphore_custom
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
web/src/components/TaskParamsForm.vue
343 строки
8 KB
Denis Gukov
feat(survey_vars): add type text
14 июл 2026, 09:38
Не верифицирован
14 июл 2026, 09:38
972d878
Код
Авторство
О чём код?
<template> <div> <v-text-field v-model="item.message" :label="$t('messageOptional')" outlined dense /> <div v-for="v in template.survey_vars || []" :key="v.name"> <v-text-field v-if="v.type === 'secret'" :label="v.title" :hint="v.description" v-model="editedSecretEnvironment[v.name]" :required="v.required" class="masked-secret-input" :rules="[(val) => !v.required || !!val || v.title + $t('isRequired')]" outlined dense /> <v-select clearable v-else-if="v.type === 'enum'" :label="v.title + (v.required ? ' *' : '')" :hint="v.description" v-model="editedEnvironment[v.name]" :required="v.required" :rules="[(val) => !v.required || val != null || v.title + ' ' + $t('isRequired')]" :items="v.values" item-text="name" item-value="value" outlined dense /> <v-textarea v-else-if="v.type === 'text'" :label="v.title + (v.required ? ' *' : '')" :hint="v.description" v-model="editedEnvironment[v.name]" :required="v.required" :rules="[(val) => !v.required || !!val || v.title + ' ' + $t('isRequired')]" rows="3" auto-grow outlined dense /> <v-text-field v-else :label="v.title + (v.required ? ' *' : '')" :hint="v.description" v-model="editedEnvironment[v.name]" :required="v.required" :rules="[ (val) => !v.required || !!val || v.title + ' ' + $t('isRequired'), (val) => !val || v.type !== 'int' || /^\d+$/.test(val) || v.title + ' ' + $t('mustBeInteger'), ]" outlined dense /> </div> <v-text-field v-model="git_branch" :label="fieldLabel('branch')" outlined dense required v-if="needField('allow_override_branch') && template.allow_override_branch_in_task" /> <v-autocomplete v-model="inventory_id" :label="fieldLabel('inventory')" :items="inventory" item-value="id" item-text="name" outlined dense required v-if="inventory != null && needInventory" ></v-autocomplete> <v-skeleton-loader v-else-if="needInventory" type="card" height="46" style="margin-bottom: 16px; margin-top: 4px" ></v-skeleton-loader> <TaskParamsAnsibleForm v-if="template.app === 'ansible'" v-model="item.params" :app="template.app" :template-params="template.task_params || {}" /> <TaskParamsTerraformForm v-else-if="['terraform', 'tofu', 'terragrunt'].includes(template.app)" v-model="item.params" :app="template.app" :template-params="template.task_params || {}" /> <ArgsPicker v-if="template.allow_override_args_in_task" :vars="args" title="CLI args" @change="setArgs" /> </div> </template> <script> /* eslint-disable import/no-extraneous-dependencies,import/extensions */ import axios from 'axios'; import ArgsPicker from '@/components/ArgsPicker.vue'; import AppFieldsMixin from '@/components/AppFieldsMixin'; import TaskParamsAnsibleForm from '@/components/TaskParamsAnsibleForm.vue'; import TaskParamsTerraformForm from '@/components/TaskParamsTerraformForm.vue'; export default { mixins: [AppFieldsMixin], props: { value: Object, template: Object, }, components: { TaskParamsAnsibleForm, TaskParamsTerraformForm, ArgsPicker, }, data() { return { item: null, editedEnvironment: null, editedSecretEnvironment: null, inventory: null, }; }, computed: { needInventory() { return this.template.task_params?.allow_override_inventory; }, args() { let res = this.item.arguments; if (res == null) { res = this.template.arguments; } if (res == null) { res = '[]'; } return JSON.parse(res); }, app() { return this.template.app; }, inventory_id: { get() { return (this.item || {}).inventory_id || this.template.inventory_id; }, set(newValue) { this.item.inventory_id = newValue; }, }, git_branch: { get() { return (this.item || {}).git_branch || this.template.git_branch; }, set(newValue) { this.item.git_branch = newValue; }, }, }, watch: { editedEnvironment: { handler(newVal, oldVal) { if (oldVal == null) { return; } this.item.environment = JSON.stringify(this.editedEnvironment); this.$emit('input', this.item); }, deep: true, immediate: true, }, editedSecretEnvironment: { handler(newVal, oldVal) { if (oldVal == null) { return; } this.item.secret = JSON.stringify(this.editedSecretEnvironment); this.$emit('input', this.item); }, deep: true, immediate: true, }, item: { handler(newVal, oldVal) { if (oldVal == null) { return; } this.$emit('input', newVal); }, deep: true, immediate: true, }, needReset(val) { if (val) { // if (this.item) { // this.item.template_id = this.template.id; // } this.buildTasks = null; this.inventory = null; // this.template = null; } }, }, async created() { await this.afterLoadData(); }, methods: { setArgs(args) { this.item.arguments = JSON.stringify(args || []); }, assignItem(val) { const v = val || {}; // Build the item in one assignment so every edited key is reactive and // the deep `item` watcher (which emits `input`) fires on any change. // Keys added to an already-reactive object one by one are NOT reactive // in Vue 2, which silently swallowed edits of params/message/branch/etc. this.item = { message: '', arguments: null, git_branch: null, inventory_id: null, params: {}, ...this.item, ...v, }; this.editedEnvironment = JSON.parse(v.environment || '{}'); this.editedSecretEnvironment = JSON.parse(v.secret || '{}'); }, isLoaded() { return this.item != null && this.template != null; }, refreshItem() { this.assignItem(this.value); if (!this.item.params) { this.item.params = {}; } ['tags', 'limit', 'skip_tags'].forEach((param) => { if (!this.item.params[param]) { this.item.params[param] = (this.template.task_params || {})[param]; } }); }, async afterLoadData() { this.refreshItem(); [this.buildTasks, this.inventory] = await Promise.all([ this.template.type === 'deploy' ? ( await axios({ keys: 'get', url: `/api/project/${this.template.project_id}/templates/${this.template.build_template_id}/tasks?status=success&limit=20`, responseType: 'json', }) ).data.filter((task) => task.status === 'success') : [], this.needInventory ? ( await axios({ keys: 'get', url: this.getInventoryUrl(), responseType: 'json', }) ).data : [], ]); ['tags', 'limit', 'skip_tags'].forEach((param) => { if (!this.item.params[param]) { this.item.params[param] = (this.template.task_params || {})[param]; } }); const defaultVars = (this.template.survey_vars || []) .filter((s) => s.default_value) .reduce( (res, curr) => ({ ...res, [curr.name]: curr.default_value, }), {}, ); this.editedEnvironment = { ...defaultVars, ...this.editedEnvironment, }; }, getInventoryUrl() { let res = `/api/project/${this.template.project_id}/inventory?app=${this.app}`; switch (this.app) { case 'terraform': case 'tofu': res += `&template_id=${this.template.id}`; break; default: break; } return res; }, }, }; </script>