@zeedhi/teknisa-components-vuetify 3.0.0 → 3.0.1

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.
Files changed (59) hide show
  1. package/.package.json +10 -7
  2. package/dist/teknisa-vuetify.css +1 -1
  3. package/dist/teknisa-vuetify.js +3777 -14
  4. package/package.json +3 -3
  5. package/src/components/index.ts +22 -0
  6. package/src/components/public.ts +14 -18
  7. package/src/components/tek-grid/TekGrid.ts +318 -0
  8. package/src/components/tek-grid/TekGrid.vue +235 -0
  9. package/src/components/tek-grid/column-filter/TekGridColumnFilter.ts +244 -0
  10. package/src/components/tek-grid/column-filter/TekGridColumnFilter.vue +93 -0
  11. package/src/components/tek-grid/column-header/TekGridHeaderRow.ts +147 -0
  12. package/src/components/tek-grid/column-header/TekGridHeaderRow.vue +78 -0
  13. package/src/components/tek-grid/columns-button/TekGridColumnsButton.ts +96 -0
  14. package/src/components/tek-grid/columns-button/TekGridColumnsButton.vue +273 -0
  15. package/src/components/tek-grid/columns-button/TekGridColumnsOptionsController.ts +470 -0
  16. package/src/components/tek-grid/columns-button/TekGridColumnsOptionsModal.ts +513 -0
  17. package/src/components/tek-grid/filter-button/TekGridFilterButton.ts +47 -0
  18. package/src/components/tek-grid/filter-button/TekGridFilterButton.vue +28 -0
  19. package/src/components/tek-grid/indentation/TekGridIndentation.ts +21 -0
  20. package/src/components/tek-grid/indentation/TekGridIndentation.vue +33 -0
  21. package/src/components/tek-grid/layout-options/TekGridLayoutOptions.ts +119 -0
  22. package/src/components/tek-grid/layout-options/TekGridLayoutOptions.vue +172 -0
  23. package/src/components/tek-grid/row/TekGridFooterRow.ts +62 -0
  24. package/src/components/tek-grid/row/TekGridFooterRow.vue +64 -0
  25. package/src/components/tek-grid/row/TekGridGroupRow.ts +65 -0
  26. package/src/components/tek-grid/row/TekGridGroupRow.vue +65 -0
  27. package/src/components/tek-user-info/TekUserInfo.ts +51 -0
  28. package/src/components/tek-user-info/TekUserInfo.vue +53 -0
  29. package/src/components/tek-user-info/TekUserInfoList.ts +39 -0
  30. package/src/components/tek-user-info/TekUserInfoList.vue +12 -0
  31. package/src/composables/useTableLayout.ts +290 -0
  32. package/src/utils/isArrayOperation.ts +5 -0
  33. package/types/components/public.d.ts +8 -1
  34. package/types/components/tek-grid/TekGrid.d.ts +7211 -0
  35. package/types/components/tek-grid/TekGrid.ts.d.ts +7211 -0
  36. package/types/components/tek-grid/column-filter/TekGridColumnFilter.d.ts +130 -0
  37. package/types/components/tek-grid/column-filter/TekGridColumnFilter.ts.d.ts +130 -0
  38. package/types/components/tek-grid/column-header/TekGridHeaderRow.d.ts +225 -0
  39. package/types/components/tek-grid/column-header/TekGridHeaderRow.ts.d.ts +225 -0
  40. package/types/components/tek-grid/columns-button/TekGridColumnsButton.d.ts +2432 -0
  41. package/types/components/tek-grid/columns-button/TekGridColumnsButton.ts.d.ts +2432 -0
  42. package/types/components/tek-grid/columns-button/TekGridColumnsOptionsController.d.ts +66 -0
  43. package/types/components/tek-grid/columns-button/TekGridColumnsOptionsModal.d.ts +9 -0
  44. package/types/components/tek-grid/filter-button/TekGridFilterButton.d.ts +2920 -0
  45. package/types/components/tek-grid/filter-button/TekGridFilterButton.ts.d.ts +2920 -0
  46. package/types/components/tek-grid/indentation/TekGridIndentation.d.ts +32 -0
  47. package/types/components/tek-grid/indentation/TekGridIndentation.ts.d.ts +32 -0
  48. package/types/components/tek-grid/layout-options/TekGridLayoutOptions.d.ts +1893 -0
  49. package/types/components/tek-grid/layout-options/TekGridLayoutOptions.ts.d.ts +1893 -0
  50. package/types/components/tek-grid/row/TekGridFooterRow.d.ts +90 -0
  51. package/types/components/tek-grid/row/TekGridFooterRow.ts.d.ts +90 -0
  52. package/types/components/tek-grid/row/TekGridGroupRow.d.ts +87 -0
  53. package/types/components/tek-grid/row/TekGridGroupRow.ts.d.ts +87 -0
  54. package/types/components/tek-user-info/TekUserInfo.d.ts +1940 -0
  55. package/types/components/tek-user-info/TekUserInfo.ts.d.ts +1940 -0
  56. package/types/components/tek-user-info/TekUserInfoList.d.ts +1015 -0
  57. package/types/components/tek-user-info/TekUserInfoList.ts.d.ts +1015 -0
  58. package/types/composables/useTableLayout.d.ts +26 -0
  59. package/types/utils/isArrayOperation.d.ts +2 -0
@@ -0,0 +1,244 @@
1
+ import { Input, Radio, Select } from '@zeedhi/common';
2
+ import { IDynamicFilterItem } from '@zeedhi/teknisa-components-common';
3
+ import { Config, IEventParam, Metadata, Utils, dayjs } from '@zeedhi/core';
4
+ import cloneDeep from 'lodash.clonedeep';
5
+ import debounce from 'lodash.debounce';
6
+ import { PropType, computed, defineComponent, reactive } from 'vue';
7
+ import { isArrayOperation } from '../../../utils/isArrayOperation';
8
+
9
+ export const TekGridColumnFilterProps = {
10
+ hasFilterData: {
11
+ type: Boolean,
12
+ default: false,
13
+ },
14
+ column: {
15
+ type: Object,
16
+ required: true,
17
+ },
18
+ modelValue: {
19
+ type: Array as PropType<IDynamicFilterItem[]>,
20
+ default: [],
21
+ },
22
+ instanceName: {
23
+ type: String,
24
+ required: true,
25
+ },
26
+ filterRelationsDatasource: {
27
+ type: [Object, null] as PropType<boolean | null>,
28
+ required: false,
29
+ },
30
+ filterOperationsDatasource: {
31
+ type: [Object, null] as PropType<boolean | null>,
32
+ required: false,
33
+ },
34
+ isHovering: {
35
+ type: Boolean,
36
+ default: false,
37
+ },
38
+ multiple: {
39
+ type: Boolean,
40
+ required: true,
41
+ },
42
+ } as const;
43
+
44
+ type InputType = Input | Select | Radio;
45
+
46
+ const tekGridColumnFilter = defineComponent({
47
+ props: TekGridColumnFilterProps,
48
+ inheritAttrs: false,
49
+ emits: ['update:modelValue'],
50
+ setup(props, ctx) {
51
+ const getValueInputName = (index: number) => `${props.instanceName}-${props.column.name}-filter-value-${index}`;
52
+
53
+ const focusValueInput = (index: number) => {
54
+ const valueInputName = getValueInputName(index);
55
+ const input = Metadata.getInstance<Input>(valueInputName);
56
+
57
+ input.setFocus();
58
+ };
59
+
60
+ const createNewFilter = () => {
61
+ return reactive<IDynamicFilterItem>({
62
+ operation: 'CONTAINS',
63
+ relation: 'AND',
64
+ value: undefined,
65
+ });
66
+ };
67
+
68
+ let newFilter = createNewFilter();
69
+
70
+ const convertToDateFormat = (value: string, revert: boolean) => {
71
+ const dateFormat = props.column!.componentProps.dateFormat || Config.dateFormat;
72
+ const displayFormat = props.column!.componentProps.displayFormat || Config.displayFormat;
73
+
74
+ if (revert) {
75
+ if (dayjs(value, displayFormat).isValid() || !dayjs(value, dateFormat).isValid()) {
76
+ return value;
77
+ }
78
+ return dayjs(value, dateFormat).format(displayFormat);
79
+ }
80
+
81
+ if (dayjs(value, dateFormat).isValid() || !dayjs(value, displayFormat).isValid()) {
82
+ return value;
83
+ }
84
+ return dayjs(value, displayFormat).format(dateFormat);
85
+ };
86
+
87
+ const checkDateValueFormat = (value: string | string[], revert = false) => {
88
+ if (!['ZdDate', 'ZdDateRange'].includes(props.column!.componentProps.component)) return value;
89
+
90
+ if (Array.isArray(value)) {
91
+ return value.map((item) => convertToDateFormat(item, revert));
92
+ }
93
+ return convertToDateFormat(value, revert);
94
+ };
95
+
96
+ // use WeakMap to avoid memory leaks
97
+ const idMap = new WeakMap<object, string>();
98
+ let idCounter = 0;
99
+
100
+ // retrieves a unique id for each item
101
+ const getId = (item: object) => {
102
+ if (!idMap.has(item)) {
103
+ idMap.set(item, `__item__${idCounter++}`);
104
+ }
105
+ return idMap.get(item)!;
106
+ };
107
+
108
+ // use computed to generate unique ids for each filter item
109
+ // this is needed for the v-for :key updates
110
+ const modelWithIds = computed(() => {
111
+ if (!props.multiple) {
112
+ if (props.modelValue.length > 0) {
113
+ return [{ id: getId(props.modelValue[0]), item: props.modelValue[0] }];
114
+ }
115
+
116
+ return [{ id: getId(newFilter), item: newFilter }];
117
+ }
118
+
119
+ return [...props.modelValue, newFilter].map((item) => ({
120
+ id: getId(item),
121
+ item,
122
+ }));
123
+ });
124
+
125
+ const debounceUpdateModel = debounce((modelValue: IDynamicFilterItem[]) => {
126
+ if (Utils.isEqual(modelValue, props.modelValue)) return;
127
+ ctx.emit('update:modelValue', modelValue);
128
+ newFilter = createNewFilter();
129
+ }, 500);
130
+
131
+ const changeRelation = (index: number, { component }: IEventParam<InputType>) => {
132
+ const modelValue = cloneDeep(props.modelValue);
133
+ const isNewFilter = index === modelValue.length;
134
+ const filter = isNewFilter ? newFilter : modelValue[index];
135
+ const { value } = component;
136
+
137
+ focusValueInput(index);
138
+
139
+ // update item type value
140
+ filter.relation = value;
141
+
142
+ if (isNewFilter) return;
143
+
144
+ debounceUpdateModel(modelValue);
145
+ };
146
+
147
+ const changeOperation = (index: number, { component }: IEventParam<InputType>) => {
148
+ const modelValue = cloneDeep(props.modelValue);
149
+ const filterItem = modelValue[index];
150
+ const isNewFilter = index === modelValue.length;
151
+ const filter = isNewFilter ? newFilter : filterItem;
152
+ const { value } = component;
153
+
154
+ focusValueInput(index);
155
+
156
+ // if operation is IN, NOT_IN or BETWEEN, value should be an array
157
+ if (isArrayOperation(value)) {
158
+ filter.value = Array.isArray(filterItem.value) ? filterItem.value : [filterItem.value];
159
+ }
160
+
161
+ // update item type value
162
+ filter.operation = value;
163
+
164
+ if (isNewFilter) return;
165
+
166
+ debounceUpdateModel(modelValue);
167
+ };
168
+
169
+ const changeValue = (item: IDynamicFilterItem, index: number, { component }: IEventParam<InputType>) => {
170
+ const modelValue = cloneDeep(props.modelValue);
171
+ const filter = cloneDeep(item);
172
+ const { value } = component;
173
+ const isNewFilter = props.multiple && index === modelValue.length;
174
+ let formattedValue = value;
175
+
176
+ if (value && isArrayOperation(filter.operation)) {
177
+ formattedValue = value.split(';');
178
+ }
179
+
180
+ filter.value = checkDateValueFormat(formattedValue);
181
+
182
+ if (!props.multiple) {
183
+ debounceUpdateModel([filter]);
184
+ return;
185
+ }
186
+
187
+ if (isNewFilter) {
188
+ // only emit event when newFilter has value
189
+ if (!filter.value) return;
190
+
191
+ debounceUpdateModel([...modelValue, filter]);
192
+ return;
193
+ }
194
+
195
+ if (!filter.value) {
196
+ // when removing the last (not new) filter, should pass its operation and relation to the new filter
197
+ if (index === modelValue.length - 1) {
198
+ newFilter.operation = filter.operation;
199
+ newFilter.relation = filter.relation;
200
+ }
201
+
202
+ modelValue.splice(index, 1);
203
+
204
+ // if the removed filter was the first, should set the new first relation to AND
205
+ if (modelValue.length > 0 && index === 0) {
206
+ modelValue[0].relation = 'AND';
207
+ }
208
+
209
+ // if the removed filter was the last, should set the newFilter relation to AND
210
+ if (modelValue.length === 0) {
211
+ newFilter.relation = 'AND';
212
+ }
213
+ }
214
+
215
+ debounceUpdateModel(modelValue);
216
+ };
217
+
218
+ const getComponentType = (operation: string) => {
219
+ return isArrayOperation(operation) ? 'ZdTextInput' : props.column.componentProps.component;
220
+ };
221
+
222
+ const getComponentHint = (operation: string) => {
223
+ return isArrayOperation(operation) ? 'TEKGRID_MULTIPLE_VALUE_HINT' : '';
224
+ };
225
+
226
+ const getItemValue = (item: IDynamicFilterItem) => {
227
+ return isArrayOperation(item.operation) ? item.value.join(';') : item.value;
228
+ };
229
+
230
+ return {
231
+ changeValue,
232
+ changeRelation,
233
+ changeOperation,
234
+ getValueInputName,
235
+ newFilter,
236
+ getComponentType,
237
+ getComponentHint,
238
+ modelWithIds,
239
+ getItemValue,
240
+ };
241
+ },
242
+ });
243
+
244
+ export default tekGridColumnFilter;
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <v-menu
3
+ offset-overflow
4
+ offset-y
5
+ transition="scale-transition"
6
+ content-class="tek-grid-column-filter__menu"
7
+ :close-on-content-click="false"
8
+ >
9
+ <template #activator="{ props }">
10
+ <zd-grid-header-icon
11
+ v-bind="props"
12
+ :icon="$getIcon('filter')"
13
+ :hidden="!isHovering && !hasFilterData"
14
+ :color="hasFilterData ? 'primary' : ''"
15
+ ></zd-grid-header-icon>
16
+ </template>
17
+
18
+ <v-card
19
+ class="zd-pa-4 zd-pb-0"
20
+ :min-width="200"
21
+ :max-height="300"
22
+ >
23
+ <template
24
+ v-for="({ item, id }, filterIndex) in modelWithIds"
25
+ :key="id"
26
+ >
27
+ <!-- relation -->
28
+ <zd-radio
29
+ v-if="multiple && filterIndex > 0"
30
+ :name="`${instanceName}-${column.name}-filter-relation-${filterIndex}`"
31
+ v-bind="{
32
+ showLabel: false,
33
+ showHelper: false,
34
+ vertical: false,
35
+ cssClass: 'zd-mb-2',
36
+ datasource: filterRelationsDatasource,
37
+ dataValue: 'value',
38
+ dataLabel: 'text',
39
+ value: item.relation,
40
+ events: {
41
+ change: (params) => changeRelation(filterIndex, params),
42
+ },
43
+ }"
44
+ />
45
+
46
+ <!-- operation -->
47
+ <zd-select
48
+ v-if="multiple && item.operation"
49
+ :name="`${instanceName}-${column.name}-filter-operation-${filterIndex}`"
50
+ v-bind="{
51
+ autocomplete: false,
52
+ showLabel: false,
53
+ showHelper: false,
54
+ clearable: false,
55
+ cssClass: 'zd-mb-2',
56
+ datasource: filterOperationsDatasource,
57
+ dataValue: 'value',
58
+ dataText: 'text',
59
+ value: item.operation,
60
+ events: {
61
+ change: (params) => changeOperation(filterIndex, params),
62
+ },
63
+ }"
64
+ />
65
+
66
+ <!-- value -->
67
+ <component
68
+ :name="`${instanceName}-${column.name}-filter-value-${filterIndex}`"
69
+ :is="getComponentType(item.operation)"
70
+ v-bind="{
71
+ ...column.componentProps,
72
+ showLabel: false,
73
+ showHelper: true,
74
+ autofill: false,
75
+ cssClass: 'zd-mb-2',
76
+ value: getItemValue(item),
77
+ persistentHint: true,
78
+ hint: getComponentHint(item.operation),
79
+ events: {
80
+ input: (params) => changeValue(item, filterIndex, params),
81
+ change: (params) => changeValue(item, filterIndex, params),
82
+ },
83
+ }"
84
+ />
85
+ </template>
86
+ </v-card>
87
+ </v-menu>
88
+ </template>
89
+
90
+ <script lang="ts" src="./TekGridColumnFilter.ts"></script>
91
+
92
+ <style lang="scss">
93
+ </style>
@@ -0,0 +1,147 @@
1
+ import { Column, GridColumn } from '@zeedhi/common';
2
+ import { IDynamicFilterItem, TekGridColumn } from '@zeedhi/teknisa-components-common';
3
+ import { IDictionary } from '@zeedhi/core';
4
+ import { PropType, UnwrapRef, defineComponent, inject } from 'vue';
5
+ import { ResizeParams, CalcWidth } from '@zeedhi/vuetify';
6
+
7
+ export default defineComponent({
8
+ props: {
9
+ selectable: {
10
+ type: Boolean,
11
+ default: false,
12
+ },
13
+ headerBackground: {
14
+ type: String,
15
+ default: '',
16
+ },
17
+ showSelectAll: {
18
+ type: Boolean,
19
+ default: false,
20
+ },
21
+ allselectedState: {
22
+ type: Number,
23
+ default: 0,
24
+ },
25
+ visibleColumns: {
26
+ type: Array as PropType<GridColumn[]>,
27
+ default: () => [],
28
+ },
29
+ dragColumns: {
30
+ type: Boolean,
31
+ default: false,
32
+ },
33
+ headerCellTextColor: {
34
+ type: String,
35
+ default: '',
36
+ },
37
+ resizeColumns: {
38
+ type: Boolean,
39
+ default: false,
40
+ },
41
+ getSortIcon: {
42
+ type: Function,
43
+ default: () => {},
44
+ },
45
+ isSorted: {
46
+ type: Function,
47
+ default: () => {},
48
+ },
49
+ toggleSort: {
50
+ type: Function,
51
+ default: () => {},
52
+ },
53
+ tableColumns: {
54
+ type: Array as PropType<any[]>,
55
+ default: () => [],
56
+ },
57
+ sortBy: {
58
+ type: Array as PropType<any[]>,
59
+ default: () => [],
60
+ },
61
+ disableCheckbox: {
62
+ type: Boolean,
63
+ default: false,
64
+ },
65
+ sortable: {
66
+ type: Boolean,
67
+ default: true,
68
+ },
69
+ name: {
70
+ type: String,
71
+ default: '',
72
+ },
73
+ modelValue: {
74
+ type: Object as PropType<IDictionary<IDynamicFilterItem[]>>,
75
+ default: () => [],
76
+ },
77
+ instanceName: {
78
+ type: String,
79
+ required: true,
80
+ },
81
+ filterRelationsDatasource: {
82
+ type: [Object, null],
83
+ required: false,
84
+ },
85
+ filterOperationsDatasource: {
86
+ type: [Object, null],
87
+ required: false,
88
+ },
89
+ columnFilterButton: {
90
+ type: Boolean,
91
+ required: true,
92
+ },
93
+ columnHasFilter: {
94
+ type: Function as PropType<(columnName: string) => boolean>,
95
+ required: true,
96
+ },
97
+ level: {
98
+ type: Number,
99
+ default: 0,
100
+ },
101
+ },
102
+ emits: ['selectAllClick', 'resizeMousedown', 'resizeClick', 'update:modelValue'],
103
+ setup(props, { emit }) {
104
+ const calcWidth = inject<CalcWidth>('calcWidth');
105
+
106
+ if (!calcWidth) {
107
+ // TODO: use NotProvidedError
108
+ throw new Error('calcWidth');
109
+ }
110
+
111
+ const selectAllClick = (event: Event) => {
112
+ emit('selectAllClick', event);
113
+ };
114
+
115
+ const resizeMousedown = (column: GridColumn, event: ResizeParams) => {
116
+ emit('resizeMousedown', { event, column });
117
+ };
118
+
119
+ const resizeClick = (event: Event) => {
120
+ emit('resizeClick', { event });
121
+ };
122
+
123
+ const findOrderIndex = (sortBy: readonly any[], column: UnwrapRef<Column>) => {
124
+ return sortBy.findIndex((sort) => sort.key === column.name);
125
+ };
126
+
127
+ const updateModelValue = (columnName: string, value: IDynamicFilterItem[]) => {
128
+ const modelValue = { ...props.modelValue };
129
+ modelValue[columnName] = value;
130
+ emit('update:modelValue', modelValue);
131
+ };
132
+
133
+ const showFilterButton = (column: TekGridColumn) => {
134
+ return column.type !== 'action' && props.columnFilterButton && column.filterable;
135
+ };
136
+
137
+ return {
138
+ calcWidth,
139
+ resizeMousedown,
140
+ resizeClick,
141
+ findOrderIndex,
142
+ updateModelValue,
143
+ showFilterButton,
144
+ selectAllClick,
145
+ };
146
+ },
147
+ });
@@ -0,0 +1,78 @@
1
+ <template>
2
+ <zd-grid-header-row
3
+ :name="name"
4
+ :selectable="selectable"
5
+ :headerBackground="headerBackground"
6
+ :showSelectAll="showSelectAll"
7
+ :allselectedState="allselectedState"
8
+ :visibleColumns="visibleColumns"
9
+ :dragColumns="dragColumns"
10
+ :headerCellTextColor="headerCellTextColor"
11
+ :resizeColumns="resizeColumns"
12
+ :getSortIcon="getSortIcon"
13
+ :toggleSort="toggleSort"
14
+ :sortBy="sortBy"
15
+ :tableColumns="tableColumns"
16
+ :isSorted="isSorted"
17
+ :disableCheckbox="disableCheckbox"
18
+ @selectAllClick="selectAllClick"
19
+ >
20
+ <template #default="{ column, index, isHovering }">
21
+ <zd-grid-column-header
22
+ :cssStyle="{
23
+ 'color': headerCellTextColor,
24
+ width: calcWidth(column),
25
+ }"
26
+ :action="column.type === 'action'"
27
+ :overflow="column.overflow"
28
+ :helperText="column.helperText"
29
+ :label="column.label"
30
+ :columnAlign="column.align"
31
+ :orderIndex="findOrderIndex(sortBy, column)"
32
+ :isSortable="sortable && column.sortable"
33
+ :resizeColumns="resizeColumns"
34
+ :sortIcon="getSortIcon(tableColumns[index])"
35
+ :isSorted="isSorted(tableColumns[index])"
36
+ :isHovering="isHovering"
37
+ @click="toggleSort(tableColumns[index])"
38
+ @resizeMousedown="resizeMousedown(column, $event)"
39
+ @resizeClick="resizeClick($event)"
40
+ >
41
+ <template #prepend v-if="index === 0">
42
+ <tek-grid-indentation
43
+ :level="level"
44
+ :show-divider="false"
45
+ ></tek-grid-indentation>
46
+ </template>
47
+ <template #label>
48
+ <span
49
+ v-if="column.aggregation"
50
+ class="tek-grid-column-aggregation"
51
+ >({{ $t(`TEKGRID_AGGREGATION_${column.aggregation}`) }})
52
+ </span>
53
+ </template>
54
+
55
+ <template
56
+ #append="{ isHovering }"
57
+ v-if="showFilterButton(column)"
58
+ >
59
+ <tek-grid-column-filter
60
+ :modelValue="modelValue[column.name]"
61
+ :hasFilterData="columnHasFilter(column.name)"
62
+ :column="column"
63
+ :instanceName="instanceName"
64
+ :filterRelationsDatasource="filterRelationsDatasource"
65
+ :filterOperationsDatasource="filterOperationsDatasource"
66
+ :isHovering="isHovering"
67
+ :multiple="!!filterRelationsDatasource && !!filterOperationsDatasource"
68
+ @update:modelValue="updateModelValue(column.name, $event)"
69
+ ></tek-grid-column-filter>
70
+ </template>
71
+ </zd-grid-column-header>
72
+ </template>
73
+ </zd-grid-header-row>
74
+ </template>
75
+
76
+ <script lang="ts" src="./TekGridHeaderRow.ts"></script>
77
+
78
+ <style lang="scss"></style>
@@ -0,0 +1,96 @@
1
+ import { TekGrid, TekGridColumnsButton } from '@zeedhi/teknisa-components-common';
2
+ import sortable from 'sortablejs';
3
+ import { ComponentPublicInstance, computed, defineComponent, mergeProps, nextTick, ref, watch } from 'vue';
4
+ import { ZdIterableColumnsButtonProps, useButtonInstance, useCreateInstance } from '@zeedhi/vuetify';
5
+ import optionsModal from './TekGridColumnsOptionsModal';
6
+
7
+ export const TekGridColumnsButtonProps = {
8
+ ...ZdIterableColumnsButtonProps,
9
+ hideGroups: {
10
+ type: [Boolean, String],
11
+ default: false,
12
+ },
13
+ };
14
+
15
+ const tekGridColumnsButton = defineComponent({
16
+ props: TekGridColumnsButtonProps,
17
+ inheritAttrs: false,
18
+ setup(props, ctx) {
19
+ const { instance, root } = useCreateInstance<TekGridColumnsButton, ComponentPublicInstance>(
20
+ props,
21
+ ctx,
22
+ TekGridColumnsButton,
23
+ );
24
+ const buttonScope = useButtonInstance({ instance, root });
25
+
26
+ const menuIsOpened = ref(false);
27
+
28
+ const sortableInitialized = ref(false);
29
+
30
+ const teste = (a: any) => {
31
+ console.warn(a);
32
+ };
33
+
34
+ watch(menuIsOpened, () => {
35
+ if (!menuIsOpened.value || sortableInitialized.value) return;
36
+
37
+ sortableInitialized.value = true;
38
+ nextTick(() => {
39
+ const columnsTableBody = document.querySelector(`#${instance.name}_columns_table tbody`);
40
+ if (columnsTableBody) {
41
+ sortable.create(columnsTableBody as HTMLElement, {
42
+ handle: '.sortHandle',
43
+ dragClass: 'tek-grid-columns-button-sortable-drag',
44
+ onEnd: sortEnd,
45
+ });
46
+ }
47
+ });
48
+ });
49
+
50
+ const gridGroupColumnNames = computed(() => {
51
+ return instance.iterableComponent.columns.filter((column) => column.grouped).map((column) => column.name) || [];
52
+ });
53
+
54
+ const sortEnd = (event: any) => {
55
+ const grid: TekGrid = instance.iterableComponent as any;
56
+ const newOrder = Array.from(event.srcElement.querySelectorAll('tr')).map((row: any) => row.getAttribute('name'));
57
+ const groupColumnNames: string[] = [];
58
+ const newColumns = newOrder.map((columnName) => {
59
+ const column = grid.getColumn(columnName);
60
+ if (column.grouped) {
61
+ groupColumnNames.push(columnName);
62
+ }
63
+
64
+ return column;
65
+ });
66
+ const ignoredColumns = grid.columns.filter((column) => instance.ignoreColumns.indexOf(column.name) !== -1);
67
+ grid.columns = newColumns.concat(ignoredColumns);
68
+
69
+ if (grid.updateGrouping && JSON.stringify(groupColumnNames) !== JSON.stringify(gridGroupColumnNames)) {
70
+ grid.updateGrouping();
71
+ }
72
+ grid.changeLayout();
73
+ };
74
+
75
+ const moreOptions = () => {
76
+ optionsModal.show(instance);
77
+ };
78
+
79
+ const close = () => {
80
+ menuIsOpened.value = false;
81
+ };
82
+
83
+ return {
84
+ ...buttonScope,
85
+ instance,
86
+ root,
87
+ menuIsOpened,
88
+ moreOptions,
89
+ close,
90
+ teste,
91
+ mergeProps,
92
+ };
93
+ },
94
+ });
95
+
96
+ export default tekGridColumnsButton;