@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.
Files changed (46) hide show
  1. package/AGENTS.md +3 -2
  2. package/package.json +21 -18
  3. package/src/react/components/errors/DefaultErrors.js +64 -82
  4. package/src/react/components/filters/CompactFilterSelector.js +58 -23
  5. package/src/react/components/filters/CompactFilterSelector.styles.js +17 -5
  6. package/src/react/components/filters/DefaultColumnFilter.js +177 -45
  7. package/src/react/components/filters/DefaultExternalFilters.js +201 -143
  8. package/src/react/components/filters/DefaultSearch.js +27 -25
  9. package/src/react/components/form/DefaultForm.js +72 -53
  10. package/src/react/components/form/DefaultForm.styles.js +71 -66
  11. package/src/react/components/inputs/DefaultDateInput.js +150 -0
  12. package/src/react/components/inputs/DefaultInput.js +44 -11
  13. package/src/react/components/inputs/DefaultInput.styles.js +6 -0
  14. package/src/react/components/inputs/DefaultSelect.js +200 -43
  15. package/src/react/components/inputs/defaultInputUtils.js +40 -19
  16. package/src/react/components/table/DefaultColumnMenu.js +108 -0
  17. package/src/react/components/table/DefaultDebug.js +234 -0
  18. package/src/react/components/table/DefaultFiltersModal.js +142 -0
  19. package/src/react/components/table/DefaultModalButton.js +18 -0
  20. package/src/react/components/table/DefaultSearchModal.js +49 -0
  21. package/src/react/components/table/DefaultTable.js +322 -1964
  22. package/src/react/components/table/DefaultTable.styles.js +234 -102
  23. package/src/react/components/table/DefaultTable.utils.js +502 -0
  24. package/src/react/components/table/DefaultTableBody.js +26 -0
  25. package/src/react/components/table/DefaultTableCards.js +171 -0
  26. package/src/react/components/table/DefaultTableControls.js +205 -0
  27. package/src/react/components/table/DefaultTableEmptyState.js +22 -0
  28. package/src/react/components/table/DefaultTableFooter.js +172 -0
  29. package/src/react/components/table/DefaultTableInput.js +145 -0
  30. package/src/react/components/table/DefaultTableRows.js +344 -0
  31. package/src/react/components/table/DefaultTableSearch.js +100 -0
  32. package/src/react/components/table/DefaultTableToolbar.js +98 -0
  33. package/src/react/components/table/DefaultToolbarAction.js +56 -0
  34. package/src/react/components/table/useDefaultTablePagination.js +370 -0
  35. package/src/react/components/table/useDefaultTableSorting.js +126 -0
  36. package/src/react/components/table/useDefaultTableTheme.js +52 -0
  37. package/src/react/utils/tableVisibleColumnsPreferences.js +239 -211
  38. package/src/store/default/actions.js +51 -13
  39. package/src/store/default/getters.js +10 -8
  40. package/src/store/default/mutation_types.js +4 -2
  41. package/src/store/default/mutations.js +10 -1
  42. package/src/tests/react/components/form/DefaultForm.test.js +81 -0
  43. package/src/tests/react/components/inputs/DefaultSelect.test.js +106 -14
  44. package/src/tests/react/components/table/DefaultTable.test.js +1318 -334
  45. package/src/tests/react/store/defaultActions.test.js +59 -0
  46. package/src/tests/react/utils/tableVisibleColumnsPreferences.test.js +247 -168
@@ -19,6 +19,7 @@ const {
19
19
  splitStoreActionPayload,
20
20
  buildStoreErrorCommitOptions,
21
21
  get,
22
+ save,
22
23
  } = require('../../../store/default/actions')
23
24
 
24
25
  describe('default store action controls', () => {
@@ -109,4 +110,62 @@ describe('default store action controls', () => {
109
110
  })
110
111
  expect(commit).toHaveBeenCalledWith(types.SET_ISLOADING, false)
111
112
  })
113
+
114
+ it('merges saved list object patches into the visible collection without sending them to the API', async () => {
115
+ api.fetch.mockResolvedValue({
116
+ '@id': '/invoices/332',
117
+ id: 332,
118
+ status: '/statuses/33',
119
+ })
120
+
121
+ const commit = jest.fn()
122
+ const getters = {
123
+ resourceEndpoint: 'invoices',
124
+ items: [
125
+ {
126
+ '@id': '/invoices/332',
127
+ id: 332,
128
+ status: {
129
+ id: 1,
130
+ status: 'Aberto',
131
+ },
132
+ },
133
+ ],
134
+ }
135
+
136
+ await save(
137
+ {commit, getters},
138
+ {
139
+ id: '332',
140
+ status: '/statuses/33',
141
+ [STORE_ACTION_META_KEY]: {
142
+ savedItemPatch: {
143
+ status: {
144
+ id: 33,
145
+ status: 'Pago',
146
+ context: 'invoice',
147
+ },
148
+ },
149
+ },
150
+ },
151
+ )
152
+
153
+ expect(api.fetch).toHaveBeenCalledWith('invoices/332', {
154
+ method: 'PUT',
155
+ body: {
156
+ status: '/statuses/33',
157
+ },
158
+ })
159
+ expect(commit).toHaveBeenCalledWith(types.SET_ITEMS, [
160
+ {
161
+ '@id': '/invoices/332',
162
+ id: 332,
163
+ status: {
164
+ id: 33,
165
+ status: 'Pago',
166
+ context: 'invoice',
167
+ },
168
+ },
169
+ ])
170
+ })
112
171
  })
@@ -1,223 +1,302 @@
1
1
  const {
2
2
  DEFAULT_TABLE_PREFERENCES_STORAGE_KEY,
3
- TABLE_SORT_DIRECTION_PREFERENCES_KEY,
4
- TABLE_SORT_FIELD_PREFERENCES_KEY,
3
+ TABLE_FILTER_PREFERENCES_KEY,
5
4
  TABLE_SORT_PREFERENCES_KEY,
6
5
  TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY,
7
6
  TABLE_VIEW_MODE_PREFERENCES_KEY,
8
7
  buildDefaultVisibleColumns,
8
+ persistTableFiltersPreference,
9
9
  persistTableSortPreference,
10
10
  persistTableViewModePreference,
11
11
  persistVisibleColumnsPreference,
12
+ resolveDefaultTablePreferenceScope,
13
+ resolveStoredTableFiltersPreference,
12
14
  resolveStoredTableSortPreference,
13
15
  resolveStoredTableViewModePreference,
14
16
  resolveStoredVisibleColumnsPreference,
17
+ sanitizeTableFiltersPreference,
15
18
  sanitizeVisibleColumnsPreference,
16
19
  } = require('../../../react/utils/tableVisibleColumnsPreferences');
17
-
18
- const { beforeEach, describe, expect, it } = global;
19
-
20
- const createLocalStorageMock = () => {
21
- let storage = {};
22
-
23
- return {
24
- clear: () => {
25
- storage = {};
26
- },
27
- getItem: key => (key in storage ? storage[key] : null),
28
- removeItem: key => {
29
- delete storage[key];
30
- },
31
- setItem: (key, value) => {
32
- storage[key] = String(value);
33
- },
34
- };
35
- };
36
-
37
- describe('tableVisibleColumnsPreferences', () => {
38
- const columns = [
39
- { name: 'id' },
40
- { name: 'status' },
41
- { name: 'price', visible: false },
42
- ];
43
-
44
- beforeEach(() => {
45
- global.localStorage = createLocalStorageMock();
46
- });
47
-
48
- it('builds the default visibility map from store columns', () => {
49
- expect(buildDefaultVisibleColumns(columns)).toEqual({
50
- id: true,
51
- status: true,
52
- price: false,
53
- });
54
- });
55
-
56
- it('sanitizes stored preferences against the current columns', () => {
57
- expect(
58
- sanitizeVisibleColumnsPreference({
59
- columns,
60
- visibleColumns: {
61
- id: false,
62
- unknown: true,
63
- },
64
- }),
65
- ).toEqual({
66
- id: false,
67
- status: true,
68
- price: false,
69
- });
70
- });
71
-
72
- it('reads and writes visible columns preferences under the per-page bucket', () => {
73
- global.localStorage.setItem(
74
- DEFAULT_TABLE_PREFERENCES_STORAGE_KEY,
75
- JSON.stringify({
76
- theme: 'light',
77
- [TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY]: {
78
- 'financialEntries:receivables': {
79
- id: false,
80
- },
81
- },
82
- }),
83
- );
84
-
85
- expect(
86
- resolveStoredVisibleColumnsPreference('financialEntries:receivables'),
87
- ).toEqual({
88
- id: false,
89
- });
90
-
91
- persistVisibleColumnsPreference('financialEntries:payables', {
92
- id: true,
93
- status: false,
94
- });
95
-
96
- expect(
97
- JSON.parse(
98
- global.localStorage.getItem(DEFAULT_TABLE_PREFERENCES_STORAGE_KEY),
99
- ),
100
- ).toEqual({
101
- theme: 'light',
102
- [TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY]: {
103
- 'financialEntries:receivables': {
104
- id: false,
105
- },
106
- 'financialEntries:payables': {
107
- id: true,
108
- status: false,
109
- },
110
- },
111
- });
112
- });
113
-
114
- it('reads and writes the preferred table view mode by page', () => {
115
- global.localStorage.setItem(
116
- DEFAULT_TABLE_PREFERENCES_STORAGE_KEY,
117
- JSON.stringify({
118
- [TABLE_VIEW_MODE_PREFERENCES_KEY]: {
119
- 'financialEntries:payables': 'cards',
120
- },
121
- }),
122
- );
123
-
124
- expect(
125
- resolveStoredTableViewModePreference(
126
- 'financialEntries:payables',
127
- 'table',
128
- ),
129
- ).toBe('cards');
130
-
131
- expect(
132
- resolveStoredTableViewModePreference(
133
- 'financialEntries:receivables',
134
- 'table',
135
- ),
136
- ).toBe('table');
137
-
138
- persistTableViewModePreference('financialEntries:receivables', 'table');
139
-
140
- expect(
141
- JSON.parse(
142
- global.localStorage.getItem(DEFAULT_TABLE_PREFERENCES_STORAGE_KEY),
143
- ),
144
- ).toEqual({
145
- [TABLE_VIEW_MODE_PREFERENCES_KEY]: {
146
- 'financialEntries:payables': 'cards',
147
- 'financialEntries:receivables': 'table',
148
- },
20
+
21
+ const { beforeEach, describe, expect, it } = global;
22
+
23
+ const createLocalStorageMock = () => {
24
+ let storage = {};
25
+
26
+ return {
27
+ clear: () => {
28
+ storage = {};
29
+ },
30
+ getItem: key => (key in storage ? storage[key] : null),
31
+ removeItem: key => {
32
+ delete storage[key];
33
+ },
34
+ setItem: (key, value) => {
35
+ storage[key] = String(value);
36
+ },
37
+ };
38
+ };
39
+
40
+ describe('tableVisibleColumnsPreferences', () => {
41
+ const columns = [
42
+ { name: 'id' },
43
+ { name: 'status' },
44
+ { name: 'price', visible: false },
45
+ ];
46
+ const scope = {
47
+ storeKey: 'financialEntries',
48
+ routeKey: 'receivables',
49
+ };
50
+
51
+ beforeEach(() => {
52
+ global.localStorage = createLocalStorageMock();
53
+ });
54
+
55
+ it('builds the default visibility map from store columns', () => {
56
+ expect(buildDefaultVisibleColumns(columns)).toEqual({
57
+ id: true,
58
+ status: true,
59
+ price: false,
60
+ });
61
+ });
62
+
63
+ it('sanitizes stored preferences against the current columns', () => {
64
+ expect(
65
+ sanitizeVisibleColumnsPreference({
66
+ columns,
67
+ visibleColumns: {
68
+ id: false,
69
+ unknown: true,
70
+ },
71
+ }),
72
+ ).toEqual({
73
+ id: false,
74
+ status: true,
75
+ price: false,
76
+ });
77
+ });
78
+
79
+ it('builds the route and store preference scope', () => {
80
+ global.location = {pathname: '/order-history-page'};
81
+
82
+ expect(
83
+ resolveDefaultTablePreferenceScope({
84
+ route: {name: 'IgnoredRoute'},
85
+ storeName: 'orders',
86
+ }),
87
+ ).toEqual({
88
+ routeKey: 'order-history-page',
89
+ storeKey: 'orders',
90
+ });
91
+
92
+ delete global.location;
93
+ });
94
+
95
+ it('uses an explicit preference key before the route pathname', () => {
96
+ global.location = {pathname: '/product-showcases-page'};
97
+
98
+ expect(
99
+ resolveDefaultTablePreferenceScope({
100
+ preferenceKey: 'product_showcase_items',
101
+ route: {name: 'ProductShowcasesPage'},
102
+ storeName: 'product_showcase_items',
103
+ }),
104
+ ).toEqual({
105
+ routeKey: 'product_showcase_items',
106
+ storeKey: 'product_showcase_items',
107
+ });
108
+
109
+ delete global.location;
110
+ });
111
+
112
+ it('sanitizes stored filters against filterable columns and search key', () => {
113
+ expect(
114
+ sanitizeTableFiltersPreference({
115
+ columns: [
116
+ {name: 'status'},
117
+ {name: 'internal', filter: false},
118
+ ],
119
+ filters: {
120
+ internal: 'hidden',
121
+ search: 'pedido',
122
+ status: 'paid',
123
+ unknown: 'ignored',
124
+ },
125
+ }),
126
+ ).toEqual({
127
+ search: 'pedido',
128
+ status: 'paid',
149
129
  });
150
130
  });
151
131
 
152
- it('reads and writes the preferred sort by page', () => {
132
+ it('reads and writes visible columns under default-table[store][route]', () => {
153
133
  global.localStorage.setItem(
154
134
  DEFAULT_TABLE_PREFERENCES_STORAGE_KEY,
155
135
  JSON.stringify({
156
- [TABLE_SORT_FIELD_PREFERENCES_KEY]: {
157
- 'financialEntries:payables': 'price',
158
- },
159
- [TABLE_SORT_DIRECTION_PREFERENCES_KEY]: {
160
- 'financialEntries:payables': 'asc',
136
+ theme: 'light',
137
+ financialEntries: {
138
+ receivables: {
139
+ [TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY]: {
140
+ id: false,
141
+ },
142
+ },
161
143
  },
162
144
  }),
163
145
  );
164
146
 
147
+ expect(resolveStoredVisibleColumnsPreference(scope)).toEqual({
148
+ id: false,
149
+ });
150
+
151
+ persistVisibleColumnsPreference({
152
+ storeKey: 'financialEntries',
153
+ routeKey: 'payables',
154
+ }, {
155
+ id: true,
156
+ status: false,
157
+ });
158
+
165
159
  expect(
166
- resolveStoredTableSortPreference('financialEntries:payables'),
160
+ JSON.parse(
161
+ global.localStorage.getItem(DEFAULT_TABLE_PREFERENCES_STORAGE_KEY),
162
+ ),
167
163
  ).toEqual({
168
- direction: 'asc',
169
- field: 'price',
164
+ theme: 'light',
165
+ financialEntries: {
166
+ receivables: {
167
+ [TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY]: {
168
+ id: false,
169
+ },
170
+ },
171
+ payables: {
172
+ [TABLE_VISIBLE_COLUMNS_PREFERENCES_KEY]: {
173
+ id: true,
174
+ status: false,
175
+ },
176
+ },
177
+ },
170
178
  });
179
+ });
180
+
181
+ it('reads and writes view mode under default-table[store][route]', () => {
182
+ global.localStorage.setItem(
183
+ DEFAULT_TABLE_PREFERENCES_STORAGE_KEY,
184
+ JSON.stringify({
185
+ financialEntries: {
186
+ payables: {
187
+ [TABLE_VIEW_MODE_PREFERENCES_KEY]: 'cards',
188
+ },
189
+ },
190
+ }),
191
+ );
171
192
 
172
193
  expect(
173
- resolveStoredTableSortPreference('financialEntries:receivables'),
174
- ).toBeNull();
194
+ resolveStoredTableViewModePreference(
195
+ {storeKey: 'financialEntries', routeKey: 'payables'},
196
+ 'table',
197
+ ),
198
+ ).toBe('cards');
175
199
 
176
- persistTableSortPreference('financialEntries:receivables', {
177
- direction: 'desc',
178
- field: 'dueDate',
179
- });
200
+ expect(
201
+ resolveStoredTableViewModePreference(scope, 'table'),
202
+ ).toBe('table');
203
+
204
+ persistTableViewModePreference(scope, 'table');
180
205
 
181
206
  expect(
182
207
  JSON.parse(
183
208
  global.localStorage.getItem(DEFAULT_TABLE_PREFERENCES_STORAGE_KEY),
184
209
  ),
185
210
  ).toEqual({
186
- [TABLE_SORT_FIELD_PREFERENCES_KEY]: {
187
- 'financialEntries:payables': 'price',
188
- 'financialEntries:receivables': 'dueDate',
189
- },
190
- [TABLE_SORT_DIRECTION_PREFERENCES_KEY]: {
191
- 'financialEntries:payables': 'asc',
192
- 'financialEntries:receivables': 'desc',
193
- },
194
- [TABLE_SORT_PREFERENCES_KEY]: {
195
- 'financialEntries:receivables': {
196
- direction: 'desc',
197
- field: 'dueDate',
211
+ financialEntries: {
212
+ payables: {
213
+ [TABLE_VIEW_MODE_PREFERENCES_KEY]: 'cards',
214
+ },
215
+ receivables: {
216
+ [TABLE_VIEW_MODE_PREFERENCES_KEY]: 'table',
198
217
  },
199
218
  },
200
219
  });
201
220
  });
202
221
 
203
- it('keeps reading the legacy combined sort format when needed', () => {
222
+ it('reads and writes sort under default-table[store][route]', () => {
204
223
  global.localStorage.setItem(
205
224
  DEFAULT_TABLE_PREFERENCES_STORAGE_KEY,
206
225
  JSON.stringify({
207
- [TABLE_SORT_PREFERENCES_KEY]: {
208
- 'financialEntries:ownTransfers': {
209
- direction: 'asc',
210
- field: 'createdAt',
226
+ financialEntries: {
227
+ payables: {
228
+ [TABLE_SORT_PREFERENCES_KEY]: {
229
+ direction: 'asc',
230
+ field: 'price',
231
+ },
211
232
  },
212
233
  },
213
234
  }),
214
235
  );
215
236
 
216
237
  expect(
217
- resolveStoredTableSortPreference('financialEntries:ownTransfers'),
238
+ resolveStoredTableSortPreference({
239
+ storeKey: 'financialEntries',
240
+ routeKey: 'payables',
241
+ }),
218
242
  ).toEqual({
219
243
  direction: 'asc',
220
- field: 'createdAt',
244
+ field: 'price',
245
+ });
246
+
247
+ expect(resolveStoredTableSortPreference(scope)).toBeNull();
248
+
249
+ persistTableSortPreference(scope, {
250
+ direction: 'desc',
251
+ field: 'dueDate',
252
+ });
253
+
254
+ expect(
255
+ JSON.parse(
256
+ global.localStorage.getItem(DEFAULT_TABLE_PREFERENCES_STORAGE_KEY),
257
+ ),
258
+ ).toEqual({
259
+ financialEntries: {
260
+ payables: {
261
+ [TABLE_SORT_PREFERENCES_KEY]: {
262
+ direction: 'asc',
263
+ field: 'price',
264
+ },
265
+ },
266
+ receivables: {
267
+ [TABLE_SORT_PREFERENCES_KEY]: {
268
+ direction: 'desc',
269
+ field: 'dueDate',
270
+ },
271
+ },
272
+ },
273
+ });
274
+ });
275
+
276
+ it('reads and writes filters under default-table[store][route]', () => {
277
+ persistTableFiltersPreference(scope, {
278
+ search: '72813',
279
+ status: 'paid',
280
+ });
281
+
282
+ expect(resolveStoredTableFiltersPreference(scope)).toEqual({
283
+ search: '72813',
284
+ status: 'paid',
285
+ });
286
+
287
+ expect(
288
+ JSON.parse(
289
+ global.localStorage.getItem(DEFAULT_TABLE_PREFERENCES_STORAGE_KEY),
290
+ ),
291
+ ).toEqual({
292
+ financialEntries: {
293
+ receivables: {
294
+ [TABLE_FILTER_PREFERENCES_KEY]: {
295
+ search: '72813',
296
+ status: 'paid',
297
+ },
298
+ },
299
+ },
221
300
  });
222
301
  });
223
302
  });