pui9-components 1.17.3 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pui9-components.common.js +75007 -52512
- package/dist/pui9-components.css +9 -2
- package/package-lock.json +6651 -6827
- package/package.json +22 -26
- package/src/components/PuiCauDialog.vue +192 -0
- package/src/components/PuiCheckbox.vue +25 -4
- package/src/components/PuiCodeEditor.vue +2 -1
- package/src/components/PuiDateField.vue +653 -614
- package/src/components/PuiField.vue +1 -1
- package/src/components/PuiFileUpload.vue +275 -0
- package/src/components/PuiFileUploadGroup.vue +241 -0
- package/src/components/PuiFilter.vue +54 -52
- package/src/components/PuiFilterGroup.vue +179 -179
- package/src/components/PuiFilterRule.vue +481 -162
- package/src/components/PuiFormFooter.vue +5 -38
- package/src/components/PuiFormTooltip.vue +50 -0
- package/src/components/PuiMasterDetail.vue +18 -11
- package/src/components/PuiModalDialog.vue +4 -1
- package/src/components/PuiModalDialogForm.vue +5 -1
- package/src/components/PuiMultiSelect.vue +383 -280
- package/src/components/PuiNumberField.vue +216 -285
- package/src/components/PuiRichTextEditor.vue +43 -44
- package/src/components/PuiSelect.vue +382 -355
- package/src/components/PuiSelectDetailDialog.vue +10 -3
- package/src/components/PuiSelectorList.vue +169 -0
- package/src/components/PuiSort.vue +98 -0
- package/src/components/PuiSpinnerField.vue +101 -121
- package/src/components/PuiTextField.vue +374 -258
- package/src/index.js +8 -0
- package/src/main.js +1 -0
- package/src/mixins/PuiFormComponentMixin.js +2 -8
- package/src/mixins/PuiSortMixin.js +136 -0
- package/src/mixins/PuiUtilsNumberMixin.js +15 -5
- package/src/plugins/vuetify.js +2 -1
- package/src/utils.js +10 -0
- package/dist/demo.html +0 -10
- package/dist/pui9-components.common.js.map +0 -1
- package/dist/pui9-components.umd.js +0 -86432
- package/dist/pui9-components.umd.js.map +0 -1
- package/dist/pui9-components.umd.min.js +0 -308
- package/dist/pui9-components.umd.min.js.map +0 -1
- package/src/mixins/PuiFilterMixin.js +0 -157
- package/src/mixins/PuiMultiSelectMixin.js +0 -106
|
@@ -2,95 +2,78 @@
|
|
|
2
2
|
<v-layout wrap class="pui-multiselect">
|
|
3
3
|
<v-flex xs12>
|
|
4
4
|
<v-card :flat="flat" elevation="0">
|
|
5
|
-
<
|
|
5
|
+
<v-container class="pb-2 mb-n2" :class="{ 'pui-multiselect--flat': flat, 'pui-multiselect--disabled': disabled }">
|
|
6
6
|
<v-layout wrap>
|
|
7
7
|
<v-flex xs12 sm6>
|
|
8
8
|
<!-- slot1, TODO MAKE SLOTS IN FILTER AND SORTING DIALOGS-->
|
|
9
|
-
<v-flex xs12 class="pt-
|
|
9
|
+
<v-flex xs12 class="pa-2 pt-0 pl-1">
|
|
10
10
|
<span class="pui-dialog__title pui-dialog__title--margin">
|
|
11
11
|
{{ $t(textAvailable) }}
|
|
12
12
|
</span>
|
|
13
13
|
</v-flex>
|
|
14
14
|
<v-flex xs12 class="pui-multiselect__searchpanel">
|
|
15
15
|
<pui-text-field
|
|
16
|
-
:placeholder="
|
|
17
|
-
v-model="
|
|
16
|
+
:placeholder="$t('pui9.components.multiSelect.search')"
|
|
17
|
+
v-model="searchTextAvailableItems"
|
|
18
18
|
clearable
|
|
19
19
|
prepend-inner-icon="far fa-search"
|
|
20
20
|
noeditable
|
|
21
21
|
realtime
|
|
22
22
|
></pui-text-field>
|
|
23
23
|
</v-flex>
|
|
24
|
-
<v-flex xs12>
|
|
24
|
+
<v-flex xs12 class="py-0 px-1">
|
|
25
25
|
<v-list
|
|
26
|
-
:style="
|
|
27
|
-
|
|
26
|
+
:style="`height: ${heightList}px`"
|
|
27
|
+
:two-line="itemDescription !== null"
|
|
28
|
+
class="overflow-y-auto pui-multiselect__itemListContainer"
|
|
28
29
|
>
|
|
29
30
|
<draggable
|
|
30
31
|
v-model="availableItems"
|
|
31
32
|
v-bind="dragOptions"
|
|
32
|
-
@change="
|
|
33
|
-
@end="
|
|
34
|
-
searchSelected = '';
|
|
35
|
-
setSelectedItems();
|
|
36
|
-
"
|
|
33
|
+
@change="onChangeAvailableItems"
|
|
37
34
|
class="pui-multiselect__item-draggable"
|
|
38
|
-
:class="{ 'pui-multiselect__item--tall':
|
|
35
|
+
:class="{ 'pui-multiselect__item--tall': filteredAvailableItems.length === 0 }"
|
|
39
36
|
>
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
:disabled="disabled"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
</
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
v-bind="attrs"
|
|
81
|
-
v-on="on"
|
|
82
|
-
:disabled="disabled"
|
|
83
|
-
>
|
|
84
|
-
<v-icon>far fa-info-circle</v-icon>
|
|
85
|
-
</v-btn>
|
|
86
|
-
</template>
|
|
87
|
-
<span v-html="item[itemTooltip]"/>
|
|
88
|
-
</v-tooltip>
|
|
89
|
-
</v-list-item-action>
|
|
90
|
-
</v-list-item>
|
|
91
|
-
</v-flex>
|
|
92
|
-
</v-layout>
|
|
93
|
-
</template>
|
|
37
|
+
<v-layout
|
|
38
|
+
v-for="(item, index) in filteredAvailableItems"
|
|
39
|
+
:key="`${index}__${item.itemText}__${item.itemValue}`"
|
|
40
|
+
class="pui-multiselect__item"
|
|
41
|
+
>
|
|
42
|
+
<v-flex xs1 d-flex align-center>
|
|
43
|
+
<v-list-item class="move draggable_point">
|
|
44
|
+
<v-icon small>far fa-ellipsis-v</v-icon>
|
|
45
|
+
<v-icon small>far fa-ellipsis-v</v-icon>
|
|
46
|
+
</v-list-item>
|
|
47
|
+
</v-flex>
|
|
48
|
+
<v-flex xs11>
|
|
49
|
+
<v-list-item class>
|
|
50
|
+
<v-list-item-content @dblclick="selectItemFromClick(item)">
|
|
51
|
+
<v-list-item-title
|
|
52
|
+
class="pui-multiselect--title"
|
|
53
|
+
v-html="item[itemText]"
|
|
54
|
+
:title="item[itemText]"
|
|
55
|
+
></v-list-item-title>
|
|
56
|
+
<v-list-item-subtitle
|
|
57
|
+
v-if="itemDescription"
|
|
58
|
+
v-html="item[itemDescription]"
|
|
59
|
+
></v-list-item-subtitle>
|
|
60
|
+
</v-list-item-content>
|
|
61
|
+
<v-list-item-action>
|
|
62
|
+
<v-btn x-small icon ripple @click.native="selectItemFromClick(item)" :disabled="disabled">
|
|
63
|
+
<v-icon>far fa-plus</v-icon>
|
|
64
|
+
</v-btn>
|
|
65
|
+
<v-tooltip class="overflow-y-hidden" max-width="30%" max-height="30%" top v-if="itemTooltip">
|
|
66
|
+
<template v-slot:activator="{ on, attrs }">
|
|
67
|
+
<v-btn x-small icon ripple v-bind="attrs" v-on="on" :disabled="disabled">
|
|
68
|
+
<v-icon>far fa-info-circle</v-icon>
|
|
69
|
+
</v-btn>
|
|
70
|
+
</template>
|
|
71
|
+
<div class="tooltipText">{{ itemTooltip }}</div>
|
|
72
|
+
</v-tooltip>
|
|
73
|
+
</v-list-item-action>
|
|
74
|
+
</v-list-item>
|
|
75
|
+
</v-flex>
|
|
76
|
+
</v-layout>
|
|
94
77
|
</draggable>
|
|
95
78
|
<v-card v-show="availableItems.length === 0" flat class="pui-multiselect__itemListContainer-cardHelper pl-3 pr-3">
|
|
96
79
|
<div class="pui-multiselect__itemListContainer-cardHelper-text pb-1 pl-2 pr-2">
|
|
@@ -107,24 +90,24 @@
|
|
|
107
90
|
</v-flex>
|
|
108
91
|
<v-flex xs12 sm6>
|
|
109
92
|
<v-layout wrap>
|
|
110
|
-
<v-flex xs12 class="pt-
|
|
93
|
+
<v-flex xs12 class="pa-2 pt-0 pl-1">
|
|
111
94
|
<span class="pui-dialog__title pui-dialog__title--margin">
|
|
112
95
|
{{ $t(textSelected) }}
|
|
113
96
|
</span>
|
|
114
97
|
</v-flex>
|
|
115
98
|
<v-flex xs12 class="pui-multiselect__searchpanel">
|
|
116
99
|
<pui-text-field
|
|
117
|
-
:placeholder="
|
|
118
|
-
v-model="
|
|
100
|
+
:placeholder="$t('pui9.components.multiSelect.search')"
|
|
101
|
+
v-model="searchTextSelectedItems"
|
|
119
102
|
clearable
|
|
120
103
|
prepend-inner-icon="far fa-search"
|
|
121
104
|
noeditable
|
|
122
105
|
realtime
|
|
123
106
|
></pui-text-field>
|
|
124
107
|
</v-flex>
|
|
125
|
-
<v-flex xs12>
|
|
108
|
+
<v-flex xs12 class="py-0 px-1">
|
|
126
109
|
<v-list
|
|
127
|
-
:style="
|
|
110
|
+
:style="`height: ${heightList}px`"
|
|
128
111
|
:two-line="itemDescription !== null"
|
|
129
112
|
class="overflow-y-auto pui-multiselect__itemListContainer"
|
|
130
113
|
:class="compClassItemListSelected"
|
|
@@ -132,68 +115,56 @@
|
|
|
132
115
|
<draggable
|
|
133
116
|
v-model="selectedItems"
|
|
134
117
|
v-bind="dragOptions"
|
|
135
|
-
@change="
|
|
136
|
-
@end="
|
|
137
|
-
searchAvailable = '';
|
|
138
|
-
setSelectedItems();
|
|
139
|
-
"
|
|
118
|
+
@change="onChangeSelectedItems"
|
|
140
119
|
class="pui-multiselect__item-draggable"
|
|
141
|
-
:class="{ 'pui-multiselect__item--tall':
|
|
120
|
+
:class="{ 'pui-multiselect__item--tall': filteredSelectedItems.length === 0 }"
|
|
142
121
|
>
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
</template>
|
|
190
|
-
<span v-html="item[itemTooltip]"/>
|
|
191
|
-
</v-tooltip>
|
|
192
|
-
</v-list-item-action>
|
|
193
|
-
</v-list-item>
|
|
194
|
-
</v-flex>
|
|
195
|
-
</v-layout>
|
|
196
|
-
</template>
|
|
122
|
+
<v-layout
|
|
123
|
+
v-for="(item, index) in filteredSelectedItems"
|
|
124
|
+
:key="`${index}__${item.itemText}__${item.itemValue}`"
|
|
125
|
+
class="pui-multiselect__item"
|
|
126
|
+
>
|
|
127
|
+
<v-flex xs1 d-flex align-center>
|
|
128
|
+
<v-list-item class="move draggable_point">
|
|
129
|
+
<v-icon small>far fa-ellipsis-v</v-icon>
|
|
130
|
+
<v-icon small>far fa-ellipsis-v</v-icon>
|
|
131
|
+
</v-list-item>
|
|
132
|
+
</v-flex>
|
|
133
|
+
<v-flex xs11>
|
|
134
|
+
<v-list-item>
|
|
135
|
+
<v-list-item-content @dblclick="unselectItemFromClick(item)">
|
|
136
|
+
<v-list-item-title
|
|
137
|
+
class="pui-multiselect--title"
|
|
138
|
+
v-html="item[itemText]"
|
|
139
|
+
:title="item[itemText]"
|
|
140
|
+
></v-list-item-title>
|
|
141
|
+
<v-list-item-subtitle
|
|
142
|
+
v-if="itemDescription"
|
|
143
|
+
v-html="item[itemDescription]"
|
|
144
|
+
></v-list-item-subtitle>
|
|
145
|
+
</v-list-item-content>
|
|
146
|
+
<v-list-item-action>
|
|
147
|
+
<v-btn
|
|
148
|
+
x-small
|
|
149
|
+
icon
|
|
150
|
+
ripple
|
|
151
|
+
@click.native="unselectItemFromClick(item)"
|
|
152
|
+
:disabled="disabled"
|
|
153
|
+
>
|
|
154
|
+
<v-icon>far fa-times</v-icon>
|
|
155
|
+
</v-btn>
|
|
156
|
+
<v-tooltip top v-if="itemTooltip">
|
|
157
|
+
<template v-slot:activator="{ on, attrs }">
|
|
158
|
+
<v-btn x-small icon ripple v-bind="attrs" v-on="on" :disabled="disabled">
|
|
159
|
+
<v-icon>far fa-info-circle</v-icon>
|
|
160
|
+
</v-btn>
|
|
161
|
+
</template>
|
|
162
|
+
<span v-html="item[itemTooltip]" />
|
|
163
|
+
</v-tooltip>
|
|
164
|
+
</v-list-item-action>
|
|
165
|
+
</v-list-item>
|
|
166
|
+
</v-flex>
|
|
167
|
+
</v-layout>
|
|
197
168
|
</draggable>
|
|
198
169
|
<v-card
|
|
199
170
|
v-show="selectedItems.length === 0"
|
|
@@ -219,15 +190,16 @@
|
|
|
219
190
|
text
|
|
220
191
|
outlined
|
|
221
192
|
:disabled="disabled || availableItems.length === 0"
|
|
222
|
-
class="puiToolbar-dialog__button"
|
|
193
|
+
class="puiToolbar-dialog__button ml-n1 mt-3 mr-2"
|
|
223
194
|
@click.native="selectAllItems()"
|
|
224
195
|
>{{ $t('pui9.components.multiSelect.add_all') }}</v-btn
|
|
225
196
|
>
|
|
197
|
+
<span class="pl-2 mt-3">{{ `${availableItems.length} ${$t('pui9.components.multiSelect.available').toLowerCase()}` }}</span>
|
|
226
198
|
<v-spacer></v-spacer>
|
|
227
|
-
<span class="pr-2" v-show="selectedItems.length === 1">{{
|
|
199
|
+
<span class="pr-2 mt-3" v-show="selectedItems.length === 1">{{
|
|
228
200
|
`${selectedItems.length} ${$t('pui9.components.multiSelect.selected_item')}`
|
|
229
201
|
}}</span>
|
|
230
|
-
<span class="pr-2" v-show="selectedItems.length > 1">{{
|
|
202
|
+
<span class="pr-2 mt-3" v-show="selectedItems.length > 1">{{
|
|
231
203
|
`${selectedItems.length} ${$t('pui9.components.multiSelect.selected_items')}`
|
|
232
204
|
}}</span>
|
|
233
205
|
<v-btn
|
|
@@ -235,33 +207,63 @@
|
|
|
235
207
|
outlined
|
|
236
208
|
:disabled="disabled || selectedItems.length === 0"
|
|
237
209
|
@click.native="unselectAllItems()"
|
|
238
|
-
class="puiToolbar-dialog__button"
|
|
210
|
+
class="puiToolbar-dialog__button mr-n1 mt-3"
|
|
239
211
|
>{{ $t('pui9.components.multiSelect.empty') }}</v-btn
|
|
240
212
|
>
|
|
241
213
|
</v-card-actions>
|
|
242
|
-
</
|
|
214
|
+
</v-container>
|
|
243
215
|
</v-card>
|
|
244
216
|
</v-flex>
|
|
245
217
|
</v-layout>
|
|
246
218
|
</template>
|
|
247
219
|
|
|
248
220
|
<script>
|
|
249
|
-
import
|
|
221
|
+
import { isEqual } from 'lodash';
|
|
250
222
|
import PuiTextField from './PuiTextField';
|
|
251
223
|
import draggable from 'vuedraggable';
|
|
252
224
|
|
|
253
225
|
export default {
|
|
254
226
|
name: 'PuiMultiSelect',
|
|
255
|
-
mixins: [PuiMultiSelectMixin],
|
|
256
227
|
components: {
|
|
257
228
|
PuiTextField,
|
|
258
229
|
draggable
|
|
259
230
|
},
|
|
260
|
-
/**
|
|
261
|
-
* !important there are more properties in PuiMultiSelectMixin:
|
|
262
|
-
* items,itemsToSelect,itemText,itemValue
|
|
263
|
-
*/
|
|
264
231
|
props: {
|
|
232
|
+
value: {
|
|
233
|
+
required: false
|
|
234
|
+
},
|
|
235
|
+
/* Array of Objects provided by the parent component */
|
|
236
|
+
items: {
|
|
237
|
+
type: Array,
|
|
238
|
+
default: null,
|
|
239
|
+
required: true
|
|
240
|
+
},
|
|
241
|
+
/**
|
|
242
|
+
* Los items seleccionados que se pasan de inicio, se pasa en la directiva v-model al utilizar este componente
|
|
243
|
+
* puede ser un array de Items igual que en la propiedad :items, o un array con los id's solamente
|
|
244
|
+
*/
|
|
245
|
+
itemsToSelect: {
|
|
246
|
+
type: Array,
|
|
247
|
+
default: () => []
|
|
248
|
+
},
|
|
249
|
+
// reactividad de los items seleccionados, solamente actualiza si viene true
|
|
250
|
+
trackItemsToSelect: {
|
|
251
|
+
type: Boolean,
|
|
252
|
+
default: false
|
|
253
|
+
},
|
|
254
|
+
/* Type: String
|
|
255
|
+
The items text property name */
|
|
256
|
+
itemText: {
|
|
257
|
+
type: String,
|
|
258
|
+
//type: [String, Array, Function],
|
|
259
|
+
default: 'text'
|
|
260
|
+
},
|
|
261
|
+
/* Type: String
|
|
262
|
+
The items id property name */
|
|
263
|
+
itemValue: {
|
|
264
|
+
type: String,
|
|
265
|
+
default: 'value'
|
|
266
|
+
},
|
|
265
267
|
flat: {
|
|
266
268
|
default: false
|
|
267
269
|
},
|
|
@@ -300,22 +302,20 @@ export default {
|
|
|
300
302
|
},
|
|
301
303
|
data() {
|
|
302
304
|
return {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
305
|
+
itemTextMultiple: false,
|
|
306
|
+
itemValueMultiple: false,
|
|
307
|
+
itemTextNested: false,
|
|
308
|
+
itemValueNested: false,
|
|
309
|
+
searchTextAvailableItems: '',
|
|
310
|
+
searchTextSelectedItems: '',
|
|
307
311
|
dragOptions: {
|
|
308
312
|
group: 'multiselect',
|
|
309
313
|
disabled: this.disabled
|
|
310
314
|
},
|
|
311
|
-
|
|
312
|
-
|
|
315
|
+
availableItems: [],
|
|
316
|
+
selectedItems: []
|
|
313
317
|
};
|
|
314
318
|
},
|
|
315
|
-
updated() {
|
|
316
|
-
this.searchingAvailable = false;
|
|
317
|
-
this.searchingSelected = false;
|
|
318
|
-
},
|
|
319
319
|
computed: {
|
|
320
320
|
compClassItemListSelected() {
|
|
321
321
|
if (!this.selectedItems) {
|
|
@@ -329,205 +329,308 @@ export default {
|
|
|
329
329
|
'pui-multiselect__itemListContainer-selected': this.selectedItems.length === 0
|
|
330
330
|
};
|
|
331
331
|
},
|
|
332
|
-
|
|
333
|
-
if (!this.
|
|
332
|
+
filteredAvailableItems() {
|
|
333
|
+
if (!this.searchTextAvailableItems) {
|
|
334
334
|
return this.availableItems;
|
|
335
335
|
}
|
|
336
|
-
|
|
336
|
+
|
|
337
337
|
return this.availableItems
|
|
338
338
|
.filter((item) => {
|
|
339
339
|
try {
|
|
340
340
|
const match =
|
|
341
|
-
item[this.itemText].toUpperCase().includes(this.
|
|
342
|
-
(this.itemDescription && item[this.itemDescription].toUpperCase().includes(this.
|
|
341
|
+
item[this.itemText].toUpperCase().includes(this.searchTextAvailableItems.toUpperCase()) ||
|
|
342
|
+
(this.itemDescription && item[this.itemDescription].toUpperCase().includes(this.searchTextAvailableItems.toUpperCase()));
|
|
343
343
|
return match;
|
|
344
344
|
} catch (e) {
|
|
345
345
|
//al item le falta el texto o la descripción
|
|
346
346
|
return false;
|
|
347
347
|
}
|
|
348
|
-
})
|
|
349
|
-
.sort((a, b) => {
|
|
350
|
-
const aValue = a[this.itemText];
|
|
351
|
-
const bValue = b[this.itemText];
|
|
352
|
-
return aValue.localeCompare(bValue);
|
|
353
348
|
});
|
|
354
|
-
//this.searchingAvailable = false;
|
|
355
349
|
},
|
|
356
|
-
|
|
357
|
-
if (!this.
|
|
350
|
+
filteredSelectedItems() {
|
|
351
|
+
if (!this.searchTextSelectedItems) {
|
|
358
352
|
return this.selectedItems;
|
|
359
353
|
}
|
|
360
|
-
|
|
354
|
+
|
|
361
355
|
return this.selectedItems
|
|
362
356
|
.filter((item) => {
|
|
363
357
|
try {
|
|
364
358
|
const match =
|
|
365
|
-
item[this.itemText].toUpperCase().includes(this.
|
|
366
|
-
(this.itemDescription && item[this.itemDescription].toUpperCase().includes(this.
|
|
359
|
+
item[this.itemText].toUpperCase().includes(this.searchTextSelectedItems.toUpperCase()) ||
|
|
360
|
+
(this.itemDescription && item[this.itemDescription].toUpperCase().includes(this.searchTextSelectedItems.toUpperCase()));
|
|
367
361
|
return match;
|
|
368
362
|
} catch (e) {
|
|
369
363
|
//al item le falta el texto o la descripción
|
|
370
364
|
return false;
|
|
371
365
|
}
|
|
372
|
-
})
|
|
373
|
-
.sort((a, b) => {
|
|
374
|
-
const aValue = a[this.itemText];
|
|
375
|
-
const bValue = b[this.itemText];
|
|
376
|
-
return aValue.localeCompare(bValue);
|
|
377
366
|
});
|
|
378
|
-
//this.searchingSelected = false;
|
|
379
367
|
},
|
|
380
|
-
|
|
381
|
-
return
|
|
368
|
+
selected() {
|
|
369
|
+
return this.selectedItems.length > 0;
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
watch: {
|
|
373
|
+
items(newValue, oldValue) {
|
|
374
|
+
if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
|
|
375
|
+
this.checkItemText();
|
|
376
|
+
this.checkItemValue();
|
|
377
|
+
|
|
378
|
+
this.setAvailableItems();
|
|
379
|
+
this.setSelectedItems();
|
|
380
|
+
}
|
|
382
381
|
},
|
|
383
|
-
|
|
384
|
-
|
|
382
|
+
itemsToSelect: {
|
|
383
|
+
handler() {
|
|
384
|
+
if (this.trackItemsToSelect) {
|
|
385
|
+
this.setAvailableItems();
|
|
386
|
+
this.setSelectedItems();
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
deep: true
|
|
385
390
|
}
|
|
386
391
|
},
|
|
392
|
+
mounted() {
|
|
393
|
+
this.checkItemText();
|
|
394
|
+
this.checkItemValue();
|
|
395
|
+
|
|
396
|
+
this.setAvailableItems();
|
|
397
|
+
this.setSelectedItems();
|
|
398
|
+
},
|
|
387
399
|
methods: {
|
|
400
|
+
checkItemText() {
|
|
401
|
+
this.itemTextMultiple = Array.isArray(this.itemText);
|
|
402
|
+
|
|
403
|
+
if (this.itemTextMultiple === false) {
|
|
404
|
+
this.itemTextNested = this.checkForNestedFields(this.itemText);
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
checkItemValue() {
|
|
408
|
+
this.itemValueMultiple = Array.isArray(this.itemValue);
|
|
409
|
+
|
|
410
|
+
if (this.itemValueMultiple === false) {
|
|
411
|
+
this.itemValueNested = this.checkForNestedFields(this.itemValue);
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
checkForNestedFields(stringField) {
|
|
415
|
+
if (stringField instanceof Function) {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return stringField.split('.').length > 1;
|
|
420
|
+
},
|
|
421
|
+
// order items by itemText alphabetically
|
|
422
|
+
orderItems(items) {
|
|
423
|
+
return items.sort((a, b) => {
|
|
424
|
+
const aValue = a[this.itemText] ? a[this.itemText] : '';
|
|
425
|
+
const bValue = b[this.itemText] ? b[this.itemText] : '';
|
|
426
|
+
return aValue.localeCompare(bValue);
|
|
427
|
+
});
|
|
428
|
+
},
|
|
388
429
|
setAvailableItems() {
|
|
389
|
-
this.availableItems = [];
|
|
390
|
-
this.items
|
|
391
|
-
.sort((item1, item2) => {
|
|
392
|
-
if (item1[this.itemText] > item2[this.itemText]) {
|
|
393
|
-
return 1;
|
|
394
|
-
} else if (item1[this.itemText] < item2[this.itemText]) {
|
|
395
|
-
return -1;
|
|
396
|
-
}
|
|
397
|
-
return 0;
|
|
398
|
-
})
|
|
399
|
-
.forEach((item) => this.availableItems.push(item));
|
|
430
|
+
this.availableItems = [...this.items];
|
|
400
431
|
},
|
|
401
|
-
|
|
402
|
-
this.selectedItems
|
|
403
|
-
|
|
404
|
-
|
|
432
|
+
setSelectedItems() {
|
|
433
|
+
this.selectedItems = [];
|
|
434
|
+
|
|
435
|
+
if (!this.itemsToSelect || this.itemsToSelect.length === 0) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
for (let i = 0, length = this.itemsToSelect.length; i < length; i++) {
|
|
440
|
+
// this.selectItem(this.itemsToSelect[i]);
|
|
441
|
+
this.selectItemFromItemValue(this.itemsToSelect[i]);
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
// solo compara los valores de los items, se usa en setSelectItems
|
|
445
|
+
selectItemFromItemValue(item) {
|
|
446
|
+
for (let index = 0, length = this.availableItems.length; index < length; index++) {
|
|
447
|
+
const availableItem = this.availableItems[index];
|
|
448
|
+
if (availableItem[this.itemValue] === item[this.itemValue]) {
|
|
449
|
+
this.selectedItems.push({ ...item });
|
|
405
450
|
this.availableItems.splice(index, 1);
|
|
451
|
+
return;
|
|
406
452
|
}
|
|
407
|
-
}
|
|
408
|
-
this.$emit('input', this.selectedItems);
|
|
453
|
+
}
|
|
409
454
|
},
|
|
410
|
-
|
|
411
|
-
|
|
455
|
+
// compara la equivalencia del objeto
|
|
456
|
+
selectItem(item) {
|
|
412
457
|
for (let index = 0, length = this.availableItems.length; index < length; index++) {
|
|
413
458
|
const availableItem = this.availableItems[index];
|
|
414
|
-
if (availableItem
|
|
415
|
-
|
|
416
|
-
//en este caso hay que theItem que se acaba de añadir 4 lineas de código atras, y añadimos el bueno
|
|
417
|
-
//esto significa que theItem solo lleva los campos de la pk y no es el item "entero"
|
|
418
|
-
if (availableItem !== theItem) {
|
|
419
|
-
this.selectedItems.pop();
|
|
420
|
-
this.selectedItems.push(availableItem);
|
|
421
|
-
}
|
|
459
|
+
if (isEqual(availableItem, item)) {
|
|
460
|
+
this.selectedItems.push({ ...item });
|
|
422
461
|
this.availableItems.splice(index, 1);
|
|
423
462
|
return;
|
|
424
463
|
}
|
|
425
464
|
}
|
|
426
465
|
},
|
|
427
|
-
setSelectedItems() {
|
|
428
|
-
this.$emit('input', this.selectedItems);
|
|
429
|
-
},
|
|
430
466
|
unselectItem(item) {
|
|
431
|
-
this.
|
|
432
|
-
|
|
433
|
-
if (item
|
|
467
|
+
for (let index = 0, length = this.selectedItems.length; index < length; index++) {
|
|
468
|
+
const selectedItem = this.selectedItems[index];
|
|
469
|
+
if (isEqual(selectedItem, item)) {
|
|
470
|
+
this.availableItems.push({ ...item });
|
|
434
471
|
this.selectedItems.splice(index, 1);
|
|
472
|
+
return;
|
|
435
473
|
}
|
|
436
|
-
}
|
|
437
|
-
this.$emit('input', this.selectedItems);
|
|
474
|
+
}
|
|
438
475
|
},
|
|
439
|
-
|
|
476
|
+
selectItemFromClick(item) {
|
|
440
477
|
if (this.disabled) {
|
|
441
478
|
return;
|
|
442
479
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
this.selectItem(item);
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
this.availableItems.splice(index, 1);
|
|
449
|
-
this.selectedItems.push(item);
|
|
480
|
+
|
|
481
|
+
this.selectItem(item);
|
|
450
482
|
this.$emit('input', this.selectedItems);
|
|
451
483
|
},
|
|
452
|
-
|
|
484
|
+
unselectItemFromClick(item) {
|
|
453
485
|
if (this.disabled) {
|
|
454
486
|
return;
|
|
455
487
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
this.unselectItem(item);
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
this.selectedItems.splice(index, 1);
|
|
462
|
-
this.availableItems.push(item);
|
|
488
|
+
|
|
489
|
+
this.unselectItem(item);
|
|
463
490
|
this.$emit('input', this.selectedItems);
|
|
464
491
|
},
|
|
465
492
|
selectAllItems() {
|
|
466
|
-
this.
|
|
467
|
-
this.searchingAvailable = true;
|
|
468
|
-
this.searchingSelected = true;
|
|
493
|
+
this.searchTextSelectedItems = '';
|
|
469
494
|
this.selectedItems = this.selectedItems.concat(this.availableItems);
|
|
470
495
|
this.availableItems = [];
|
|
471
496
|
this.$emit('input', this.selectedItems);
|
|
472
497
|
},
|
|
473
498
|
unselectAllItems() {
|
|
474
|
-
this.
|
|
475
|
-
this.searchingSelected = true;
|
|
476
|
-
this.searchAvailable = '';
|
|
499
|
+
this.searchTextAvailableItems = '';
|
|
477
500
|
this.availableItems = this.availableItems.concat(this.selectedItems);
|
|
478
501
|
this.selectedItems = [];
|
|
479
502
|
this.$emit('input', this.selectedItems);
|
|
480
503
|
},
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
504
|
+
|
|
505
|
+
// due to drag and drop, if searchTextAvailableItems or searchTextSelectedItems have values,
|
|
506
|
+
// the item selected by the user is not the real item so we need to disapply the operations manually
|
|
507
|
+
// and apply them again transforming the indexes of the filtered items to the real items
|
|
508
|
+
|
|
509
|
+
onChangeAvailableItems(event) {
|
|
510
|
+
if (event.moved) {
|
|
511
|
+
if (this.filteredAvailableItems.length > 0 && this.filteredAvailableItems.length < this.availableItems.length) {
|
|
512
|
+
// deshacer movimiento con indices equivocados
|
|
513
|
+
this.availableItems.splice(event.moved.newIndex, 1);
|
|
514
|
+
this.availableItems.splice(event.moved.oldIndex, 0, event.moved.element);
|
|
515
|
+
|
|
516
|
+
// realizar verdadero movimiento
|
|
517
|
+
const realItem = this.filteredAvailableItems[event.moved.oldIndex];
|
|
518
|
+
const realOldIndex = this.availableItems.indexOf(realItem);
|
|
519
|
+
this.availableItems.splice(realOldIndex, 1);
|
|
520
|
+
|
|
521
|
+
const previousItem = this.filteredAvailableItems[event.moved.newIndex - 1];
|
|
522
|
+
const realNewIndex = this.availableItems.indexOf(previousItem) + 1;
|
|
523
|
+
this.availableItems.splice(realNewIndex, 0, realItem);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
this.$emit('input', this.selectedItems);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (event.removed) {
|
|
530
|
+
if (this.filteredAvailableItems.length > 0 && this.filteredAvailableItems.length < this.availableItems.length) {
|
|
531
|
+
// deshacer el borrado de availableItems
|
|
532
|
+
this.availableItems.splice(event.removed.oldIndex, 0, event.removed.element);
|
|
533
|
+
// borrar el verdadero item
|
|
534
|
+
const realItem = this.filteredAvailableItems[event.removed.oldIndex];
|
|
535
|
+
for (let index = 0, length = this.availableItems.length; index < length; index++) {
|
|
536
|
+
const availableItem = this.availableItems[index];
|
|
537
|
+
if (isEqual(availableItem, realItem)) {
|
|
538
|
+
console.log('deleting', this.availableItems[index][this.itemValue]);
|
|
539
|
+
this.availableItems.splice(index, 1);
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
507
542
|
}
|
|
508
|
-
|
|
543
|
+
// añadir el verdadero item a partir de la posición guardada previamente (added ejecuta antes que removed)
|
|
544
|
+
console.log('newIndex', this.newIndex);
|
|
545
|
+
|
|
546
|
+
const previousItem = this.filteredSelectedItems[this.newIndex - 1];
|
|
547
|
+
const realNewIndex = this.selectedItems.indexOf(previousItem) + 1;
|
|
548
|
+
this.selectedItems.splice(realNewIndex, 0, realItem);
|
|
549
|
+
}
|
|
550
|
+
this.$emit('input', this.selectedItems);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
if (event.added) {
|
|
554
|
+
if (this.filteredSelectedItems.length > 0 && this.filteredSelectedItems.length < this.selectedItems.length) {
|
|
555
|
+
// deshacer el añadido de availableItems
|
|
556
|
+
this.availableItems.splice(event.added.newIndex, 1);
|
|
557
|
+
// guardar la posición donde se desea insertar el nuevo item
|
|
558
|
+
this.newIndex = event.added.newIndex;
|
|
559
|
+
}
|
|
560
|
+
this.$emit('input', this.selectedItems);
|
|
509
561
|
}
|
|
510
562
|
},
|
|
511
|
-
|
|
512
|
-
if (event.
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
563
|
+
onChangeSelectedItems(event) {
|
|
564
|
+
if (event.moved) {
|
|
565
|
+
if (this.filteredSelectedItems.length > 0 && this.filteredSelectedItems.length < this.selectedItems.length) {
|
|
566
|
+
// deshacer movimiento con indices equivocados
|
|
567
|
+
this.selectedItems.splice(event.moved.newIndex, 1);
|
|
568
|
+
this.selectedItems.splice(event.moved.oldIndex, 0, event.moved.element);
|
|
569
|
+
|
|
570
|
+
// realizar verdadero movimiento
|
|
571
|
+
const realItem = this.filteredSelectedItems[event.moved.oldIndex];
|
|
572
|
+
const realOldIndex = this.selectedItems.indexOf(realItem);
|
|
573
|
+
this.selectedItems.splice(realOldIndex, 1);
|
|
574
|
+
|
|
575
|
+
const previousItem = this.filteredSelectedItems[event.moved.newIndex - 1];
|
|
576
|
+
const realNewIndex = this.selectedItems.indexOf(previousItem) + 1;
|
|
577
|
+
this.selectedItems.splice(realNewIndex, 0, realItem);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
this.$emit('input', this.selectedItems);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (event.removed) {
|
|
584
|
+
if (this.filteredSelectedItems.length > 0 && this.filteredSelectedItems.length < this.selectedItems.length) {
|
|
585
|
+
// deshacer el borrado de selectedItems
|
|
586
|
+
this.selectedItems.splice(event.removed.oldIndex, 0, event.removed.element);
|
|
587
|
+
// borrar el verdadero item
|
|
588
|
+
const realItem = this.filteredSelectedItems[event.removed.oldIndex];
|
|
589
|
+
for (let index = 0, length = this.selectedItems.length; index < length; index++) {
|
|
590
|
+
const selectedItem = this.selectedItems[index];
|
|
591
|
+
if (isEqual(selectedItem, realItem)) {
|
|
592
|
+
console.log('deleting', this.selectedItems[index][this.itemValue]);
|
|
593
|
+
this.selectedItems.splice(index, 1);
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
527
596
|
}
|
|
528
|
-
|
|
597
|
+
// añadir el verdadero item a partir de la posición guardada previamente (added ejecuta antes que removed)
|
|
598
|
+
const previousItem = this.filteredAvailableItems[this.newIndex - 1];
|
|
599
|
+
const realNewIndex = this.availableItems.indexOf(previousItem) + 1;
|
|
600
|
+
this.availableItems.splice(realNewIndex, 0, realItem);
|
|
601
|
+
}
|
|
602
|
+
this.$emit('input', this.selectedItems);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
if (event.added) {
|
|
606
|
+
if (this.filteredAvailableItems.length > 0 && this.filteredAvailableItems.length < this.availableItems.length) {
|
|
607
|
+
// deshacer el añadido de selectedItems
|
|
608
|
+
this.selectedItems.splice(event.added.newIndex, 1);
|
|
609
|
+
// guardar la posición donde se desea insertar el nuevo item
|
|
610
|
+
this.newIndex = event.added.newIndex;
|
|
611
|
+
}
|
|
612
|
+
this.$emit('input', this.selectedItems);
|
|
529
613
|
}
|
|
614
|
+
},
|
|
615
|
+
getItemIndexFromFilteredIndex(filteredIndex, filteredList, list) {
|
|
616
|
+
const filteredItem = filteredList[filteredIndex];
|
|
617
|
+
for (let index = 0, length = list.length; index < length; index++) {
|
|
618
|
+
const item = list[index];
|
|
619
|
+
if (isEqual(item, filteredItem)) {
|
|
620
|
+
return index;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
return -1;
|
|
530
624
|
}
|
|
531
625
|
}
|
|
532
626
|
};
|
|
533
627
|
</script>
|
|
628
|
+
|
|
629
|
+
<style scoped>
|
|
630
|
+
.tooltipText {
|
|
631
|
+
word-break: break-all;
|
|
632
|
+
max-width: 100% !important;
|
|
633
|
+
max-height: 100% !important;
|
|
634
|
+
font: normal;
|
|
635
|
+
}
|
|
636
|
+
</style>
|