@controleonline/ui-common 1.2.87 → 1.2.89

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 (77) hide show
  1. package/.github/workflows/integration-source-gate.yml +68 -0
  2. package/.github/workflows/manager-worker.yml +7 -156
  3. package/.github/workflows/publish-npm.yml +73 -27
  4. package/.github/workflows/pull-request-checks.yml +7 -5
  5. package/docs/technical/Device-Detail-Alias-UI-Sync.md +141 -0
  6. package/package.json +13 -8
  7. package/src/api/localDB.js +86 -131
  8. package/src/react/components/BottomNavigationBar.js +178 -174
  9. package/src/react/components/BottomNavigationBar.styles.js +139 -118
  10. package/src/react/components/DefaultProvider.native.js +427 -421
  11. package/src/react/components/DefaultProvider.web.js +131 -125
  12. package/src/react/components/RemoteCheckoutService.js +3 -3
  13. package/src/react/components/RuntimeFooterMarqueeText.js +88 -36
  14. package/src/react/components/RuntimeInfoFooter.js +76 -43
  15. package/src/react/components/RuntimeInfoFooter.styles.js +22 -14
  16. package/src/react/config/deviceConfigBootstrap.js +71 -233
  17. package/src/react/config/deviceConfigValues.js +238 -0
  18. package/src/react/pages/Devices/detail/DeviceChargePermissionSection.js +32 -0
  19. package/src/react/pages/Devices/detail/DeviceDetailAlertsCommandsSection.js +4 -22
  20. package/src/react/pages/Devices/detail/DeviceDetailMovementSections.js +6 -2
  21. package/src/react/pages/Devices/detail/DeviceDetailOrdersPrintSection.js +4 -0
  22. package/src/react/pages/Devices/detail/DeviceDetailPdvConfigSection.js +7 -0
  23. package/src/react/pages/Devices/detail/DeviceDetailScreen.js +24 -335
  24. package/src/react/pages/Devices/detail/createDeviceDetailContext.js +20 -0
  25. package/src/react/pages/Devices/detail/deviceDetailHelpers.js +2 -11
  26. package/src/react/pages/Devices/detail/useDeviceDetailActions.js +11 -36
  27. package/src/react/pages/Devices/detail/useDeviceDetailLoaders.js +129 -37
  28. package/src/react/pages/Devices/detail/useDeviceDetailSaves.js +11 -38
  29. package/src/react/pages/Devices/detail/useDeviceDetailStateA.js +9 -28
  30. package/src/react/pages/IntegrationConfigFields.js +1 -0
  31. package/src/react/pages/IntegrationConfigPage.js +101 -45
  32. package/src/react/pages/IntegrationConfigPage.utils.js +21 -13
  33. package/src/react/pages/fetchPeopleConfigs.js +21 -0
  34. package/src/react/pages/integrationsCatalog.js +15 -110
  35. package/src/react/services/Cielo/Cielo.js +9 -9
  36. package/src/react/services/Getnet/Getnet.web.js +25 -0
  37. package/src/react/utils/companyAuthority.js +36 -0
  38. package/src/react/utils/confirmAction.js +12 -0
  39. package/src/react/utils/fileUrl.js +14 -5
  40. package/src/react/utils/paymentDevices.js +375 -270
  41. package/src/react/utils/printerDevices.js +2 -2
  42. package/src/react/utils/runtimeFooter.js +178 -224
  43. package/src/react/utils/runtimeFooterText.js +160 -0
  44. package/src/react/utils/runtimeLanguage.js +5 -5
  45. package/src/react/utils/runtimeZoom.js +29 -5
  46. package/src/react/utils/shopFranchises.js +167 -12
  47. package/src/react/utils/storeColumns.js +235 -217
  48. package/src/react/utils/systemErrorMessage.js +2 -1
  49. package/src/store/integration/index.js +43 -0
  50. package/src/tests/browser/manager/device-detail-apply-config-defined.spec.js +31 -0
  51. package/src/tests/browser/manager/device-detail-composition.spec.js +295 -0
  52. package/src/tests/browser/manager/device-detail-copy-config.spec.js +11 -1
  53. package/src/tests/browser/manager/device-detail-pdv-current-company.spec.js +273 -0
  54. package/src/tests/browser/manager/runtime-footer-rotation.spec.js +397 -0
  55. package/src/tests/react/components/DefaultProviderAuthority.test.js +28 -0
  56. package/src/tests/react/components/RuntimeFooterMarqueeText.build.test.js +29 -0
  57. package/src/tests/react/config/deviceConfigBootstrap.test.js +24 -1
  58. package/src/tests/react/pages/DeviceChargePermissionSection.test.js +42 -0
  59. package/src/tests/react/pages/applyCurrentDeviceConfig.test.js +85 -0
  60. package/src/tests/react/pages/deviceDetailComposition.test.js +65 -0
  61. package/src/tests/react/pages/deviceDetailHookDependencies.test.mjs +31 -0
  62. package/src/tests/react/pages/deviceDetailLoaderDependencies.test.mjs +28 -0
  63. package/src/tests/react/pages/receitaFederalIntegrationContract.test.mjs +27 -6
  64. package/src/tests/react/services/Cielo.test.js +2 -2
  65. package/src/tests/react/utils/companyAuthority.test.js +53 -0
  66. package/src/tests/react/utils/formatter.test.mjs +6 -0
  67. package/src/tests/react/utils/paymentDevices.test.js +72 -0
  68. package/src/tests/react/utils/runtimeFooter.test.js +35 -0
  69. package/src/tests/react/utils/runtimeFooterText.test.js +88 -0
  70. package/src/tests/react/utils/runtimeLanguage.test.js +4 -4
  71. package/src/tests/react/utils/runtimeZoom.test.js +20 -0
  72. package/src/tests/react/utils/shopFranchises.test.js +32 -13
  73. package/src/tests/react/utils/translate.test.mjs +6 -6
  74. package/src/utils/formatter.js +7 -3
  75. package/src/utils/translate.js +16 -16
  76. package/src/utils/translatePending.js +6 -6
  77. package/src/utils/translateStorage.js +2 -2
@@ -1,13 +1,27 @@
1
- import { getDeviceTypeLabel } from '@controleonline/ui-common/src/react/utils/printerDevices';
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 getRuntimeFooterRotationEntries = ({companyFooterText, primaryText}) =>
131
- [...getRuntimeFooterTextLines(companyFooterText), safeTrim(primaryText)].filter(
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
- defaultCompany,
32
+ mainCompany,
33
33
  currentConfig,
34
34
  sessionData,
35
35
  fallback = 'pt-br',
36
36
  } = {}) {
37
37
  return (
38
38
  resolveCompanyLanguageCode(currentCompany) ||
39
- resolveCompanyLanguageCode(defaultCompany) ||
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
- defaultCompanyId,
49
+ mainCompanyId,
50
50
  } = {}) {
51
51
  const normalizedLanguage = normalizeLanguageCode(language)
52
52
  const normalizedCurrentCompanyId = String(currentCompanyId || '').trim()
53
- const normalizedDefaultCompanyId = String(defaultCompanyId || '').trim()
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
- normalizedDefaultCompanyId,
62
+ normalizedMainCompanyId,
63
63
  ].join('::')
64
64
  }
65
65