@zeedhi/vuetify 3.0.9 → 3.0.10
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/components/tek-grid/TekGrid.js +287 -0
- package/dist/components/tek-grid/column-filter/TekGridColumnFilter.js +201 -0
- package/dist/components/tek-grid/column-header/TekGridHeaderRow.js +134 -0
- package/dist/components/tek-grid/columns-button/TekGridColumnsButton.js +79 -0
- package/dist/components/tek-grid/columns-button/TekGridColumnsOptionsController.js +416 -0
- package/dist/components/tek-grid/columns-button/TekGridColumnsOptionsModal.js +501 -0
- package/dist/components/tek-grid/filter-button/TekGridFilterButton.js +36 -0
- package/dist/components/tek-grid/indentation/TekGridIndentation.js +20 -0
- package/dist/components/tek-grid/layout-options/TekGridLayoutOptions.js +101 -0
- package/dist/components/tek-grid/row/TekGridFooterRow.js +57 -0
- package/dist/components/tek-grid/row/TekGridGroupRow.js +58 -0
- package/dist/components/zd-date-input/ZdDateInput.js +23 -86
- package/dist/components/zd-date-range/ZdDateRange.js +22 -84
- package/dist/components/zd-tabs/ZdTab.js +0 -3
- package/dist/components/zd-text/ZdText.js +3 -2
- package/dist/composables/index.js +2 -0
- package/dist/composables/useDateKeydown.js +87 -0
- package/dist/composables/usePickerValue.js +19 -0
- package/dist/composables/useTableLayout.js +212 -0
- package/dist/utils/isArrayOperation.js +4 -0
- package/dist/zd-vuetify.css +14120 -13554
- package/dist/zd-vuetify.js +8322 -4831
- package/package.json +4 -4
- package/src/components/zd-badge/ZdBadge.vue +2 -2
- package/src/components/zd-card/ZdCard.vue +2 -2
- package/src/components/zd-col/ZdCol.vue +1 -0
- package/src/components/zd-container/ZdContainer.vue +2 -2
- package/src/components/zd-date-input/ZdDateInput.ts +27 -94
- package/src/components/zd-date-input/ZdDateInput.vue +1 -0
- package/src/components/zd-date-range/ZdDateRange.ts +22 -88
- package/src/components/zd-date-range/ZdDateRange.vue +12 -14
- package/src/components/zd-footer/ZdFooter.vue +1 -0
- package/src/components/zd-grid/footer/ZdGridFooter.vue +2 -2
- package/src/components/zd-grid/toolbar/ZdGridToolbar.vue +2 -2
- package/src/components/zd-header/ZdHeader.vue +5 -5
- package/src/components/zd-iterable/ZdIterableNoData.vue +6 -6
- package/src/components/zd-iterable-component-render/ZdIterableComponentRender.vue +10 -10
- package/src/components/zd-layout/ZdLayout.vue +2 -2
- package/src/components/zd-login/ZdLogin.vue +4 -4
- package/src/components/zd-main/ZdMain.vue +2 -2
- package/src/components/zd-master-detail/ZdMasterDetail.vue +2 -2
- package/src/components/zd-modal/ZdModal.vue +2 -2
- package/src/components/zd-progress/ZdProgress.vue +2 -2
- package/src/components/zd-row/ZdRow.vue +1 -0
- package/src/components/zd-select/ZdSelect.vue +4 -4
- package/src/components/zd-select-multiple/ZdSelectMultiple.vue +4 -4
- package/src/components/zd-tabs/ZdTab.ts +0 -3
- package/src/components/zd-tabs/ZdTab.vue +1 -1
- package/src/components/zd-tabs/ZdTabItem.vue +11 -10
- package/src/components/zd-tabs/ZdTabs.vue +4 -20
- package/src/components/zd-text/ZdText.ts +3 -2
- package/src/components/zd-time/ZdTime.vue +1 -0
- package/src/components/zd-tooltip/ZdTooltip.vue +2 -2
- package/src/components/zd-tree/ZdTree.vue +4 -4
- package/src/composables/index.ts +2 -0
- package/src/composables/useDateKeydown.ts +109 -0
- package/src/composables/usePickerValue.ts +22 -0
- package/types/components/tek-grid/TekGrid.d.ts +7258 -0
- package/types/components/tek-grid/column-filter/TekGridColumnFilter.d.ts +129 -0
- package/types/components/tek-grid/column-header/TekGridHeaderRow.d.ts +225 -0
- package/types/components/tek-grid/columns-button/TekGridColumnsButton.d.ts +2432 -0
- package/types/components/tek-grid/columns-button/TekGridColumnsOptionsController.d.ts +65 -0
- package/types/components/tek-grid/columns-button/TekGridColumnsOptionsModal.d.ts +9 -0
- package/types/components/tek-grid/filter-button/TekGridFilterButton.d.ts +2920 -0
- package/types/components/tek-grid/indentation/TekGridIndentation.d.ts +32 -0
- package/types/components/tek-grid/layout-options/TekGridLayoutOptions.d.ts +1892 -0
- package/types/components/tek-grid/row/TekGridFooterRow.d.ts +90 -0
- package/types/components/tek-grid/row/TekGridGroupRow.d.ts +87 -0
- package/types/components/zd-date-input/ZdDateInput.d.ts +2 -2
- package/types/components/zd-date-range/ZdDateRange.d.ts +22 -7
- package/types/components/zd-grid-editable/cell/ZdGridEditableCell.d.ts +1 -1
- package/types/components/zd-layout/ZdLayout.d.ts +1 -1
- package/types/components/zd-list/ZdList.d.ts +3 -3
- package/types/components/zd-list/ZdListGroup.d.ts +2 -2
- package/types/components/zd-list/ZdListItem.d.ts +1 -1
- package/types/components/zd-month/ZdMonth.d.ts +2 -2
- package/types/components/zd-tabs/ZdTab.d.ts +0 -9
- package/types/components/zd-text/ZdText.d.ts +46 -37
- package/types/components/zd-time/ZdTime.d.ts +2 -2
- package/types/composables/index.d.ts +2 -0
- package/types/composables/useDateKeydown.d.ts +5 -0
- package/types/composables/usePickerValue.d.ts +10 -0
- package/types/composables/useTableLayout.d.ts +25 -0
- package/types/utils/isArrayOperation.d.ts +2 -0
- package/.package.json +0 -54
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { TekGrid, TekMemoryDatasource, TekRestDatasource, } from '@zeedhi/common';
|
|
2
|
+
import { Config, Utils } from '@zeedhi/core';
|
|
3
|
+
import cloneDeep from 'lodash.clonedeep';
|
|
4
|
+
import debounce from 'lodash.debounce';
|
|
5
|
+
import { computed, defineComponent, nextTick } from 'vue';
|
|
6
|
+
import { provideTableLayout, useGridColumns } from '../../composables';
|
|
7
|
+
import { buildProps } from '../../utils';
|
|
8
|
+
import { getRootElement, useCreateInstance } from '../zd-component/ZdComponent';
|
|
9
|
+
import { ZdGridEditableProps, useGridEditableInstance } from '../zd-grid-editable/ZdGridEditable';
|
|
10
|
+
export const TekGridProps = buildProps({
|
|
11
|
+
...ZdGridEditableProps,
|
|
12
|
+
toolbarSlot: {
|
|
13
|
+
type: Array,
|
|
14
|
+
default: undefined,
|
|
15
|
+
},
|
|
16
|
+
title: {
|
|
17
|
+
type: String,
|
|
18
|
+
default: '',
|
|
19
|
+
},
|
|
20
|
+
addButton: {
|
|
21
|
+
type: [Boolean, String],
|
|
22
|
+
default: false,
|
|
23
|
+
},
|
|
24
|
+
deleteButton: {
|
|
25
|
+
type: [String, Boolean],
|
|
26
|
+
default: 'none',
|
|
27
|
+
},
|
|
28
|
+
columnsButton: {
|
|
29
|
+
type: [Boolean, String],
|
|
30
|
+
default: false,
|
|
31
|
+
},
|
|
32
|
+
columnsButtonIgnore: {
|
|
33
|
+
type: [Array, String],
|
|
34
|
+
default: () => [],
|
|
35
|
+
},
|
|
36
|
+
showEditButtons: {
|
|
37
|
+
type: [Boolean, String],
|
|
38
|
+
default: true,
|
|
39
|
+
},
|
|
40
|
+
filterButton: {
|
|
41
|
+
type: [Boolean, String],
|
|
42
|
+
default: false,
|
|
43
|
+
},
|
|
44
|
+
modalFilterProps: {
|
|
45
|
+
type: Object,
|
|
46
|
+
default: () => ({}),
|
|
47
|
+
},
|
|
48
|
+
showSearch: {
|
|
49
|
+
type: [Boolean, String],
|
|
50
|
+
default: true,
|
|
51
|
+
},
|
|
52
|
+
columnFilterButton: {
|
|
53
|
+
type: [Boolean, String],
|
|
54
|
+
default: false,
|
|
55
|
+
},
|
|
56
|
+
hideActions: {
|
|
57
|
+
type: [Boolean, String],
|
|
58
|
+
default: false,
|
|
59
|
+
},
|
|
60
|
+
actions: {
|
|
61
|
+
type: Array,
|
|
62
|
+
default: () => [],
|
|
63
|
+
},
|
|
64
|
+
dragColumns: {
|
|
65
|
+
type: [Boolean, String],
|
|
66
|
+
default: true,
|
|
67
|
+
},
|
|
68
|
+
resizeColumns: {
|
|
69
|
+
type: [Boolean, String],
|
|
70
|
+
default: true,
|
|
71
|
+
},
|
|
72
|
+
showLayoutOptions: {
|
|
73
|
+
type: [Boolean, String],
|
|
74
|
+
default: true,
|
|
75
|
+
},
|
|
76
|
+
showExport: {
|
|
77
|
+
type: [String, Boolean],
|
|
78
|
+
default: false,
|
|
79
|
+
},
|
|
80
|
+
showReload: {
|
|
81
|
+
type: [Boolean, String],
|
|
82
|
+
default: true,
|
|
83
|
+
},
|
|
84
|
+
exportConfig: {
|
|
85
|
+
type: Array,
|
|
86
|
+
},
|
|
87
|
+
exportActions: {
|
|
88
|
+
type: Array,
|
|
89
|
+
},
|
|
90
|
+
groupsOpened: {
|
|
91
|
+
type: [Boolean, String],
|
|
92
|
+
default: false,
|
|
93
|
+
},
|
|
94
|
+
showSummaryTotal: {
|
|
95
|
+
type: [Boolean, String],
|
|
96
|
+
default: true,
|
|
97
|
+
},
|
|
98
|
+
mainGrid: {
|
|
99
|
+
type: [Boolean, String],
|
|
100
|
+
default: true,
|
|
101
|
+
},
|
|
102
|
+
xlsDefaultType: {
|
|
103
|
+
type: String,
|
|
104
|
+
default: undefined,
|
|
105
|
+
},
|
|
106
|
+
showCheckboxAllFilter: {
|
|
107
|
+
type: [Boolean, String],
|
|
108
|
+
default: Config.gridShowCheckboxAllFilter,
|
|
109
|
+
},
|
|
110
|
+
toolbarOpened: {
|
|
111
|
+
type: [Boolean],
|
|
112
|
+
default: true,
|
|
113
|
+
},
|
|
114
|
+
defaultFilter: {
|
|
115
|
+
type: Object,
|
|
116
|
+
},
|
|
117
|
+
reportTitle: {
|
|
118
|
+
type: String,
|
|
119
|
+
},
|
|
120
|
+
editNewRowsOnly: {
|
|
121
|
+
type: [Boolean, String],
|
|
122
|
+
default: false,
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
const gridEditableComponent = defineComponent({
|
|
126
|
+
props: TekGridProps,
|
|
127
|
+
inheritAttrs: false,
|
|
128
|
+
setup(props, ctx) {
|
|
129
|
+
const { instance, root } = useCreateInstance(props, ctx, TekGrid);
|
|
130
|
+
const renderedData = computed(() => {
|
|
131
|
+
if (instance.isGrouped()) {
|
|
132
|
+
return instance.getGroupedData();
|
|
133
|
+
}
|
|
134
|
+
return instance.getData();
|
|
135
|
+
});
|
|
136
|
+
const visibleData = computed(() => {
|
|
137
|
+
return renderedData.value.filter((row) => instance.isItemVisible(row));
|
|
138
|
+
});
|
|
139
|
+
const gridEditableScope = useGridEditableInstance({ instance, root, renderedData: visibleData });
|
|
140
|
+
const rootEl = getRootElement(root);
|
|
141
|
+
const { visibleColumns } = useGridColumns({
|
|
142
|
+
instance,
|
|
143
|
+
rootEl,
|
|
144
|
+
visibilityCondition: (column) => column.isVisible && !column.grouped,
|
|
145
|
+
});
|
|
146
|
+
provideTableLayout({ instance, rootEl });
|
|
147
|
+
const debouncedDatasourceGet = debounce((instance) => {
|
|
148
|
+
const event = new Event('change', { cancelable: true });
|
|
149
|
+
instance.callEvent('beforeApplyFilter', { component: instance, event });
|
|
150
|
+
if (event.defaultPrevented)
|
|
151
|
+
return;
|
|
152
|
+
const { datasource } = instance;
|
|
153
|
+
if (datasource instanceof TekRestDatasource || datasource instanceof TekMemoryDatasource) {
|
|
154
|
+
datasource.updateDynamicFilter();
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
datasource.get();
|
|
158
|
+
}
|
|
159
|
+
}, 500);
|
|
160
|
+
const filter = computed(() => {
|
|
161
|
+
if (instance.datasource instanceof TekRestDatasource || instance.datasource instanceof TekMemoryDatasource) {
|
|
162
|
+
return instance.datasource.dynamicFilter;
|
|
163
|
+
}
|
|
164
|
+
const datasourceFilter = instance.datasource.filter;
|
|
165
|
+
const simpleFilter = {};
|
|
166
|
+
Object.keys(datasourceFilter).forEach((key) => {
|
|
167
|
+
simpleFilter[key] = [{ relation: 'AND', operation: 'CONTAINS', value: datasourceFilter[key] }];
|
|
168
|
+
});
|
|
169
|
+
return simpleFilter;
|
|
170
|
+
});
|
|
171
|
+
const setFilter = (newFilter) => {
|
|
172
|
+
if (Utils.isEqual(filter, newFilter))
|
|
173
|
+
return;
|
|
174
|
+
if (instance.datasource instanceof TekRestDatasource || instance.datasource instanceof TekMemoryDatasource) {
|
|
175
|
+
instance.datasource.dynamicFilter = cloneDeep(newFilter);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
const normalFilter = {};
|
|
179
|
+
Object.keys(newFilter).forEach((key) => {
|
|
180
|
+
if (!newFilter[key][0].value)
|
|
181
|
+
return;
|
|
182
|
+
normalFilter[key] = newFilter[key][0].value;
|
|
183
|
+
});
|
|
184
|
+
instance.datasource.filter = normalFilter;
|
|
185
|
+
}
|
|
186
|
+
debouncedDatasourceGet(instance);
|
|
187
|
+
instance.changeLayout();
|
|
188
|
+
};
|
|
189
|
+
const columnHasFilter = (columnName) => {
|
|
190
|
+
return instance.columnHasFilter(columnName);
|
|
191
|
+
};
|
|
192
|
+
const isRowVisible = (row, index) => {
|
|
193
|
+
return instance.isItemVisible(row) && gridEditableScope.shouldRender(index);
|
|
194
|
+
};
|
|
195
|
+
const isCurrentRowGroup = (row) => {
|
|
196
|
+
const { uniqueKey, currentRow } = instance.datasource;
|
|
197
|
+
return !!((row.group && row.groupValue === currentRow.groupValue) ||
|
|
198
|
+
(row[uniqueKey] && row[uniqueKey] === currentRow[uniqueKey]));
|
|
199
|
+
};
|
|
200
|
+
const isGroupSelectIndeterminate = (item) => {
|
|
201
|
+
let hasSelected = false;
|
|
202
|
+
let hasNotSelected = false;
|
|
203
|
+
const { uniqueKey } = instance.datasource;
|
|
204
|
+
item.children.forEach((child) => {
|
|
205
|
+
const idx = instance.selectedRows.findIndex((row) => child[uniqueKey] === row[uniqueKey]);
|
|
206
|
+
hasSelected = hasSelected || idx !== -1;
|
|
207
|
+
hasNotSelected = hasNotSelected || idx === -1;
|
|
208
|
+
});
|
|
209
|
+
return hasSelected && hasNotSelected;
|
|
210
|
+
};
|
|
211
|
+
const isGroupSelected = (item) => {
|
|
212
|
+
return item.children.every((child) => {
|
|
213
|
+
const { uniqueKey } = instance.datasource;
|
|
214
|
+
const idx = instance.selectedRows.findIndex((row) => child[uniqueKey] === row[uniqueKey]);
|
|
215
|
+
return idx !== -1;
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
const selectGroupRowClick = (row, isSelected, event) => {
|
|
219
|
+
nextTick(() => {
|
|
220
|
+
const rootElement = getRootElement(root);
|
|
221
|
+
instance.selectGroupClick(row, isSelected, event, rootElement.value);
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
const selectGroup = (item, event) => {
|
|
225
|
+
const { uniqueKey } = instance.datasource;
|
|
226
|
+
const isSelected = isGroupSelected(item);
|
|
227
|
+
if (!isSelected) {
|
|
228
|
+
// here we fetch the item from renderedData because vuetify isSelected checks for object reference
|
|
229
|
+
// so we need to find the item inside renderedData to call selectRow() with the correct reference
|
|
230
|
+
// https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VDataTable/composables/select.ts#L128
|
|
231
|
+
const items = item.children.map((child) => {
|
|
232
|
+
return renderedData.value.find((row) => child[uniqueKey] === row[uniqueKey]);
|
|
233
|
+
});
|
|
234
|
+
items.forEach((child) => {
|
|
235
|
+
if (!child)
|
|
236
|
+
return;
|
|
237
|
+
const idx = instance.selectedRows.findIndex((row) => child[uniqueKey] === row[uniqueKey]);
|
|
238
|
+
if (idx === -1) {
|
|
239
|
+
instance.selectRow(child, true);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
item.children.forEach((child) => {
|
|
245
|
+
const idx = instance.selectedRows.findIndex((row) => child[uniqueKey] === row[uniqueKey]);
|
|
246
|
+
if (idx !== -1) {
|
|
247
|
+
instance.selectRow(child, false);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
selectGroupRowClick(item, !isSelected, event);
|
|
252
|
+
};
|
|
253
|
+
const openGroup = (item) => {
|
|
254
|
+
instance.openGroup(item);
|
|
255
|
+
};
|
|
256
|
+
const isGroup = (item) => {
|
|
257
|
+
return !!item.group;
|
|
258
|
+
};
|
|
259
|
+
const isFooter = (item) => {
|
|
260
|
+
return !!item.groupFooter;
|
|
261
|
+
};
|
|
262
|
+
const groupColumnNames = computed(() => {
|
|
263
|
+
return instance.columns.filter((column) => column.grouped).map((column) => column.name) || [];
|
|
264
|
+
});
|
|
265
|
+
return {
|
|
266
|
+
...gridEditableScope,
|
|
267
|
+
instance,
|
|
268
|
+
root,
|
|
269
|
+
filter,
|
|
270
|
+
setFilter,
|
|
271
|
+
columnHasFilter,
|
|
272
|
+
visibleColumns,
|
|
273
|
+
isRowVisible,
|
|
274
|
+
isCurrentRowGroup,
|
|
275
|
+
isGroupSelectIndeterminate,
|
|
276
|
+
selectGroup,
|
|
277
|
+
isGroup,
|
|
278
|
+
openGroup,
|
|
279
|
+
renderedData,
|
|
280
|
+
isGroupSelected,
|
|
281
|
+
groupColumnNames,
|
|
282
|
+
isFooter,
|
|
283
|
+
visibleData,
|
|
284
|
+
};
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
export default gridEditableComponent;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { Config, Metadata, Utils, dayjs } from '@zeedhi/core';
|
|
2
|
+
import cloneDeep from 'lodash.clonedeep';
|
|
3
|
+
import debounce from 'lodash.debounce';
|
|
4
|
+
import { computed, defineComponent, reactive } from 'vue';
|
|
5
|
+
import { isArrayOperation } from '../../../utils';
|
|
6
|
+
export const TekGridColumnFilterProps = {
|
|
7
|
+
hasFilterData: {
|
|
8
|
+
type: Boolean,
|
|
9
|
+
default: false,
|
|
10
|
+
},
|
|
11
|
+
column: {
|
|
12
|
+
type: Object,
|
|
13
|
+
required: true,
|
|
14
|
+
},
|
|
15
|
+
modelValue: {
|
|
16
|
+
type: Array,
|
|
17
|
+
default: [],
|
|
18
|
+
},
|
|
19
|
+
instanceName: {
|
|
20
|
+
type: String,
|
|
21
|
+
required: true,
|
|
22
|
+
},
|
|
23
|
+
filterRelationsDatasource: {
|
|
24
|
+
type: [Object, null],
|
|
25
|
+
required: false,
|
|
26
|
+
},
|
|
27
|
+
filterOperationsDatasource: {
|
|
28
|
+
type: [Object, null],
|
|
29
|
+
required: false,
|
|
30
|
+
},
|
|
31
|
+
isHovering: {
|
|
32
|
+
type: Boolean,
|
|
33
|
+
default: false,
|
|
34
|
+
},
|
|
35
|
+
multiple: {
|
|
36
|
+
type: Boolean,
|
|
37
|
+
required: true,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
const tekGridColumnFilter = defineComponent({
|
|
41
|
+
props: TekGridColumnFilterProps,
|
|
42
|
+
inheritAttrs: false,
|
|
43
|
+
emits: ['update:modelValue'],
|
|
44
|
+
setup(props, ctx) {
|
|
45
|
+
const getValueInputName = (index) => `${props.instanceName}-${props.column.name}-filter-value-${index}`;
|
|
46
|
+
const focusValueInput = (index) => {
|
|
47
|
+
const valueInputName = getValueInputName(index);
|
|
48
|
+
const input = Metadata.getInstance(valueInputName);
|
|
49
|
+
input.setFocus();
|
|
50
|
+
};
|
|
51
|
+
const createNewFilter = () => {
|
|
52
|
+
return reactive({
|
|
53
|
+
operation: 'CONTAINS',
|
|
54
|
+
relation: 'AND',
|
|
55
|
+
value: undefined,
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
let newFilter = createNewFilter();
|
|
59
|
+
const convertToDateFormat = (value, revert) => {
|
|
60
|
+
const dateFormat = props.column.componentProps.dateFormat || Config.dateFormat;
|
|
61
|
+
const displayFormat = props.column.componentProps.displayFormat || Config.displayFormat;
|
|
62
|
+
if (revert) {
|
|
63
|
+
if (dayjs(value, displayFormat).isValid() || !dayjs(value, dateFormat).isValid()) {
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
return dayjs(value, dateFormat).format(displayFormat);
|
|
67
|
+
}
|
|
68
|
+
if (dayjs(value, dateFormat).isValid() || !dayjs(value, displayFormat).isValid()) {
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
return dayjs(value, displayFormat).format(dateFormat);
|
|
72
|
+
};
|
|
73
|
+
const checkDateValueFormat = (value, revert = false) => {
|
|
74
|
+
if (!['ZdDate', 'ZdDateRange'].includes(props.column.componentProps.component))
|
|
75
|
+
return value;
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
return value.map((item) => convertToDateFormat(item, revert));
|
|
78
|
+
}
|
|
79
|
+
return convertToDateFormat(value, revert);
|
|
80
|
+
};
|
|
81
|
+
// use WeakMap to avoid memory leaks
|
|
82
|
+
const idMap = new WeakMap();
|
|
83
|
+
let idCounter = 0;
|
|
84
|
+
// retrieves a unique id for each item
|
|
85
|
+
const getId = (item) => {
|
|
86
|
+
if (!idMap.has(item)) {
|
|
87
|
+
idMap.set(item, `__item__${idCounter++}`);
|
|
88
|
+
}
|
|
89
|
+
return idMap.get(item);
|
|
90
|
+
};
|
|
91
|
+
// use computed to generate unique ids for each filter item
|
|
92
|
+
// this is needed for the v-for :key updates
|
|
93
|
+
const modelWithIds = computed(() => {
|
|
94
|
+
if (!props.multiple) {
|
|
95
|
+
if (props.modelValue.length > 0) {
|
|
96
|
+
return [{ id: getId(props.modelValue[0]), item: props.modelValue[0] }];
|
|
97
|
+
}
|
|
98
|
+
return [{ id: getId(newFilter), item: newFilter }];
|
|
99
|
+
}
|
|
100
|
+
return [...props.modelValue, newFilter].map((item) => ({
|
|
101
|
+
id: getId(item),
|
|
102
|
+
item,
|
|
103
|
+
}));
|
|
104
|
+
});
|
|
105
|
+
const debounceUpdateModel = debounce((modelValue) => {
|
|
106
|
+
if (Utils.isEqual(modelValue, props.modelValue))
|
|
107
|
+
return;
|
|
108
|
+
ctx.emit('update:modelValue', modelValue);
|
|
109
|
+
newFilter = createNewFilter();
|
|
110
|
+
}, 500);
|
|
111
|
+
const changeRelation = (index, { component }) => {
|
|
112
|
+
const modelValue = cloneDeep(props.modelValue);
|
|
113
|
+
const isNewFilter = index === modelValue.length;
|
|
114
|
+
const filter = isNewFilter ? newFilter : modelValue[index];
|
|
115
|
+
const { value } = component;
|
|
116
|
+
focusValueInput(index);
|
|
117
|
+
// update item type value
|
|
118
|
+
filter.relation = value;
|
|
119
|
+
if (isNewFilter)
|
|
120
|
+
return;
|
|
121
|
+
debounceUpdateModel(modelValue);
|
|
122
|
+
};
|
|
123
|
+
const changeOperation = (index, { component }) => {
|
|
124
|
+
const modelValue = cloneDeep(props.modelValue);
|
|
125
|
+
const filterItem = modelValue[index];
|
|
126
|
+
const isNewFilter = index === modelValue.length;
|
|
127
|
+
const filter = isNewFilter ? newFilter : filterItem;
|
|
128
|
+
const { value } = component;
|
|
129
|
+
focusValueInput(index);
|
|
130
|
+
// if operation is IN, NOT_IN or BETWEEN, value should be an array
|
|
131
|
+
if (isArrayOperation(value)) {
|
|
132
|
+
filter.value = Array.isArray(filterItem.value) ? filterItem.value : [filterItem.value];
|
|
133
|
+
}
|
|
134
|
+
// update item type value
|
|
135
|
+
filter.operation = value;
|
|
136
|
+
if (isNewFilter)
|
|
137
|
+
return;
|
|
138
|
+
debounceUpdateModel(modelValue);
|
|
139
|
+
};
|
|
140
|
+
const changeValue = (item, index, { component }) => {
|
|
141
|
+
const modelValue = cloneDeep(props.modelValue);
|
|
142
|
+
const filter = cloneDeep(item);
|
|
143
|
+
const { value } = component;
|
|
144
|
+
const isNewFilter = props.multiple && index === modelValue.length;
|
|
145
|
+
let formattedValue = value;
|
|
146
|
+
if (value && isArrayOperation(filter.operation)) {
|
|
147
|
+
formattedValue = value.split(';');
|
|
148
|
+
}
|
|
149
|
+
filter.value = checkDateValueFormat(formattedValue);
|
|
150
|
+
if (!props.multiple) {
|
|
151
|
+
debounceUpdateModel([filter]);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (isNewFilter) {
|
|
155
|
+
// only emit event when newFilter has value
|
|
156
|
+
if (!filter.value)
|
|
157
|
+
return;
|
|
158
|
+
debounceUpdateModel([...modelValue, filter]);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (!filter.value) {
|
|
162
|
+
// when removing the last (not new) filter, should pass its operation and relation to the new filter
|
|
163
|
+
if (index === modelValue.length - 1) {
|
|
164
|
+
newFilter.operation = filter.operation;
|
|
165
|
+
newFilter.relation = filter.relation;
|
|
166
|
+
}
|
|
167
|
+
modelValue.splice(index, 1);
|
|
168
|
+
// if the removed filter was the first, should set the new first relation to AND
|
|
169
|
+
if (modelValue.length > 0 && index === 0) {
|
|
170
|
+
modelValue[0].relation = 'AND';
|
|
171
|
+
}
|
|
172
|
+
// if the removed filter was the last, should set the newFilter relation to AND
|
|
173
|
+
if (modelValue.length === 0) {
|
|
174
|
+
newFilter.relation = 'AND';
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
debounceUpdateModel(modelValue);
|
|
178
|
+
};
|
|
179
|
+
const getComponentType = (operation) => {
|
|
180
|
+
return isArrayOperation(operation) ? 'ZdTextInput' : props.column.componentProps.component;
|
|
181
|
+
};
|
|
182
|
+
const getComponentHint = (operation) => {
|
|
183
|
+
return isArrayOperation(operation) ? 'TEKGRID_MULTIPLE_VALUE_HINT' : '';
|
|
184
|
+
};
|
|
185
|
+
const getItemValue = (item) => {
|
|
186
|
+
return isArrayOperation(item.operation) ? item.value.join(';') : item.value;
|
|
187
|
+
};
|
|
188
|
+
return {
|
|
189
|
+
changeValue,
|
|
190
|
+
changeRelation,
|
|
191
|
+
changeOperation,
|
|
192
|
+
getValueInputName,
|
|
193
|
+
newFilter,
|
|
194
|
+
getComponentType,
|
|
195
|
+
getComponentHint,
|
|
196
|
+
modelWithIds,
|
|
197
|
+
getItemValue,
|
|
198
|
+
};
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
export default tekGridColumnFilter;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { defineComponent, inject } from 'vue';
|
|
2
|
+
export default defineComponent({
|
|
3
|
+
props: {
|
|
4
|
+
selectable: {
|
|
5
|
+
type: Boolean,
|
|
6
|
+
default: false,
|
|
7
|
+
},
|
|
8
|
+
headerBackground: {
|
|
9
|
+
type: String,
|
|
10
|
+
default: '',
|
|
11
|
+
},
|
|
12
|
+
showSelectAll: {
|
|
13
|
+
type: Boolean,
|
|
14
|
+
default: false,
|
|
15
|
+
},
|
|
16
|
+
allselectedState: {
|
|
17
|
+
type: Number,
|
|
18
|
+
default: 0,
|
|
19
|
+
},
|
|
20
|
+
visibleColumns: {
|
|
21
|
+
type: Array,
|
|
22
|
+
default: () => [],
|
|
23
|
+
},
|
|
24
|
+
dragColumns: {
|
|
25
|
+
type: Boolean,
|
|
26
|
+
default: false,
|
|
27
|
+
},
|
|
28
|
+
headerCellTextColor: {
|
|
29
|
+
type: String,
|
|
30
|
+
default: '',
|
|
31
|
+
},
|
|
32
|
+
resizeColumns: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
default: false,
|
|
35
|
+
},
|
|
36
|
+
getSortIcon: {
|
|
37
|
+
type: Function,
|
|
38
|
+
default: () => { },
|
|
39
|
+
},
|
|
40
|
+
isSorted: {
|
|
41
|
+
type: Function,
|
|
42
|
+
default: () => { },
|
|
43
|
+
},
|
|
44
|
+
toggleSort: {
|
|
45
|
+
type: Function,
|
|
46
|
+
default: () => { },
|
|
47
|
+
},
|
|
48
|
+
tableColumns: {
|
|
49
|
+
type: Array,
|
|
50
|
+
default: () => [],
|
|
51
|
+
},
|
|
52
|
+
sortBy: {
|
|
53
|
+
type: Array,
|
|
54
|
+
default: () => [],
|
|
55
|
+
},
|
|
56
|
+
disableCheckbox: {
|
|
57
|
+
type: Boolean,
|
|
58
|
+
default: false,
|
|
59
|
+
},
|
|
60
|
+
sortable: {
|
|
61
|
+
type: Boolean,
|
|
62
|
+
default: true,
|
|
63
|
+
},
|
|
64
|
+
name: {
|
|
65
|
+
type: String,
|
|
66
|
+
default: '',
|
|
67
|
+
},
|
|
68
|
+
modelValue: {
|
|
69
|
+
type: Object,
|
|
70
|
+
default: () => [],
|
|
71
|
+
},
|
|
72
|
+
instanceName: {
|
|
73
|
+
type: String,
|
|
74
|
+
required: true,
|
|
75
|
+
},
|
|
76
|
+
filterRelationsDatasource: {
|
|
77
|
+
type: [Object, null],
|
|
78
|
+
required: false,
|
|
79
|
+
},
|
|
80
|
+
filterOperationsDatasource: {
|
|
81
|
+
type: [Object, null],
|
|
82
|
+
required: false,
|
|
83
|
+
},
|
|
84
|
+
columnFilterButton: {
|
|
85
|
+
type: Boolean,
|
|
86
|
+
required: true,
|
|
87
|
+
},
|
|
88
|
+
columnHasFilter: {
|
|
89
|
+
type: Function,
|
|
90
|
+
required: true,
|
|
91
|
+
},
|
|
92
|
+
level: {
|
|
93
|
+
type: Number,
|
|
94
|
+
default: 0,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
emits: ['selectAllClick', 'resizeMousedown', 'resizeClick', 'update:modelValue'],
|
|
98
|
+
setup(props, { emit }) {
|
|
99
|
+
const calcWidth = inject('calcWidth');
|
|
100
|
+
if (!calcWidth) {
|
|
101
|
+
// TODO: use NotProvidedError
|
|
102
|
+
throw new Error('calcWidth');
|
|
103
|
+
}
|
|
104
|
+
const selectAllClick = (event) => {
|
|
105
|
+
emit('selectAllClick', event);
|
|
106
|
+
};
|
|
107
|
+
const resizeMousedown = (column, event) => {
|
|
108
|
+
emit('resizeMousedown', { event, column });
|
|
109
|
+
};
|
|
110
|
+
const resizeClick = (event) => {
|
|
111
|
+
emit('resizeClick', { event });
|
|
112
|
+
};
|
|
113
|
+
const findOrderIndex = (sortBy, column) => {
|
|
114
|
+
return sortBy.findIndex((sort) => sort.key === column.name);
|
|
115
|
+
};
|
|
116
|
+
const updateModelValue = (columnName, value) => {
|
|
117
|
+
const modelValue = { ...props.modelValue };
|
|
118
|
+
modelValue[columnName] = value;
|
|
119
|
+
emit('update:modelValue', modelValue);
|
|
120
|
+
};
|
|
121
|
+
const showFilterButton = (column) => {
|
|
122
|
+
return column.type !== 'action' && props.columnFilterButton && column.filterable;
|
|
123
|
+
};
|
|
124
|
+
return {
|
|
125
|
+
calcWidth,
|
|
126
|
+
resizeMousedown,
|
|
127
|
+
resizeClick,
|
|
128
|
+
findOrderIndex,
|
|
129
|
+
updateModelValue,
|
|
130
|
+
showFilterButton,
|
|
131
|
+
selectAllClick,
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { TekGridColumnsButton } from '@zeedhi/common';
|
|
2
|
+
import sortable from 'sortablejs';
|
|
3
|
+
import { computed, defineComponent, mergeProps, nextTick, ref, watch } from 'vue';
|
|
4
|
+
import { useButtonInstance, useCreateInstance } from '../..';
|
|
5
|
+
import { ZdIterableColumnsButtonProps } from '../../zd-iterable/zd-iterable-columns-button/ZdIterableColumnsButton';
|
|
6
|
+
import optionsModal from './TekGridColumnsOptionsModal';
|
|
7
|
+
export const TekGridColumnsButtonProps = {
|
|
8
|
+
...ZdIterableColumnsButtonProps,
|
|
9
|
+
hideGroups: {
|
|
10
|
+
type: [Boolean, String],
|
|
11
|
+
default: false,
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
const tekGridColumnsButton = defineComponent({
|
|
15
|
+
props: TekGridColumnsButtonProps,
|
|
16
|
+
inheritAttrs: false,
|
|
17
|
+
setup(props, ctx) {
|
|
18
|
+
const { instance, root } = useCreateInstance(props, ctx, TekGridColumnsButton);
|
|
19
|
+
const buttonScope = useButtonInstance({ instance, root });
|
|
20
|
+
const menuIsOpened = ref(false);
|
|
21
|
+
const sortableInitialized = ref(false);
|
|
22
|
+
const teste = (a) => {
|
|
23
|
+
console.warn(a);
|
|
24
|
+
};
|
|
25
|
+
watch(menuIsOpened, () => {
|
|
26
|
+
if (!menuIsOpened.value || sortableInitialized.value)
|
|
27
|
+
return;
|
|
28
|
+
sortableInitialized.value = true;
|
|
29
|
+
nextTick(() => {
|
|
30
|
+
const columnsTableBody = document.querySelector(`#${instance.name}_columns_table tbody`);
|
|
31
|
+
if (columnsTableBody) {
|
|
32
|
+
sortable.create(columnsTableBody, {
|
|
33
|
+
handle: '.sortHandle',
|
|
34
|
+
dragClass: 'tek-grid-columns-button-sortable-drag',
|
|
35
|
+
onEnd: sortEnd,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
const gridGroupColumnNames = computed(() => {
|
|
41
|
+
return instance.iterableComponent.columns.filter((column) => column.grouped).map((column) => column.name) || [];
|
|
42
|
+
});
|
|
43
|
+
const sortEnd = (event) => {
|
|
44
|
+
const grid = instance.iterableComponent;
|
|
45
|
+
const newOrder = Array.from(event.srcElement.querySelectorAll('tr')).map((row) => row.getAttribute('name'));
|
|
46
|
+
const groupColumnNames = [];
|
|
47
|
+
const newColumns = newOrder.map((columnName) => {
|
|
48
|
+
const column = grid.getColumn(columnName);
|
|
49
|
+
if (column.grouped) {
|
|
50
|
+
groupColumnNames.push(columnName);
|
|
51
|
+
}
|
|
52
|
+
return column;
|
|
53
|
+
});
|
|
54
|
+
const ignoredColumns = grid.columns.filter((column) => instance.ignoreColumns.indexOf(column.name) !== -1);
|
|
55
|
+
grid.columns = newColumns.concat(ignoredColumns);
|
|
56
|
+
if (grid.updateGrouping && JSON.stringify(groupColumnNames) !== JSON.stringify(gridGroupColumnNames)) {
|
|
57
|
+
grid.updateGrouping();
|
|
58
|
+
}
|
|
59
|
+
grid.changeLayout();
|
|
60
|
+
};
|
|
61
|
+
const moreOptions = () => {
|
|
62
|
+
optionsModal.show(instance);
|
|
63
|
+
};
|
|
64
|
+
const close = () => {
|
|
65
|
+
menuIsOpened.value = false;
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
...buttonScope,
|
|
69
|
+
instance,
|
|
70
|
+
root,
|
|
71
|
+
menuIsOpened,
|
|
72
|
+
moreOptions,
|
|
73
|
+
close,
|
|
74
|
+
teste,
|
|
75
|
+
mergeProps,
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
export default tekGridColumnsButton;
|