@controleonline/ui-common 1.2.99 → 1.2.100
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/homepage-1056.md +12 -0
- package/package.json +1 -1
- package/src/react/pages/IntegrationConfigPage.js +59 -13
- package/src/react/pages/IntegrationConfigPage.utils.js +17 -0
- package/src/react/pages/integrationsCatalog.js +71 -0
- package/src/tests/react/utils/runtimeFooter.test.js +189 -189
- package/src/utils/integrationConfigs.js +23 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Homepage ADMIN/MANAGER — app-community#1056
|
|
2
|
+
|
|
3
|
+
Soft appearance is opt-in for HomePage only. Existing menu routes/parameters, permissions, stores and translations are preserved. App-provided homepage colors and components are used only in this appearance. Default consumers retain their current behavior.
|
|
4
|
+
|
|
5
|
+
Source: https://github.com/ControleOnline/app-community/issues/1056
|
|
6
|
+
Local evidence: 40 homepage tests and 34 runtime footer/zoom tests passed. No production authorization.
|
|
7
|
+
|
|
8
|
+
## Web login translation bootstrap
|
|
9
|
+
|
|
10
|
+
Keep the navigation tree mounted while translations initialize. Hide the shell and disable pointer/accessibility interaction until the existing translation readiness contract succeeds. Unmounting navigation during login resets its route and repeatedly mounts/registers the bottom bar, causing React maximum update depth. No route, permission, translation source, theme or zoom changes. Native behavior is unchanged.
|
|
11
|
+
|
|
12
|
+
Regression evidence: app-community homepage bootstrapNavigation.test.js reproduced maximum update depth before the fix, then passed after it. 44 tests across 9 homepage suites passed. Runtime Dev reproduced the unfixed bug; new runtime verification is required after consuming ui-common 1.2.95.
|
package/package.json
CHANGED
|
@@ -14,6 +14,7 @@ import { fetchPeopleConfigs } from './fetchPeopleConfigs';
|
|
|
14
14
|
import IntegrationConfigFields from './IntegrationConfigFields';
|
|
15
15
|
import {
|
|
16
16
|
ROUTE_PROVIDER_MAP,
|
|
17
|
+
expandBundledConfig,
|
|
17
18
|
extractAuthorizationUrl,
|
|
18
19
|
formatApiError,
|
|
19
20
|
formatUberOAuthError,
|
|
@@ -112,6 +113,8 @@ export default function IntegrationConfigPage({ route, embedded = false, fiscalT
|
|
|
112
113
|
const allFieldKeysSig = useMemo(() => allFieldKeys.join('|'), [allFieldKeys]);
|
|
113
114
|
// Pure config providers (e.g. receita-federal) do not use marketplace/integrations.
|
|
114
115
|
const needsMarketplaceIntegration = Boolean(providerConfig?.oauthConnect);
|
|
116
|
+
const bundleKey = normalizeTextValue(providerConfig?.bundleKey);
|
|
117
|
+
const configVisibility = normalizeTextValue(providerConfig?.visibility) || 'public';
|
|
115
118
|
|
|
116
119
|
useEffect(() => {
|
|
117
120
|
setConfigValues({});
|
|
@@ -135,14 +138,28 @@ export default function IntegrationConfigPage({ route, embedded = false, fiscalT
|
|
|
135
138
|
}
|
|
136
139
|
if (showLoading) setLoading(true);
|
|
137
140
|
try {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
141
|
+
if (bundleKey) {
|
|
142
|
+
const configItems = await fetchPeopleConfigs({
|
|
143
|
+
peopleIri: providerIri,
|
|
144
|
+
configKeys: [bundleKey],
|
|
145
|
+
});
|
|
146
|
+
const bundled = configItems.find(
|
|
147
|
+
item => String(item?.configKey || '').trim() === bundleKey,
|
|
148
|
+
);
|
|
144
149
|
const mergeFields = allConfigFields.length ? allConfigFields : visibleFields;
|
|
145
|
-
setConfigValues(current =>
|
|
150
|
+
setConfigValues(current =>
|
|
151
|
+
expandBundledConfig(mergeFields, bundled?.configValue, current),
|
|
152
|
+
);
|
|
153
|
+
} else {
|
|
154
|
+
const keys = allFieldKeys.length
|
|
155
|
+
? allFieldKeys
|
|
156
|
+
: visibleFields.map(field => field.key).filter(Boolean);
|
|
157
|
+
|
|
158
|
+
if (keys.length) {
|
|
159
|
+
const configItems = await fetchPeopleConfigs({ peopleIri: providerIri, configKeys: keys });
|
|
160
|
+
const mergeFields = allConfigFields.length ? allConfigFields : visibleFields;
|
|
161
|
+
setConfigValues(current => mergeTabValues(mergeFields, configItems, current));
|
|
162
|
+
}
|
|
146
163
|
}
|
|
147
164
|
|
|
148
165
|
if (needsMarketplaceIntegration) {
|
|
@@ -170,6 +187,7 @@ export default function IntegrationConfigPage({ route, embedded = false, fiscalT
|
|
|
170
187
|
allConfigFields,
|
|
171
188
|
allFieldKeys,
|
|
172
189
|
allFieldKeysSig,
|
|
190
|
+
bundleKey,
|
|
173
191
|
needsMarketplaceIntegration,
|
|
174
192
|
providerConfig,
|
|
175
193
|
providerIri,
|
|
@@ -246,16 +264,44 @@ export default function IntegrationConfigPage({ route, embedded = false, fiscalT
|
|
|
246
264
|
showError('Nao foi possivel identificar a integracao selecionada.');
|
|
247
265
|
return;
|
|
248
266
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
267
|
+
|
|
268
|
+
let configs;
|
|
269
|
+
if (bundleKey) {
|
|
270
|
+
const payloadObject = {};
|
|
271
|
+
(visibleFields || []).forEach(field => {
|
|
272
|
+
payloadObject[field.key] = normalizeTextValue(configValues[field.key]);
|
|
273
|
+
});
|
|
274
|
+
configs = [
|
|
275
|
+
{
|
|
276
|
+
configKey: bundleKey,
|
|
277
|
+
configValue: toConfigRequestValue(payloadObject),
|
|
278
|
+
},
|
|
279
|
+
];
|
|
280
|
+
} else {
|
|
281
|
+
configs = visibleFields.map(field => ({
|
|
282
|
+
configKey: field.key,
|
|
283
|
+
configValue: toConfigRequestValue(normalizeTextValue(configValues[field.key])),
|
|
284
|
+
}));
|
|
285
|
+
}
|
|
286
|
+
|
|
253
287
|
try {
|
|
254
|
-
await persistConfigs({ configs, people: providerIri, module: 4, visibility:
|
|
288
|
+
await persistConfigs({ configs, people: providerIri, module: 4, visibility: configVisibility });
|
|
255
289
|
showSuccess(`${activeTabDef?.label || providerConfig.label} salvo com sucesso.`);
|
|
256
290
|
await loadPageData({ showLoading: false });
|
|
257
291
|
} catch (error) { showError(error?.message || 'Nao foi possivel salvar a integracao.'); }
|
|
258
|
-
}, [
|
|
292
|
+
}, [
|
|
293
|
+
activeTabDef,
|
|
294
|
+
bundleKey,
|
|
295
|
+
configValues,
|
|
296
|
+
configVisibility,
|
|
297
|
+
loadPageData,
|
|
298
|
+
persistConfigs,
|
|
299
|
+
providerConfig,
|
|
300
|
+
providerIri,
|
|
301
|
+
showError,
|
|
302
|
+
showSuccess,
|
|
303
|
+
visibleFields,
|
|
304
|
+
]);
|
|
259
305
|
|
|
260
306
|
if (!providerConfig) return <CenterState icon="alert-triangle" iconColor="#e67e22" title="Integracao indisponivel" text="A tela solicitada nao possui configuracao cadastrada." />;
|
|
261
307
|
if (!providerId) return <CenterState icon="building" iconColor="#94A3B8" title="Empresa nao identificada" text="Abra a ficha da empresa para gravar as configuracoes fiscais nela." />;
|
|
@@ -5,6 +5,7 @@ export const ROUTE_PROVIDER_MAP = {
|
|
|
5
5
|
AsaasIntegrationPage: 'asaas',
|
|
6
6
|
ClickSignIntegrationPage: 'clicksign',
|
|
7
7
|
ReceitaFederalIntegrationPage: 'receita-federal',
|
|
8
|
+
SemPararIntegrationPage: 'sem-parar',
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
export const routeNameToPath = routeName =>
|
|
@@ -53,6 +54,22 @@ export const mergeTabValues = (fields, source, current = {}) => {
|
|
|
53
54
|
return next;
|
|
54
55
|
};
|
|
55
56
|
|
|
57
|
+
/** Expand a single JSON config (bundleKey) into flat field values. */
|
|
58
|
+
export const expandBundledConfig = (fields, rawValue, current = {}) => {
|
|
59
|
+
let parsed = rawValue;
|
|
60
|
+
if (typeof rawValue === 'string') {
|
|
61
|
+
try {
|
|
62
|
+
parsed = JSON.parse(rawValue);
|
|
63
|
+
} catch {
|
|
64
|
+
parsed = {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
68
|
+
parsed = {};
|
|
69
|
+
}
|
|
70
|
+
return mergeTabValues(fields, parsed, current);
|
|
71
|
+
};
|
|
72
|
+
|
|
56
73
|
export const buildFieldValues = (providerConfig, source) =>
|
|
57
74
|
mergeTabValues(getConfigFields(providerConfig), source, {});
|
|
58
75
|
|
|
@@ -70,6 +70,16 @@ export const INTEGRATION_LIST = [
|
|
|
70
70
|
accent: '#166534',
|
|
71
71
|
icon: 'file-text',
|
|
72
72
|
},
|
|
73
|
+
{
|
|
74
|
+
key: 'sem-parar',
|
|
75
|
+
label: 'Sem Parar',
|
|
76
|
+
route: 'IntegrationConfigPage',
|
|
77
|
+
routeParams: {
|
|
78
|
+
providerKey: 'sem-parar',
|
|
79
|
+
},
|
|
80
|
+
accent: '#0EA5E9',
|
|
81
|
+
icon: 'truck',
|
|
82
|
+
},
|
|
73
83
|
];
|
|
74
84
|
|
|
75
85
|
export const INTEGRATION_CONFIGS = {
|
|
@@ -257,6 +267,67 @@ export const INTEGRATION_CONFIGS = {
|
|
|
257
267
|
],
|
|
258
268
|
fields: [],
|
|
259
269
|
},
|
|
270
|
+
|
|
271
|
+
'sem-parar': {
|
|
272
|
+
key: 'sem-parar',
|
|
273
|
+
label: 'Sem Parar',
|
|
274
|
+
accent: '#0EA5E9',
|
|
275
|
+
icon: 'truck',
|
|
276
|
+
description:
|
|
277
|
+
'Credenciais da empresa para emissao de vale-pedagio via Sem Parar.',
|
|
278
|
+
saveLabel: 'Salvar Sem Parar',
|
|
279
|
+
// Backend (api-platform-integration SemPararConfig) reads a single private JSON key.
|
|
280
|
+
bundleKey: 'SEM_PARAR',
|
|
281
|
+
visibility: 'private',
|
|
282
|
+
requiredKeys: ['ENABLED', 'CLIENT_ID', 'CLIENT_SECRET', 'USERNAME', 'PASSWORD'],
|
|
283
|
+
fields: [
|
|
284
|
+
{
|
|
285
|
+
key: 'ENABLED',
|
|
286
|
+
label: 'Ativo',
|
|
287
|
+
type: 'select',
|
|
288
|
+
options: [
|
|
289
|
+
{value: '1', label: 'Sim'},
|
|
290
|
+
{value: '0', label: 'Nao'},
|
|
291
|
+
],
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
key: 'ENVIRONMENT',
|
|
295
|
+
label: 'Ambiente',
|
|
296
|
+
type: 'select',
|
|
297
|
+
options: [
|
|
298
|
+
{value: 'sandbox', label: 'Sandbox'},
|
|
299
|
+
{value: 'production', label: 'Producao'},
|
|
300
|
+
],
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
key: 'CLIENT_ID',
|
|
304
|
+
label: 'Client ID',
|
|
305
|
+
placeholder: 'Client ID Sem Parar',
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
key: 'CLIENT_SECRET',
|
|
309
|
+
label: 'Client secret',
|
|
310
|
+
placeholder: 'Client secret Sem Parar',
|
|
311
|
+
secureTextEntry: true,
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
key: 'USERNAME',
|
|
315
|
+
label: 'Usuario',
|
|
316
|
+
placeholder: 'Usuario da API',
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
key: 'PASSWORD',
|
|
320
|
+
label: 'Senha',
|
|
321
|
+
placeholder: 'Senha da API',
|
|
322
|
+
secureTextEntry: true,
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
key: 'CONVENIADO',
|
|
326
|
+
label: 'Conveniado',
|
|
327
|
+
placeholder: 'Codigo do conveniado (se aplicavel)',
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
},
|
|
260
331
|
};
|
|
261
332
|
|
|
262
333
|
export const getIntegrationListItem = key =>
|
|
@@ -30,17 +30,17 @@ const setLocation = value => {
|
|
|
30
30
|
Object.defineProperty(globalThis, 'location', {
|
|
31
31
|
configurable: true,
|
|
32
32
|
enumerable: true,
|
|
33
|
-
writable: true,
|
|
34
|
-
value,
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const restoreLocation = () => {
|
|
39
|
-
if (originalLocationDescriptor) {
|
|
40
|
-
Object.defineProperty(globalThis, 'location', originalLocationDescriptor)
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
|
|
33
|
+
writable: true,
|
|
34
|
+
value,
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const restoreLocation = () => {
|
|
39
|
+
if (originalLocationDescriptor) {
|
|
40
|
+
Object.defineProperty(globalThis, 'location', originalLocationDescriptor)
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
44
|
delete globalThis.location
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -59,101 +59,101 @@ after(() => {
|
|
|
59
59
|
|
|
60
60
|
test('prefers the persisted public ip for web runtime devices', () => {
|
|
61
61
|
setLocation({hostname: '10.0.0.15'})
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
assert.equal(
|
|
65
|
-
getRuntimeFooterPrimaryText({
|
|
66
|
-
device: {
|
|
67
|
-
alias: 'app',
|
|
68
|
-
appVersion: '1.3.6',
|
|
69
|
-
deviceType: 'web',
|
|
70
|
-
id: 'web-12',
|
|
71
|
-
externalIp: '198.51.100.21',
|
|
72
|
-
metadata: {
|
|
73
|
-
network: {
|
|
74
|
-
publicIp: '198.51.100.21',
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
appVersion: '1.3.6',
|
|
79
|
-
deviceConfig: {
|
|
80
|
-
device: {
|
|
81
|
-
metadata: {
|
|
82
|
-
network: {
|
|
83
|
-
publicIp: '203.0.113.42',
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
configs: {
|
|
88
|
-
'config-version': '1.3.5',
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
}),
|
|
92
|
-
'web (203.0.113.42) / v1.3.6',
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
const debugInfo = getRuntimeFooterDebugInfo({
|
|
96
|
-
device: {
|
|
97
|
-
alias: 'app',
|
|
98
|
-
appVersion: '1.3.6',
|
|
99
|
-
deviceType: 'web',
|
|
100
|
-
id: 'web-12',
|
|
101
|
-
externalIp: '198.51.100.21',
|
|
102
|
-
metadata: {
|
|
103
|
-
network: {
|
|
104
|
-
publicIp: '198.51.100.21',
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
appVersion: '1.3.6',
|
|
109
|
-
deviceConfig: {
|
|
110
|
-
device: {
|
|
111
|
-
metadata: {
|
|
112
|
-
network: {
|
|
113
|
-
publicIp: '203.0.113.42',
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
configs: {
|
|
118
|
-
'config-version': '1.3.5',
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
assert.equal(debugInfo.runtimeDetailSource, 'device_config.device.metadata.network.publicIp')
|
|
124
|
-
assert.equal(debugInfo.rawValues.storedDeviceMetadataPublicIp, '203.0.113.42')
|
|
125
|
-
assert.equal(debugInfo.rawValues.deviceMetadataPublicIp, '198.51.100.21')
|
|
126
|
-
} finally {
|
|
127
|
-
restoreLocation()
|
|
128
|
-
}
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
test('normalizes localhost to the loopback address on web', () => {
|
|
132
|
-
setLocation({hostname: 'localhost'})
|
|
133
|
-
|
|
134
|
-
try {
|
|
135
|
-
assert.equal(getRuntimeFooterWebHost(), '127.0.0.1')
|
|
136
|
-
} finally {
|
|
137
|
-
restoreLocation()
|
|
138
|
-
}
|
|
139
|
-
})
|
|
140
|
-
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
assert.equal(
|
|
65
|
+
getRuntimeFooterPrimaryText({
|
|
66
|
+
device: {
|
|
67
|
+
alias: 'app',
|
|
68
|
+
appVersion: '1.3.6',
|
|
69
|
+
deviceType: 'web',
|
|
70
|
+
id: 'web-12',
|
|
71
|
+
externalIp: '198.51.100.21',
|
|
72
|
+
metadata: {
|
|
73
|
+
network: {
|
|
74
|
+
publicIp: '198.51.100.21',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
appVersion: '1.3.6',
|
|
79
|
+
deviceConfig: {
|
|
80
|
+
device: {
|
|
81
|
+
metadata: {
|
|
82
|
+
network: {
|
|
83
|
+
publicIp: '203.0.113.42',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
configs: {
|
|
88
|
+
'config-version': '1.3.5',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
'web (203.0.113.42) / v1.3.6',
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
const debugInfo = getRuntimeFooterDebugInfo({
|
|
96
|
+
device: {
|
|
97
|
+
alias: 'app',
|
|
98
|
+
appVersion: '1.3.6',
|
|
99
|
+
deviceType: 'web',
|
|
100
|
+
id: 'web-12',
|
|
101
|
+
externalIp: '198.51.100.21',
|
|
102
|
+
metadata: {
|
|
103
|
+
network: {
|
|
104
|
+
publicIp: '198.51.100.21',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
appVersion: '1.3.6',
|
|
109
|
+
deviceConfig: {
|
|
110
|
+
device: {
|
|
111
|
+
metadata: {
|
|
112
|
+
network: {
|
|
113
|
+
publicIp: '203.0.113.42',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
configs: {
|
|
118
|
+
'config-version': '1.3.5',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
assert.equal(debugInfo.runtimeDetailSource, 'device_config.device.metadata.network.publicIp')
|
|
124
|
+
assert.equal(debugInfo.rawValues.storedDeviceMetadataPublicIp, '203.0.113.42')
|
|
125
|
+
assert.equal(debugInfo.rawValues.deviceMetadataPublicIp, '198.51.100.21')
|
|
126
|
+
} finally {
|
|
127
|
+
restoreLocation()
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
test('normalizes localhost to the loopback address on web', () => {
|
|
132
|
+
setLocation({hostname: 'localhost'})
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
assert.equal(getRuntimeFooterWebHost(), '127.0.0.1')
|
|
136
|
+
} finally {
|
|
137
|
+
restoreLocation()
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
|
|
141
141
|
test('falls back to the browser hostname for web when no persisted public ip exists', () => {
|
|
142
142
|
setLocation({hostname: 'localhost'})
|
|
143
|
-
|
|
144
|
-
try {
|
|
145
|
-
const candidates = getRuntimeFooterWebIdentifierCandidates({
|
|
146
|
-
device: {
|
|
147
|
-
deviceType: 'web',
|
|
148
|
-
id: 'web-12',
|
|
149
|
-
},
|
|
150
|
-
deviceConfig: {},
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
assert.equal(candidates[0]?.value, '127.0.0.1')
|
|
154
|
-
assert.equal(candidates[0]?.source, 'location.hostname')
|
|
155
|
-
} finally {
|
|
156
|
-
restoreLocation()
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
const candidates = getRuntimeFooterWebIdentifierCandidates({
|
|
146
|
+
device: {
|
|
147
|
+
deviceType: 'web',
|
|
148
|
+
id: 'web-12',
|
|
149
|
+
},
|
|
150
|
+
deviceConfig: {},
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
assert.equal(candidates[0]?.value, '127.0.0.1')
|
|
154
|
+
assert.equal(candidates[0]?.source, 'location.hostname')
|
|
155
|
+
} finally {
|
|
156
|
+
restoreLocation()
|
|
157
157
|
}
|
|
158
158
|
})
|
|
159
159
|
|
|
@@ -191,91 +191,91 @@ test('recognizes backend web devices by their persisted runtime metadata or devi
|
|
|
191
191
|
|
|
192
192
|
test('reads the persisted config-version for non-web runtimes', () => {
|
|
193
193
|
assert.equal(
|
|
194
|
-
getRuntimeFooterStoredVersion({
|
|
195
|
-
configs: JSON.stringify({
|
|
196
|
-
'config-version': '1.3.5',
|
|
197
|
-
}),
|
|
198
|
-
}),
|
|
199
|
-
'v1.3.5',
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
assert.equal(
|
|
203
|
-
getRuntimeFooterPrimaryText({
|
|
204
|
-
device: {
|
|
205
|
-
alias: 'PDV',
|
|
206
|
-
appVersion: '1.3.7',
|
|
207
|
-
deviceType: 'android',
|
|
208
|
-
id: 'native-12',
|
|
209
|
-
},
|
|
210
|
-
appVersion: '1.3.6',
|
|
211
|
-
deviceConfig: {
|
|
212
|
-
device: {
|
|
213
|
-
device: '229252771069b294',
|
|
214
|
-
},
|
|
215
|
-
configs: {
|
|
216
|
-
'config-version': '1.3.5',
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
}),
|
|
220
|
-
'PDV (229252771069b294) / v1.3.7',
|
|
221
|
-
)
|
|
222
|
-
})
|
|
223
|
-
|
|
194
|
+
getRuntimeFooterStoredVersion({
|
|
195
|
+
configs: JSON.stringify({
|
|
196
|
+
'config-version': '1.3.5',
|
|
197
|
+
}),
|
|
198
|
+
}),
|
|
199
|
+
'v1.3.5',
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
assert.equal(
|
|
203
|
+
getRuntimeFooterPrimaryText({
|
|
204
|
+
device: {
|
|
205
|
+
alias: 'PDV',
|
|
206
|
+
appVersion: '1.3.7',
|
|
207
|
+
deviceType: 'android',
|
|
208
|
+
id: 'native-12',
|
|
209
|
+
},
|
|
210
|
+
appVersion: '1.3.6',
|
|
211
|
+
deviceConfig: {
|
|
212
|
+
device: {
|
|
213
|
+
device: '229252771069b294',
|
|
214
|
+
},
|
|
215
|
+
configs: {
|
|
216
|
+
'config-version': '1.3.5',
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
}),
|
|
220
|
+
'PDV (229252771069b294) / v1.3.7',
|
|
221
|
+
)
|
|
222
|
+
})
|
|
223
|
+
|
|
224
224
|
test('prefers the backend device identifier used by the devices page', () => {
|
|
225
225
|
assert.equal(
|
|
226
226
|
getRuntimeFooterPrimaryText({
|
|
227
227
|
device: {
|
|
228
228
|
alias: 'PDV',
|
|
229
|
-
appVersion: '1.3.7',
|
|
230
|
-
deviceType: 'android',
|
|
231
|
-
id: 'd41ac8afb9f178eb',
|
|
232
|
-
},
|
|
233
|
-
appVersion: '1.3.6',
|
|
234
|
-
deviceConfig: {
|
|
235
|
-
device: {
|
|
236
|
-
device: '229252771069b294',
|
|
237
|
-
metadata: {
|
|
238
|
-
app: {
|
|
239
|
-
version: '1.3.7',
|
|
240
|
-
},
|
|
241
|
-
},
|
|
242
|
-
},
|
|
243
|
-
configs: {
|
|
244
|
-
'config-version': '1.3.7',
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
}),
|
|
248
|
-
'PDV (229252771069b294) / v1.3.7',
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
const debugInfo = getRuntimeFooterDebugInfo({
|
|
252
|
-
device: {
|
|
253
|
-
alias: 'PDV',
|
|
254
|
-
appVersion: '1.3.7',
|
|
255
|
-
deviceType: 'android',
|
|
256
|
-
id: 'd41ac8afb9f178eb',
|
|
257
|
-
},
|
|
258
|
-
appVersion: '1.3.6',
|
|
259
|
-
deviceConfig: {
|
|
260
|
-
device: {
|
|
261
|
-
device: '229252771069b294',
|
|
262
|
-
metadata: {
|
|
263
|
-
app: {
|
|
264
|
-
version: '1.3.7',
|
|
265
|
-
},
|
|
266
|
-
},
|
|
267
|
-
},
|
|
268
|
-
configs: {
|
|
269
|
-
'config-version': '1.3.7',
|
|
270
|
-
},
|
|
271
|
-
},
|
|
272
|
-
})
|
|
273
|
-
|
|
274
|
-
assert.equal(debugInfo.versionLabel, 'v1.3.7')
|
|
275
|
-
assert.equal(debugInfo.displayName, 'PDV (229252771069b294)')
|
|
276
|
-
assert.equal(debugInfo.runtimeDetail, '229252771069b294')
|
|
277
|
-
assert.equal(debugInfo.runtimeDetailSource, 'device_config.device.device')
|
|
278
|
-
assert.equal(debugInfo.versionCandidates[0]?.source, 'device_config.device.metadata.app.version')
|
|
229
|
+
appVersion: '1.3.7',
|
|
230
|
+
deviceType: 'android',
|
|
231
|
+
id: 'd41ac8afb9f178eb',
|
|
232
|
+
},
|
|
233
|
+
appVersion: '1.3.6',
|
|
234
|
+
deviceConfig: {
|
|
235
|
+
device: {
|
|
236
|
+
device: '229252771069b294',
|
|
237
|
+
metadata: {
|
|
238
|
+
app: {
|
|
239
|
+
version: '1.3.7',
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
configs: {
|
|
244
|
+
'config-version': '1.3.7',
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
}),
|
|
248
|
+
'PDV (229252771069b294) / v1.3.7',
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
const debugInfo = getRuntimeFooterDebugInfo({
|
|
252
|
+
device: {
|
|
253
|
+
alias: 'PDV',
|
|
254
|
+
appVersion: '1.3.7',
|
|
255
|
+
deviceType: 'android',
|
|
256
|
+
id: 'd41ac8afb9f178eb',
|
|
257
|
+
},
|
|
258
|
+
appVersion: '1.3.6',
|
|
259
|
+
deviceConfig: {
|
|
260
|
+
device: {
|
|
261
|
+
device: '229252771069b294',
|
|
262
|
+
metadata: {
|
|
263
|
+
app: {
|
|
264
|
+
version: '1.3.7',
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
configs: {
|
|
269
|
+
'config-version': '1.3.7',
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
assert.equal(debugInfo.versionLabel, 'v1.3.7')
|
|
275
|
+
assert.equal(debugInfo.displayName, 'PDV (229252771069b294)')
|
|
276
|
+
assert.equal(debugInfo.runtimeDetail, '229252771069b294')
|
|
277
|
+
assert.equal(debugInfo.runtimeDetailSource, 'device_config.device.device')
|
|
278
|
+
assert.equal(debugInfo.versionCandidates[0]?.source, 'device_config.device.metadata.app.version')
|
|
279
279
|
assert.equal(debugInfo.rawValues.deviceId, 'd41ac8afb9f178eb')
|
|
280
280
|
assert.equal(debugInfo.rawValues.storedDeviceIdentifier, '229252771069b294')
|
|
281
281
|
})
|
|
@@ -417,11 +417,11 @@ test('falls back to the local device id when the backend identifier is unavailab
|
|
|
417
417
|
const candidates = getRuntimeFooterNativeIdentifierCandidates({
|
|
418
418
|
device: {
|
|
419
419
|
id: 'local-device-99',
|
|
420
|
-
},
|
|
421
|
-
deviceConfig: {
|
|
422
|
-
device: {},
|
|
423
|
-
},
|
|
424
|
-
})
|
|
420
|
+
},
|
|
421
|
+
deviceConfig: {
|
|
422
|
+
device: {},
|
|
423
|
+
},
|
|
424
|
+
})
|
|
425
425
|
|
|
426
426
|
assert.equal(candidates[0]?.value, 'local-device-99')
|
|
427
427
|
assert.equal(candidates[0]?.source, 'device.id')
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const CIELO_CONFIG_KEY = 'CIELO';
|
|
2
2
|
export const NEW_RELIC_CONFIG_KEY = 'NEW_RELIC';
|
|
3
3
|
export const SPOTIFY_CONFIG_KEY = 'SPOTIFY';
|
|
4
|
+
export const SEM_PARAR_CONFIG_KEY = 'SEM_PARAR';
|
|
4
5
|
|
|
5
6
|
export const DEFAULT_CIELO_CONFIG = {
|
|
6
7
|
ACCESS_TOKEN: '',
|
|
@@ -23,6 +24,21 @@ export const DEFAULT_SPOTIFY_CONFIG = {
|
|
|
23
24
|
CLIENT_SECRET: '',
|
|
24
25
|
};
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Company-scoped Sem Parar credentials for vale-pedágio emission.
|
|
29
|
+
* ENABLED: "1" | "0"
|
|
30
|
+
* ENVIRONMENT: "sandbox" | "production"
|
|
31
|
+
*/
|
|
32
|
+
export const DEFAULT_SEM_PARAR_CONFIG = {
|
|
33
|
+
ENABLED: '0',
|
|
34
|
+
CLIENT_ID: '',
|
|
35
|
+
CLIENT_SECRET: '',
|
|
36
|
+
USERNAME: '',
|
|
37
|
+
PASSWORD: '',
|
|
38
|
+
ENVIRONMENT: 'sandbox',
|
|
39
|
+
CONVENIADO: '',
|
|
40
|
+
};
|
|
41
|
+
|
|
26
42
|
const isConfigMap = value =>
|
|
27
43
|
value && typeof value === 'object' && !Array.isArray(value);
|
|
28
44
|
|
|
@@ -78,3 +94,10 @@ export const resolveSpotifyConfig = configs =>
|
|
|
78
94
|
SPOTIFY_CONFIG_KEY,
|
|
79
95
|
DEFAULT_SPOTIFY_CONFIG,
|
|
80
96
|
);
|
|
97
|
+
|
|
98
|
+
export const resolveSemPararConfig = configs =>
|
|
99
|
+
resolveIntegrationConfig(
|
|
100
|
+
configs,
|
|
101
|
+
SEM_PARAR_CONFIG_KEY,
|
|
102
|
+
DEFAULT_SEM_PARAR_CONFIG,
|
|
103
|
+
);
|