@controleonline/ui-common 1.2.86 → 1.2.88
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/.github/workflows/integration-source-gate.yml +68 -0
- package/.github/workflows/manager-worker.yml +7 -156
- package/.github/workflows/publish-npm.yml +73 -27
- package/.github/workflows/pull-request-checks.yml +7 -5
- package/docs/technical/Device-Detail-Alias-UI-Sync.md +141 -0
- package/package.json +13 -8
- package/src/react/components/AddImportModal.js +61 -34
- package/src/react/components/BottomNavigationBar.js +178 -174
- package/src/react/components/BottomNavigationBar.styles.js +139 -118
- package/src/react/components/DefaultProvider.native.js +427 -421
- package/src/react/components/DefaultProvider.web.js +131 -125
- package/src/react/components/RemoteCheckoutService.js +3 -3
- package/src/react/components/RuntimeFooterMarqueeText.js +88 -36
- package/src/react/components/RuntimeInfoFooter.js +76 -43
- package/src/react/components/RuntimeInfoFooter.styles.js +22 -14
- package/src/react/config/deviceConfigBootstrap.js +3 -3
- package/src/react/pages/Devices/detail/DeviceDetailAlertsCommandsSection.js +4 -22
- package/src/react/pages/Devices/detail/DeviceDetailMovementSections.js +6 -2
- package/src/react/pages/Devices/detail/DeviceDetailOrdersPrintSection.js +4 -0
- package/src/react/pages/Devices/detail/DeviceDetailScreen.js +23 -338
- package/src/react/pages/Devices/detail/createDeviceDetailContext.js +20 -0
- package/src/react/pages/Devices/detail/useDeviceDetailActions.js +11 -36
- package/src/react/pages/Devices/detail/useDeviceDetailLoaders.js +129 -37
- package/src/react/pages/Devices/detail/useDeviceDetailSaves.js +11 -38
- package/src/react/pages/Devices/detail/useDeviceDetailStateA.js +9 -28
- package/src/react/pages/Imports.js +13 -11
- package/src/react/pages/IntegrationConfigFields.js +1 -0
- package/src/react/pages/IntegrationConfigPage.js +101 -45
- package/src/react/pages/IntegrationConfigPage.utils.js +21 -13
- package/src/react/pages/fetchPeopleConfigs.js +21 -0
- package/src/react/pages/integrationsCatalog.js +15 -110
- package/src/react/services/Cielo/Cielo.js +9 -9
- package/src/react/services/Getnet/Getnet.web.js +25 -0
- package/src/react/utils/companyAuthority.js +36 -0
- package/src/react/utils/fileUrl.js +14 -5
- package/src/react/utils/paymentDevices.js +375 -270
- package/src/react/utils/printerDevices.js +2 -2
- package/src/react/utils/runtimeFooter.js +178 -224
- package/src/react/utils/runtimeFooterText.js +160 -0
- package/src/react/utils/runtimeLanguage.js +5 -5
- package/src/react/utils/runtimeZoom.js +29 -5
- package/src/react/utils/shopFranchises.js +167 -12
- package/src/react/utils/storeColumns.js +235 -217
- package/src/react/utils/systemErrorMessage.js +2 -1
- package/src/store/imports/customActions.js +42 -2
- package/src/store/integration/index.js +43 -0
- package/src/tests/browser/manager/device-detail-apply-config-defined.spec.js +31 -0
- package/src/tests/browser/manager/device-detail-composition.spec.js +295 -0
- package/src/tests/browser/manager/device-detail-copy-config.spec.js +11 -1
- package/src/tests/browser/manager/device-detail-pdv-current-company.spec.js +273 -0
- package/src/tests/browser/manager/runtime-footer-rotation.spec.js +397 -0
- package/src/tests/react/components/DefaultProviderAuthority.test.js +28 -0
- package/src/tests/react/components/RuntimeFooterMarqueeText.build.test.js +29 -0
- package/src/tests/react/config/deviceConfigBootstrap.test.js +24 -1
- package/src/tests/react/pages/applyCurrentDeviceConfig.test.js +85 -0
- package/src/tests/react/pages/deviceDetailComposition.test.js +65 -0
- package/src/tests/react/pages/deviceDetailHookDependencies.test.mjs +31 -0
- package/src/tests/react/pages/deviceDetailLoaderDependencies.test.mjs +28 -0
- package/src/tests/react/pages/receitaFederalIntegrationContract.test.mjs +27 -6
- package/src/tests/react/services/Cielo.test.js +2 -2
- package/src/tests/react/utils/companyAuthority.test.js +53 -0
- package/src/tests/react/utils/formatter.test.mjs +6 -0
- package/src/tests/react/utils/paymentDevices.test.js +72 -0
- package/src/tests/react/utils/runtimeFooter.test.js +35 -0
- package/src/tests/react/utils/runtimeFooterText.test.js +88 -0
- package/src/tests/react/utils/runtimeLanguage.test.js +4 -4
- package/src/tests/react/utils/runtimeZoom.test.js +20 -0
- package/src/tests/react/utils/shopFranchises.test.js +32 -13
- package/src/tests/react/utils/translate.test.mjs +6 -6
- package/src/utils/formatter.js +7 -3
- package/src/utils/translate.js +16 -16
- package/src/utils/translatePending.js +6 -6
- package/src/utils/translateStorage.js +2 -2
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
const {
|
|
2
|
+
DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY,
|
|
3
|
+
getRuntimeFooterRotationEntries,
|
|
4
|
+
getRuntimeFooterText,
|
|
5
|
+
getRuntimeFooterTextLines,
|
|
6
|
+
normalizeRuntimeFooterText,
|
|
7
|
+
parseJsonStringValue,
|
|
8
|
+
parseObjectValue,
|
|
9
|
+
safeTrim,
|
|
10
|
+
} = require('./runtimeFooterText');
|
|
11
|
+
|
|
12
|
+
const getDeviceTypeLabel = type => {
|
|
13
|
+
const normalizedType = String(type || '').trim().toUpperCase();
|
|
14
|
+
if (['PRINT', 'PRINTER'].includes(normalizedType)) return 'Impressora';
|
|
15
|
+
if (normalizedType === 'IP_CAMERA') return 'Camera IP';
|
|
16
|
+
return normalizedType || 'DEVICE';
|
|
17
|
+
};
|
|
18
|
+
|
|
2
19
|
|
|
3
|
-
const DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY = 'device-runtime-footer-text';
|
|
4
20
|
const RUNTIME_FOOTER_HIDDEN_ROUTES = new Set(['PaylistPage']);
|
|
5
21
|
|
|
6
22
|
const shouldShowRuntimeFooter = currentRouteName =>
|
|
7
23
|
!RUNTIME_FOOTER_HIDDEN_ROUTES.has(String(currentRouteName || '').trim());
|
|
8
24
|
|
|
9
|
-
const safeTrim = value => String(value || '').trim();
|
|
10
|
-
|
|
11
25
|
const POS_OPERATION_MODE_TRANSLATION_KEYS = {
|
|
12
26
|
counter: 'counterService',
|
|
13
27
|
waiter: 'waiterService',
|
|
@@ -69,69 +83,9 @@ const buildRuntimeFooterDisplayName = ({
|
|
|
69
83
|
|
|
70
84
|
return parts.join(' • ');
|
|
71
85
|
};
|
|
72
|
-
|
|
73
|
-
const parseJsonStringValue = value => {
|
|
74
|
-
try {
|
|
75
|
-
return JSON.parse(value);
|
|
76
|
-
} catch {
|
|
77
|
-
return value;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const parseObjectValue = value => {
|
|
82
|
-
if (!value) {
|
|
83
|
-
return {};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (typeof value === 'string') {
|
|
87
|
-
const parsed = parseJsonStringValue(value);
|
|
88
|
-
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return typeof value === 'object' ? value : {};
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const parseDeviceMetadata = metadata => parseObjectValue(metadata);
|
|
95
|
-
const parseDeviceConfigs = configs => parseObjectValue(configs);
|
|
96
|
-
|
|
97
|
-
const normalizeRuntimeFooterText = value => {
|
|
98
|
-
if (value === null || value === undefined) {
|
|
99
|
-
return '';
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const parsedValue =
|
|
103
|
-
typeof value === 'string' ? parseJsonStringValue(value) : value;
|
|
104
|
-
|
|
105
|
-
if (parsedValue && typeof parsedValue === 'object') {
|
|
106
|
-
return '';
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return safeTrim(String(parsedValue).replace(/\r\n?/g, '\n'))
|
|
110
|
-
.split('\n')
|
|
111
|
-
.map(line => safeTrim(line).replace(/\s+/g, ' '))
|
|
112
|
-
.filter(Boolean)
|
|
113
|
-
.join('\n');
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const getRuntimeFooterText = company =>
|
|
117
|
-
normalizeRuntimeFooterText(
|
|
118
|
-
company?.configs?.[DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY],
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
const getRuntimeFooterTextLines = value => {
|
|
122
|
-
const normalizedText =
|
|
123
|
-
typeof value === 'string'
|
|
124
|
-
? normalizeRuntimeFooterText(value)
|
|
125
|
-
: getRuntimeFooterText(value);
|
|
126
|
-
|
|
127
|
-
return normalizedText ? normalizedText.split('\n').filter(Boolean) : [];
|
|
128
|
-
};
|
|
129
86
|
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
Boolean,
|
|
133
|
-
);
|
|
134
|
-
|
|
87
|
+
const parseDeviceMetadata = metadata => parseObjectValue(metadata);
|
|
88
|
+
const parseDeviceConfigs = configs => parseObjectValue(configs);
|
|
135
89
|
const isWebRuntimeDevice = device => {
|
|
136
90
|
const metadata = parseDeviceMetadata(device?.metadata);
|
|
137
91
|
const runtime = safeTrim(metadata?.runtime).toLowerCase();
|
|
@@ -150,77 +104,77 @@ const isWebRuntimeDevice = device => {
|
|
|
150
104
|
identifier.startsWith('web-')
|
|
151
105
|
);
|
|
152
106
|
};
|
|
153
|
-
|
|
154
|
-
const getRuntimeFooterDeviceName = device => {
|
|
155
|
-
if (isWebRuntimeDevice(device)) {
|
|
156
|
-
return 'web';
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const metadata = parseDeviceMetadata(device?.metadata);
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
safeTrim(device?.alias) ||
|
|
163
|
-
safeTrim(device?.name) ||
|
|
164
|
-
safeTrim(metadata?.system?.name) ||
|
|
165
|
-
safeTrim(metadata?.system?.model) ||
|
|
166
|
-
safeTrim(device?.appName) ||
|
|
167
|
-
safeTrim(device?.deviceType) ||
|
|
168
|
-
safeTrim(device?.id)
|
|
169
|
-
);
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
const formatRuntimeFooterVersion = version => {
|
|
173
|
-
const normalizedVersion = safeTrim(version).replace(/^v/i, '');
|
|
174
|
-
return normalizedVersion ? `v${normalizedVersion}` : '';
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const getRuntimeFooterWebHost = () => {
|
|
178
|
-
const hostname = safeTrim(globalThis?.location?.hostname);
|
|
179
|
-
|
|
180
|
-
if (!hostname) {
|
|
181
|
-
return '';
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (['localhost', '::1', '[::1]'].includes(hostname)) {
|
|
185
|
-
return '127.0.0.1';
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return hostname;
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
const getRuntimeFooterWebIdentifierCandidates = ({device, deviceConfig}) => {
|
|
192
|
-
const deviceMetadata = parseDeviceMetadata(device?.metadata);
|
|
193
|
-
const storedDeviceMetadata = parseDeviceMetadata(deviceConfig?.device?.metadata);
|
|
194
|
-
const candidates = [
|
|
195
|
-
{
|
|
196
|
-
value: safeTrim(storedDeviceMetadata?.network?.publicIp),
|
|
197
|
-
source: 'device_config.device.metadata.network.publicIp',
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
value: safeTrim(deviceMetadata?.network?.publicIp),
|
|
201
|
-
source: 'device.metadata.network.publicIp',
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
value: safeTrim(device?.externalIp),
|
|
205
|
-
source: 'device.externalIp',
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
value: getRuntimeFooterWebHost(),
|
|
209
|
-
source: 'location.hostname',
|
|
210
|
-
},
|
|
211
|
-
];
|
|
212
|
-
const seenValues = new Set();
|
|
213
|
-
|
|
214
|
-
return candidates.filter(candidate => {
|
|
215
|
-
if (!candidate.value || seenValues.has(candidate.value)) {
|
|
216
|
-
return false;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
seenValues.add(candidate.value);
|
|
220
|
-
return true;
|
|
221
|
-
});
|
|
222
|
-
};
|
|
223
|
-
|
|
107
|
+
|
|
108
|
+
const getRuntimeFooterDeviceName = device => {
|
|
109
|
+
if (isWebRuntimeDevice(device)) {
|
|
110
|
+
return 'web';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const metadata = parseDeviceMetadata(device?.metadata);
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
safeTrim(device?.alias) ||
|
|
117
|
+
safeTrim(device?.name) ||
|
|
118
|
+
safeTrim(metadata?.system?.name) ||
|
|
119
|
+
safeTrim(metadata?.system?.model) ||
|
|
120
|
+
safeTrim(device?.appName) ||
|
|
121
|
+
safeTrim(device?.deviceType) ||
|
|
122
|
+
safeTrim(device?.id)
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const formatRuntimeFooterVersion = version => {
|
|
127
|
+
const normalizedVersion = safeTrim(version).replace(/^v/i, '');
|
|
128
|
+
return normalizedVersion ? `v${normalizedVersion}` : '';
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const getRuntimeFooterWebHost = () => {
|
|
132
|
+
const hostname = safeTrim(globalThis?.location?.hostname);
|
|
133
|
+
|
|
134
|
+
if (!hostname) {
|
|
135
|
+
return '';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (['localhost', '::1', '[::1]'].includes(hostname)) {
|
|
139
|
+
return '127.0.0.1';
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return hostname;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const getRuntimeFooterWebIdentifierCandidates = ({device, deviceConfig}) => {
|
|
146
|
+
const deviceMetadata = parseDeviceMetadata(device?.metadata);
|
|
147
|
+
const storedDeviceMetadata = parseDeviceMetadata(deviceConfig?.device?.metadata);
|
|
148
|
+
const candidates = [
|
|
149
|
+
{
|
|
150
|
+
value: safeTrim(storedDeviceMetadata?.network?.publicIp),
|
|
151
|
+
source: 'device_config.device.metadata.network.publicIp',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
value: safeTrim(deviceMetadata?.network?.publicIp),
|
|
155
|
+
source: 'device.metadata.network.publicIp',
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
value: safeTrim(device?.externalIp),
|
|
159
|
+
source: 'device.externalIp',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
value: getRuntimeFooterWebHost(),
|
|
163
|
+
source: 'location.hostname',
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
const seenValues = new Set();
|
|
167
|
+
|
|
168
|
+
return candidates.filter(candidate => {
|
|
169
|
+
if (!candidate.value || seenValues.has(candidate.value)) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
seenValues.add(candidate.value);
|
|
174
|
+
return true;
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
|
|
224
178
|
const getRuntimeFooterStoredVersion = deviceConfig => {
|
|
225
179
|
const configs = parseDeviceConfigs(deviceConfig?.configs);
|
|
226
180
|
return formatRuntimeFooterVersion(configs?.['config-version']);
|
|
@@ -304,74 +258,74 @@ const getRuntimeFooterOperationalSummary = ({device, deviceConfig} = {}) => {
|
|
|
304
258
|
|
|
305
259
|
const getRuntimeFooterVersionCandidates = ({device, appVersion, deviceConfig}) => {
|
|
306
260
|
const deviceMetadata = parseDeviceMetadata(device?.metadata);
|
|
307
|
-
const storedDeviceMetadata = parseDeviceMetadata(deviceConfig?.device?.metadata);
|
|
308
|
-
const configs = parseDeviceConfigs(deviceConfig?.configs);
|
|
309
|
-
const candidates = [
|
|
310
|
-
{
|
|
311
|
-
label: formatRuntimeFooterVersion(storedDeviceMetadata?.app?.version),
|
|
312
|
-
rawValue: safeTrim(storedDeviceMetadata?.app?.version),
|
|
313
|
-
source: 'device_config.device.metadata.app.version',
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
label: formatRuntimeFooterVersion(deviceMetadata?.app?.version),
|
|
317
|
-
rawValue: safeTrim(deviceMetadata?.app?.version),
|
|
318
|
-
source: 'device.metadata.app.version',
|
|
319
|
-
},
|
|
320
|
-
{
|
|
321
|
-
label: formatRuntimeFooterVersion(device?.appVersion),
|
|
322
|
-
rawValue: safeTrim(device?.appVersion),
|
|
323
|
-
source: 'device.appVersion',
|
|
324
|
-
},
|
|
325
|
-
{
|
|
326
|
-
label: formatRuntimeFooterVersion(appVersion),
|
|
327
|
-
rawValue: safeTrim(appVersion),
|
|
328
|
-
source: 'appVersion',
|
|
329
|
-
},
|
|
330
|
-
{
|
|
331
|
-
label: formatRuntimeFooterVersion(configs?.['config-version']),
|
|
332
|
-
rawValue: safeTrim(configs?.['config-version']),
|
|
333
|
-
source: 'device_config.configs.config-version',
|
|
334
|
-
},
|
|
335
|
-
];
|
|
336
|
-
const seenLabels = new Set();
|
|
337
|
-
|
|
338
|
-
return candidates.filter(candidate => {
|
|
339
|
-
if (!candidate.label || seenLabels.has(candidate.label)) {
|
|
340
|
-
return false;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
seenLabels.add(candidate.label);
|
|
344
|
-
return true;
|
|
345
|
-
});
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
const getRuntimeFooterNativeIdentifierCandidates = ({device, deviceConfig}) => {
|
|
349
|
-
const candidates = [
|
|
350
|
-
{
|
|
351
|
-
value: safeTrim(deviceConfig?.device?.device),
|
|
352
|
-
source: 'device_config.device.device',
|
|
353
|
-
},
|
|
354
|
-
{
|
|
355
|
-
value: safeTrim(device?.id),
|
|
356
|
-
source: 'device.id',
|
|
357
|
-
},
|
|
358
|
-
{
|
|
359
|
-
value: safeTrim(deviceConfig?.device?.id),
|
|
360
|
-
source: 'device_config.device.id',
|
|
361
|
-
},
|
|
362
|
-
];
|
|
363
|
-
const seenValues = new Set();
|
|
364
|
-
|
|
365
|
-
return candidates.filter(candidate => {
|
|
366
|
-
if (!candidate.value || seenValues.has(candidate.value)) {
|
|
367
|
-
return false;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
seenValues.add(candidate.value);
|
|
371
|
-
return true;
|
|
372
|
-
});
|
|
373
|
-
};
|
|
374
|
-
|
|
261
|
+
const storedDeviceMetadata = parseDeviceMetadata(deviceConfig?.device?.metadata);
|
|
262
|
+
const configs = parseDeviceConfigs(deviceConfig?.configs);
|
|
263
|
+
const candidates = [
|
|
264
|
+
{
|
|
265
|
+
label: formatRuntimeFooterVersion(storedDeviceMetadata?.app?.version),
|
|
266
|
+
rawValue: safeTrim(storedDeviceMetadata?.app?.version),
|
|
267
|
+
source: 'device_config.device.metadata.app.version',
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
label: formatRuntimeFooterVersion(deviceMetadata?.app?.version),
|
|
271
|
+
rawValue: safeTrim(deviceMetadata?.app?.version),
|
|
272
|
+
source: 'device.metadata.app.version',
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
label: formatRuntimeFooterVersion(device?.appVersion),
|
|
276
|
+
rawValue: safeTrim(device?.appVersion),
|
|
277
|
+
source: 'device.appVersion',
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
label: formatRuntimeFooterVersion(appVersion),
|
|
281
|
+
rawValue: safeTrim(appVersion),
|
|
282
|
+
source: 'appVersion',
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
label: formatRuntimeFooterVersion(configs?.['config-version']),
|
|
286
|
+
rawValue: safeTrim(configs?.['config-version']),
|
|
287
|
+
source: 'device_config.configs.config-version',
|
|
288
|
+
},
|
|
289
|
+
];
|
|
290
|
+
const seenLabels = new Set();
|
|
291
|
+
|
|
292
|
+
return candidates.filter(candidate => {
|
|
293
|
+
if (!candidate.label || seenLabels.has(candidate.label)) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
seenLabels.add(candidate.label);
|
|
298
|
+
return true;
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
const getRuntimeFooterNativeIdentifierCandidates = ({device, deviceConfig}) => {
|
|
303
|
+
const candidates = [
|
|
304
|
+
{
|
|
305
|
+
value: safeTrim(deviceConfig?.device?.device),
|
|
306
|
+
source: 'device_config.device.device',
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
value: safeTrim(device?.id),
|
|
310
|
+
source: 'device.id',
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
value: safeTrim(deviceConfig?.device?.id),
|
|
314
|
+
source: 'device_config.device.id',
|
|
315
|
+
},
|
|
316
|
+
];
|
|
317
|
+
const seenValues = new Set();
|
|
318
|
+
|
|
319
|
+
return candidates.filter(candidate => {
|
|
320
|
+
if (!candidate.value || seenValues.has(candidate.value)) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
seenValues.add(candidate.value);
|
|
325
|
+
return true;
|
|
326
|
+
});
|
|
327
|
+
};
|
|
328
|
+
|
|
375
329
|
const getRuntimeFooterDebugInfo = ({device, appVersion, deviceConfig}) => {
|
|
376
330
|
const deviceName = getRuntimeFooterDeviceName(device);
|
|
377
331
|
const versionCandidates = getRuntimeFooterVersionCandidates({
|
|
@@ -400,8 +354,8 @@ const getRuntimeFooterDebugInfo = ({device, appVersion, deviceConfig}) => {
|
|
|
400
354
|
? getRuntimeFooterWebIdentifierCandidates({
|
|
401
355
|
device,
|
|
402
356
|
deviceConfig,
|
|
403
|
-
})
|
|
404
|
-
: [];
|
|
357
|
+
})
|
|
358
|
+
: [];
|
|
405
359
|
const webIdentifier = webIdentifierCandidates[0]?.value || '';
|
|
406
360
|
const nativeIdentifierCandidates = getRuntimeFooterNativeIdentifierCandidates({
|
|
407
361
|
device,
|
|
@@ -442,8 +396,8 @@ const getRuntimeFooterDebugInfo = ({device, appVersion, deviceConfig}) => {
|
|
|
442
396
|
versionCandidates,
|
|
443
397
|
webIdentifierCandidates,
|
|
444
398
|
nativeIdentifierCandidates,
|
|
445
|
-
rawValues: {
|
|
446
|
-
appVersionProp: safeTrim(appVersion),
|
|
399
|
+
rawValues: {
|
|
400
|
+
appVersionProp: safeTrim(appVersion),
|
|
447
401
|
deviceId: safeTrim(device?.id),
|
|
448
402
|
deviceType: safeTrim(device?.type),
|
|
449
403
|
deviceExternalIp: safeTrim(device?.externalIp),
|
|
@@ -451,9 +405,9 @@ const getRuntimeFooterDebugInfo = ({device, appVersion, deviceConfig}) => {
|
|
|
451
405
|
deviceMetadataAppVersion: safeTrim(
|
|
452
406
|
parseDeviceMetadata(device?.metadata)?.app?.version,
|
|
453
407
|
),
|
|
454
|
-
deviceMetadataPublicIp: safeTrim(
|
|
455
|
-
parseDeviceMetadata(device?.metadata)?.network?.publicIp,
|
|
456
|
-
),
|
|
408
|
+
deviceMetadataPublicIp: safeTrim(
|
|
409
|
+
parseDeviceMetadata(device?.metadata)?.network?.publicIp,
|
|
410
|
+
),
|
|
457
411
|
storedDeviceRecordId: safeTrim(deviceConfig?.device?.id),
|
|
458
412
|
storedDeviceType: safeTrim(deviceConfig?.device?.type),
|
|
459
413
|
storedDeviceIdentifier: safeTrim(deviceConfig?.device?.device),
|
|
@@ -475,16 +429,16 @@ const getRuntimeFooterDebugInfo = ({device, appVersion, deviceConfig}) => {
|
|
|
475
429
|
},
|
|
476
430
|
};
|
|
477
431
|
};
|
|
478
|
-
|
|
479
|
-
const getRuntimeFooterPrimaryText = params =>
|
|
480
|
-
getRuntimeFooterDebugInfo(params).primaryText;
|
|
481
|
-
|
|
482
|
-
module.exports = {
|
|
483
|
-
DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY,
|
|
484
|
-
formatRuntimeFooterVersion,
|
|
485
|
-
getRuntimeFooterDebugInfo,
|
|
486
|
-
getRuntimeFooterDeviceName,
|
|
487
|
-
getRuntimeFooterNativeIdentifierCandidates,
|
|
432
|
+
|
|
433
|
+
const getRuntimeFooterPrimaryText = params =>
|
|
434
|
+
getRuntimeFooterDebugInfo(params).primaryText;
|
|
435
|
+
|
|
436
|
+
module.exports = {
|
|
437
|
+
DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY,
|
|
438
|
+
formatRuntimeFooterVersion,
|
|
439
|
+
getRuntimeFooterDebugInfo,
|
|
440
|
+
getRuntimeFooterDeviceName,
|
|
441
|
+
getRuntimeFooterNativeIdentifierCandidates,
|
|
488
442
|
getRuntimeFooterPrimaryText,
|
|
489
443
|
getRuntimeFooterRotationEntries,
|
|
490
444
|
getRuntimeFooterStoredVersion,
|
|
@@ -492,7 +446,7 @@ module.exports = {
|
|
|
492
446
|
getRuntimeFooterVersionCandidates,
|
|
493
447
|
getRuntimeFooterWebIdentifierCandidates,
|
|
494
448
|
getRuntimeFooterText,
|
|
495
|
-
getRuntimeFooterWebHost,
|
|
449
|
+
getRuntimeFooterWebHost,
|
|
496
450
|
normalizeRuntimeFooterText,
|
|
497
451
|
shouldShowRuntimeFooter,
|
|
498
|
-
};
|
|
452
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
const DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY = 'device-runtime-footer-text';
|
|
2
|
+
|
|
3
|
+
const safeTrim = value => String(value || '').trim();
|
|
4
|
+
|
|
5
|
+
const parseJsonStringValue = value => {
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(value);
|
|
8
|
+
} catch {
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const parseObjectValue = value => {
|
|
14
|
+
if (!value) {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
if (typeof value === 'string') {
|
|
18
|
+
const parsed = parseJsonStringValue(value);
|
|
19
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
20
|
+
}
|
|
21
|
+
return typeof value === 'object' ? value : {};
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const unwrapConfigScalar = value => {
|
|
25
|
+
if (value === null || value === undefined) {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let current = value;
|
|
30
|
+
for (let i = 0; i < 3; i += 1) {
|
|
31
|
+
if (typeof current === 'string') {
|
|
32
|
+
const trimmed = current.trim();
|
|
33
|
+
if (
|
|
34
|
+
(trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
35
|
+
(trimmed.startsWith('{') && trimmed.endsWith('}')) ||
|
|
36
|
+
(trimmed.startsWith('[') && trimmed.endsWith(']'))
|
|
37
|
+
) {
|
|
38
|
+
const parsed = parseJsonStringValue(trimmed);
|
|
39
|
+
if (parsed !== trimmed) {
|
|
40
|
+
current = parsed;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return current;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (current && typeof current === 'object' && !Array.isArray(current)) {
|
|
48
|
+
if (current.configValue !== undefined) {
|
|
49
|
+
current = current.configValue;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (current.value !== undefined) {
|
|
53
|
+
current = current.value;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (current.config_value !== undefined) {
|
|
57
|
+
current = current.config_value;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return current;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const normalizeRuntimeFooterText = value => {
|
|
69
|
+
if (value === null || value === undefined) {
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const scalar = unwrapConfigScalar(value);
|
|
74
|
+
if (scalar === null || scalar === undefined) {
|
|
75
|
+
return '';
|
|
76
|
+
}
|
|
77
|
+
if (typeof scalar === 'object') {
|
|
78
|
+
return '';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return safeTrim(String(scalar).replace(/\r\n?/g, '\n'))
|
|
82
|
+
.split('\n')
|
|
83
|
+
.map(line => safeTrim(line).replace(/\s+/g, ' '))
|
|
84
|
+
.filter(Boolean)
|
|
85
|
+
.join('\n');
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const resolveConfigValue = configs => {
|
|
89
|
+
if (configs == null) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (Array.isArray(configs)) {
|
|
94
|
+
const hit = configs.find(
|
|
95
|
+
e =>
|
|
96
|
+
safeTrim(e?.configKey || e?.key || e?.name || e?.config_key) ===
|
|
97
|
+
DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY,
|
|
98
|
+
);
|
|
99
|
+
return hit?.value ?? hit?.configValue ?? hit?.config_value;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const parsed = parseObjectValue(configs);
|
|
103
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const direct = parsed[DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY];
|
|
108
|
+
if (direct !== undefined && direct !== null && direct !== '') {
|
|
109
|
+
return direct;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Some stores nest Config entities under arbitrary keys
|
|
113
|
+
for (const value of Object.values(parsed)) {
|
|
114
|
+
if (!value || typeof value !== 'object') {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const key = safeTrim(
|
|
118
|
+
value.configKey || value.key || value.name || value.config_key,
|
|
119
|
+
);
|
|
120
|
+
if (key === DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY) {
|
|
121
|
+
return value.value ?? value.configValue ?? value.config_value;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return undefined;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const getRuntimeFooterText = (company, extraConfigs) => {
|
|
129
|
+
for (const configs of [company?.configs, extraConfigs]) {
|
|
130
|
+
const normalized = normalizeRuntimeFooterText(resolveConfigValue(configs));
|
|
131
|
+
if (normalized) {
|
|
132
|
+
return normalized;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return '';
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const getRuntimeFooterTextLines = value => {
|
|
139
|
+
const normalizedText =
|
|
140
|
+
typeof value === 'string'
|
|
141
|
+
? normalizeRuntimeFooterText(value)
|
|
142
|
+
: getRuntimeFooterText(value);
|
|
143
|
+
return normalizedText ? normalizedText.split('\n').filter(Boolean) : [];
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const getRuntimeFooterRotationEntries = ({companyFooterText, primaryText}) =>
|
|
147
|
+
[...getRuntimeFooterTextLines(companyFooterText), safeTrim(primaryText)].filter(
|
|
148
|
+
Boolean,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
module.exports = {
|
|
152
|
+
DEVICE_RUNTIME_FOOTER_TEXT_CONFIG_KEY,
|
|
153
|
+
getRuntimeFooterRotationEntries,
|
|
154
|
+
getRuntimeFooterText,
|
|
155
|
+
getRuntimeFooterTextLines,
|
|
156
|
+
normalizeRuntimeFooterText,
|
|
157
|
+
parseObjectValue,
|
|
158
|
+
parseJsonStringValue,
|
|
159
|
+
safeTrim,
|
|
160
|
+
};
|
|
@@ -29,14 +29,14 @@ function resolveCompanyLanguageCode(company) {
|
|
|
29
29
|
|
|
30
30
|
function resolveConfiguredLanguage({
|
|
31
31
|
currentCompany,
|
|
32
|
-
|
|
32
|
+
mainCompany,
|
|
33
33
|
currentConfig,
|
|
34
34
|
sessionData,
|
|
35
35
|
fallback = 'pt-br',
|
|
36
36
|
} = {}) {
|
|
37
37
|
return (
|
|
38
38
|
resolveCompanyLanguageCode(currentCompany) ||
|
|
39
|
-
resolveCompanyLanguageCode(
|
|
39
|
+
resolveCompanyLanguageCode(mainCompany) ||
|
|
40
40
|
normalizeLanguageCode(currentConfig?.language) ||
|
|
41
41
|
normalizeLanguageCode(sessionData?.language) ||
|
|
42
42
|
fallback
|
|
@@ -46,11 +46,11 @@ function resolveConfiguredLanguage({
|
|
|
46
46
|
function buildTranslationBootstrapKey({
|
|
47
47
|
language,
|
|
48
48
|
currentCompanyId,
|
|
49
|
-
|
|
49
|
+
mainCompanyId,
|
|
50
50
|
} = {}) {
|
|
51
51
|
const normalizedLanguage = normalizeLanguageCode(language)
|
|
52
52
|
const normalizedCurrentCompanyId = String(currentCompanyId || '').trim()
|
|
53
|
-
const
|
|
53
|
+
const normalizedMainCompanyId = String(mainCompanyId || '').trim()
|
|
54
54
|
|
|
55
55
|
if (!normalizedLanguage || !normalizedCurrentCompanyId) {
|
|
56
56
|
return ''
|
|
@@ -59,7 +59,7 @@ function buildTranslationBootstrapKey({
|
|
|
59
59
|
return [
|
|
60
60
|
normalizedLanguage,
|
|
61
61
|
normalizedCurrentCompanyId,
|
|
62
|
-
|
|
62
|
+
normalizedMainCompanyId,
|
|
63
63
|
].join('::')
|
|
64
64
|
}
|
|
65
65
|
|