@controleonline/ui-common 1.2.71 → 1.2.75
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/actions/workers/manager/action.yml +147 -0
- package/.github/actions/workers/qa/action.yml +44 -0
- package/.github/actions/workers/security/action.yml +44 -0
- package/.github/actions/workers/technical-documenter/action.yml +51 -0
- package/.github/workflows/manager-worker.yml +168 -0
- package/.github/workflows/publish-npm.yml +45 -0
- package/.gitmodules +3 -0
- package/AGENTS.md +6 -0
- package/README.md +14 -0
- package/package.json +3 -2
- package/src/api/fetch.js +1 -1
- package/src/api/index.js +92 -22
- package/src/react/components/AddImportModal.js +94 -110
- package/src/react/components/BottomNavigationBar.config.js +211 -231
- package/src/react/components/CategoryForm.js +52 -35
- package/src/react/components/DefaultProvider.native.js +131 -95
- package/src/react/components/DefaultProvider.web.js +148 -74
- package/src/react/components/NetworkPrinterPreviewModal.js +249 -0
- package/src/react/components/NetworkPrinterPreviewModal.styles.js +159 -0
- package/src/react/components/RuntimeInfoFooter.js +100 -36
- package/src/react/components/RuntimeInfoFooter.styles.js +3 -0
- package/src/react/components/UnifiedPaymentBar.js +7 -4
- package/src/react/components/UserAvatar.js +160 -0
- package/src/react/components/integrations/IntegrationHero/index.js +48 -0
- package/src/react/components/integrations/IntegrationHero/styles.js +57 -0
- package/src/react/components/integrations/IntegrationTabs/index.js +89 -0
- package/src/react/components/integrations/IntegrationTabs/styles.js +44 -0
- package/src/react/config/deviceConfigBootstrap.js +5 -3
- package/src/react/pages/Connections.js +229 -0
- package/src/react/pages/Connections.styles.js +222 -0
- package/src/react/pages/DeviceDetailPage.js +2814 -0
- package/src/react/pages/DeviceDetailPage.styles.js +308 -0
- package/src/react/pages/Devices/currentDevice.js +194 -0
- package/src/react/pages/Devices/deviceTypes/DeviceGroupCard.js +257 -0
- package/src/react/pages/Devices/deviceTypes/all.js +23 -0
- package/src/react/pages/Devices/deviceTypes/device.js +25 -0
- package/src/react/pages/Devices/deviceTypes/deviceListHelpers.js +178 -0
- package/src/react/pages/Devices/deviceTypes/display.js +26 -0
- package/src/react/pages/Devices/deviceTypes/index.js +145 -0
- package/src/react/pages/Devices/deviceTypes/ipCamera.js +35 -0
- package/src/react/pages/Devices/deviceTypes/pdv.js +88 -0
- package/src/react/pages/Devices/deviceTypes/printer.js +37 -0
- package/src/react/pages/Devices/deviceTypes/shared.js +453 -0
- package/src/react/pages/Devices/deviceTypes/useDeviceNetworkConnectivity.js +145 -0
- package/src/react/pages/Devices.js +183 -0
- package/src/react/pages/Devices.styles.js +353 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99CatalogTab.js +219 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99OverviewTab.js +134 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99PreviewModal.js +173 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99ProductCard.js +1 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99QuickWalletModal.js +181 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99SettingsTab.js +306 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99StoreTab.js +417 -0
- package/src/react/pages/Food99IntegrationPage/index.js +1530 -0
- package/src/react/pages/Food99IntegrationPage/styles.js +792 -0
- package/src/react/pages/Food99IntegrationPage/utils.js +155 -0
- package/src/react/pages/Food99IntegrationPage.js +1 -0
- package/src/react/pages/Food99IntegrationPage.styles.js +1 -0
- package/src/react/pages/GenericLogPage.js +42 -167
- package/src/react/pages/IFoodIntegrationPage/components/IFoodCatalogTab.js +8 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOperationsTab.js +420 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOverviewTab.js +118 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodPreviewModal.js +103 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodProductCard.js +1 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodStoreTab.js +150 -0
- package/src/react/pages/IFoodIntegrationPage/index.js +1298 -0
- package/src/react/pages/IFoodIntegrationPage/styles.js +764 -0
- package/src/react/pages/IFoodIntegrationPage/utils.js +91 -0
- package/src/react/pages/IFoodIntegrationPage.js +1 -0
- package/src/react/pages/IFoodIntegrationPage.styles.js +1 -0
- package/src/react/pages/Imports.js +214 -166
- package/src/react/pages/IntegrationConfigPage.js +744 -0
- package/src/react/pages/IntegrationConfigPage.styles.js +269 -0
- package/src/react/pages/Integrations.js +299 -0
- package/src/react/pages/Integrations.styles.js +130 -0
- package/src/react/pages/ManagerOrderNotificationsPage.js +642 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/MarketplaceProductCard.js +205 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/RemoteMarketplaceMenuTab.js +335 -0
- package/src/react/pages/MarketplaceIntegrationPage/index.js +60 -0
- package/src/react/pages/MarketplaceIntegrationPage/utils.js +137 -0
- package/src/react/pages/MercadoLivreIntegrationPage.js +538 -0
- package/src/react/pages/PrinterDeviceDetailPage.js +1916 -0
- package/src/react/pages/PrinterDeviceDetailPage.styles.js +223 -0
- package/src/react/pages/PrinterDeviceFormPage.js +521 -0
- package/src/react/pages/PrinterDeviceFormPage.styles.js +159 -0
- package/src/react/pages/WhatsAppConnectionPage.js +459 -0
- package/src/react/pages/WhatsAppConnectionPage.styles.js +284 -0
- package/src/react/pages/integrationsCatalog.js +399 -0
- package/src/react/services/Cielo/Cielo.js +193 -193
- package/src/react/utils/categoryContexts.js +46 -0
- package/src/react/utils/entityDisplay.js +222 -217
- package/src/react/utils/fileUrl.js +39 -20
- package/src/react/utils/integrationPage.js +16 -0
- package/src/react/utils/runtimeFooter.js +40 -22
- package/src/react/utils/runtimeLanguage.js +50 -9
- package/src/react/utils/runtimeMenu.js +191 -131
- package/src/react/utils/runtimeZoom.js +43 -0
- package/src/react/utils/shopConfig.js +27 -15
- package/src/react/utils/shopFranchises.js +126 -1
- package/src/react/utils/storeColumns.js +23 -4
- package/src/react/utils/userAvatar.js +104 -0
- package/src/store/categories/index.js +48 -20
- package/src/store/device_config/index.js +62 -21
- package/src/store/entity_log/index.js +22 -1
- package/src/store/imports/customActions.js +51 -0
- package/src/store/imports/index.js +89 -88
- package/src/store/status/index.js +11 -11
- package/src/store/themes/index.js +22 -0
- package/src/store/timezones/index.js +3 -1
- package/src/tests/browser/manager/connections.spec.js +143 -0
- package/src/tests/browser/manager/devices-current.spec.js +343 -0
- package/src/tests/browser/manager/mercado-livre-integration.spec.js +268 -0
- package/src/tests/react/api/deviceHeaders.test.js +114 -0
- package/src/tests/react/components/AddImportModal.test.js +166 -0
- package/src/tests/react/components/BottomNavigationBar.config.test.js +20 -0
- package/src/tests/react/components/UserAvatar.test.js +52 -0
- package/src/tests/react/pages/DevicePickerStyles.test.js +47 -0
- package/src/tests/react/pages/Devices/deviceListHelpers.test.js +39 -0
- package/src/tests/react/pages/DevicesCurrentDevice.test.js +198 -0
- package/src/tests/react/pages/connectionsHelpers.test.js +34 -0
- package/src/tests/react/pages/mercadoLivreIntegrationPageContract.test.mjs +16 -0
- package/src/tests/react/services/Cielo.test.js +190 -190
- package/src/tests/react/store/categoriesOrdering.test.js +26 -0
- package/src/tests/react/utils/appDomain.test.js +62 -0
- package/src/tests/react/utils/entityDisplay.test.js +2 -2
- package/src/tests/react/utils/fileUrl.test.js +3 -3
- package/src/tests/react/utils/formatter.test.mjs +33 -0
- package/src/tests/react/utils/runtimeFooter.test.js +29 -4
- package/src/tests/react/utils/runtimeLanguage.test.js +79 -9
- package/src/tests/react/utils/runtimeMenu.test.js +198 -134
- package/src/tests/react/utils/runtimeZoom.test.js +38 -0
- package/src/tests/react/utils/shopConfig.test.js +10 -9
- package/src/tests/react/utils/shopFranchises.test.js +43 -0
- package/src/tests/react/utils/translate.discovery.test.mjs +170 -0
- package/src/tests/react/utils/translate.test.helpers.mjs +152 -0
- package/src/tests/react/utils/translate.test.mjs +141 -349
- package/src/tests/react/utils/userAvatar.test.js +63 -0
- package/src/utils/appDomain.js +15 -4
- package/src/utils/formatter.js +104 -16
- package/src/utils/integrationConfigs.js +80 -80
- package/src/utils/translate.js +222 -438
- package/src/utils/translateDiscovery.js +96 -0
- package/src/utils/translateNormalize.js +33 -0
- package/src/utils/translatePending.js +92 -0
- package/src/utils/translateStorage.js +142 -0
- package/.github/agents/developer.agent.md +0 -30
- package/.github/agents/devops.agent.md +0 -30
- package/.github/agents/qa.agent.md +0 -30
- package/.github/agents/security.agent.md +0 -30
- package/.github/workflows/npmjs.yml +0 -35
|
@@ -1,239 +1,92 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import test from 'node:test';
|
|
3
|
-
|
|
4
|
-
import Translate from '../../../utils/translate.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (
|
|
92
|
-
!pendingMessages[normalizedLanguage].companies[normalizedCompanyId][storeName][type]
|
|
93
|
-
) {
|
|
94
|
-
pendingMessages[normalizedLanguage].companies[normalizedCompanyId][storeName][type] =
|
|
95
|
-
{};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
pendingMessages[normalizedLanguage].companies[normalizedCompanyId][storeName][type][
|
|
99
|
-
key
|
|
100
|
-
] = translate;
|
|
101
|
-
|
|
102
|
-
return pendingMessages;
|
|
103
|
-
},
|
|
104
|
-
removePendingTranslate: ({language, companyId, store: storeName, type, key}) => {
|
|
105
|
-
const normalizedLanguage = normalizeLanguage(language);
|
|
106
|
-
const normalizedCompanyId = normalizeId(companyId);
|
|
107
|
-
const pendingMessages = store.getters.pendingMessages;
|
|
108
|
-
const languageBucket = pendingMessages[normalizedLanguage];
|
|
109
|
-
const companyBucket = languageBucket?.companies?.[normalizedCompanyId];
|
|
110
|
-
const storeBucket = companyBucket?.[storeName];
|
|
111
|
-
const typeBucket = storeBucket?.[type];
|
|
112
|
-
|
|
113
|
-
if (!typeBucket || !Object.prototype.hasOwnProperty.call(typeBucket, key)) {
|
|
114
|
-
return pendingMessages;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
delete typeBucket[key];
|
|
118
|
-
|
|
119
|
-
if (Object.keys(typeBucket).length === 0) {
|
|
120
|
-
delete storeBucket[type];
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (Object.keys(storeBucket).length === 0) {
|
|
124
|
-
delete companyBucket[storeName];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (Object.keys(companyBucket).length === 0) {
|
|
128
|
-
delete languageBucket.companies[normalizedCompanyId];
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (Object.keys(languageBucket.companies || {}).length === 0) {
|
|
132
|
-
delete languageBucket.companies;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (Object.keys(languageBucket).length === 0) {
|
|
136
|
-
delete pendingMessages[normalizedLanguage];
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return pendingMessages;
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
store.actions = translateActions;
|
|
144
|
-
|
|
145
|
-
return {
|
|
146
|
-
getters: store.getters,
|
|
147
|
-
actions: store.actions,
|
|
148
|
-
get messages() {
|
|
149
|
-
return store.getters.messages;
|
|
150
|
-
},
|
|
151
|
-
get pendingMessages() {
|
|
152
|
-
return store.getters.pendingMessages;
|
|
153
|
-
},
|
|
154
|
-
translateActions,
|
|
155
|
-
};
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
test('prefers the current company translation and falls back to the default company', () => {
|
|
159
|
-
installLocalStorage();
|
|
160
|
-
|
|
161
|
-
const translateStore = createPendingTranslateStore();
|
|
162
|
-
const translate = new Translate(
|
|
163
|
-
[{id: 1}, {id: 5}],
|
|
164
|
-
{id: 1},
|
|
165
|
-
{id: 5},
|
|
166
|
-
['orders'],
|
|
167
|
-
translateStore,
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
translate.findMessage('orders', 'label', 'save', 'Salvar', 1);
|
|
171
|
-
translate.findMessage('orders', 'label', 'save', 'Save for ASC', 5);
|
|
172
|
-
translate.persist();
|
|
173
|
-
|
|
174
|
-
assert.equal(translate.t('orders', 'label', 'save'), 'Save for ASC');
|
|
175
|
-
|
|
176
|
-
const fallbackTranslate = new Translate(
|
|
177
|
-
[{id: 1}, {id: 5}],
|
|
178
|
-
{id: 1},
|
|
179
|
-
{id: 9},
|
|
180
|
-
['orders'],
|
|
181
|
-
createPendingTranslateStore(),
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
assert.equal(fallbackTranslate.t('orders', 'label', 'save'), 'Salvar');
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
test('keeps the translate method bound when passed as a standalone function', () => {
|
|
188
|
-
installLocalStorage();
|
|
189
|
-
|
|
190
|
-
const translate = new Translate(
|
|
191
|
-
[{id: 1}],
|
|
192
|
-
{id: 1},
|
|
193
|
-
{id: 1},
|
|
194
|
-
['orders'],
|
|
195
|
-
createPendingTranslateStore(),
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
translate.findMessage('orders', 'label', 'save', 'Salvar', 1);
|
|
199
|
-
|
|
200
|
-
const detachedTranslate = translate.t;
|
|
201
|
-
|
|
202
|
-
assert.equal(detachedTranslate('orders', 'label', 'save'), 'Salvar');
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
test('hydrates the cached translations into the translate store on startup', () => {
|
|
206
|
-
installLocalStorage();
|
|
207
|
-
localStorage.setItem('translates', JSON.stringify({
|
|
208
|
-
'pt-br': {
|
|
209
|
-
companies: {
|
|
210
|
-
1: {
|
|
211
|
-
invoice: {
|
|
212
|
-
label: {
|
|
213
|
-
accountsReceivable: 'Contas a receber',
|
|
214
|
-
},
|
|
215
|
-
},
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
}));
|
|
220
|
-
|
|
221
|
-
const translateStore = createPendingTranslateStore();
|
|
222
|
-
|
|
223
|
-
new Translate(
|
|
224
|
-
[{id: 1}],
|
|
225
|
-
{id: 1},
|
|
226
|
-
{id: 1},
|
|
227
|
-
['invoice'],
|
|
228
|
-
translateStore,
|
|
229
|
-
);
|
|
230
|
-
|
|
231
|
-
assert.equal(
|
|
232
|
-
translateStore.messages['pt-br'].companies[1].invoice.label.accountsReceivable,
|
|
233
|
-
'Contas a receber',
|
|
234
|
-
);
|
|
235
|
-
});
|
|
236
|
-
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import Translate from '../../../utils/translate.js';
|
|
5
|
+
import {
|
|
6
|
+
installLocalStorage,
|
|
7
|
+
flushAsync,
|
|
8
|
+
createPendingTranslateStore,
|
|
9
|
+
} from './translate.test.helpers.mjs';
|
|
10
|
+
|
|
11
|
+
test('prefers the current company translation and falls back to the default company', () => {
|
|
12
|
+
installLocalStorage();
|
|
13
|
+
|
|
14
|
+
const translateStore = createPendingTranslateStore();
|
|
15
|
+
const translate = new Translate(
|
|
16
|
+
[{id: 1}, {id: 5}],
|
|
17
|
+
{id: 1},
|
|
18
|
+
{id: 5},
|
|
19
|
+
['orders'],
|
|
20
|
+
translateStore,
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
translate.findMessage('orders', 'label', 'save', 'Salvar', 1);
|
|
24
|
+
translate.findMessage('orders', 'label', 'save', 'Save for ASC', 5);
|
|
25
|
+
translate.persist();
|
|
26
|
+
|
|
27
|
+
assert.equal(translate.t('orders', 'label', 'save'), 'Save for ASC');
|
|
28
|
+
|
|
29
|
+
const fallbackTranslate = new Translate(
|
|
30
|
+
[{id: 1}, {id: 5}],
|
|
31
|
+
{id: 1},
|
|
32
|
+
{id: 9},
|
|
33
|
+
['orders'],
|
|
34
|
+
createPendingTranslateStore(),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
assert.equal(fallbackTranslate.t('orders', 'label', 'save'), 'Salvar');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('keeps the translate method bound when passed as a standalone function', () => {
|
|
41
|
+
installLocalStorage();
|
|
42
|
+
|
|
43
|
+
const translate = new Translate(
|
|
44
|
+
[{id: 1}],
|
|
45
|
+
{id: 1},
|
|
46
|
+
{id: 1},
|
|
47
|
+
['orders'],
|
|
48
|
+
createPendingTranslateStore(),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
translate.findMessage('orders', 'label', 'save', 'Salvar', 1);
|
|
52
|
+
|
|
53
|
+
const detachedTranslate = translate.t;
|
|
54
|
+
|
|
55
|
+
assert.equal(detachedTranslate('orders', 'label', 'save'), 'Salvar');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('hydrates the cached translations into the translate store on startup', () => {
|
|
59
|
+
installLocalStorage();
|
|
60
|
+
localStorage.setItem('translates', JSON.stringify({
|
|
61
|
+
'pt-br': {
|
|
62
|
+
companies: {
|
|
63
|
+
1: {
|
|
64
|
+
invoice: {
|
|
65
|
+
label: {
|
|
66
|
+
accountsReceivable: 'Contas a receber',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
}));
|
|
73
|
+
|
|
74
|
+
const translateStore = createPendingTranslateStore();
|
|
75
|
+
|
|
76
|
+
new Translate(
|
|
77
|
+
[{id: 1}],
|
|
78
|
+
{id: 1},
|
|
79
|
+
{id: 1},
|
|
80
|
+
['invoice'],
|
|
81
|
+
translateStore,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
assert.equal(
|
|
85
|
+
translateStore.messages['pt-br'].companies[1].invoice.label.accountsReceivable,
|
|
86
|
+
'Contas a receber',
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
237
90
|
test('posts missing translations once and keeps the fallback until review', async () => {
|
|
238
91
|
installLocalStorage();
|
|
239
92
|
|
|
@@ -242,36 +95,36 @@ test('posts missing translations once and keeps the fallback until review', asyn
|
|
|
242
95
|
save: async payload => {
|
|
243
96
|
saveCalls.push(payload);
|
|
244
97
|
return payload;
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
const translate = new Translate(
|
|
248
|
-
[{id: 1}],
|
|
249
|
-
{id: 1},
|
|
250
|
-
{id: 1},
|
|
251
|
-
['contract'],
|
|
252
|
-
translateStore,
|
|
253
|
-
);
|
|
254
|
-
|
|
255
|
-
const firstValue = translate.t('contract', 'empty', 'none_registered_title');
|
|
256
|
-
const secondValue = translate.t('contract', 'empty', 'none_registered_title');
|
|
257
|
-
|
|
258
|
-
assert.equal(firstValue, 'None registered title');
|
|
259
|
-
assert.equal(secondValue, 'None registered title');
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
const translate = new Translate(
|
|
101
|
+
[{id: 1}],
|
|
102
|
+
{id: 1},
|
|
103
|
+
{id: 1},
|
|
104
|
+
['contract'],
|
|
105
|
+
translateStore,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const firstValue = translate.t('contract', 'empty', 'none_registered_title');
|
|
109
|
+
const secondValue = translate.t('contract', 'empty', 'none_registered_title');
|
|
110
|
+
|
|
111
|
+
assert.equal(firstValue, 'None registered title');
|
|
112
|
+
assert.equal(secondValue, 'None registered title');
|
|
260
113
|
|
|
261
114
|
await flushAsync();
|
|
262
115
|
|
|
263
116
|
assert.deepEqual(saveCalls, [{
|
|
264
117
|
people: '/people/1',
|
|
265
118
|
language: 'pt-br',
|
|
266
|
-
store: 'contract',
|
|
267
|
-
type: 'empty',
|
|
268
|
-
key: 'none_registered_title',
|
|
269
|
-
translate: 'None registered title',
|
|
270
|
-
revised: false,
|
|
271
|
-
}]);
|
|
272
|
-
assert.equal(
|
|
273
|
-
translateStore.messages['pt-br'].companies[1].contract.empty.none_registered_title,
|
|
274
|
-
'None registered title',
|
|
119
|
+
store: 'contract',
|
|
120
|
+
type: 'empty',
|
|
121
|
+
key: 'none_registered_title',
|
|
122
|
+
translate: 'None registered title',
|
|
123
|
+
revised: false,
|
|
124
|
+
}]);
|
|
125
|
+
assert.equal(
|
|
126
|
+
translateStore.messages['pt-br'].companies[1].contract.empty.none_registered_title,
|
|
127
|
+
'None registered title',
|
|
275
128
|
);
|
|
276
129
|
assert.deepEqual(translateStore.pendingMessages, {});
|
|
277
130
|
});
|
|
@@ -359,102 +212,41 @@ test('queues missing translations in a single batch resolve request', async () =
|
|
|
359
212
|
assert.deepEqual(translateStore.pendingMessages, {});
|
|
360
213
|
});
|
|
361
214
|
|
|
362
|
-
test('
|
|
363
|
-
installLocalStorage({language: 'en_US'});
|
|
364
|
-
|
|
365
|
-
const saveCalls = [];
|
|
366
|
-
const translateStore = createPendingTranslateStore({
|
|
367
|
-
getItems: async () => [],
|
|
368
|
-
save: async payload => {
|
|
369
|
-
saveCalls.push(payload);
|
|
370
|
-
return payload;
|
|
371
|
-
},
|
|
372
|
-
});
|
|
373
|
-
const translate = new Translate(
|
|
374
|
-
[{id: 1}],
|
|
375
|
-
{id: 1},
|
|
376
|
-
{id: 1},
|
|
377
|
-
['contract'],
|
|
378
|
-
translateStore,
|
|
379
|
-
);
|
|
380
|
-
|
|
381
|
-
translate.t('contract', 'empty', 'none_registered_title');
|
|
382
|
-
|
|
383
|
-
await flushAsync();
|
|
384
|
-
|
|
385
|
-
assert.equal(
|
|
386
|
-
saveCalls[0].language,
|
|
387
|
-
'en-us',
|
|
388
|
-
);
|
|
389
|
-
assert.equal(
|
|
390
|
-
translateStore.messages['en-us'].companies[1].contract.empty.none_registered_title,
|
|
391
|
-
'None registered title',
|
|
392
|
-
);
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
test('loads each requested store only for the current and default companies', async () => {
|
|
215
|
+
test('falls back past empty current-company values to the main company', () => {
|
|
396
216
|
installLocalStorage();
|
|
217
|
+
const translateStore = createPendingTranslateStore();
|
|
218
|
+
const currentCompany = {id: 2};
|
|
219
|
+
const defaultCompany = {id: 1};
|
|
220
|
+
const translate = new Translate(
|
|
221
|
+
[defaultCompany, currentCompany],
|
|
222
|
+
defaultCompany,
|
|
223
|
+
currentCompany,
|
|
224
|
+
['orders'],
|
|
225
|
+
translateStore,
|
|
226
|
+
);
|
|
397
227
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
{id: 5},
|
|
403
|
-
['orders', 'crm'],
|
|
404
|
-
createPendingTranslateStore({
|
|
405
|
-
getItems: async params => {
|
|
406
|
-
calls.push(params);
|
|
407
|
-
return [];
|
|
408
|
-
},
|
|
409
|
-
}),
|
|
410
|
-
);
|
|
411
|
-
|
|
412
|
-
await translate.discoveryAll();
|
|
413
|
-
|
|
414
|
-
assert.deepEqual(calls, [
|
|
415
|
-
{store: 'orders', 'language.language': 'pt-br', people: '/people/1', page: 1},
|
|
416
|
-
{store: 'crm', 'language.language': 'pt-br', people: '/people/1', page: 1},
|
|
417
|
-
{store: 'orders', 'language.language': 'pt-br', people: '/people/5', page: 1},
|
|
418
|
-
{store: 'crm', 'language.language': 'pt-br', people: '/people/5', page: 1},
|
|
419
|
-
]);
|
|
228
|
+
translate.findMessage('orders', 'menu', 'overview', ' ', 2, 'pt-br');
|
|
229
|
+
translate.findMessage('orders', 'menu', 'overview', 'Visão geral', 1, 'pt-br');
|
|
230
|
+
|
|
231
|
+
assert.equal(translate.t('orders', 'menu', 'overview'), 'Visão geral');
|
|
420
232
|
});
|
|
421
233
|
|
|
422
|
-
test('
|
|
234
|
+
test('getResolveCompaniesToCache returns current and main companies', () => {
|
|
423
235
|
installLocalStorage();
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
1: {
|
|
428
|
-
contract: {
|
|
429
|
-
empty: {
|
|
430
|
-
none_registered_title: 'None registered title',
|
|
431
|
-
},
|
|
432
|
-
},
|
|
433
|
-
},
|
|
434
|
-
},
|
|
435
|
-
},
|
|
436
|
-
}));
|
|
437
|
-
|
|
438
|
-
const calls = [];
|
|
439
|
-
const translateStore = createPendingTranslateStore({
|
|
440
|
-
getItems: async params => {
|
|
441
|
-
calls.push(params);
|
|
442
|
-
return [];
|
|
443
|
-
},
|
|
444
|
-
});
|
|
236
|
+
const translateStore = createPendingTranslateStore();
|
|
237
|
+
const currentCompany = {id: 2};
|
|
238
|
+
const defaultCompany = {id: 1};
|
|
445
239
|
const translate = new Translate(
|
|
446
|
-
[
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
['
|
|
240
|
+
[defaultCompany, currentCompany],
|
|
241
|
+
defaultCompany,
|
|
242
|
+
currentCompany,
|
|
243
|
+
['orders'],
|
|
450
244
|
translateStore,
|
|
451
245
|
);
|
|
452
246
|
|
|
453
|
-
translate
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
assert.deepEqual(calls, []);
|
|
247
|
+
const ids = translate
|
|
248
|
+
.getResolveCompaniesToCache()
|
|
249
|
+
.map((company) => String(company.id))
|
|
250
|
+
.sort();
|
|
251
|
+
assert.deepEqual(ids, ['1', '2']);
|
|
460
252
|
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAvatarDisplayName,
|
|
3
|
+
getGravatarUrl,
|
|
4
|
+
getUserInitials,
|
|
5
|
+
resolveUserAvatarUrl,
|
|
6
|
+
resolveUserPeopleIri,
|
|
7
|
+
} from '../../../react/utils/userAvatar';
|
|
8
|
+
|
|
9
|
+
describe('userAvatar', () => {
|
|
10
|
+
it('uses the first and last names for two initials', () => {
|
|
11
|
+
expect(getUserInitials({name: 'Alexandre AleMac Cunha'})).toBe('AC');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('uses one initial for a single name', () => {
|
|
15
|
+
expect(getUserInitials({name: 'Alexandre'})).toBe('A');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('falls back to the email initial when the name is unavailable', () => {
|
|
19
|
+
expect(getUserInitials({email: 'claudio@example.com'})).toBe('C');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('asks Gravatar for a real image without an identicon fallback', () => {
|
|
23
|
+
expect(getGravatarUrl(' MyEmailAddress@example.com ', 120)).toBe(
|
|
24
|
+
'https://www.gravatar.com/avatar/0bc83cb571cd1c50ba6f3e8a78ef1346?s=120&d=404',
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('does not call Gravatar without an email', () => {
|
|
29
|
+
expect(getGravatarUrl('')).toBe('');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('uses the complete person name and never the functional alias', () => {
|
|
33
|
+
const user = {name: 'Claudio Medeiros', realname: 'Claudio Owner', alias: 'owner'};
|
|
34
|
+
|
|
35
|
+
expect(getAvatarDisplayName(user)).toBe('Claudio Medeiros');
|
|
36
|
+
expect(getUserInitials({name: getAvatarDisplayName(user)})).toBe('CM');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('resolves the person from the same stored session shape used by Profile', () => {
|
|
40
|
+
expect(
|
|
41
|
+
resolveUserPeopleIri({id: 131}, {people: '/people/14'}),
|
|
42
|
+
).toBe('/people/14');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('resolves only the canonical persisted avatar', () => {
|
|
46
|
+
const user = {avatar: {id: 42}};
|
|
47
|
+
|
|
48
|
+
expect(
|
|
49
|
+
resolveUserAvatarUrl(user, avatar =>
|
|
50
|
+
avatar?.id ? `https://api.example/files/${avatar.id}/download` : '',
|
|
51
|
+
),
|
|
52
|
+
).toBe('https://api.example/files/42/download');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('does not treat avatarUrl as an avatar source', () => {
|
|
56
|
+
expect(
|
|
57
|
+
resolveUserAvatarUrl(
|
|
58
|
+
{avatarUrl: 'https://legacy.example/avatar.png'},
|
|
59
|
+
() => '',
|
|
60
|
+
),
|
|
61
|
+
).toBe('');
|
|
62
|
+
});
|
|
63
|
+
});
|
package/src/utils/appDomain.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const INVALID_DOMAIN_VALUES = new Set(['undefined', 'null', 'false']);
|
|
2
|
+
|
|
3
|
+
const toRawString = value => {
|
|
4
|
+
const raw = String(value || '').trim();
|
|
5
|
+
return INVALID_DOMAIN_VALUES.has(raw.toLowerCase()) ? '' : raw;
|
|
6
|
+
};
|
|
2
7
|
|
|
3
8
|
const tryParseHost = value => {
|
|
4
9
|
const raw = toRawString(value);
|
|
@@ -23,10 +28,16 @@ export const resolveRuntimeHost = () => {
|
|
|
23
28
|
return toRawString(location?.host || '');
|
|
24
29
|
};
|
|
25
30
|
|
|
31
|
+
/**
|
|
32
|
+
* App-Domain header value.
|
|
33
|
+
* Browser (web multi-tenant): always prefer window.location.host so custom
|
|
34
|
+
* domains (e.g. erpjaguncos.com.br) resolve the correct tenant.
|
|
35
|
+
* Native / no location: fall back to configured DOMAIN from env.
|
|
36
|
+
*/
|
|
26
37
|
export const resolveAppDomain = configuredDomain => {
|
|
27
|
-
const
|
|
28
|
-
if (
|
|
29
|
-
return tryParseHost(
|
|
38
|
+
const runtimeHost = tryParseHost(resolveRuntimeHost());
|
|
39
|
+
if (runtimeHost) return runtimeHost;
|
|
40
|
+
return tryParseHost(configuredDomain);
|
|
30
41
|
};
|
|
31
42
|
|
|
32
43
|
export const resolveCompanyDomain = (company, fallbackDomain = '') => {
|