quasar-ui-danx 0.3.24 → 0.3.26

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar-ui-danx",
3
- "version": "0.3.24",
3
+ "version": "0.3.26",
4
4
  "author": "Dan <dan@flytedesk.com>",
5
5
  "description": "DanX Vue / Quasar component library",
6
6
  "license": "MIT",
@@ -5,6 +5,7 @@
5
5
  v-if="field.options?.length > 0 || loading"
6
6
  :model-value="modelValue"
7
7
  :options="field.options"
8
+ :clearable="field.clearable === undefined ? true : field.clearable"
8
9
  multiple
9
10
  :loading="loading"
10
11
  :chip-limit="1"
@@ -30,6 +31,7 @@
30
31
  v-else-if="field.type === 'single-select'"
31
32
  :model-value="modelValue"
32
33
  :options="field.options"
34
+ :clearable="field.clearable === undefined ? true : field.clearable"
33
35
  :placeholder="field.placeholder"
34
36
  :loading="loading"
35
37
  :label="field.label"
@@ -108,41 +110,41 @@
108
110
  </template>
109
111
  <script setup>
110
112
  import {
111
- BooleanField,
112
- DateField,
113
- DateRangeField,
114
- MultiKeywordField,
115
- NumberRangeField,
116
- SelectField,
117
- SelectWithChildrenField
113
+ BooleanField,
114
+ DateField,
115
+ DateRangeField,
116
+ MultiKeywordField,
117
+ NumberRangeField,
118
+ SelectField,
119
+ SelectWithChildrenField
118
120
  } from "../Form/Fields";
119
121
 
120
122
  const emit = defineEmits(["update:model-value"]);
121
123
  const props = defineProps({
122
- field: {
123
- type: Object,
124
- required: true
125
- },
126
- modelValue: {
127
- type: [String, Array, Number, Object, Boolean],
128
- default: undefined
129
- },
130
- loading: Boolean
124
+ field: {
125
+ type: Object,
126
+ required: true
127
+ },
128
+ modelValue: {
129
+ type: [String, Array, Number, Object, Boolean],
130
+ default: undefined
131
+ },
132
+ loading: Boolean
131
133
  });
132
134
 
133
135
  function onUpdate(val) {
134
- let newVal = val || undefined;
136
+ let newVal = val || undefined;
135
137
 
136
- switch (props.field.type) {
137
- case "multi-select":
138
- newVal = val.length > 0 ? val : undefined;
139
- break;
140
- case "single-select":
141
- case "boolean":
142
- newVal = val === null ? undefined : val;
143
- break;
144
- }
138
+ switch (props.field.type) {
139
+ case "multi-select":
140
+ newVal = (val && val.length > 0) ? val : undefined;
141
+ break;
142
+ case "single-select":
143
+ case "boolean":
144
+ newVal = val === null ? undefined : val;
145
+ break;
146
+ }
145
147
 
146
- emit("update:model-value", newVal);
148
+ emit("update:model-value", newVal);
147
149
  }
148
150
  </script>
@@ -75,6 +75,7 @@
75
75
  :label="field.label || undefined"
76
76
  :no-label="noLabel"
77
77
  :show-name="showName"
78
+ :clearable="field.clearable || clearable"
78
79
  :disable="disable"
79
80
  :readonly="readonly"
80
81
  @update:model-value="onInput(field.name, $event)"
@@ -111,65 +112,66 @@ import { FlashMessages, incrementName, replace } from "../../../helpers";
111
112
  import { TrashIcon as RemoveIcon } from "../../../svg";
112
113
  import { ConfirmDialog } from "../../Utility";
113
114
  import {
114
- BooleanField,
115
- DateField,
116
- DateRangeField,
117
- IntegerField,
118
- MultiFileField,
119
- NumberField,
120
- SingleFileField,
121
- TextField,
122
- WysiwygField
115
+ BooleanField,
116
+ DateField,
117
+ DateRangeField,
118
+ IntegerField,
119
+ MultiFileField,
120
+ NumberField,
121
+ SingleFileField,
122
+ TextField,
123
+ WysiwygField
123
124
  } from "./Fields";
124
125
 
125
126
  const emit = defineEmits(["update:values"]);
126
127
  const props = defineProps({
127
- values: {
128
- type: Array,
129
- default: null
130
- },
131
- form: {
132
- type: Object,
133
- required: true
134
- },
135
- noLabel: Boolean,
136
- showName: Boolean,
137
- disable: Boolean,
138
- readonly: Boolean,
139
- saving: Boolean,
140
- emptyValue: {
141
- type: [String, Number, Boolean],
142
- default: undefined
143
- },
144
- canModifyVariations: Boolean
128
+ values: {
129
+ type: Array,
130
+ default: null
131
+ },
132
+ form: {
133
+ type: Object,
134
+ required: true
135
+ },
136
+ noLabel: Boolean,
137
+ showName: Boolean,
138
+ disable: Boolean,
139
+ clearable: Boolean,
140
+ readonly: Boolean,
141
+ saving: Boolean,
142
+ emptyValue: {
143
+ type: [String, Number, Boolean],
144
+ default: undefined
145
+ },
146
+ canModifyVariations: Boolean
145
147
  });
146
148
 
147
149
  const FORM_FIELD_MAP = {
148
- BOOLEAN: BooleanField,
149
- DATE: DateField,
150
- DATE_RANGE: DateRangeField,
151
- INTEGER: IntegerField,
152
- NUMBER: NumberField,
153
- TEXT: TextField,
154
- SINGLE_FILE: SingleFileField,
155
- MULTI_FILE: MultiFileField,
156
- WYSIWYG: WysiwygField
150
+ BOOLEAN: BooleanField,
151
+ DATE: DateField,
152
+ DATE_RANGE: DateRangeField,
153
+ INTEGER: IntegerField,
154
+ NUMBER: NumberField,
155
+ TEXT: TextField,
156
+ SINGLE_FILE: SingleFileField,
157
+ MULTI_FILE: MultiFileField,
158
+ WYSIWYG: WysiwygField
157
159
  };
158
160
 
159
161
  const mappedFields = props.form.fields.map((field) => ({
160
- placeholder: `Enter ${field.label}`,
161
- ...field,
162
- component: FORM_FIELD_MAP[field.type],
163
- default: field.type === "BOOLEAN" ? false : ""
162
+ placeholder: `Enter ${field.label}`,
163
+ ...field,
164
+ component: FORM_FIELD_MAP[field.type],
165
+ default: field.type === "BOOLEAN" ? false : ""
164
166
  }));
165
167
 
166
168
  const variationNames = computed(() => {
167
- const names = [...new Set(props.values.map(v => v.variation))].sort();
168
- // Always guarantee that we show the default variation
169
- if (names.length === 0) {
170
- names.push("");
171
- }
172
- return names;
169
+ const names = [...new Set(props.values.map(v => v.variation))].sort();
170
+ // Always guarantee that we show the default variation
171
+ if (names.length === 0) {
172
+ names.push("");
173
+ }
174
+ return names;
173
175
  });
174
176
 
175
177
  const currentVariation = ref(variationNames.value[0] || "");
@@ -179,88 +181,88 @@ const variationToDelete = ref("");
179
181
  const canAddVariation = computed(() => props.canModifyVariations && !props.readonly && !props.disable && variationNames.value.length < props.form.variations);
180
182
 
181
183
  function getFieldResponse(name, variation) {
182
- if (!props.values) return undefined;
183
- return props.values.find((v) => v.variation === (variation !== undefined ? variation : currentVariation.value) && v.name === name);
184
+ if (!props.values) return undefined;
185
+ return props.values.find((v) => v.variation === (variation !== undefined ? variation : currentVariation.value) && v.name === name);
184
186
  }
185
187
  function getFieldValue(name) {
186
- return getFieldResponse(name)?.value;
188
+ return getFieldResponse(name)?.value;
187
189
  }
188
190
  function onInput(name, value) {
189
- const fieldResponse = getFieldResponse(name);
190
- const newFieldResponse = {
191
- name,
192
- variation: currentVariation.value || "",
193
- value: value === undefined ? props.emptyValue : value
194
- };
195
- const newValues = replace(props.values, fieldResponse, newFieldResponse, true);
196
- emit("update:values", newValues);
191
+ const fieldResponse = getFieldResponse(name);
192
+ const newFieldResponse = {
193
+ name,
194
+ variation: currentVariation.value || "",
195
+ value: value === undefined ? props.emptyValue : value
196
+ };
197
+ const newValues = replace(props.values, fieldResponse, newFieldResponse, true);
198
+ emit("update:values", newValues);
197
199
  }
198
200
 
199
201
  function createVariation(variation) {
200
- return props.form.fields.map((field) => ({
201
- variation,
202
- name: field.name,
203
- value: field.type === "BOOLEAN" ? false : null
204
- }));
202
+ return props.form.fields.map((field) => ({
203
+ variation,
204
+ name: field.name,
205
+ value: field.type === "BOOLEAN" ? false : null
206
+ }));
205
207
  }
206
208
 
207
209
  function onAddVariation() {
208
- if (props.saving) return;
209
- let newValues = [...props.values];
210
+ if (props.saving) return;
211
+ let newValues = [...props.values];
210
212
 
211
- if (newValues.length === 0) {
212
- newValues = createVariation("");
213
- }
214
- const previousName = variationNames.value[variationNames.value.length - 1];
215
- const newName = incrementName(!previousName ? "1" : previousName);
216
- const newVariation = createVariation(newName);
217
- emit("update:values", [...newValues, ...newVariation]);
218
- currentVariation.value = newName;
213
+ if (newValues.length === 0) {
214
+ newValues = createVariation("");
215
+ }
216
+ const previousName = variationNames.value[variationNames.value.length - 1];
217
+ const newName = incrementName(!previousName ? "1" : previousName);
218
+ const newVariation = createVariation(newName);
219
+ emit("update:values", [...newValues, ...newVariation]);
220
+ currentVariation.value = newName;
219
221
  }
220
222
 
221
223
  function onChangeVariationName() {
222
- if (!newVariationName.value) return;
223
- if (variationNames.value.includes(newVariationName.value)) {
224
- FlashMessages.error("Variation name already exists");
225
- return;
226
- }
227
- const newValues = props.values.map((v) => {
228
- if (v.variation === variationToEdit.value) {
229
- return { ...v, variation: newVariationName.value };
230
- }
231
- return v;
232
- });
233
- emit("update:values", newValues);
224
+ if (!newVariationName.value) return;
225
+ if (variationNames.value.includes(newVariationName.value)) {
226
+ FlashMessages.error("Variation name already exists");
227
+ return;
228
+ }
229
+ const newValues = props.values.map((v) => {
230
+ if (v.variation === variationToEdit.value) {
231
+ return { ...v, variation: newVariationName.value };
232
+ }
233
+ return v;
234
+ });
235
+ emit("update:values", newValues);
234
236
 
235
- currentVariation.value = newVariationName.value;
236
- variationToEdit.value = false;
237
- newVariationName.value = "";
237
+ currentVariation.value = newVariationName.value;
238
+ variationToEdit.value = false;
239
+ newVariationName.value = "";
238
240
  }
239
241
 
240
242
  function onRemoveVariation(name) {
241
- if (!name) return;
243
+ if (!name) return;
242
244
 
243
- const newValues = props.values.filter((v) => v.variation !== name);
244
- emit("update:values", newValues);
245
+ const newValues = props.values.filter((v) => v.variation !== name);
246
+ emit("update:values", newValues);
245
247
 
246
- if (currentVariation.value === name) {
247
- currentVariation.value = variationNames.value[0];
248
- }
249
- variationToDelete.value = "";
248
+ if (currentVariation.value === name) {
249
+ currentVariation.value = variationNames.value[0];
250
+ }
251
+ variationToDelete.value = "";
250
252
  }
251
253
 
252
254
  function isVariationFormComplete(variation) {
253
- const requiredGroups = {};
254
- return props.form.fields.filter(r => r.required || r.required_group).every((field) => {
255
- const fieldResponse = getFieldResponse(field.name, variation);
256
- const hasValue = !!fieldResponse && fieldResponse.value !== null;
257
- if (field.required_group) {
258
- // This required group has already been satisfied
259
- if (requiredGroups[field.required_group]) return true;
260
- return requiredGroups[field.required_group] = hasValue;
261
- } else {
262
- return hasValue;
263
- }
264
- });
255
+ const requiredGroups = {};
256
+ return props.form.fields.filter(r => r.required || r.required_group).every((field) => {
257
+ const fieldResponse = getFieldResponse(field.name, variation);
258
+ const hasValue = !!fieldResponse && fieldResponse.value !== null;
259
+ if (field.required_group) {
260
+ // This required group has already been satisfied
261
+ if (requiredGroups[field.required_group]) return true;
262
+ return requiredGroups[field.required_group] = hasValue;
263
+ } else {
264
+ return hasValue;
265
+ }
266
+ });
265
267
  }
266
268
  </script>
@@ -2,81 +2,82 @@ import { computed, ref, watch } from "vue";
2
2
  import { getItem, setItem } from "../../helpers";
3
3
 
4
4
  export interface TableColumn {
5
- actionMenu?: object,
6
- align?: string,
7
- category?: string,
8
- class?: string | object,
9
- field: string,
10
- format?: Function,
11
- innerClass?: string | object,
12
- style?: string | object,
13
- headerStyle?: string | object,
14
- isSavingRow?: boolean | Function,
15
- label: string,
16
- maxWidth?: number,
17
- minWidth?: number,
18
- name: string,
19
- onClick?: Function,
20
- required?: boolean,
21
- resizeable?: boolean,
22
- sortable?: boolean,
23
- sortBy?: string,
24
- sortByExpression?: string,
25
- titleColumns?: Function,
26
- vnode?: Function,
5
+ actionMenu?: object,
6
+ align?: string,
7
+ category?: string,
8
+ class?: string | object,
9
+ field: string,
10
+ format?: Function,
11
+ innerClass?: string | object,
12
+ style?: string | object,
13
+ headerStyle?: string | object,
14
+ isSavingRow?: boolean | Function,
15
+ label: string,
16
+ maxWidth?: number,
17
+ minWidth?: number,
18
+ name: string,
19
+ onClick?: Function,
20
+ required?: boolean,
21
+ resizeable?: boolean,
22
+ sortable?: boolean,
23
+ sortBy?: string,
24
+ sortByExpression?: string,
25
+ titleColumns?: Function,
26
+ vnode?: Function,
27
27
  }
28
28
 
29
29
  export function useTableColumns(name: string, columns: TableColumn[]) {
30
- const COLUMN_ORDER_KEY = `${name}-column-order`;
31
- const VISIBLE_COLUMNS_KEY = `${name}-visible-columns`;
32
- const TITLE_COLUMNS_KEY = `${name}-title-columns`;
30
+ const COLUMN_ORDER_KEY = `${name}-column-order`;
31
+ const VISIBLE_COLUMNS_KEY = `${name}-visible-columns`;
32
+ const TITLE_COLUMNS_KEY = `${name}-title-columns`;
33
33
 
34
- // The list that defines the order the columns should appear in
35
- const columnOrder = ref(getItem(COLUMN_ORDER_KEY) || []);
34
+ // The list that defines the order the columns should appear in
35
+ const columnOrder = ref(getItem(COLUMN_ORDER_KEY) || []);
36
36
 
37
- // Manages visible columns on the table
38
- const hiddenColumnNames = ref(getItem(VISIBLE_COLUMNS_KEY, []));
37
+ // Manages visible columns on the table
38
+ const hiddenColumnNames = ref(getItem(VISIBLE_COLUMNS_KEY, []));
39
39
 
40
- // Title columns will have their name appear on the first column of the table as part of the records' title
41
- const titleColumnNames = ref(getItem(TITLE_COLUMNS_KEY, []));
40
+ // Title columns will have their name appear on the first column of the table as part of the records' title
41
+ const titleColumnNames = ref(getItem(TITLE_COLUMNS_KEY, []));
42
42
 
43
- // Columns that should be locked to the left side of the table
44
- const lockedColumns = computed(() => orderedColumns.value.slice(0, 1));
43
+ // Columns that should be locked to the left side of the table
44
+ const lockedColumns = computed(() => orderedColumns.value.slice(0, 1));
45
45
 
46
- // The resolved list of columns in the order they should appear in
47
- const orderedColumns = computed(() => [...columns].sort((a, b) => {
48
- const aIndex = columnOrder.value.indexOf(a.name);
49
- const bIndex = columnOrder.value.indexOf(b.name);
50
- return aIndex === -1 ? 1 : bIndex === -1 ? -1 : aIndex - bIndex;
51
- }));
46
+ // The resolved list of columns in the order they should appear in
47
+ const orderedColumns = computed(() => [...columns].sort((a, b) => {
48
+ const aIndex = columnOrder.value.indexOf(a.name);
49
+ const bIndex = columnOrder.value.indexOf(b.name);
50
+ return aIndex === -1 ? 1 : bIndex === -1 ? -1 : aIndex - bIndex;
51
+ }));
52
52
 
53
- // The ordered list of columns. The ordering of this list is editable and will be stored in localStorage
54
- const sortableColumns = computed({
55
- get() {
56
- return orderedColumns.value.slice(1);
57
- },
58
- set(newColumns) {
59
- columnOrder.value = [...lockedColumns.value.map(c => c.name), ...newColumns.map(c => c.name)];
60
- setItem(COLUMN_ORDER_KEY, columnOrder.value);
61
- }
62
- });
53
+ // The ordered list of columns. The ordering of this list is editable and will be stored in localStorage
54
+ const sortableColumns = computed({
55
+ get() {
56
+ return orderedColumns.value.slice(1);
57
+ },
58
+ set(newColumns) {
59
+ columnOrder.value = [...lockedColumns.value.map(c => c.name), ...newColumns.map(c => c.name)];
60
+ setItem(COLUMN_ORDER_KEY, columnOrder.value);
61
+ }
62
+ });
63
63
 
64
- // The list of columns that are visible. To edit the visible columns, edit the hiddenColumnNames list
65
- const visibleColumns = computed(() => orderedColumns.value.filter(c => !hiddenColumnNames.value.includes(c.name)));
64
+ // The list of columns that are visible. To edit the visible columns, edit the hiddenColumnNames list
65
+ const visibleColumns = computed(() => orderedColumns.value.filter(c => !hiddenColumnNames.value.includes(c.name)));
66
66
 
67
- // The list of columns that should be included in the title of a row
68
- const orderedTitleColumns = computed(() => orderedColumns.value.filter(c => titleColumnNames.value.includes(c.name)));
67
+ // The list of columns that should be included in the title of a row
68
+ const orderedTitleColumns = computed(() => orderedColumns.value.filter(c => titleColumnNames.value.includes(c.name)));
69
69
 
70
- // Save changes to the list of hidden columns in localStorage
71
- watch(() => hiddenColumnNames.value, () => setItem(VISIBLE_COLUMNS_KEY, hiddenColumnNames.value));
72
- watch(() => titleColumnNames.value, () => setItem(TITLE_COLUMNS_KEY, titleColumnNames.value));
70
+ // Save changes to the list of hidden columns in localStorage
71
+ watch(() => hiddenColumnNames.value, () => setItem(VISIBLE_COLUMNS_KEY, hiddenColumnNames.value));
72
+ watch(() => titleColumnNames.value, () => setItem(TITLE_COLUMNS_KEY, titleColumnNames.value));
73
73
 
74
- return {
75
- sortableColumns,
76
- lockedColumns,
77
- visibleColumns,
78
- hiddenColumnNames,
79
- titleColumnNames,
80
- orderedTitleColumns
81
- };
74
+ return {
75
+ sortableColumns,
76
+ lockedColumns,
77
+ visibleColumns,
78
+ hiddenColumnNames,
79
+ columnOrder,
80
+ titleColumnNames,
81
+ orderedTitleColumns
82
+ };
82
83
  }