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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprintify-ui",
3
- "version": "0.6.75",
3
+ "version": "0.6.76",
4
4
  "scripts": {
5
5
  "build": "rimraf dist && vue-tsc && vite build",
6
6
  "build-fast": "rimraf dist && vite build",
@@ -144,21 +144,21 @@ const autocompleteFetch = ref<InstanceType<
144
144
  typeof BaseAutocompleteFetch
145
145
  > | null>(null);
146
146
 
147
- const model = ref(props.currentModel);
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
- return { args, value };
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([currentModel.value]);
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, isEqual } from 'lodash';
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(props.currentModels ?? []);
116
+ const models = ref<Option[]>([]);
117
+ const ensureModelIsFilledDebounced = debounce(() => ensureModelsAreFilled(), 100);
117
118
 
118
119
  watch(
119
120
  () => props.currentModels,
120
- (newValue, oldValue) => {
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
- debounce(() => fetchModels(), 100),
133
- { immediate: true }
127
+ ensureModelIsFilledDebounced,
128
+ { deep: true }
134
129
  );
135
130
 
136
- function fetchModels() {
131
+ ensureModelIsFilledDebounced();
137
132
 
138
- if (props.currentModels !== undefined) {
139
- return;
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
- if (props.showRouteUrl == undefined) {
142
+ function ensureModelsAreFilled() {
143
+
144
+ if (!Array.isArray(props.modelValue)) {
145
+ models.value = [];
143
146
  return;
144
147
  }
145
148
 
146
- if (!props.modelValue) {
149
+ if (props.modelValue.length == 0) {
147
150
  models.value = [];
148
151
  return;
149
152
  }
150
153
 
151
- // Do not fetch if the modelValue is the same as the local models
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
- if (isEqual(ids, localModelIds)) {
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(ids))
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('' + i[props.primaryKey]);
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',