Skip to content

Commit 7f00817

Browse files
author
Prachya Saechua
committed
feat: enhance handling of select type variables in TaskParamsForm for improved default value normalization
Signed-off-by: Prachya Saechua <psaechua@cpaxtra.co.th>
1 parent 0a3e86e commit 7f00817

File tree

1 file changed

+130
-100
lines changed

1 file changed

+130
-100
lines changed

web/src/components/TaskParamsForm.vue

Lines changed: 130 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,107 @@
11
<template>
22
<div>
3-
<v-text-field
4-
v-model="item.message"
5-
:label="$t('messageOptional')"
6-
outlined
7-
dense
8-
/>
9-
10-
<div v-for="(v) in template.survey_vars || []" :key="v.name">
3+
<v-text-field v-model="item.message" :label="$t('messageOptional')" outlined dense />
114

5+
<div v-for="v in template.survey_vars || []" :key="v.name">
126
<v-text-field
13-
v-if="v.type === 'secret'"
14-
:label="v.title"
15-
:hint="v.description"
16-
v-model="editedSecretEnvironment[v.name]"
17-
:required="v.required"
18-
type="password"
19-
:rules="[
20-
val => !v.required || !!val || v.title + $t('isRequired'),
21-
]"
22-
outlined
23-
dense
7+
v-if="v.type === 'secret'"
8+
:label="v.title"
9+
:hint="v.description"
10+
v-model="editedSecretEnvironment[v.name]"
11+
:required="v.required"
12+
type="password"
13+
:rules="[(val) => !v.required || !!val || v.title + $t('isRequired')]"
14+
outlined
15+
dense
2416
/>
2517

2618
<v-select
27-
clearable
28-
v-else-if="v.type === 'enum'"
29-
:label="v.title + (v.required ? ' *' : '')"
30-
:hint="v.description"
31-
v-model="editedEnvironment[v.name]"
32-
:required="v.required"
33-
:rules="[
34-
val => !v.required || val != null || v.title + ' ' + $t('isRequired')
35-
]"
36-
:items="v.values"
37-
item-text="name"
38-
item-value="value"
39-
outlined
40-
dense
41-
/>
19+
clearable
20+
v-else-if="v.type === 'enum' || v.type === 'select'"
21+
:label="v.title + (v.required ? ' *' : '')"
22+
:hint="v.description"
23+
v-model="editedEnvironment[v.name]"
24+
:required="v.required"
25+
:rules="[(val) => !v.required || val != null || v.title + ' ' + $t('isRequired')]"
26+
:items="v.values"
27+
item-text="name"
28+
item-value="value"
29+
:multiple="v.type === 'select'"
30+
:chips="v.type === 'select'"
31+
outlined
32+
dense
33+
>
34+
<template v-slot:selection="{ item, index }" v-if="v.type === 'select'">
35+
<v-chip small close @click:close="removeSelectedItem(v.name, index)"
36+
>{{ item.name || item }}
37+
</v-chip>
38+
</template>
39+
</v-select>
4240

4341
<v-text-field
44-
v-else
45-
:label="v.title + (v.required ? ' *' : '')"
46-
:hint="v.description"
47-
v-model="editedEnvironment[v.name]"
48-
:required="v.required"
49-
:rules="[
50-
val => !v.required || !!val || v.title + ' ' + $t('isRequired'),
51-
val => !val || v.type !== 'int' || /^\d+$/.test(val) ||
52-
v.title + ' ' + $t('mustBeInteger'),
42+
v-else
43+
:label="v.title + (v.required ? ' *' : '')"
44+
:hint="v.description"
45+
v-model="editedEnvironment[v.name]"
46+
:required="v.required"
47+
:rules="[
48+
(val) => !v.required || !!val || v.title + ' ' + $t('isRequired'),
49+
(val) =>
50+
!val || v.type !== 'int' || /^\d+$/.test(val) || v.title + ' ' + $t('mustBeInteger'),
5351
]"
54-
outlined
55-
dense
52+
outlined
53+
dense
5654
/>
5755
</div>
5856

5957
<v-text-field
60-
v-model="git_branch"
61-
:label="fieldLabel('branch')"
62-
outlined
63-
dense
64-
required
65-
v-if="
66-
needField('allow_override_branch')
67-
&& template.allow_override_branch_in_task"
58+
v-model="git_branch"
59+
:label="fieldLabel('branch')"
60+
outlined
61+
dense
62+
required
63+
v-if="needField('allow_override_branch') && template.allow_override_branch_in_task"
6864
/>
6965

7066
<v-autocomplete
71-
v-model="inventory_id"
72-
:label="fieldLabel('inventory')"
73-
:items="inventory"
74-
item-value="id"
75-
item-text="name"
76-
outlined
77-
dense
78-
required
79-
v-if="inventory != null && needInventory"
67+
v-model="inventory_id"
68+
:label="fieldLabel('inventory')"
69+
:items="inventory"
70+
item-value="id"
71+
item-text="name"
72+
outlined
73+
dense
74+
required
75+
v-if="inventory != null && needInventory"
8076
></v-autocomplete>
8177

8278
<v-skeleton-loader
83-
v-else-if="needInventory"
84-
type="card"
85-
height="46"
86-
style="margin-bottom: 16px; margin-top: 4px;"
79+
v-else-if="needInventory"
80+
type="card"
81+
height="46"
82+
style="margin-bottom: 16px; margin-top: 4px"
8783
></v-skeleton-loader>
8884

8985
<TaskParamsAnsibleForm
90-
v-if="template.app === 'ansible'"
91-
v-model="item.params"
92-
:app="template.app"
93-
:template-params="template.task_params || {}"
86+
v-if="template.app === 'ansible'"
87+
v-model="item.params"
88+
:app="template.app"
89+
:template-params="template.task_params || {}"
9490
/>
9591

9692
<TaskParamsTerraformForm
97-
v-else-if="['terraform', 'tofu', 'terragrunt'].includes(template.app)"
98-
v-model="item.params"
99-
:app="template.app"
100-
:template-params="template.task_params || {}"
93+
v-else-if="['terraform', 'tofu', 'terragrunt'].includes(template.app)"
94+
v-model="item.params"
95+
:app="template.app"
96+
:template-params="template.task_params || {}"
10197
/>
10298

10399
<ArgsPicker
104-
v-if="template.allow_override_args_in_task"
105-
:vars="args"
106-
title="CLI args"
107-
@change="setArgs"
100+
v-if="template.allow_override_args_in_task"
101+
:vars="args"
102+
title="CLI args"
103+
@change="setArgs"
108104
/>
109-
110105
</div>
111106
</template>
112107
<script>
@@ -236,7 +231,6 @@ export default {
236231
},
237232
238233
methods: {
239-
240234
setArgs(args) {
241235
this.item.arguments = JSON.stringify(args || []);
242236
},
@@ -254,6 +248,19 @@ export default {
254248
255249
this.editedEnvironment = JSON.parse(v.environment || '{}');
256250
this.editedSecretEnvironment = JSON.parse(v.secret || '{}');
251+
252+
// Normalize select type variables to ensure they are arrays
253+
if (this.template && this.template.survey_vars) {
254+
this.template.survey_vars.forEach((surveyVar) => {
255+
if (surveyVar.type === 'select' && this.editedEnvironment[surveyVar.name] !== undefined) {
256+
const currentValue = this.editedEnvironment[surveyVar.name];
257+
if (!Array.isArray(currentValue)) {
258+
this.editedEnvironment[surveyVar.name] =
259+
currentValue == null || currentValue === '' ? [] : [currentValue];
260+
}
261+
}
262+
});
263+
}
257264
},
258265
259266
isLoaded() {
@@ -277,22 +284,26 @@ export default {
277284
async afterLoadData() {
278285
this.refreshItem();
279286
280-
[
281-
this.buildTasks,
282-
this.inventory,
283-
] = await Promise.all([
284-
285-
this.template.type === 'deploy' ? (await axios({
286-
keys: 'get',
287-
url: `/api/project/${this.projectId}/templates/${this.template.build_template_id}/tasks?status=success&limit=20`,
288-
responseType: 'json',
289-
})).data.filter((task) => task.status === 'success') : [],
290-
291-
this.needInventory ? (await axios({
292-
keys: 'get',
293-
url: this.getInventoryUrl(),
294-
responseType: 'json',
295-
})).data : [],
287+
[this.buildTasks, this.inventory] = await Promise.all([
288+
this.template.type === 'deploy'
289+
? (
290+
await axios({
291+
keys: 'get',
292+
url: `/api/project/${this.projectId}/templates/${this.template.build_template_id}/tasks?status=success&limit=20`,
293+
responseType: 'json',
294+
})
295+
).data.filter((task) => task.status === 'success')
296+
: [],
297+
298+
this.needInventory
299+
? (
300+
await axios({
301+
keys: 'get',
302+
url: this.getInventoryUrl(),
303+
responseType: 'json',
304+
})
305+
).data
306+
: [],
296307
]);
297308
298309
['tags', 'limit', 'skip_tags'].forEach((param) => {
@@ -303,15 +314,25 @@ export default {
303314
304315
const defaultVars = (this.template.survey_vars || [])
305316
.filter((s) => s.default_value)
306-
.reduce((res, curr) => ({
307-
...res,
308-
[curr.name]: curr.default_value,
309-
}), {});
317+
.reduce(
318+
(res, curr) => ({
319+
...res,
320+
[curr.name]: curr.default_value,
321+
}),
322+
{},
323+
);
310324
311325
this.editedEnvironment = {
312326
...defaultVars,
313327
...this.editedEnvironment,
314328
};
329+
330+
// Ensure select type variables without values are initialized as empty arrays
331+
(this.template.survey_vars || []).forEach((surveyVar) => {
332+
if (surveyVar.type === 'select' && this.editedEnvironment[surveyVar.name] === undefined) {
333+
this.editedEnvironment[surveyVar.name] = [];
334+
}
335+
});
315336
},
316337
317338
getInventoryUrl() {
@@ -326,6 +347,15 @@ export default {
326347
}
327348
return res;
328349
},
350+
351+
removeSelectedItem(varName, index) {
352+
if (!this.editedEnvironment[varName] || !Array.isArray(this.editedEnvironment[varName])) {
353+
return;
354+
}
355+
if (index >= 0 && index < this.editedEnvironment[varName].length) {
356+
this.editedEnvironment[varName].splice(index, 1);
357+
}
358+
},
329359
},
330360
};
331361
</script>

0 commit comments

Comments
 (0)