@controleonline/ui-common 1.2.90 → 1.2.91
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/docs/compact-order-history-1047.md +25 -0
- package/package.json +1 -1
- package/src/react/components/DefaultProvider.native.configuration.js +275 -0
- package/src/react/components/DefaultProvider.native.js +24 -534
- package/src/react/components/DefaultProvider.native.lifecycle.js +323 -0
- package/src/react/components/DefaultProvider.web.configuration.js +327 -0
- package/src/react/components/DefaultProvider.web.js +23 -603
- package/src/react/components/DefaultProvider.web.lifecycle.js +336 -0
- package/src/react/components/resolveDomainThemeColors.js +5 -0
- package/src/react/pages/Connections.js +1 -1
- package/src/tests/browser/manager/device-detail-alias-save.spec.js +1 -1
- package/src/tests/browser/manager/device-detail-pdv-current-company.spec.js +1 -1
- package/src/tests/react/components/DefaultProviderAuthority.test.js +4 -1
- package/src/tests/react/components/providerEffects.fingerprint.json +47 -0
- package/src/tests/react/components/providerEffects.test.js +24 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# DefaultTable compact pilot — app-community #1047
|
|
2
|
+
|
|
3
|
+
The compact appearance is opt-in. Order History is the pilot; default consumers retain their existing appearance and actions. Search, controlled filters, accessible card sorting, column visibility, table/cards, numbered pagination and report totals reuse the shared table and order services.
|
|
4
|
+
|
|
5
|
+
Theme authority remains the main company/domain. Theme tokens override status colors; registered status.color follows; neutral theme text is last. Franchise switching does not override domain authority. No database writes or staging Theme bindings are shipped. Business permissions, payment/cancellation eligibility and request/security filters are preserved.
|
|
6
|
+
|
|
7
|
+
Header logos send authentication only to the exact API origin; external images use Image without headers. Inline row/card navigation stays blocked during editing/saving, preserving existing store save callbacks. Provider extraction preserves hook order and unrelated bootstrap dependencies, checked by ordered AST fingerprints.
|
|
8
|
+
|
|
9
|
+
Pre-existing published dependencies are merged by their exact gitHeads rather than importing latest dev:
|
|
10
|
+
- ui-default 1.0.276 f0083eb73074f402e81f4e0c832af0bb829c2047; published patch277 1dff39dc32be3320cd4a786baf5621e8a2d3ac00.
|
|
11
|
+
- ui-orders 1.3.42 bfe2f013dc9bcaf033ba0db80894f021bfb2fbfb.
|
|
12
|
+
- ui-layout 1.0.15 37f1dff3fecf1f08bc8846a319af83c9fcbff502.
|
|
13
|
+
- ui-common 1.2.89 4919724c04f3d6e66280db4c9e2a66db65c47cc0; published patch90 e19f14d4afefb89a0700d63753785815364af835.
|
|
14
|
+
|
|
15
|
+
Patch90 Connections.js had an unterminated searchKey quote. Only that quote is repaired to make the retained published fixes compilable. Existing DefaultTable tests are split without discarding cases; fixtures now model reactive stores, company-scoped preferences, route context and CSS sticky positioning. Legacy toolbar tests isolate the inactive compact branch; dedicated compact suites cover its controls.
|
|
16
|
+
|
|
17
|
+
Validation: 135 assertions in 22 suites, 591 React files parsed, and isolated Expo web export (5492 modules). These are source/composition checks; authenticated staging validation remains a separate promotion gate. Isolation used source-module copies; final released-package pins must be verified again by release validation.
|
|
18
|
+
|
|
19
|
+
From app-community with installed release packages:
|
|
20
|
+
```sh
|
|
21
|
+
node scripts/validate-compact-sources.cjs
|
|
22
|
+
node node_modules/jest/bin/jest.js --config jest.compact.config.cjs --maxWorkers=2 --testPathPattern='compact|Compact|headerLogoProtocol|DefaultCompanyHeaderLogo|useDefaultTableStoreSync|providerEffects|DefaultProviderAuthority|deviceConfigBootstrap|mercadoLivreIntegrationHelpers|DefaultTable\.(group[123]\.)?test.js|OrderHistoryPage.test.js|DefaultTableCards.layout|DefaultTableToolbar.waiter'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
For isolated sibling source clones, set CONTROLEONLINE_MODULES_ROOT to their common directory. The committed configuration has no machine-specific absolute path. Published versions planned: ui-default1.0.278, ui-orders1.3.43, ui-layout1.0.16, ui-common1.2.91.
|
package/package.json
CHANGED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import {useEffect} from 'react';
|
|
2
|
+
|
|
3
|
+
// Extracted bootstrap effects retain their dependency arrays and invocation order.
|
|
4
|
+
|
|
5
|
+
export function useNativeDeviceConfigSync({deviceConfigFetched, isLogged, deviceConfigPeopleIri, device, deviceRuntimeConfigSynced, runtimeDeviceType, device_config, buildDefaultDeviceConfigs, buildProviderManagedDeviceConfigs, appVersion, setDeviceRuntimeConfigSynced, deviceConfigsActions, user}) {
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
if (
|
|
8
|
+
!deviceConfigFetched ||
|
|
9
|
+
!isLogged ||
|
|
10
|
+
!deviceConfigPeopleIri ||
|
|
11
|
+
!device?.id ||
|
|
12
|
+
deviceRuntimeConfigSynced
|
|
13
|
+
) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const isNewPdvConfig =
|
|
18
|
+
runtimeDeviceType === 'PDV' &&
|
|
19
|
+
!device_config?.id &&
|
|
20
|
+
!device_config?.['@id'];
|
|
21
|
+
const buildDeviceConfigs = isNewPdvConfig
|
|
22
|
+
? buildDefaultDeviceConfigs
|
|
23
|
+
: buildProviderManagedDeviceConfigs;
|
|
24
|
+
const {nextConfigs, needsUpdate} = buildDeviceConfigs({
|
|
25
|
+
configs: device_config?.configs,
|
|
26
|
+
appVersion,
|
|
27
|
+
deviceInfo: device,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (!needsUpdate) {
|
|
31
|
+
setDeviceRuntimeConfigSynced(true);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// app-community#821: never auto-persist device_config from global bootstrap.
|
|
36
|
+
// Provider-managed fields stay in memory only; API mutations only from
|
|
37
|
+
// explicit device settings UI (avoids 403 on order-history / PDV|MANAGER).
|
|
38
|
+
const currentItem = device_config || {};
|
|
39
|
+
deviceConfigsActions.setItem({
|
|
40
|
+
...currentItem,
|
|
41
|
+
configs: nextConfigs,
|
|
42
|
+
device: currentItem.device || device.id,
|
|
43
|
+
people: currentItem.people || deviceConfigPeopleIri,
|
|
44
|
+
type: currentItem.type || runtimeDeviceType,
|
|
45
|
+
});
|
|
46
|
+
setDeviceRuntimeConfigSynced(true);
|
|
47
|
+
}, [
|
|
48
|
+
appVersion,
|
|
49
|
+
device?.id,
|
|
50
|
+
device?.manufacturer,
|
|
51
|
+
device?.isEmulator,
|
|
52
|
+
deviceConfigFetched,
|
|
53
|
+
deviceConfigPeopleIri,
|
|
54
|
+
deviceRuntimeConfigSynced,
|
|
55
|
+
deviceConfigsActions,
|
|
56
|
+
device_config,
|
|
57
|
+
isLogged,
|
|
58
|
+
runtimeDeviceType,
|
|
59
|
+
user,
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function useNativeMainConfigReset({isLogged, currentCompany, device, setMainConfigsDiscovered}) {
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (!isLogged || !currentCompany?.id || !device?.id) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
setMainConfigsDiscovered(false);
|
|
70
|
+
}, [isLogged, currentCompany?.id, device?.id]);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function useNativeMainConfigDiscovery({isLogged, currentCompany, device, mainConfigsDiscovered, configActions, setMainConfigsDiscovered}) {
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (
|
|
76
|
+
!isLogged ||
|
|
77
|
+
!currentCompany?.id ||
|
|
78
|
+
!device?.id ||
|
|
79
|
+
mainConfigsDiscovered
|
|
80
|
+
) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
configActions
|
|
85
|
+
.discoveryMainConfigs({
|
|
86
|
+
people: '/people/' + currentCompany.id,
|
|
87
|
+
})
|
|
88
|
+
.catch(() => {})
|
|
89
|
+
.finally(() => {
|
|
90
|
+
setMainConfigsDiscovered(true);
|
|
91
|
+
});
|
|
92
|
+
}, [configActions, currentCompany?.id, device?.id, isLogged, mainConfigsDiscovered]);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function useNativeMainConfigSeed({isLogged, currentCompany, mainConfigsDiscovered, configActions}) {
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (
|
|
98
|
+
isLogged &&
|
|
99
|
+
currentCompany &&
|
|
100
|
+
Object.entries(currentCompany).length > 0 &&
|
|
101
|
+
!mainConfigsDiscovered
|
|
102
|
+
) {
|
|
103
|
+
configActions.setItems(currentCompany.configs);
|
|
104
|
+
}
|
|
105
|
+
}, [currentCompany, isLogged, mainConfigsDiscovered]);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function useNativeTranslationBootstrap({currentRouteName, isPublicRouteActive, isLogged, hasCurrentCompany, deviceConfigFetched, expectedTranslateBootstrapKey, translateBootstrapKeyRef, companies, currentCompany, mainCompany, setActiveTranslateBootstrapKey, setTranslateReady, configuredTranslationLanguage, Translate, stores, translateStore}) {
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (!currentRouteName || isPublicRouteActive) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (
|
|
115
|
+
!isLogged ||
|
|
116
|
+
!hasCurrentCompany ||
|
|
117
|
+
!deviceConfigFetched ||
|
|
118
|
+
!expectedTranslateBootstrapKey
|
|
119
|
+
) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const currentConfig = JSON.parse(localStorage.getItem('config') || '{}');
|
|
124
|
+
|
|
125
|
+
if (
|
|
126
|
+
translateBootstrapKeyRef.current === expectedTranslateBootstrapKey &&
|
|
127
|
+
global.t
|
|
128
|
+
) {
|
|
129
|
+
global.t.companies = companies;
|
|
130
|
+
global.t.currentCompany = currentCompany;
|
|
131
|
+
global.t.mainCompany = mainCompany;
|
|
132
|
+
setActiveTranslateBootstrapKey(expectedTranslateBootstrapKey);
|
|
133
|
+
setTranslateReady(true);
|
|
134
|
+
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
setTranslateReady(false);
|
|
139
|
+
|
|
140
|
+
if (currentConfig.language !== configuredTranslationLanguage) {
|
|
141
|
+
const nextConfig = {
|
|
142
|
+
...currentConfig,
|
|
143
|
+
language: configuredTranslationLanguage,
|
|
144
|
+
};
|
|
145
|
+
localStorage.setItem(
|
|
146
|
+
'config',
|
|
147
|
+
JSON.stringify(nextConfig),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
translateBootstrapKeyRef.current = expectedTranslateBootstrapKey;
|
|
152
|
+
global.t = new Translate(
|
|
153
|
+
companies,
|
|
154
|
+
mainCompany,
|
|
155
|
+
currentCompany,
|
|
156
|
+
Object.keys(stores),
|
|
157
|
+
translateStore,
|
|
158
|
+
);
|
|
159
|
+
setActiveTranslateBootstrapKey(expectedTranslateBootstrapKey);
|
|
160
|
+
setTranslateReady(true);
|
|
161
|
+
global.refreshTranslationsUI?.();
|
|
162
|
+
}, [
|
|
163
|
+
companies,
|
|
164
|
+
configuredTranslationLanguage,
|
|
165
|
+
currentCompany,
|
|
166
|
+
currentRouteName,
|
|
167
|
+
mainCompany,
|
|
168
|
+
deviceConfigFetched,
|
|
169
|
+
expectedTranslateBootstrapKey,
|
|
170
|
+
hasCurrentCompany,
|
|
171
|
+
isLogged,
|
|
172
|
+
isPublicRouteActive,
|
|
173
|
+
translateStore,
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function useNativeBootstrapReady({isLogged, hasCurrentCompany, currentRouteName, isTranslateBootstrapReady, onBootstrapReady}) {
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
if (
|
|
180
|
+
!isLogged ||
|
|
181
|
+
!hasCurrentCompany ||
|
|
182
|
+
(currentRouteName && isTranslateBootstrapReady)
|
|
183
|
+
) {
|
|
184
|
+
onBootstrapReady?.();
|
|
185
|
+
}
|
|
186
|
+
}, [
|
|
187
|
+
currentRouteName,
|
|
188
|
+
hasCurrentCompany,
|
|
189
|
+
isLogged,
|
|
190
|
+
isTranslateBootstrapReady,
|
|
191
|
+
onBootstrapReady,
|
|
192
|
+
]);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function useNativeCompanies({device, isLogged, peopleActions}) {
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
if (
|
|
198
|
+
device &&
|
|
199
|
+
device.id &&
|
|
200
|
+
isLogged
|
|
201
|
+
) {
|
|
202
|
+
peopleActions.myCompanies();
|
|
203
|
+
}
|
|
204
|
+
}, [isLogged, device?.id]);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function useNativeMenus({isLogged, currentCompany, actions, api, appType, normalizeRuntimeMenuResponse}) {
|
|
208
|
+
useEffect(() => {
|
|
209
|
+
if (!isLogged || !currentCompany?.id) {
|
|
210
|
+
actions.setMenus([]);
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
let cancelled = false;
|
|
215
|
+
|
|
216
|
+
api
|
|
217
|
+
.fetch('menus-people', {
|
|
218
|
+
params: {
|
|
219
|
+
myCompany: currentCompany.id,
|
|
220
|
+
appType,
|
|
221
|
+
menuType: 'home',
|
|
222
|
+
},
|
|
223
|
+
})
|
|
224
|
+
.then(result => {
|
|
225
|
+
if (!cancelled) {
|
|
226
|
+
actions.setMenus(normalizeRuntimeMenuResponse(result, {appType}));
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
.catch(() => {
|
|
230
|
+
if (!cancelled) {
|
|
231
|
+
actions.setMenus(normalizeRuntimeMenuResponse(null, {appType}));
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
return () => {
|
|
236
|
+
cancelled = true;
|
|
237
|
+
};
|
|
238
|
+
}, [actions, appType, currentCompany?.id, isLogged]);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function useNativeThemeFetch({api, parseThemeCss, setBaseThemeColors, actions, device, currentCompany, mainCompany}) {
|
|
242
|
+
useEffect(() => {
|
|
243
|
+
const fetchColors = async () => {
|
|
244
|
+
try {
|
|
245
|
+
const cssText = await api.fetch('themes-colors.css', {
|
|
246
|
+
responseType: 'text',
|
|
247
|
+
});
|
|
248
|
+
const parsedColors = parseThemeCss(cssText);
|
|
249
|
+
setBaseThemeColors(parsedColors);
|
|
250
|
+
actions.setColors(parsedColors);
|
|
251
|
+
} catch {
|
|
252
|
+
setBaseThemeColors({});
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
if (device?.id) {
|
|
257
|
+
fetchColors();
|
|
258
|
+
}
|
|
259
|
+
}, [actions, currentCompany?.id, mainCompany?.id, device?.id]);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function useNativeThemePalette({resolveDomainThemeColors, baseThemeColors, mainCompany, resolveThemePalette, runtimeColors, applyPaletteToRuntimeColors, applyThemeCssVariables, actions, currentCompany}) {
|
|
263
|
+
useEffect(() => {
|
|
264
|
+
const mergedThemeColors = resolveDomainThemeColors(baseThemeColors, mainCompany);
|
|
265
|
+
|
|
266
|
+
const palette = resolveThemePalette(mergedThemeColors, runtimeColors);
|
|
267
|
+
applyPaletteToRuntimeColors(palette, runtimeColors);
|
|
268
|
+
applyThemeCssVariables({
|
|
269
|
+
themeColors: mergedThemeColors,
|
|
270
|
+
palette,
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
actions.setColors(mergedThemeColors);
|
|
274
|
+
}, [actions, baseThemeColors, currentCompany?.id, currentCompany?.theme?.colors]);
|
|
275
|
+
}
|