sprintify-ui 0.6.75 → 0.6.76
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/package.json
CHANGED
|
@@ -144,21 +144,21 @@ const autocompleteFetch = ref<InstanceType<
|
|
|
144
144
|
typeof BaseAutocompleteFetch
|
|
145
145
|
> | null>(null);
|
|
146
146
|
|
|
147
|
-
const model = ref(
|
|
147
|
+
const model = ref<Option | null>(null);
|
|
148
148
|
const ensureModelIsFilledDebounced = debounce(ensureModelIsFilled, 100);
|
|
149
149
|
|
|
150
150
|
watch(
|
|
151
151
|
() => props.currentModel,
|
|
152
152
|
ensureModelIsFilledDebounced,
|
|
153
|
-
{ immediate: true },
|
|
154
153
|
);
|
|
155
154
|
|
|
156
155
|
watch(
|
|
157
156
|
() => props.modelValue,
|
|
158
157
|
ensureModelIsFilledDebounced,
|
|
159
|
-
{ immediate: true },
|
|
160
158
|
);
|
|
161
159
|
|
|
160
|
+
ensureModelIsFilledDebounced();
|
|
161
|
+
|
|
162
162
|
function onUpdate(newModel: Option | null) {
|
|
163
163
|
if (!newModel) {
|
|
164
164
|
model.value = null;
|
|
@@ -36,12 +36,17 @@ const Template = (args) => {
|
|
|
36
36
|
"4",
|
|
37
37
|
"6",
|
|
38
38
|
]);
|
|
39
|
-
|
|
39
|
+
const currentModels = ref([
|
|
40
|
+
{ id: 4, name: 'Todo 4 (local)' },
|
|
41
|
+
{ id: 6, name: 'Todo 6 (local)' },
|
|
42
|
+
])
|
|
43
|
+
return { args, value, currentModels };
|
|
40
44
|
},
|
|
41
45
|
template: `
|
|
42
46
|
<BaseHasMany
|
|
43
47
|
v-model="value"
|
|
44
48
|
v-bind="args"
|
|
49
|
+
:current-models="currentModels"
|
|
45
50
|
></BaseHasMany>
|
|
46
51
|
<ShowValue :value="value" />
|
|
47
52
|
<BaseAppNotifications />
|
|
@@ -56,8 +61,9 @@ export const Disabled = (args) => {
|
|
|
56
61
|
return {
|
|
57
62
|
components: { BaseHasMany, ShowValue },
|
|
58
63
|
setup() {
|
|
64
|
+
// current model is incorrect, to test component's resilience
|
|
59
65
|
const currentModel = options[1];
|
|
60
|
-
const value = ref([
|
|
66
|
+
const value = ref([7]);
|
|
61
67
|
return { args, value, currentModel };
|
|
62
68
|
},
|
|
63
69
|
template: `<BaseHasMany
|
|
@@ -65,8 +71,6 @@ export const Disabled = (args) => {
|
|
|
65
71
|
v-model="value"
|
|
66
72
|
:current-models="[currentModel]"
|
|
67
73
|
:disabled="true"
|
|
68
|
-
primaryKey="value"
|
|
69
|
-
field="label"
|
|
70
74
|
></BaseHasMany>
|
|
71
75
|
<ShowValue :value="value" />`,
|
|
72
76
|
};
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
</template>
|
|
45
45
|
|
|
46
46
|
<script lang="ts" setup>
|
|
47
|
-
import { debounce
|
|
47
|
+
import { debounce } from 'lodash';
|
|
48
48
|
import { Option } from '@/types';
|
|
49
49
|
import { config } from '@/index';
|
|
50
50
|
import { PropType } from 'vue';
|
|
@@ -113,74 +113,98 @@ const tagAutocompleteFetch = ref<InstanceType<
|
|
|
113
113
|
typeof BaseTagAutocompleteFetch
|
|
114
114
|
> | null>(null);
|
|
115
115
|
|
|
116
|
-
const models = ref(
|
|
116
|
+
const models = ref<Option[]>([]);
|
|
117
|
+
const ensureModelIsFilledDebounced = debounce(() => ensureModelsAreFilled(), 100);
|
|
117
118
|
|
|
118
119
|
watch(
|
|
119
120
|
() => props.currentModels,
|
|
120
|
-
|
|
121
|
-
if (isEqual(newValue, oldValue)) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
models.value = newValue ?? [];
|
|
126
|
-
},
|
|
121
|
+
ensureModelIsFilledDebounced,
|
|
127
122
|
{ deep: true }
|
|
128
123
|
);
|
|
129
124
|
|
|
130
125
|
watch(
|
|
131
126
|
() => props.modelValue,
|
|
132
|
-
|
|
133
|
-
{
|
|
127
|
+
ensureModelIsFilledDebounced,
|
|
128
|
+
{ deep: true }
|
|
134
129
|
);
|
|
135
130
|
|
|
136
|
-
|
|
131
|
+
ensureModelIsFilledDebounced();
|
|
137
132
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
function onUpdate(newModels: Option[]) {
|
|
134
|
+
models.value = newModels;
|
|
135
|
+
emit(
|
|
136
|
+
'update:modelValue',
|
|
137
|
+
newModels.map((m) => m[props.primaryKey]),
|
|
138
|
+
newModels,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
function ensureModelsAreFilled() {
|
|
143
|
+
|
|
144
|
+
if (!Array.isArray(props.modelValue)) {
|
|
145
|
+
models.value = [];
|
|
143
146
|
return;
|
|
144
147
|
}
|
|
145
148
|
|
|
146
|
-
if (
|
|
149
|
+
if (props.modelValue.length == 0) {
|
|
147
150
|
models.value = [];
|
|
148
151
|
return;
|
|
149
152
|
}
|
|
150
153
|
|
|
151
|
-
//
|
|
154
|
+
// Remove incorrect models
|
|
152
155
|
|
|
153
|
-
// Get primaryKeys as string for comparison
|
|
154
156
|
const ids = props.modelValue.map((id: number | string) => id.toString());
|
|
155
|
-
const localModelIds = models.value.map((m) => '' + m[props.primaryKey]);
|
|
156
157
|
|
|
157
|
-
|
|
158
|
+
models.value = models.value.filter((m) => ids.includes(m[props.primaryKey] + ''));
|
|
159
|
+
|
|
160
|
+
const localModelIds = models.value.map((m) => m[props.primaryKey] + '');
|
|
161
|
+
|
|
162
|
+
let missingIds = ids.filter((id) => !localModelIds.includes(id));
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
// Current models are fully set
|
|
166
|
+
if (missingIds.length == 0) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Try with current models
|
|
171
|
+
|
|
172
|
+
if (Array.isArray(props.currentModels)) {
|
|
173
|
+
missingIds.forEach((id) => {
|
|
174
|
+
const model = props.currentModels?.find((m) => m[props.primaryKey as never] == id);
|
|
175
|
+
|
|
176
|
+
if (model) {
|
|
177
|
+
models.value.push(model);
|
|
178
|
+
missingIds = missingIds.filter((i) => i != id);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Current models are fully set
|
|
184
|
+
if (missingIds.length == 0) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Try with show route
|
|
189
|
+
|
|
190
|
+
if (props.showRouteUrl == null) {
|
|
158
191
|
return;
|
|
159
192
|
}
|
|
160
193
|
|
|
161
194
|
http
|
|
162
|
-
.get(props.showRouteUrl(
|
|
195
|
+
.get(props.showRouteUrl(missingIds))
|
|
163
196
|
.then((response: AxiosResponse) => {
|
|
164
197
|
|
|
165
198
|
const items = getItems(response.data);
|
|
166
199
|
|
|
167
200
|
models.value = items.filter((i: Record<string, any>) => {
|
|
168
201
|
// convert primary keys to string for comparison
|
|
169
|
-
return ids.includes(
|
|
202
|
+
return ids.includes(i[props.primaryKey] + '');
|
|
170
203
|
});
|
|
171
204
|
})
|
|
172
205
|
.catch((e: Error) => e);
|
|
173
206
|
}
|
|
174
207
|
|
|
175
|
-
function onUpdate(newModels: Option[]) {
|
|
176
|
-
models.value = newModels;
|
|
177
|
-
emit(
|
|
178
|
-
'update:modelValue',
|
|
179
|
-
newModels.map((m) => m[props.primaryKey]),
|
|
180
|
-
newModels,
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
208
|
defineExpose({
|
|
185
209
|
focus: () => tagAutocompleteFetch.value?.focus(),
|
|
186
210
|
blur: () => tagAutocompleteFetch.value?.blur(),
|
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
:key="selection.value ? selection.value : 'null'"
|
|
13
13
|
:class="selectionClass(selection)"
|
|
14
14
|
>
|
|
15
|
-
<div
|
|
15
|
+
<div
|
|
16
|
+
:title="selection.label"
|
|
17
|
+
class="truncate"
|
|
18
|
+
>
|
|
16
19
|
{{ selection.label }}
|
|
17
20
|
</div>
|
|
18
21
|
|
|
@@ -459,7 +462,7 @@ const inputClasses = computed(() => {
|
|
|
459
462
|
|
|
460
463
|
const selectionClass = (selection: NormalizedOption): string => {
|
|
461
464
|
|
|
462
|
-
const base = 'flex items-center rounded border';
|
|
465
|
+
const base = 'flex items-center rounded border overflow-hidden';
|
|
463
466
|
|
|
464
467
|
const fontSize = {
|
|
465
468
|
'xs': 'text-xs',
|