@zeedhi/teknisa-components-common 1.107.0 → 1.107.2
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/coverage/clover.xml +636 -550
- package/coverage/coverage-final.json +12 -10
- package/coverage/lcov-report/index.html +20 -20
- package/coverage/lcov-report/tests/__helpers__/component-event-helper.ts.html +1 -1
- package/coverage/lcov-report/tests/__helpers__/flush-promises-helper.ts.html +2 -2
- package/coverage/lcov-report/tests/__helpers__/get-child-helper.ts.html +1 -1
- package/coverage/lcov-report/tests/__helpers__/index.html +1 -1
- package/coverage/lcov-report/tests/__helpers__/index.ts.html +1 -1
- package/coverage/lcov-report/tests/__helpers__/mock-created-helper.ts.html +1 -1
- package/coverage/lcov.info +1210 -1047
- package/dist/tek-components-common.esm.js +223 -18
- package/dist/tek-components-common.umd.js +223 -18
- package/package.json +2 -2
- package/tests/unit/components/tek-datasource/memory-datasource.spec.ts +10 -0
- package/tests/unit/components/tek-datasource/rest-datasource.spec.ts +4 -2
- package/tests/unit/components/tek-grid/grid-filter-button.spec.ts +4 -10
- package/tests/unit/components/tek-grid/grid.spec.ts +417 -2
- package/types/components/tek-datasource/memory-datasource.d.ts +7 -1
- package/types/components/tek-datasource/rest-datasource.d.ts +7 -1
- package/types/components/tek-grid/grid.d.ts +45 -2
- package/types/components/tek-grid/interfaces.d.ts +19 -0
- package/types/error/incomplete-groups-error.d.ts +8 -0
- package/types/utils/extract-properties.d.ts +7 -0
- package/types/utils/index.d.ts +1 -0
|
@@ -1508,6 +1508,22 @@ class GridController {
|
|
|
1508
1508
|
}
|
|
1509
1509
|
}
|
|
1510
1510
|
|
|
1511
|
+
/**
|
|
1512
|
+
* Extracts properties from an object based on a list of properties
|
|
1513
|
+
* @param obj object whose properties will be extracted
|
|
1514
|
+
* @param props array of strings with the properties to be extracted
|
|
1515
|
+
* @returns object containing the extracted properties
|
|
1516
|
+
*/
|
|
1517
|
+
const extractProperties = (obj, props) => {
|
|
1518
|
+
const result = {};
|
|
1519
|
+
props.forEach((prop) => {
|
|
1520
|
+
if (obj[prop] !== undefined) {
|
|
1521
|
+
result[prop] = obj[prop];
|
|
1522
|
+
}
|
|
1523
|
+
});
|
|
1524
|
+
return result;
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1511
1527
|
const DynamicFilterOperations = {
|
|
1512
1528
|
CONTAINS: true,
|
|
1513
1529
|
NOT_CONTAINS: true,
|
|
@@ -1597,6 +1613,14 @@ class TekMemoryDatasource extends MemoryDatasource {
|
|
|
1597
1613
|
}
|
|
1598
1614
|
return superQueryString + dynamicFilterQuerystring + searchJoinQuerystring;
|
|
1599
1615
|
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Allows the comunication between the base filter and the dynamic filter
|
|
1618
|
+
* @param filtroDinamico
|
|
1619
|
+
* @returns
|
|
1620
|
+
*/
|
|
1621
|
+
setBaseFilter(filtroDinamico) {
|
|
1622
|
+
return this.setDynamicFilter(filtroDinamico);
|
|
1623
|
+
}
|
|
1600
1624
|
/**
|
|
1601
1625
|
* Adds a new dynamic filter position or replace if exists
|
|
1602
1626
|
* @param column Dynamic Filter column name
|
|
@@ -1674,12 +1698,15 @@ class TekMemoryDatasource extends MemoryDatasource {
|
|
|
1674
1698
|
* @returns Is valid filter value
|
|
1675
1699
|
*/
|
|
1676
1700
|
isValidDynamicFilterValue(column, value) {
|
|
1701
|
+
if (!Array.isArray(value))
|
|
1702
|
+
return false;
|
|
1677
1703
|
return !this.reservedKeys[column]
|
|
1678
|
-
&& value
|
|
1679
1704
|
&& value.length > 0
|
|
1680
|
-
&& value.every((filterValue) =>
|
|
1705
|
+
&& value.every((filterValue) => filterValue
|
|
1706
|
+
&& this.dynamicFilterOperations[filterValue.operation]
|
|
1681
1707
|
&& this.dynamicFilterRelations[filterValue.relation]
|
|
1682
|
-
&& filterValue.value !== ''
|
|
1708
|
+
&& filterValue.value !== ''
|
|
1709
|
+
&& filterValue.value !== null);
|
|
1683
1710
|
}
|
|
1684
1711
|
clone() {
|
|
1685
1712
|
return Object.assign(Object.assign({}, super.clone()), { dynamicFilter: this.dynamicFilter, searchJoin: this.searchJoin, type: 'tek-memory' });
|
|
@@ -1866,6 +1893,14 @@ class TekRestDatasource extends RestDatasource {
|
|
|
1866
1893
|
}
|
|
1867
1894
|
return superQueryString + dynamicFilterQuerystring + searchJoinQuerystring;
|
|
1868
1895
|
}
|
|
1896
|
+
/**
|
|
1897
|
+
* Allows the comunication between the base filter and the dynamic filter
|
|
1898
|
+
* @param filtroDinamico
|
|
1899
|
+
* @returns
|
|
1900
|
+
*/
|
|
1901
|
+
setBaseFilter(filtroDinamico) {
|
|
1902
|
+
return this.setDynamicFilter(filtroDinamico);
|
|
1903
|
+
}
|
|
1869
1904
|
/**
|
|
1870
1905
|
* Adds a new dynamic filter position or replace if exists
|
|
1871
1906
|
* @param column Dynamic Filter column name
|
|
@@ -1943,12 +1978,15 @@ class TekRestDatasource extends RestDatasource {
|
|
|
1943
1978
|
* @returns Is valid filter value
|
|
1944
1979
|
*/
|
|
1945
1980
|
isValidDynamicFilterValue(column, value) {
|
|
1981
|
+
if (!Array.isArray(value))
|
|
1982
|
+
return false;
|
|
1946
1983
|
return !this.reservedKeys[column]
|
|
1947
|
-
&& value
|
|
1948
1984
|
&& value.length > 0
|
|
1949
|
-
&& value.every((filterValue) =>
|
|
1985
|
+
&& value.every((filterValue) => filterValue
|
|
1986
|
+
&& this.dynamicFilterOperations[filterValue.operation]
|
|
1950
1987
|
&& this.dynamicFilterRelations[filterValue.relation]
|
|
1951
|
-
&& filterValue.value !== ''
|
|
1988
|
+
&& filterValue.value !== ''
|
|
1989
|
+
&& filterValue.value !== null);
|
|
1952
1990
|
}
|
|
1953
1991
|
/**
|
|
1954
1992
|
* Retrieves request params
|
|
@@ -2157,6 +2195,19 @@ class TekGridColumn extends GridColumnEditable {
|
|
|
2157
2195
|
}
|
|
2158
2196
|
}
|
|
2159
2197
|
|
|
2198
|
+
/**
|
|
2199
|
+
* Thrown when a row has incomplete group information.
|
|
2200
|
+
* Provides details about the missing groups and the problematic row.
|
|
2201
|
+
*/
|
|
2202
|
+
class IncompleteGroupsError extends Error {
|
|
2203
|
+
constructor(row, missingGroups) {
|
|
2204
|
+
const rowPreview = JSON.stringify(row);
|
|
2205
|
+
const message = `Row groups are incomplete. Missing groups: ${missingGroups.join(', ')}.\nRow data:\n${rowPreview}`;
|
|
2206
|
+
super(message);
|
|
2207
|
+
this.name = 'IncompleteGroupsError';
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2160
2211
|
/* TekGrid Class */
|
|
2161
2212
|
class TekGrid extends GridEditable {
|
|
2162
2213
|
/**
|
|
@@ -2602,9 +2653,10 @@ class TekGrid extends GridEditable {
|
|
|
2602
2653
|
this.groups.forEach((group) => {
|
|
2603
2654
|
group.lastGroupHeaderRow.children.push(row);
|
|
2604
2655
|
});
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2656
|
+
const groupHeaders = this.groups
|
|
2657
|
+
.map((group) => group.lastGroupHeaderRow)
|
|
2658
|
+
.filter(Boolean);
|
|
2659
|
+
this.groupedData.push(Object.assign(Object.assign({}, row), { groupHeaders }));
|
|
2608
2660
|
this.calcSummary(row);
|
|
2609
2661
|
});
|
|
2610
2662
|
if (this.groupedData.length > 0) {
|
|
@@ -2660,14 +2712,14 @@ class TekGrid extends GridEditable {
|
|
|
2660
2712
|
return;
|
|
2661
2713
|
}
|
|
2662
2714
|
for (let i = this.groups.length - 1; i >= groupIndex; i -= 1) {
|
|
2663
|
-
if (this.groups[i].initialized)
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
this.groupedData.push(groupFooterRow);
|
|
2715
|
+
if (!this.groups[i].initialized)
|
|
2716
|
+
return;
|
|
2717
|
+
const groupFooterRow = Object.assign({ groupFooter: true, groupIndex: i, groupHeaders: [], groupLabel: this.groups[i].lastGroupHeaderRow.groupLabel, groupValue: this.groups[i].lastGroupHeaderRow.groupValue }, this.summaryData(this.groups[i].footer));
|
|
2718
|
+
// add header for outer groups
|
|
2719
|
+
for (let g = 0; g < i; g += 1) {
|
|
2720
|
+
groupFooterRow.groupHeaders.push(this.groups[g].lastGroupHeaderRow);
|
|
2670
2721
|
}
|
|
2722
|
+
this.groupedData.push(groupFooterRow);
|
|
2671
2723
|
}
|
|
2672
2724
|
}
|
|
2673
2725
|
resetFooterVariables(group) {
|
|
@@ -2917,6 +2969,7 @@ class TekGrid extends GridEditable {
|
|
|
2917
2969
|
*/
|
|
2918
2970
|
groupRowClick(row, event, element) {
|
|
2919
2971
|
if (!this.preventRowClick) {
|
|
2972
|
+
this.datasource.currentRow = row;
|
|
2920
2973
|
this.callEvent('groupRowClick', {
|
|
2921
2974
|
event,
|
|
2922
2975
|
element,
|
|
@@ -2929,6 +2982,7 @@ class TekGrid extends GridEditable {
|
|
|
2929
2982
|
}
|
|
2930
2983
|
groupRowDoubleClick(row, event, element) {
|
|
2931
2984
|
if (!this.preventRowDoubleClick) {
|
|
2985
|
+
this.datasource.currentRow = row;
|
|
2932
2986
|
this.callEvent('groupRowDoubleClick', {
|
|
2933
2987
|
event,
|
|
2934
2988
|
element,
|
|
@@ -2978,6 +3032,157 @@ class TekGrid extends GridEditable {
|
|
|
2978
3032
|
getColumn(name) {
|
|
2979
3033
|
return super.getColumn(name);
|
|
2980
3034
|
}
|
|
3035
|
+
/**
|
|
3036
|
+
* Adds new row to the datasource data and pushes it to the editedRows
|
|
3037
|
+
* @param row Row
|
|
3038
|
+
* @param position whether the new Row will be inserted at the beginning or end of the data array
|
|
3039
|
+
*/
|
|
3040
|
+
addNewRow(row, position = 'end') {
|
|
3041
|
+
const _super = Object.create(null, {
|
|
3042
|
+
addNewRow: { get: () => super.addNewRow }
|
|
3043
|
+
});
|
|
3044
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
3045
|
+
if (!this.groupColumns.length) {
|
|
3046
|
+
yield _super.addNewRow.call(this, row, position);
|
|
3047
|
+
return;
|
|
3048
|
+
}
|
|
3049
|
+
this.insertRowInDatasource(row, position);
|
|
3050
|
+
this.saveRowReference(row);
|
|
3051
|
+
this.addGroupedRow(row, position);
|
|
3052
|
+
this.editing = true;
|
|
3053
|
+
});
|
|
3054
|
+
}
|
|
3055
|
+
/**
|
|
3056
|
+
* Takes a row and adds it to the selected group (datasource.currentRow)
|
|
3057
|
+
* @param row the new row to be added
|
|
3058
|
+
* @param position the position, at the beginning of the group or at the end
|
|
3059
|
+
*/
|
|
3060
|
+
addToSelection(row, position = 'end') {
|
|
3061
|
+
const { currentRow } = this.datasource;
|
|
3062
|
+
// if the currentRow is a group, use the groupRow as reference
|
|
3063
|
+
const referenceRow = this.isGroupHeader(currentRow) ? currentRow.groupRow : currentRow;
|
|
3064
|
+
// extract the group properties from the referenceRow to add to the new row
|
|
3065
|
+
const groupProperties = extractProperties(referenceRow, this.groupColumnNames);
|
|
3066
|
+
const rowWithGroups = Object.assign(Object.assign({}, row), groupProperties);
|
|
3067
|
+
return this.addNewRow(rowWithGroups, position);
|
|
3068
|
+
}
|
|
3069
|
+
/**
|
|
3070
|
+
* Adds a new row to the groupedData array
|
|
3071
|
+
* @param row the new row to be added
|
|
3072
|
+
* @param position the position, at the beginning of the group or at the end
|
|
3073
|
+
*/
|
|
3074
|
+
addGroupedRow(row, position) {
|
|
3075
|
+
const missingGroups = this.findMissingGroups(row);
|
|
3076
|
+
if (missingGroups.length > 0) {
|
|
3077
|
+
throw new IncompleteGroupsError(row, missingGroups);
|
|
3078
|
+
}
|
|
3079
|
+
const { index, group } = this.findLastGroupingIndex(row);
|
|
3080
|
+
const groupHeaders = [...group.groupHeaders, group];
|
|
3081
|
+
const newGroupedRow = Object.assign(Object.assign({}, row), { groupHeaders });
|
|
3082
|
+
if (position === 'end') {
|
|
3083
|
+
const childrenLength = group.children.length;
|
|
3084
|
+
this.groupedData.splice(index + childrenLength + 1, 0, newGroupedRow);
|
|
3085
|
+
}
|
|
3086
|
+
else {
|
|
3087
|
+
this.groupedData.splice(index + 1, 0, newGroupedRow);
|
|
3088
|
+
}
|
|
3089
|
+
groupHeaders.forEach((groupHeader) => {
|
|
3090
|
+
// open all groups, making the new row visible to the user
|
|
3091
|
+
groupHeader.groupOpened = true;
|
|
3092
|
+
this.addRowToGroupChildren(row, groupHeader, position);
|
|
3093
|
+
});
|
|
3094
|
+
}
|
|
3095
|
+
findMissingGroups(row) {
|
|
3096
|
+
return this.groupColumnNames.filter((group) => row[group] === undefined);
|
|
3097
|
+
}
|
|
3098
|
+
/**
|
|
3099
|
+
* Finds the last group (most internal group) where a row should be inserted
|
|
3100
|
+
* @param row to be inserted
|
|
3101
|
+
* @returns the index and the group where the row should be inserted
|
|
3102
|
+
*/
|
|
3103
|
+
findLastGroupingIndex(row) {
|
|
3104
|
+
const index = this.groupedData.findIndex((groupRow) => {
|
|
3105
|
+
// ignore rows that are not headers or not the last grouping (most internal groping)
|
|
3106
|
+
if (!this.isGroupHeader(groupRow) || !this.isLastGrouping(groupRow))
|
|
3107
|
+
return false;
|
|
3108
|
+
// if the new added row is not part of the group, ignore it
|
|
3109
|
+
if (groupRow.groupValue !== row[groupRow.groupColumnName])
|
|
3110
|
+
return false;
|
|
3111
|
+
if (this.groupColumns.length === 1)
|
|
3112
|
+
return true;
|
|
3113
|
+
const matchHeaders = groupRow.groupHeaders.every((groupHeader) => (groupHeader.groupValue === row[groupHeader.groupColumnName]));
|
|
3114
|
+
return matchHeaders;
|
|
3115
|
+
});
|
|
3116
|
+
if (index === -1) {
|
|
3117
|
+
// No existing group found, so we create the full group hierarchy
|
|
3118
|
+
return this.createGroupHierarchyForRow(row);
|
|
3119
|
+
}
|
|
3120
|
+
const group = this.groupedData[index];
|
|
3121
|
+
return { index, group };
|
|
3122
|
+
}
|
|
3123
|
+
/**
|
|
3124
|
+
* Creates a group hierarchy for a new row, creating intermediate groups if needed
|
|
3125
|
+
* @param row to be inserted
|
|
3126
|
+
* @returns the index and the group where the row should be inserted
|
|
3127
|
+
*/
|
|
3128
|
+
createGroupHierarchyForRow(row) {
|
|
3129
|
+
let groupHeaders = [];
|
|
3130
|
+
let insertionIndex = this.groupedData.length; // default to end
|
|
3131
|
+
this.groups.forEach((column) => {
|
|
3132
|
+
const groupValue = row[column.name];
|
|
3133
|
+
const existingGroupIndex = this.groupedData.findIndex((groupRow) => this.isGroupHeader(groupRow)
|
|
3134
|
+
&& groupRow.groupColumnName === column.name
|
|
3135
|
+
&& groupRow.groupValue === groupValue
|
|
3136
|
+
&& groupRow.groupHeaders.every((h, j) => h.groupValue === groupHeaders[j].groupValue));
|
|
3137
|
+
if (existingGroupIndex !== -1) {
|
|
3138
|
+
const existingGroup = this.groupedData[existingGroupIndex];
|
|
3139
|
+
groupHeaders = [...existingGroup.groupHeaders, existingGroup];
|
|
3140
|
+
insertionIndex = existingGroupIndex;
|
|
3141
|
+
return;
|
|
3142
|
+
}
|
|
3143
|
+
// Create new group header
|
|
3144
|
+
const newGroup = {
|
|
3145
|
+
group: true,
|
|
3146
|
+
groupHeader: true,
|
|
3147
|
+
groupValue,
|
|
3148
|
+
groupColumnName: column.name,
|
|
3149
|
+
groupHeaders: [...groupHeaders],
|
|
3150
|
+
children: [],
|
|
3151
|
+
groupRow: row,
|
|
3152
|
+
groupIndex: groupHeaders.length,
|
|
3153
|
+
groupLabel: I18n.translate(column.label),
|
|
3154
|
+
groupOpened: true,
|
|
3155
|
+
};
|
|
3156
|
+
// Insert right after last insertionIndex
|
|
3157
|
+
insertionIndex += 1;
|
|
3158
|
+
this.groupedData.splice(insertionIndex, 0, newGroup);
|
|
3159
|
+
groupHeaders.push(newGroup);
|
|
3160
|
+
});
|
|
3161
|
+
const group = groupHeaders[groupHeaders.length - 1]; // the most inner group
|
|
3162
|
+
return { index: insertionIndex, group };
|
|
3163
|
+
}
|
|
3164
|
+
/**
|
|
3165
|
+
* Adds a row to the children of a group
|
|
3166
|
+
*/
|
|
3167
|
+
addRowToGroupChildren(row, group, position) {
|
|
3168
|
+
if (position === 'end') {
|
|
3169
|
+
group.children.push(row);
|
|
3170
|
+
return;
|
|
3171
|
+
}
|
|
3172
|
+
group.children.unshift(row);
|
|
3173
|
+
}
|
|
3174
|
+
/**
|
|
3175
|
+
* Checks if a row is a group header, adding typescript type-checking
|
|
3176
|
+
*/
|
|
3177
|
+
isGroupHeader(row) {
|
|
3178
|
+
return row.groupHeader;
|
|
3179
|
+
}
|
|
3180
|
+
/**
|
|
3181
|
+
* Checks if a row is the last grouping of the grid (the most internal grouping)
|
|
3182
|
+
*/
|
|
3183
|
+
isLastGrouping(group) {
|
|
3184
|
+
return group.groupColumnName === this.groupColumns[this.groupColumns.length - 1].name;
|
|
3185
|
+
}
|
|
2981
3186
|
}
|
|
2982
3187
|
|
|
2983
3188
|
class TekGridColumnsButtonController extends IterableColumnsButtonController {
|
|
@@ -3321,7 +3526,7 @@ class TekGridFilterButton extends Button {
|
|
|
3321
3526
|
}
|
|
3322
3527
|
});
|
|
3323
3528
|
datasource.dynamicFilter = filter;
|
|
3324
|
-
this.setFilter(filter, event, datasource.
|
|
3529
|
+
this.setFilter(filter, event, datasource.setBaseFilter.bind(datasource));
|
|
3325
3530
|
}
|
|
3326
3531
|
else {
|
|
3327
3532
|
Object.keys(formValue).forEach((item) => {
|
|
@@ -3332,7 +3537,7 @@ class TekGridFilterButton extends Button {
|
|
|
3332
3537
|
}
|
|
3333
3538
|
});
|
|
3334
3539
|
datasource.filter = filter;
|
|
3335
|
-
this.setFilter(filter, event, datasource.
|
|
3540
|
+
this.setFilter(filter, event, datasource.setBaseFilter.bind(datasource));
|
|
3336
3541
|
}
|
|
3337
3542
|
this.grid.changeLayout(event);
|
|
3338
3543
|
}
|
|
@@ -1512,6 +1512,22 @@
|
|
|
1512
1512
|
}
|
|
1513
1513
|
}
|
|
1514
1514
|
|
|
1515
|
+
/**
|
|
1516
|
+
* Extracts properties from an object based on a list of properties
|
|
1517
|
+
* @param obj object whose properties will be extracted
|
|
1518
|
+
* @param props array of strings with the properties to be extracted
|
|
1519
|
+
* @returns object containing the extracted properties
|
|
1520
|
+
*/
|
|
1521
|
+
const extractProperties = (obj, props) => {
|
|
1522
|
+
const result = {};
|
|
1523
|
+
props.forEach((prop) => {
|
|
1524
|
+
if (obj[prop] !== undefined) {
|
|
1525
|
+
result[prop] = obj[prop];
|
|
1526
|
+
}
|
|
1527
|
+
});
|
|
1528
|
+
return result;
|
|
1529
|
+
};
|
|
1530
|
+
|
|
1515
1531
|
const DynamicFilterOperations = {
|
|
1516
1532
|
CONTAINS: true,
|
|
1517
1533
|
NOT_CONTAINS: true,
|
|
@@ -1601,6 +1617,14 @@
|
|
|
1601
1617
|
}
|
|
1602
1618
|
return superQueryString + dynamicFilterQuerystring + searchJoinQuerystring;
|
|
1603
1619
|
}
|
|
1620
|
+
/**
|
|
1621
|
+
* Allows the comunication between the base filter and the dynamic filter
|
|
1622
|
+
* @param filtroDinamico
|
|
1623
|
+
* @returns
|
|
1624
|
+
*/
|
|
1625
|
+
setBaseFilter(filtroDinamico) {
|
|
1626
|
+
return this.setDynamicFilter(filtroDinamico);
|
|
1627
|
+
}
|
|
1604
1628
|
/**
|
|
1605
1629
|
* Adds a new dynamic filter position or replace if exists
|
|
1606
1630
|
* @param column Dynamic Filter column name
|
|
@@ -1678,12 +1702,15 @@
|
|
|
1678
1702
|
* @returns Is valid filter value
|
|
1679
1703
|
*/
|
|
1680
1704
|
isValidDynamicFilterValue(column, value) {
|
|
1705
|
+
if (!Array.isArray(value))
|
|
1706
|
+
return false;
|
|
1681
1707
|
return !this.reservedKeys[column]
|
|
1682
|
-
&& value
|
|
1683
1708
|
&& value.length > 0
|
|
1684
|
-
&& value.every((filterValue) =>
|
|
1709
|
+
&& value.every((filterValue) => filterValue
|
|
1710
|
+
&& this.dynamicFilterOperations[filterValue.operation]
|
|
1685
1711
|
&& this.dynamicFilterRelations[filterValue.relation]
|
|
1686
|
-
&& filterValue.value !== ''
|
|
1712
|
+
&& filterValue.value !== ''
|
|
1713
|
+
&& filterValue.value !== null);
|
|
1687
1714
|
}
|
|
1688
1715
|
clone() {
|
|
1689
1716
|
return Object.assign(Object.assign({}, super.clone()), { dynamicFilter: this.dynamicFilter, searchJoin: this.searchJoin, type: 'tek-memory' });
|
|
@@ -1870,6 +1897,14 @@
|
|
|
1870
1897
|
}
|
|
1871
1898
|
return superQueryString + dynamicFilterQuerystring + searchJoinQuerystring;
|
|
1872
1899
|
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Allows the comunication between the base filter and the dynamic filter
|
|
1902
|
+
* @param filtroDinamico
|
|
1903
|
+
* @returns
|
|
1904
|
+
*/
|
|
1905
|
+
setBaseFilter(filtroDinamico) {
|
|
1906
|
+
return this.setDynamicFilter(filtroDinamico);
|
|
1907
|
+
}
|
|
1873
1908
|
/**
|
|
1874
1909
|
* Adds a new dynamic filter position or replace if exists
|
|
1875
1910
|
* @param column Dynamic Filter column name
|
|
@@ -1947,12 +1982,15 @@
|
|
|
1947
1982
|
* @returns Is valid filter value
|
|
1948
1983
|
*/
|
|
1949
1984
|
isValidDynamicFilterValue(column, value) {
|
|
1985
|
+
if (!Array.isArray(value))
|
|
1986
|
+
return false;
|
|
1950
1987
|
return !this.reservedKeys[column]
|
|
1951
|
-
&& value
|
|
1952
1988
|
&& value.length > 0
|
|
1953
|
-
&& value.every((filterValue) =>
|
|
1989
|
+
&& value.every((filterValue) => filterValue
|
|
1990
|
+
&& this.dynamicFilterOperations[filterValue.operation]
|
|
1954
1991
|
&& this.dynamicFilterRelations[filterValue.relation]
|
|
1955
|
-
&& filterValue.value !== ''
|
|
1992
|
+
&& filterValue.value !== ''
|
|
1993
|
+
&& filterValue.value !== null);
|
|
1956
1994
|
}
|
|
1957
1995
|
/**
|
|
1958
1996
|
* Retrieves request params
|
|
@@ -2161,6 +2199,19 @@
|
|
|
2161
2199
|
}
|
|
2162
2200
|
}
|
|
2163
2201
|
|
|
2202
|
+
/**
|
|
2203
|
+
* Thrown when a row has incomplete group information.
|
|
2204
|
+
* Provides details about the missing groups and the problematic row.
|
|
2205
|
+
*/
|
|
2206
|
+
class IncompleteGroupsError extends Error {
|
|
2207
|
+
constructor(row, missingGroups) {
|
|
2208
|
+
const rowPreview = JSON.stringify(row);
|
|
2209
|
+
const message = `Row groups are incomplete. Missing groups: ${missingGroups.join(', ')}.\nRow data:\n${rowPreview}`;
|
|
2210
|
+
super(message);
|
|
2211
|
+
this.name = 'IncompleteGroupsError';
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2164
2215
|
/* TekGrid Class */
|
|
2165
2216
|
class TekGrid extends common.GridEditable {
|
|
2166
2217
|
/**
|
|
@@ -2606,9 +2657,10 @@
|
|
|
2606
2657
|
this.groups.forEach((group) => {
|
|
2607
2658
|
group.lastGroupHeaderRow.children.push(row);
|
|
2608
2659
|
});
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2660
|
+
const groupHeaders = this.groups
|
|
2661
|
+
.map((group) => group.lastGroupHeaderRow)
|
|
2662
|
+
.filter(Boolean);
|
|
2663
|
+
this.groupedData.push(Object.assign(Object.assign({}, row), { groupHeaders }));
|
|
2612
2664
|
this.calcSummary(row);
|
|
2613
2665
|
});
|
|
2614
2666
|
if (this.groupedData.length > 0) {
|
|
@@ -2664,14 +2716,14 @@
|
|
|
2664
2716
|
return;
|
|
2665
2717
|
}
|
|
2666
2718
|
for (let i = this.groups.length - 1; i >= groupIndex; i -= 1) {
|
|
2667
|
-
if (this.groups[i].initialized)
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
this.groupedData.push(groupFooterRow);
|
|
2719
|
+
if (!this.groups[i].initialized)
|
|
2720
|
+
return;
|
|
2721
|
+
const groupFooterRow = Object.assign({ groupFooter: true, groupIndex: i, groupHeaders: [], groupLabel: this.groups[i].lastGroupHeaderRow.groupLabel, groupValue: this.groups[i].lastGroupHeaderRow.groupValue }, this.summaryData(this.groups[i].footer));
|
|
2722
|
+
// add header for outer groups
|
|
2723
|
+
for (let g = 0; g < i; g += 1) {
|
|
2724
|
+
groupFooterRow.groupHeaders.push(this.groups[g].lastGroupHeaderRow);
|
|
2674
2725
|
}
|
|
2726
|
+
this.groupedData.push(groupFooterRow);
|
|
2675
2727
|
}
|
|
2676
2728
|
}
|
|
2677
2729
|
resetFooterVariables(group) {
|
|
@@ -2921,6 +2973,7 @@
|
|
|
2921
2973
|
*/
|
|
2922
2974
|
groupRowClick(row, event, element) {
|
|
2923
2975
|
if (!this.preventRowClick) {
|
|
2976
|
+
this.datasource.currentRow = row;
|
|
2924
2977
|
this.callEvent('groupRowClick', {
|
|
2925
2978
|
event,
|
|
2926
2979
|
element,
|
|
@@ -2933,6 +2986,7 @@
|
|
|
2933
2986
|
}
|
|
2934
2987
|
groupRowDoubleClick(row, event, element) {
|
|
2935
2988
|
if (!this.preventRowDoubleClick) {
|
|
2989
|
+
this.datasource.currentRow = row;
|
|
2936
2990
|
this.callEvent('groupRowDoubleClick', {
|
|
2937
2991
|
event,
|
|
2938
2992
|
element,
|
|
@@ -2982,6 +3036,157 @@
|
|
|
2982
3036
|
getColumn(name) {
|
|
2983
3037
|
return super.getColumn(name);
|
|
2984
3038
|
}
|
|
3039
|
+
/**
|
|
3040
|
+
* Adds new row to the datasource data and pushes it to the editedRows
|
|
3041
|
+
* @param row Row
|
|
3042
|
+
* @param position whether the new Row will be inserted at the beginning or end of the data array
|
|
3043
|
+
*/
|
|
3044
|
+
addNewRow(row, position = 'end') {
|
|
3045
|
+
const _super = Object.create(null, {
|
|
3046
|
+
addNewRow: { get: () => super.addNewRow }
|
|
3047
|
+
});
|
|
3048
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
3049
|
+
if (!this.groupColumns.length) {
|
|
3050
|
+
yield _super.addNewRow.call(this, row, position);
|
|
3051
|
+
return;
|
|
3052
|
+
}
|
|
3053
|
+
this.insertRowInDatasource(row, position);
|
|
3054
|
+
this.saveRowReference(row);
|
|
3055
|
+
this.addGroupedRow(row, position);
|
|
3056
|
+
this.editing = true;
|
|
3057
|
+
});
|
|
3058
|
+
}
|
|
3059
|
+
/**
|
|
3060
|
+
* Takes a row and adds it to the selected group (datasource.currentRow)
|
|
3061
|
+
* @param row the new row to be added
|
|
3062
|
+
* @param position the position, at the beginning of the group or at the end
|
|
3063
|
+
*/
|
|
3064
|
+
addToSelection(row, position = 'end') {
|
|
3065
|
+
const { currentRow } = this.datasource;
|
|
3066
|
+
// if the currentRow is a group, use the groupRow as reference
|
|
3067
|
+
const referenceRow = this.isGroupHeader(currentRow) ? currentRow.groupRow : currentRow;
|
|
3068
|
+
// extract the group properties from the referenceRow to add to the new row
|
|
3069
|
+
const groupProperties = extractProperties(referenceRow, this.groupColumnNames);
|
|
3070
|
+
const rowWithGroups = Object.assign(Object.assign({}, row), groupProperties);
|
|
3071
|
+
return this.addNewRow(rowWithGroups, position);
|
|
3072
|
+
}
|
|
3073
|
+
/**
|
|
3074
|
+
* Adds a new row to the groupedData array
|
|
3075
|
+
* @param row the new row to be added
|
|
3076
|
+
* @param position the position, at the beginning of the group or at the end
|
|
3077
|
+
*/
|
|
3078
|
+
addGroupedRow(row, position) {
|
|
3079
|
+
const missingGroups = this.findMissingGroups(row);
|
|
3080
|
+
if (missingGroups.length > 0) {
|
|
3081
|
+
throw new IncompleteGroupsError(row, missingGroups);
|
|
3082
|
+
}
|
|
3083
|
+
const { index, group } = this.findLastGroupingIndex(row);
|
|
3084
|
+
const groupHeaders = [...group.groupHeaders, group];
|
|
3085
|
+
const newGroupedRow = Object.assign(Object.assign({}, row), { groupHeaders });
|
|
3086
|
+
if (position === 'end') {
|
|
3087
|
+
const childrenLength = group.children.length;
|
|
3088
|
+
this.groupedData.splice(index + childrenLength + 1, 0, newGroupedRow);
|
|
3089
|
+
}
|
|
3090
|
+
else {
|
|
3091
|
+
this.groupedData.splice(index + 1, 0, newGroupedRow);
|
|
3092
|
+
}
|
|
3093
|
+
groupHeaders.forEach((groupHeader) => {
|
|
3094
|
+
// open all groups, making the new row visible to the user
|
|
3095
|
+
groupHeader.groupOpened = true;
|
|
3096
|
+
this.addRowToGroupChildren(row, groupHeader, position);
|
|
3097
|
+
});
|
|
3098
|
+
}
|
|
3099
|
+
findMissingGroups(row) {
|
|
3100
|
+
return this.groupColumnNames.filter((group) => row[group] === undefined);
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* Finds the last group (most internal group) where a row should be inserted
|
|
3104
|
+
* @param row to be inserted
|
|
3105
|
+
* @returns the index and the group where the row should be inserted
|
|
3106
|
+
*/
|
|
3107
|
+
findLastGroupingIndex(row) {
|
|
3108
|
+
const index = this.groupedData.findIndex((groupRow) => {
|
|
3109
|
+
// ignore rows that are not headers or not the last grouping (most internal groping)
|
|
3110
|
+
if (!this.isGroupHeader(groupRow) || !this.isLastGrouping(groupRow))
|
|
3111
|
+
return false;
|
|
3112
|
+
// if the new added row is not part of the group, ignore it
|
|
3113
|
+
if (groupRow.groupValue !== row[groupRow.groupColumnName])
|
|
3114
|
+
return false;
|
|
3115
|
+
if (this.groupColumns.length === 1)
|
|
3116
|
+
return true;
|
|
3117
|
+
const matchHeaders = groupRow.groupHeaders.every((groupHeader) => (groupHeader.groupValue === row[groupHeader.groupColumnName]));
|
|
3118
|
+
return matchHeaders;
|
|
3119
|
+
});
|
|
3120
|
+
if (index === -1) {
|
|
3121
|
+
// No existing group found, so we create the full group hierarchy
|
|
3122
|
+
return this.createGroupHierarchyForRow(row);
|
|
3123
|
+
}
|
|
3124
|
+
const group = this.groupedData[index];
|
|
3125
|
+
return { index, group };
|
|
3126
|
+
}
|
|
3127
|
+
/**
|
|
3128
|
+
* Creates a group hierarchy for a new row, creating intermediate groups if needed
|
|
3129
|
+
* @param row to be inserted
|
|
3130
|
+
* @returns the index and the group where the row should be inserted
|
|
3131
|
+
*/
|
|
3132
|
+
createGroupHierarchyForRow(row) {
|
|
3133
|
+
let groupHeaders = [];
|
|
3134
|
+
let insertionIndex = this.groupedData.length; // default to end
|
|
3135
|
+
this.groups.forEach((column) => {
|
|
3136
|
+
const groupValue = row[column.name];
|
|
3137
|
+
const existingGroupIndex = this.groupedData.findIndex((groupRow) => this.isGroupHeader(groupRow)
|
|
3138
|
+
&& groupRow.groupColumnName === column.name
|
|
3139
|
+
&& groupRow.groupValue === groupValue
|
|
3140
|
+
&& groupRow.groupHeaders.every((h, j) => h.groupValue === groupHeaders[j].groupValue));
|
|
3141
|
+
if (existingGroupIndex !== -1) {
|
|
3142
|
+
const existingGroup = this.groupedData[existingGroupIndex];
|
|
3143
|
+
groupHeaders = [...existingGroup.groupHeaders, existingGroup];
|
|
3144
|
+
insertionIndex = existingGroupIndex;
|
|
3145
|
+
return;
|
|
3146
|
+
}
|
|
3147
|
+
// Create new group header
|
|
3148
|
+
const newGroup = {
|
|
3149
|
+
group: true,
|
|
3150
|
+
groupHeader: true,
|
|
3151
|
+
groupValue,
|
|
3152
|
+
groupColumnName: column.name,
|
|
3153
|
+
groupHeaders: [...groupHeaders],
|
|
3154
|
+
children: [],
|
|
3155
|
+
groupRow: row,
|
|
3156
|
+
groupIndex: groupHeaders.length,
|
|
3157
|
+
groupLabel: core.I18n.translate(column.label),
|
|
3158
|
+
groupOpened: true,
|
|
3159
|
+
};
|
|
3160
|
+
// Insert right after last insertionIndex
|
|
3161
|
+
insertionIndex += 1;
|
|
3162
|
+
this.groupedData.splice(insertionIndex, 0, newGroup);
|
|
3163
|
+
groupHeaders.push(newGroup);
|
|
3164
|
+
});
|
|
3165
|
+
const group = groupHeaders[groupHeaders.length - 1]; // the most inner group
|
|
3166
|
+
return { index: insertionIndex, group };
|
|
3167
|
+
}
|
|
3168
|
+
/**
|
|
3169
|
+
* Adds a row to the children of a group
|
|
3170
|
+
*/
|
|
3171
|
+
addRowToGroupChildren(row, group, position) {
|
|
3172
|
+
if (position === 'end') {
|
|
3173
|
+
group.children.push(row);
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3176
|
+
group.children.unshift(row);
|
|
3177
|
+
}
|
|
3178
|
+
/**
|
|
3179
|
+
* Checks if a row is a group header, adding typescript type-checking
|
|
3180
|
+
*/
|
|
3181
|
+
isGroupHeader(row) {
|
|
3182
|
+
return row.groupHeader;
|
|
3183
|
+
}
|
|
3184
|
+
/**
|
|
3185
|
+
* Checks if a row is the last grouping of the grid (the most internal grouping)
|
|
3186
|
+
*/
|
|
3187
|
+
isLastGrouping(group) {
|
|
3188
|
+
return group.groupColumnName === this.groupColumns[this.groupColumns.length - 1].name;
|
|
3189
|
+
}
|
|
2985
3190
|
}
|
|
2986
3191
|
|
|
2987
3192
|
class TekGridColumnsButtonController extends common.IterableColumnsButtonController {
|
|
@@ -3325,7 +3530,7 @@
|
|
|
3325
3530
|
}
|
|
3326
3531
|
});
|
|
3327
3532
|
datasource.dynamicFilter = filter;
|
|
3328
|
-
this.setFilter(filter, event, datasource.
|
|
3533
|
+
this.setFilter(filter, event, datasource.setBaseFilter.bind(datasource));
|
|
3329
3534
|
}
|
|
3330
3535
|
else {
|
|
3331
3536
|
Object.keys(formValue).forEach((item) => {
|
|
@@ -3336,7 +3541,7 @@
|
|
|
3336
3541
|
}
|
|
3337
3542
|
});
|
|
3338
3543
|
datasource.filter = filter;
|
|
3339
|
-
this.setFilter(filter, event, datasource.
|
|
3544
|
+
this.setFilter(filter, event, datasource.setBaseFilter.bind(datasource));
|
|
3340
3545
|
}
|
|
3341
3546
|
this.grid.changeLayout(event);
|
|
3342
3547
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeedhi/teknisa-components-common",
|
|
3
|
-
"version": "1.107.
|
|
3
|
+
"version": "1.107.2",
|
|
4
4
|
"description": "Teknisa Components Common",
|
|
5
5
|
"author": "Zeedhi <zeedhi@teknisa.com>",
|
|
6
6
|
"license": "ISC",
|
|
@@ -32,5 +32,5 @@
|
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@zeedhi/core": "^1.97.0"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "22ed04e302519474cdb354aeb93ad1a29ad0407d"
|
|
36
36
|
}
|