@controleonline/ui-default 1.0.264 → 1.0.266
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/AGENTS.md +3 -2
- package/package.json +21 -18
- package/src/react/components/errors/DefaultErrors.js +64 -82
- package/src/react/components/filters/CompactFilterSelector.js +58 -23
- package/src/react/components/filters/CompactFilterSelector.styles.js +17 -5
- package/src/react/components/filters/DefaultColumnFilter.js +177 -45
- package/src/react/components/filters/DefaultExternalFilters.js +201 -143
- package/src/react/components/filters/DefaultSearch.js +27 -25
- package/src/react/components/form/DefaultForm.js +72 -53
- package/src/react/components/form/DefaultForm.styles.js +71 -66
- package/src/react/components/inputs/DefaultDateInput.js +150 -0
- package/src/react/components/inputs/DefaultInput.js +44 -11
- package/src/react/components/inputs/DefaultInput.styles.js +6 -0
- package/src/react/components/inputs/DefaultSelect.js +200 -43
- package/src/react/components/inputs/defaultInputUtils.js +40 -19
- package/src/react/components/table/DefaultColumnMenu.js +108 -0
- package/src/react/components/table/DefaultDebug.js +234 -0
- package/src/react/components/table/DefaultFiltersModal.js +142 -0
- package/src/react/components/table/DefaultModalButton.js +18 -0
- package/src/react/components/table/DefaultSearchModal.js +49 -0
- package/src/react/components/table/DefaultTable.js +322 -1964
- package/src/react/components/table/DefaultTable.styles.js +234 -102
- package/src/react/components/table/DefaultTable.utils.js +502 -0
- package/src/react/components/table/DefaultTableBody.js +26 -0
- package/src/react/components/table/DefaultTableCards.js +171 -0
- package/src/react/components/table/DefaultTableControls.js +205 -0
- package/src/react/components/table/DefaultTableEmptyState.js +22 -0
- package/src/react/components/table/DefaultTableFooter.js +172 -0
- package/src/react/components/table/DefaultTableInput.js +145 -0
- package/src/react/components/table/DefaultTableRows.js +344 -0
- package/src/react/components/table/DefaultTableSearch.js +100 -0
- package/src/react/components/table/DefaultTableToolbar.js +98 -0
- package/src/react/components/table/DefaultToolbarAction.js +56 -0
- package/src/react/components/table/useDefaultTablePagination.js +370 -0
- package/src/react/components/table/useDefaultTableSorting.js +126 -0
- package/src/react/components/table/useDefaultTableTheme.js +52 -0
- package/src/react/utils/tableVisibleColumnsPreferences.js +239 -211
- package/src/store/default/actions.js +51 -13
- package/src/store/default/getters.js +10 -8
- package/src/store/default/mutation_types.js +4 -2
- package/src/store/default/mutations.js +10 -1
- package/src/tests/react/components/form/DefaultForm.test.js +81 -0
- package/src/tests/react/components/inputs/DefaultSelect.test.js +106 -14
- package/src/tests/react/components/table/DefaultTable.test.js +1318 -334
- package/src/tests/react/store/defaultActions.test.js +59 -0
- package/src/tests/react/utils/tableVisibleColumnsPreferences.test.js +247 -168
|
@@ -1,192 +1,233 @@
|
|
|
1
|
-
export const TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY = '
|
|
2
|
-
export const TABLE_VIEW_MODE_PREFERENCES_KEY = '
|
|
3
|
-
export const TABLE_SORT_PREFERENCES_KEY = '
|
|
4
|
-
export const
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const parsedValue = JSON.parse(rawValue);
|
|
24
|
-
return isPlainObject(parsedValue) ? parsedValue : {};
|
|
25
|
-
} catch {
|
|
26
|
-
return {};
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const writeStoredPreferences = preferences => {
|
|
31
|
-
try {
|
|
32
|
-
globalThis?.localStorage?.setItem?.(
|
|
33
|
-
DEFAULT_TABLE_PREFERENCES_STORAGE_KEY,
|
|
34
|
-
JSON.stringify(preferences),
|
|
35
|
-
);
|
|
36
|
-
} catch {
|
|
37
|
-
// localStorage can be unavailable in some runtimes
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const buildDefaultVisibleColumns = columns =>
|
|
42
|
-
(Array.isArray(columns) ? columns : []).reduce((accumulator, column) => {
|
|
43
|
-
const key = getColumnKey(column);
|
|
44
|
-
if (key) {
|
|
45
|
-
accumulator[key] = column?.visible !== false;
|
|
46
|
-
}
|
|
47
|
-
return accumulator;
|
|
48
|
-
}, {});
|
|
49
|
-
|
|
50
|
-
export const sanitizeVisibleColumnsPreference = ({
|
|
51
|
-
columns = [],
|
|
52
|
-
visibleColumns = null,
|
|
53
|
-
}) => {
|
|
54
|
-
const defaultVisibleColumns = buildDefaultVisibleColumns(columns);
|
|
55
|
-
|
|
56
|
-
if (!isPlainObject(visibleColumns)) {
|
|
57
|
-
return defaultVisibleColumns;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return Object.keys(defaultVisibleColumns).reduce((accumulator, key) => {
|
|
61
|
-
accumulator[key] =
|
|
62
|
-
typeof visibleColumns[key] === 'boolean'
|
|
63
|
-
? visibleColumns[key]
|
|
64
|
-
: defaultVisibleColumns[key];
|
|
65
|
-
return accumulator;
|
|
66
|
-
}, {});
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export const resolveStoredVisibleColumnsPreference = preferenceKey => {
|
|
70
|
-
if (!preferenceKey) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const storedPreferences = readStoredPreferences();
|
|
75
|
-
const tableVisibleColumns = storedPreferences[TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY];
|
|
76
|
-
|
|
77
|
-
if (!isPlainObject(tableVisibleColumns)) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const pagePreference = tableVisibleColumns[preferenceKey];
|
|
82
|
-
return isPlainObject(pagePreference) ? pagePreference : null;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export const persistVisibleColumnsPreference = (
|
|
86
|
-
preferenceKey = '',
|
|
87
|
-
visibleColumns = {},
|
|
88
|
-
) => {
|
|
89
|
-
if (!preferenceKey || !isPlainObject(visibleColumns)) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const storedPreferences = readStoredPreferences();
|
|
94
|
-
const tableVisibleColumns = isPlainObject(
|
|
95
|
-
storedPreferences[TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY],
|
|
96
|
-
)
|
|
97
|
-
? storedPreferences[TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY]
|
|
98
|
-
: {};
|
|
99
|
-
|
|
100
|
-
writeStoredPreferences({
|
|
101
|
-
...storedPreferences,
|
|
102
|
-
[TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY]: {
|
|
103
|
-
...tableVisibleColumns,
|
|
104
|
-
[preferenceKey]: visibleColumns,
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
export const resolveStoredTableViewModePreference = (
|
|
110
|
-
preferenceKey = '',
|
|
111
|
-
fallbackViewMode = 'table',
|
|
112
|
-
) => {
|
|
113
|
-
if (!preferenceKey) {
|
|
114
|
-
return fallbackViewMode;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const storedPreferences = readStoredPreferences();
|
|
118
|
-
const tableViewModes = storedPreferences[TABLE_VIEW_MODE_PREFERENCES_KEY];
|
|
119
|
-
|
|
120
|
-
if (!isPlainObject(tableViewModes)) {
|
|
121
|
-
return fallbackViewMode;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const resolvedViewMode = tableViewModes[preferenceKey];
|
|
125
|
-
return resolvedViewMode === 'cards' || resolvedViewMode === 'table'
|
|
126
|
-
? resolvedViewMode
|
|
127
|
-
: fallbackViewMode;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
export const persistTableViewModePreference = (
|
|
1
|
+
export const TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY = 'visibleColumns';
|
|
2
|
+
export const TABLE_VIEW_MODE_PREFERENCES_KEY = 'viewMode';
|
|
3
|
+
export const TABLE_SORT_PREFERENCES_KEY = 'sort';
|
|
4
|
+
export const TABLE_FILTER_PREFERENCES_KEY = 'filters';
|
|
5
|
+
export const DEFAULT_TABLE_PREFERENCES_STORAGE_KEY = 'default-table';
|
|
6
|
+
|
|
7
|
+
const isPlainObject = value =>
|
|
8
|
+
!!value && typeof value === 'object' && !Array.isArray(value);
|
|
9
|
+
|
|
10
|
+
const getColumnKey = column => column?.key || column?.name || '';
|
|
11
|
+
|
|
12
|
+
const normalizePreferenceSegment = value =>
|
|
13
|
+
String(value || '')
|
|
14
|
+
.trim()
|
|
15
|
+
.replace(/^\/+|\/+$/g, '')
|
|
16
|
+
.replace(/[/?#]+/g, '-')
|
|
17
|
+
.replace(/\s+/g, '-')
|
|
18
|
+
.replace(/-+/g, '-');
|
|
19
|
+
|
|
20
|
+
export const resolveDefaultTablePreferenceScope = ({
|
|
131
21
|
preferenceKey = '',
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
});
|
|
22
|
+
route = null,
|
|
23
|
+
storeName = '',
|
|
24
|
+
} = {}) => {
|
|
25
|
+
const routeName =
|
|
26
|
+
normalizePreferenceSegment(preferenceKey) ||
|
|
27
|
+
normalizePreferenceSegment(globalThis?.location?.pathname) ||
|
|
28
|
+
normalizePreferenceSegment(route?.name) ||
|
|
29
|
+
normalizePreferenceSegment(route?.key) ||
|
|
30
|
+
'unknown-route';
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* @agents DefaultTable preferences are saved as [store][route].
|
|
34
|
+
* The same store can back different screens, so filters, sort, view mode,
|
|
35
|
+
* and column visibility must never be keyed only by store or only by route.
|
|
36
|
+
*/
|
|
37
|
+
return {
|
|
38
|
+
routeKey: routeName,
|
|
39
|
+
storeKey: normalizePreferenceSegment(storeName) || 'unknown-store',
|
|
40
|
+
};
|
|
152
41
|
};
|
|
153
42
|
|
|
154
|
-
|
|
155
|
-
if (!
|
|
43
|
+
const normalizePreferenceScope = scope => {
|
|
44
|
+
if (!isPlainObject(scope)) {
|
|
156
45
|
return null;
|
|
157
46
|
}
|
|
158
47
|
|
|
48
|
+
const storeKey = normalizePreferenceSegment(scope.storeKey);
|
|
49
|
+
const routeKey = normalizePreferenceSegment(scope.routeKey);
|
|
50
|
+
|
|
51
|
+
return storeKey && routeKey ? {storeKey, routeKey} : null;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const readStoredPreferences = () => {
|
|
55
|
+
try {
|
|
56
|
+
const rawValue = globalThis?.localStorage?.getItem?.(
|
|
57
|
+
DEFAULT_TABLE_PREFERENCES_STORAGE_KEY,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
if (!rawValue) {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const parsedValue = JSON.parse(rawValue);
|
|
65
|
+
return isPlainObject(parsedValue) ? parsedValue : {};
|
|
66
|
+
} catch {
|
|
67
|
+
return {};
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const writeStoredPreferences = preferences => {
|
|
72
|
+
try {
|
|
73
|
+
globalThis?.localStorage?.setItem?.(
|
|
74
|
+
DEFAULT_TABLE_PREFERENCES_STORAGE_KEY,
|
|
75
|
+
JSON.stringify(preferences),
|
|
76
|
+
);
|
|
77
|
+
} catch {
|
|
78
|
+
// localStorage can be unavailable in some runtimes.
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const readScopedPreference = scope => {
|
|
83
|
+
const resolvedScope = normalizePreferenceScope(scope);
|
|
84
|
+
if (!resolvedScope) {
|
|
85
|
+
return {};
|
|
86
|
+
}
|
|
87
|
+
|
|
159
88
|
const storedPreferences = readStoredPreferences();
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const resolvedField = isPlainObject(tableSortFields)
|
|
166
|
-
? tableSortFields[preferenceKey]
|
|
167
|
-
: '';
|
|
168
|
-
const resolvedDirection = isPlainObject(tableSortDirections)
|
|
169
|
-
? tableSortDirections[preferenceKey]
|
|
170
|
-
: '';
|
|
89
|
+
const storePreferences = storedPreferences[resolvedScope.storeKey];
|
|
90
|
+
const routePreferences = isPlainObject(storePreferences)
|
|
91
|
+
? storePreferences[resolvedScope.routeKey]
|
|
92
|
+
: null;
|
|
171
93
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
field: resolvedField.trim(),
|
|
180
|
-
};
|
|
94
|
+
return isPlainObject(routePreferences) ? routePreferences : {};
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const writeScopedPreference = (scope, nextValues = {}) => {
|
|
98
|
+
const resolvedScope = normalizePreferenceScope(scope);
|
|
99
|
+
if (!resolvedScope || !isPlainObject(nextValues)) {
|
|
100
|
+
return;
|
|
181
101
|
}
|
|
182
102
|
|
|
183
|
-
const
|
|
103
|
+
const storedPreferences = readStoredPreferences();
|
|
104
|
+
const storePreferences = isPlainObject(storedPreferences[resolvedScope.storeKey])
|
|
105
|
+
? storedPreferences[resolvedScope.storeKey]
|
|
106
|
+
: {};
|
|
107
|
+
const routePreferences = isPlainObject(storePreferences[resolvedScope.routeKey])
|
|
108
|
+
? storePreferences[resolvedScope.routeKey]
|
|
109
|
+
: {};
|
|
184
110
|
|
|
185
|
-
|
|
186
|
-
|
|
111
|
+
writeStoredPreferences({
|
|
112
|
+
...storedPreferences,
|
|
113
|
+
[resolvedScope.storeKey]: {
|
|
114
|
+
...storePreferences,
|
|
115
|
+
[resolvedScope.routeKey]: {
|
|
116
|
+
...routePreferences,
|
|
117
|
+
...nextValues,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const buildDefaultVisibleColumns = columns =>
|
|
124
|
+
(Array.isArray(columns) ? columns : []).reduce((accumulator, column) => {
|
|
125
|
+
const key = getColumnKey(column);
|
|
126
|
+
if (key) {
|
|
127
|
+
accumulator[key] = column?.visible !== false;
|
|
128
|
+
}
|
|
129
|
+
return accumulator;
|
|
130
|
+
}, {});
|
|
131
|
+
|
|
132
|
+
export const sanitizeVisibleColumnsPreference = ({
|
|
133
|
+
columns = [],
|
|
134
|
+
visibleColumns = null,
|
|
135
|
+
}) => {
|
|
136
|
+
const defaultVisibleColumns = buildDefaultVisibleColumns(columns);
|
|
137
|
+
|
|
138
|
+
if (!isPlainObject(visibleColumns)) {
|
|
139
|
+
return defaultVisibleColumns;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return Object.keys(defaultVisibleColumns).reduce((accumulator, key) => {
|
|
143
|
+
accumulator[key] =
|
|
144
|
+
typeof visibleColumns[key] === 'boolean'
|
|
145
|
+
? visibleColumns[key]
|
|
146
|
+
: defaultVisibleColumns[key];
|
|
147
|
+
return accumulator;
|
|
148
|
+
}, {});
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export const sanitizeTableFiltersPreference = ({
|
|
152
|
+
columns = [],
|
|
153
|
+
filters = null,
|
|
154
|
+
}) => {
|
|
155
|
+
if (!isPlainObject(filters)) {
|
|
156
|
+
return {};
|
|
187
157
|
}
|
|
188
158
|
|
|
189
|
-
const
|
|
159
|
+
const columnFields = new Set(
|
|
160
|
+
(Array.isArray(columns) ? columns : [])
|
|
161
|
+
.map(getColumnKey)
|
|
162
|
+
.filter(Boolean),
|
|
163
|
+
);
|
|
164
|
+
const blockedFields = new Set(
|
|
165
|
+
(Array.isArray(columns) ? columns : [])
|
|
166
|
+
.filter(column => column?.filter === false || column?.filters === false)
|
|
167
|
+
.map(getColumnKey)
|
|
168
|
+
.filter(Boolean),
|
|
169
|
+
);
|
|
170
|
+
const allowedSpecialFields = new Set(['search']);
|
|
171
|
+
|
|
172
|
+
return Object.keys(filters).reduce((accumulator, key) => {
|
|
173
|
+
if (
|
|
174
|
+
allowedSpecialFields.has(key) ||
|
|
175
|
+
(columnFields.has(key) && !blockedFields.has(key))
|
|
176
|
+
) {
|
|
177
|
+
accumulator[key] = filters[key];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return accumulator;
|
|
181
|
+
}, {});
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
export const resolveStoredVisibleColumnsPreference = scope => {
|
|
185
|
+
const visibleColumns =
|
|
186
|
+
readScopedPreference(scope)[TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY];
|
|
187
|
+
|
|
188
|
+
return isPlainObject(visibleColumns) ? visibleColumns : null;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const persistVisibleColumnsPreference = (
|
|
192
|
+
scope = null,
|
|
193
|
+
visibleColumns = {},
|
|
194
|
+
) => {
|
|
195
|
+
if (!isPlainObject(visibleColumns)) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
writeScopedPreference(scope, {
|
|
200
|
+
[TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY]: visibleColumns,
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export const resolveStoredTableViewModePreference = (
|
|
205
|
+
scope = null,
|
|
206
|
+
fallbackViewMode = 'table',
|
|
207
|
+
) => {
|
|
208
|
+
const resolvedViewMode =
|
|
209
|
+
readScopedPreference(scope)[TABLE_VIEW_MODE_PREFERENCES_KEY];
|
|
210
|
+
|
|
211
|
+
return resolvedViewMode === 'cards' || resolvedViewMode === 'table'
|
|
212
|
+
? resolvedViewMode
|
|
213
|
+
: fallbackViewMode;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export const persistTableViewModePreference = (
|
|
217
|
+
scope = null,
|
|
218
|
+
viewMode = 'table',
|
|
219
|
+
) => {
|
|
220
|
+
if (viewMode !== 'cards' && viewMode !== 'table') {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
writeScopedPreference(scope, {
|
|
225
|
+
[TABLE_VIEW_MODE_PREFERENCES_KEY]: viewMode,
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
export const resolveStoredTableSortPreference = (scope = null) => {
|
|
230
|
+
const resolvedSort = readScopedPreference(scope)[TABLE_SORT_PREFERENCES_KEY];
|
|
190
231
|
|
|
191
232
|
if (!isPlainObject(resolvedSort)) {
|
|
192
233
|
return null;
|
|
@@ -212,11 +253,10 @@ export const resolveStoredTableSortPreference = (preferenceKey = '') => {
|
|
|
212
253
|
};
|
|
213
254
|
|
|
214
255
|
export const persistTableSortPreference = (
|
|
215
|
-
|
|
256
|
+
scope = null,
|
|
216
257
|
sort = null,
|
|
217
258
|
) => {
|
|
218
259
|
if (
|
|
219
|
-
!preferenceKey ||
|
|
220
260
|
!isPlainObject(sort) ||
|
|
221
261
|
(sort.direction !== 'asc' && sort.direction !== 'desc') ||
|
|
222
262
|
typeof sort.field !== 'string' ||
|
|
@@ -225,40 +265,28 @@ export const persistTableSortPreference = (
|
|
|
225
265
|
return;
|
|
226
266
|
}
|
|
227
267
|
|
|
228
|
-
|
|
229
|
-
const tableSortFields = isPlainObject(
|
|
230
|
-
storedPreferences[TABLE_SORT_FIELD_PREFERENCES_KEY],
|
|
231
|
-
)
|
|
232
|
-
? storedPreferences[TABLE_SORT_FIELD_PREFERENCES_KEY]
|
|
233
|
-
: {};
|
|
234
|
-
const tableSortDirections = isPlainObject(
|
|
235
|
-
storedPreferences[TABLE_SORT_DIRECTION_PREFERENCES_KEY],
|
|
236
|
-
)
|
|
237
|
-
? storedPreferences[TABLE_SORT_DIRECTION_PREFERENCES_KEY]
|
|
238
|
-
: {};
|
|
239
|
-
const legacyTableSorts = isPlainObject(
|
|
240
|
-
storedPreferences[TABLE_SORT_PREFERENCES_KEY],
|
|
241
|
-
)
|
|
242
|
-
? storedPreferences[TABLE_SORT_PREFERENCES_KEY]
|
|
243
|
-
: {};
|
|
244
|
-
|
|
245
|
-
writeStoredPreferences({
|
|
246
|
-
...storedPreferences,
|
|
247
|
-
[TABLE_SORT_FIELD_PREFERENCES_KEY]: {
|
|
248
|
-
...tableSortFields,
|
|
249
|
-
[preferenceKey]: sort.field.trim(),
|
|
250
|
-
},
|
|
251
|
-
[TABLE_SORT_DIRECTION_PREFERENCES_KEY]: {
|
|
252
|
-
...tableSortDirections,
|
|
253
|
-
[preferenceKey]: sort.direction,
|
|
254
|
-
},
|
|
268
|
+
writeScopedPreference(scope, {
|
|
255
269
|
[TABLE_SORT_PREFERENCES_KEY]: {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
direction: sort.direction,
|
|
259
|
-
field: sort.field.trim(),
|
|
260
|
-
},
|
|
270
|
+
direction: sort.direction,
|
|
271
|
+
field: sort.field.trim(),
|
|
261
272
|
},
|
|
262
273
|
});
|
|
263
274
|
};
|
|
264
|
-
|
|
275
|
+
|
|
276
|
+
export const resolveStoredTableFiltersPreference = (scope = null) => {
|
|
277
|
+
const resolvedFilters = readScopedPreference(scope)[TABLE_FILTER_PREFERENCES_KEY];
|
|
278
|
+
return isPlainObject(resolvedFilters) ? resolvedFilters : null;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export const persistTableFiltersPreference = (
|
|
282
|
+
scope = null,
|
|
283
|
+
filters = {},
|
|
284
|
+
) => {
|
|
285
|
+
if (!isPlainObject(filters)) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
writeScopedPreference(scope, {
|
|
290
|
+
[TABLE_FILTER_PREFERENCES_KEY]: filters,
|
|
291
|
+
});
|
|
292
|
+
};
|
|
@@ -54,6 +54,30 @@ const resolveCollectionTotalItems = (response, items) =>
|
|
|
54
54
|
const normalizeCollectionItemId = item =>
|
|
55
55
|
normalizeText(item?.['@id'] || item?.id || '').replace(/\D+/g, '')
|
|
56
56
|
|
|
57
|
+
const normalizeSavedItemPatch = (data, patch) => {
|
|
58
|
+
if (!isPlainObject(patch)) {
|
|
59
|
+
return {}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return Object.entries(patch).reduce((normalizedPatch, [key, value]) => {
|
|
63
|
+
const incomingValue = data?.[key]
|
|
64
|
+
normalizedPatch[key] = isPlainObject(incomingValue) ? incomingValue : value
|
|
65
|
+
|
|
66
|
+
return normalizedPatch
|
|
67
|
+
}, {})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const mergeSavedItem = ({currentItem, data, storeMeta}) => {
|
|
71
|
+
const incomingItem = isPlainObject(data) ? {...data} : {}
|
|
72
|
+
delete incomingItem['@context']
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
...(isPlainObject(currentItem) ? currentItem : {}),
|
|
76
|
+
...incomingItem,
|
|
77
|
+
...normalizeSavedItemPatch(incomingItem, storeMeta.savedItemPatch),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
57
81
|
const appendCollectionItems = (currentItems, nextItems) => {
|
|
58
82
|
const mergedItems = Array.isArray(currentItems) ? [...currentItems] : []
|
|
59
83
|
const incomingItems = Array.isArray(nextItems) ? nextItems : []
|
|
@@ -148,6 +172,7 @@ export const getOfflineItems = ({commit, getters}, params = {}) => {
|
|
|
148
172
|
commit(types.SET_ISLOADING, true);
|
|
149
173
|
commit(types.SET_ERROR, null);
|
|
150
174
|
commit(types.SET_SUMMARY, {});
|
|
175
|
+
commit(types.SET_DEBUG, {});
|
|
151
176
|
|
|
152
177
|
db = new localDB(getters);
|
|
153
178
|
|
|
@@ -189,6 +214,7 @@ export const getOnlineItems = ({commit, getters}, params = {}) => {
|
|
|
189
214
|
if (getters.items != null) commit(types.SET_ITEMS, []);
|
|
190
215
|
commit(types.SET_TOTALITEMS, 0);
|
|
191
216
|
commit(types.SET_SUMMARY, {});
|
|
217
|
+
commit(types.SET_DEBUG, {});
|
|
192
218
|
}
|
|
193
219
|
return api
|
|
194
220
|
.fetch(getters.resourceEndpoint, {params: queryParams})
|
|
@@ -207,6 +233,7 @@ export const getOnlineItems = ({commit, getters}, params = {}) => {
|
|
|
207
233
|
commit(types.SET_ITEMS, nextItems);
|
|
208
234
|
commit(types.SET_TOTALITEMS, resolveCollectionTotalItems(data, nextItems));
|
|
209
235
|
commit(types.SET_SUMMARY, data['summary'] || data?.['hydra:summary'] || {});
|
|
236
|
+
commit(types.SET_DEBUG, data?.debug || {});
|
|
210
237
|
commit(types.SET_LAST_COMPLETED_REQUEST, {
|
|
211
238
|
completedAt: Date.now(),
|
|
212
239
|
requestKey,
|
|
@@ -290,18 +317,25 @@ export const save = ({commit, getters}, params) => {
|
|
|
290
317
|
.fetch(getters.resourceEndpoint + (id ? '/' + id : ''), options)
|
|
291
318
|
.then(data => {
|
|
292
319
|
commit(types.SET_ERROR, null);
|
|
293
|
-
delete data['@context'];
|
|
294
320
|
let items = getters.items ? [...getters.items] : [];
|
|
295
|
-
if (id) {
|
|
296
|
-
const index = items.findIndex(i => {
|
|
297
|
-
return i
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
321
|
+
if (id) {
|
|
322
|
+
const index = items.findIndex(i => {
|
|
323
|
+
return normalizeCollectionItemId(i) === id;
|
|
324
|
+
});
|
|
325
|
+
const nextItem = mergeSavedItem({
|
|
326
|
+
currentItem: index >= 0 ? items[index] : null,
|
|
327
|
+
data,
|
|
328
|
+
storeMeta,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
if (index >= 0) items[index] = nextItem;
|
|
332
|
+
else items.push(nextItem);
|
|
333
|
+
} else {
|
|
334
|
+
items.push(mergeSavedItem({currentItem: null, data, storeMeta}));
|
|
335
|
+
}
|
|
336
|
+
commit(types.SET_ITEMS, items);
|
|
337
|
+
return data;
|
|
338
|
+
})
|
|
305
339
|
.catch(e => {
|
|
306
340
|
commitStoreError(commit, e, storeMeta)
|
|
307
341
|
throw e;
|
|
@@ -385,8 +419,12 @@ export const setSummary = ({commit, getters}, summary) => {
|
|
|
385
419
|
export const setColumns = ({commit, getters}, columns) => {
|
|
386
420
|
commit(types.SET_COLUMNS, columns);
|
|
387
421
|
};
|
|
388
|
-
|
|
389
|
-
export const
|
|
422
|
+
|
|
423
|
+
export const setConfigs = ({commit, getters}, configs) => {
|
|
424
|
+
commit(types.SET_CONFIGS, configs);
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
export const setResourceEndpoint = (
|
|
390
428
|
{commit, getters},
|
|
391
429
|
resourceEndpoint = null,
|
|
392
430
|
) => {
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
export const error = state => state.error;
|
|
2
|
-
export const isLoading = state => state.isLoading;
|
|
3
|
-
export const isSaving = state => state.isSaving;
|
|
4
|
-
export const totalItems = state => state.totalItems;
|
|
5
|
-
export const summary = state => state.summary;
|
|
6
|
-
export const
|
|
7
|
-
export const
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
2
|
+
export const isLoading = state => state.isLoading;
|
|
3
|
+
export const isSaving = state => state.isSaving;
|
|
4
|
+
export const totalItems = state => state.totalItems;
|
|
5
|
+
export const summary = state => state.summary;
|
|
6
|
+
export const debug = state => state.debug || {};
|
|
7
|
+
export const items = state => state.items;
|
|
8
|
+
export const item = state => state.item;
|
|
9
|
+
export const columns = state => state.columns;
|
|
10
|
+
export const configs = state => state.configs || {};
|
|
11
|
+
export const filters = state => state.filters;
|
|
10
12
|
export const resourceEndpoint = state => state.resourceEndpoint;
|
|
11
13
|
export const selected = state => state.selected;
|
|
12
14
|
export const visibleColumns = state => state.visibleColumns;
|
|
@@ -3,10 +3,12 @@ export const SET_ISLOADING = 'SET_ISLOADING';
|
|
|
3
3
|
export const SET_ISSAVING = 'SET_ISSAVING';
|
|
4
4
|
export const SET_TOTALITEMS = 'SET_TOTALITEMS';
|
|
5
5
|
export const SET_SUMMARY = 'SET_SUMMARY';
|
|
6
|
+
export const SET_DEBUG = 'SET_DEBUG';
|
|
6
7
|
export const SET_ITEMS = 'SET_ITEMS';
|
|
7
8
|
export const SET_ITEM = 'SET_ITEM';
|
|
8
|
-
export const SET_COLUMNS = 'SET_COLUMNS';
|
|
9
|
-
export const
|
|
9
|
+
export const SET_COLUMNS = 'SET_COLUMNS';
|
|
10
|
+
export const SET_CONFIGS = 'SET_CONFIGS';
|
|
11
|
+
export const SET_FILTERS = 'SET_FILTERS';
|
|
10
12
|
export const SET_RESOURCE_ENDPOINT = 'SET_RESOURCE_ENDPOINT';
|
|
11
13
|
export const SET_SELECTED = 'SET_SELECTED';
|
|
12
14
|
export const SET_VISIBLECOLUMNS = 'SET_VISIBLECOLUMNS';
|
|
@@ -37,6 +37,11 @@ export default {
|
|
|
37
37
|
return 'summary';
|
|
38
38
|
},
|
|
39
39
|
|
|
40
|
+
[types.SET_DEBUG](state, debug) {
|
|
41
|
+
state.debug = debug || {};
|
|
42
|
+
return 'debug';
|
|
43
|
+
},
|
|
44
|
+
|
|
40
45
|
[types.SET_ITEMS](state, items) {
|
|
41
46
|
state.items = items;
|
|
42
47
|
return 'items';
|
|
@@ -74,7 +79,11 @@ export default {
|
|
|
74
79
|
state.columns = columns;
|
|
75
80
|
return 'columns';
|
|
76
81
|
},
|
|
77
|
-
[types.
|
|
82
|
+
[types.SET_CONFIGS](state, configs) {
|
|
83
|
+
state.configs = configs || {};
|
|
84
|
+
return 'configs';
|
|
85
|
+
},
|
|
86
|
+
[types.SET_OFFLINE](state, offline) {
|
|
78
87
|
state.offline = offline;
|
|
79
88
|
return 'offline';
|
|
80
89
|
},
|