|
Lines 1-131
Link Here
|
| 1 |
<template> |
1 |
<template> |
| 2 |
<fieldset |
2 |
<template v-if="available_fields.length"> |
| 3 |
v-if="available_fields.length" |
3 |
<li class="additional-fields-header"> |
| 4 |
class="rows" |
4 |
<label></label> |
| 5 |
id="additional_fields" |
5 |
<h3>{{ $__("Additional fields") }}</h3> |
| 6 |
> |
6 |
</li> |
| 7 |
<legend>{{ $__("Additional fields") }}</legend> |
7 |
<template |
| 8 |
<ol> |
8 |
v-for="available_field in available_fields" |
|
|
9 |
v-bind:key="available_field.extended_attribute_type_id" |
| 10 |
> |
| 9 |
<template |
11 |
<template |
| 10 |
v-for="available_field in available_fields" |
12 |
v-if=" |
| 11 |
v-bind:key="available_field.extended_attribute_type_id" |
13 |
available_field.authorised_value_category_name && |
|
|
14 |
!available_field.repeatable |
| 15 |
" |
| 12 |
> |
16 |
> |
| 13 |
<template |
17 |
<li> |
| 14 |
v-if=" |
18 |
<label |
| 15 |
available_field.authorised_value_category_name && |
19 |
:for=" |
| 16 |
!available_field.repeatable |
20 |
`additional_field_` + |
| 17 |
" |
21 |
available_field.extended_attribute_type_id |
| 18 |
> |
22 |
" |
| 19 |
<li> |
23 |
>{{ available_field.name }}: |
| 20 |
<label |
24 |
</label> |
| 21 |
:for=" |
25 |
<v-select |
| 22 |
`additional_field_` + |
26 |
:id=" |
| 23 |
available_field.extended_attribute_type_id |
27 |
`additional_field_` + |
| 24 |
" |
28 |
available_field.extended_attribute_type_id |
| 25 |
>{{ available_field.name }}: |
29 |
" |
| 26 |
</label> |
30 |
:name="available_field.name" |
| 27 |
<v-select |
31 |
v-model=" |
| 28 |
:id=" |
32 |
current_additional_fields_values[ |
| 29 |
`additional_field_` + |
|
|
| 30 |
available_field.extended_attribute_type_id |
| 31 |
" |
| 32 |
:name="available_field.name" |
| 33 |
v-model=" |
| 34 |
current_additional_fields_values[ |
| 35 |
available_field.extended_attribute_type_id |
| 36 |
] |
| 37 |
" |
| 38 |
:options=" |
| 39 |
av_options[ |
| 40 |
available_field |
| 41 |
.authorised_value_category_name |
| 42 |
] |
| 43 |
" |
| 44 |
/> |
| 45 |
</li> |
| 46 |
</template> |
| 47 |
<template |
| 48 |
v-if=" |
| 49 |
available_field.authorised_value_category_name && |
| 50 |
available_field.repeatable |
| 51 |
" |
| 52 |
> |
| 53 |
<li> |
| 54 |
<label |
| 55 |
:for=" |
| 56 |
`additional_field_` + |
| 57 |
available_field.extended_attribute_type_id |
33 |
available_field.extended_attribute_type_id |
| 58 |
" |
34 |
] |
| 59 |
>{{ available_field.name }}: |
35 |
" |
| 60 |
</label> |
36 |
:options=" |
| 61 |
<v-select |
37 |
av_options[ |
| 62 |
:id=" |
38 |
available_field.authorised_value_category_name |
| 63 |
`additional_field_` + |
39 |
] |
|
|
40 |
" |
| 41 |
/> |
| 42 |
</li> |
| 43 |
</template> |
| 44 |
<template |
| 45 |
v-if=" |
| 46 |
available_field.authorised_value_category_name && |
| 47 |
available_field.repeatable |
| 48 |
" |
| 49 |
> |
| 50 |
<li> |
| 51 |
<label |
| 52 |
:for=" |
| 53 |
`additional_field_` + |
| 54 |
available_field.extended_attribute_type_id |
| 55 |
" |
| 56 |
>{{ available_field.name }}: |
| 57 |
</label> |
| 58 |
<v-select |
| 59 |
:id=" |
| 60 |
`additional_field_` + |
| 61 |
available_field.extended_attribute_type_id |
| 62 |
" |
| 63 |
:name="available_field.name" |
| 64 |
:multiple="available_field.repeatable" |
| 65 |
v-model=" |
| 66 |
current_additional_fields_values[ |
| 64 |
available_field.extended_attribute_type_id |
67 |
available_field.extended_attribute_type_id |
| 65 |
" |
68 |
] |
| 66 |
:name="available_field.name" |
69 |
" |
| 67 |
:multiple="available_field.repeatable" |
70 |
:options=" |
| 68 |
v-model=" |
71 |
av_options[ |
| 69 |
current_additional_fields_values[ |
72 |
available_field.authorised_value_category_name |
| 70 |
available_field.extended_attribute_type_id |
73 |
] |
| 71 |
] |
74 |
" |
| 72 |
" |
75 |
/> |
| 73 |
:options=" |
76 |
</li> |
| 74 |
av_options[ |
77 |
</template> |
| 75 |
available_field |
|
|
| 76 |
.authorised_value_category_name |
| 77 |
] |
| 78 |
" |
| 79 |
/> |
| 80 |
</li> |
| 81 |
</template> |
| 82 |
|
78 |
|
| 83 |
<template |
79 |
<template v-if="!available_field.authorised_value_category_name"> |
| 84 |
v-if="!available_field.authorised_value_category_name" |
80 |
<li |
|
|
81 |
v-for="current in current_additional_fields_values[ |
| 82 |
available_field.extended_attribute_type_id |
| 83 |
]" |
| 84 |
v-bind:key="current.id" |
| 85 |
> |
85 |
> |
| 86 |
<li |
86 |
<label |
| 87 |
v-for="current in current_additional_fields_values[ |
87 |
:for=" |
|
|
88 |
`additional_field_` + |
| 88 |
available_field.extended_attribute_type_id |
89 |
available_field.extended_attribute_type_id |
| 89 |
]" |
90 |
" |
| 90 |
v-bind:key="current.id" |
91 |
>{{ available_field.name }}: |
| 91 |
> |
92 |
</label> |
| 92 |
<label |
93 |
<span class="input-group"> |
| 93 |
:for=" |
94 |
<input |
|
|
95 |
type="text" |
| 96 |
v-model="current.value" |
| 97 |
:id=" |
| 94 |
`additional_field_` + |
98 |
`additional_field_` + |
| 95 |
available_field.extended_attribute_type_id |
99 |
available_field.extended_attribute_type_id |
| 96 |
" |
100 |
" |
| 97 |
>{{ available_field.name }}: |
101 |
class="input-with-clear" |
| 98 |
</label> |
102 |
/> |
| 99 |
<input type="text" v-model="current.value" /> |
103 |
<button |
|
|
104 |
v-if="current.value" |
| 105 |
type="button" |
| 106 |
class="clear-button" |
| 107 |
@click="clearField(current, $event)" |
| 108 |
:aria-label="$__('Clear')" |
| 109 |
tabindex="-1" |
| 110 |
> |
| 111 |
<i class="fa fa-times"></i> |
| 112 |
</button> |
| 113 |
</span> |
| 114 |
<template v-if="available_field.repeatable"> |
| 100 |
<a |
115 |
<a |
| 101 |
href="#" |
116 |
href="#" |
| 102 |
class="clear_attribute" |
117 |
class="btn btn-default btn-sm" |
| 103 |
@click="clearField(current, $event)" |
118 |
@click=" |
|
|
119 |
cloneField(available_field, current, $event) |
| 120 |
" |
| 104 |
> |
121 |
> |
| 105 |
<i class="fa fa-fw fa-trash-can"></i> |
122 |
<i class="fa fa-fw fa-plus"></i> |
| 106 |
{{ $__("Clear") }} |
123 |
{{ $__("New") }} |
| 107 |
</a> |
124 |
</a> |
| 108 |
<template v-if="available_field.repeatable"> |
125 |
</template> |
| 109 |
<a |
126 |
</li> |
| 110 |
href="#" |
|
|
| 111 |
class="clone_attribute" |
| 112 |
@click=" |
| 113 |
cloneField(available_field, current, $event) |
| 114 |
" |
| 115 |
> |
| 116 |
<i class="fa fa-fw fa-plus"></i> |
| 117 |
{{ $__("New") }} |
| 118 |
</a> |
| 119 |
</template> |
| 120 |
</li> |
| 121 |
</template> |
| 122 |
</template> |
127 |
</template> |
| 123 |
</ol> |
128 |
</template> |
| 124 |
</fieldset> |
129 |
</template> |
| 125 |
</template> |
130 |
</template> |
| 126 |
|
131 |
|
| 127 |
<script> |
132 |
<script> |
| 128 |
import { onBeforeMount, watch, ref, reactive } from "vue"; |
133 |
import { onBeforeMount, watch, ref, reactive, nextTick } from "vue"; |
| 129 |
import { APIClient } from "../fetch/api-client.js"; |
134 |
import { APIClient } from "../fetch/api-client.js"; |
| 130 |
|
135 |
|
| 131 |
export default { |
136 |
export default { |
|
Lines 149-165
export default {
Link Here
|
| 149 |
}); |
154 |
}); |
| 150 |
|
155 |
|
| 151 |
const clearField = (current_field, event) => { |
156 |
const clearField = (current_field, event) => { |
| 152 |
event.preventDefault(); |
157 |
if (event) { |
|
|
158 |
event.preventDefault(); |
| 159 |
} |
| 153 |
current_field.value = ""; |
160 |
current_field.value = ""; |
| 154 |
}; |
161 |
}; |
| 155 |
const cloneField = (available_field, current, event) => { |
162 |
const cloneField = (available_field, current, event) => { |
| 156 |
event.preventDefault(); |
163 |
event.preventDefault(); |
| 157 |
current_additional_fields_values[ |
164 |
const fieldArray = |
| 158 |
available_field.extended_attribute_type_id |
165 |
current_additional_fields_values[ |
| 159 |
].push({ |
166 |
available_field.extended_attribute_type_id |
| 160 |
value: current.value, |
167 |
]; |
|
|
168 |
fieldArray.push({ |
| 169 |
value: "", |
| 161 |
label: available_field.name, |
170 |
label: available_field.name, |
| 162 |
}); |
171 |
}); |
|
|
172 |
|
| 173 |
// Focus the newly created field after DOM updates |
| 174 |
nextTick(() => { |
| 175 |
const fieldId = `additional_field_${available_field.extended_attribute_type_id}`; |
| 176 |
const inputs = document.querySelectorAll( |
| 177 |
`input[id="${fieldId}"]` |
| 178 |
); |
| 179 |
if (inputs.length > 0) { |
| 180 |
// Focus the last input (the newly added one) |
| 181 |
inputs[inputs.length - 1].focus(); |
| 182 |
} |
| 183 |
}); |
| 163 |
}; |
184 |
}; |
| 164 |
|
185 |
|
| 165 |
const updateParentAdditionalFieldValues = |
186 |
const updateParentAdditionalFieldValues = |
|
Lines 311-313
export default {
Link Here
|
| 311 |
emits: ["additional-fields-changed"], |
332 |
emits: ["additional-fields-changed"], |
| 312 |
}; |
333 |
}; |
| 313 |
</script> |
334 |
</script> |
| 314 |
- |
335 |
|
|
|
336 |
<style scoped> |
| 337 |
/* Header for additional fields section */ |
| 338 |
.additional-fields-header { |
| 339 |
border-top: 1px solid #ddd; |
| 340 |
margin-top: 1em; |
| 341 |
padding-top: 1em; |
| 342 |
} |
| 343 |
|
| 344 |
.additional-fields-header h3 { |
| 345 |
margin: 0; |
| 346 |
font-size: 110%; |
| 347 |
font-weight: bold; |
| 348 |
color: #696969; |
| 349 |
} |
| 350 |
|
| 351 |
.additional-fields-header label { |
| 352 |
/* Empty label for alignment with other fields */ |
| 353 |
width: 10rem; |
| 354 |
} |
| 355 |
|
| 356 |
/* Input group container for positioning */ |
| 357 |
.input-group { |
| 358 |
position: relative; |
| 359 |
display: inline; |
| 360 |
} |
| 361 |
|
| 362 |
/* Input with clear button gets padding for the button */ |
| 363 |
input.input-with-clear { |
| 364 |
padding-right: 2rem; |
| 365 |
} |
| 366 |
|
| 367 |
.clear-button { |
| 368 |
position: absolute; |
| 369 |
right: 0.25rem; |
| 370 |
top: 50%; |
| 371 |
transform: translateY(-50%); |
| 372 |
background: transparent; |
| 373 |
border: none; |
| 374 |
color: #999; |
| 375 |
cursor: pointer; |
| 376 |
padding: 0.25rem 0.5rem; |
| 377 |
line-height: 1; |
| 378 |
transition: color 0.15s ease-in-out; |
| 379 |
z-index: 10; |
| 380 |
height: 1.5rem; |
| 381 |
display: flex; |
| 382 |
align-items: center; |
| 383 |
justify-content: center; |
| 384 |
margin: 0; |
| 385 |
} |
| 386 |
|
| 387 |
.clear-button:hover { |
| 388 |
color: #333; |
| 389 |
} |
| 390 |
|
| 391 |
.clear-button:focus { |
| 392 |
outline: 2px solid #007bff; |
| 393 |
outline-offset: 2px; |
| 394 |
border-radius: 2px; |
| 395 |
} |
| 396 |
|
| 397 |
.clear-button i { |
| 398 |
font-size: 1rem; |
| 399 |
} |
| 400 |
|
| 401 |
/* New button spacing */ |
| 402 |
.btn.btn-sm { |
| 403 |
margin-left: 0.5rem; |
| 404 |
} |
| 405 |
</style> |