@klauswuestefeld/jux-web 2026.3.7 → 2026.7.24
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/dist/jux/language.d.ts +3 -0
- package/dist/jux-web.js +650 -411
- package/dist/login/login-field-style.d.ts +1 -0
- package/dist/login/login-token-textarea.d.ts +1 -0
- package/dist/main.d.ts +1 -1
- package/dist/main.esm.js +649 -412
- package/dist/main.js +650 -411
- package/package.json +2 -2
package/dist/jux-web.js
CHANGED
|
@@ -36,6 +36,61 @@ var juxWeb = (function (exports) {
|
|
|
36
36
|
};
|
|
37
37
|
// @ts-ignore
|
|
38
38
|
const getTranslation = (k) => translations[k] || k;
|
|
39
|
+
const formatTextToMarkdown = (container, text) => {
|
|
40
|
+
// Split the text on bold markers (**...**), <br>, markdown-style links [text](url),
|
|
41
|
+
// and semantic color tags like {warning|text}.
|
|
42
|
+
// The regex uses a capture group to include the delimiters in the results.
|
|
43
|
+
const parts = text.split(/(\*\*.*?\*\*|<br>|\[.*?\]\(https?:\/\/.*?\)|\{[a-z0-9-]+\|.*?\})/gi);
|
|
44
|
+
parts.forEach(part => {
|
|
45
|
+
if (!part)
|
|
46
|
+
return;
|
|
47
|
+
if (part === '<br>') {
|
|
48
|
+
container.appendChild(document.createElement('br'));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (part.startsWith('**') && part.endsWith('**')) {
|
|
52
|
+
const bold = document.createElement('b');
|
|
53
|
+
bold.textContent = part.slice(2, -2);
|
|
54
|
+
container.appendChild(bold);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (part.startsWith('[') && part.includes('](') && part.endsWith(')')) {
|
|
58
|
+
const match = part.match(/\[(.*?)\]\((https?:\/\/.*?)\)/);
|
|
59
|
+
if (match) {
|
|
60
|
+
const [, label, href] = match;
|
|
61
|
+
const link = document.createElement('a');
|
|
62
|
+
link.href = href;
|
|
63
|
+
link.textContent = label;
|
|
64
|
+
link.target = '_blank';
|
|
65
|
+
link.rel = 'noopener noreferrer';
|
|
66
|
+
container.appendChild(link);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (part.startsWith('{') && part.includes('|') && part.endsWith('}')) {
|
|
71
|
+
const match = part.match(/\{([a-z0-9-]+)\|(.*?)\}/i);
|
|
72
|
+
if (match) {
|
|
73
|
+
const [, className, text] = match;
|
|
74
|
+
const coloredText = document.createElement('span');
|
|
75
|
+
coloredText.className = `${className.toLowerCase()}`;
|
|
76
|
+
formatTextToMarkdown(coloredText, text);
|
|
77
|
+
container.appendChild(coloredText);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
container.appendChild(document.createTextNode(part));
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
const createFormattedParagraph = (text) => {
|
|
85
|
+
const paragraph = document.createElement('p');
|
|
86
|
+
formatTextToMarkdown(paragraph, text);
|
|
87
|
+
return paragraph;
|
|
88
|
+
};
|
|
89
|
+
const applyFormattedTranslation = (element, key) => {
|
|
90
|
+
const wrapper = document.createElement('span');
|
|
91
|
+
formatTextToMarkdown(wrapper, getTranslation(key));
|
|
92
|
+
element.replaceChildren(...Array.from(wrapper.childNodes));
|
|
93
|
+
};
|
|
39
94
|
const initLanguage = (translations_, defaultLanguage = 'en') => {
|
|
40
95
|
exports.chosenLanguage = getLocalStorageItem(OVERRIDE_KEY) || getBrowserLanguage();
|
|
41
96
|
translations = translations_[exports.chosenLanguage] || translations_[defaultLanguage];
|
|
@@ -172,234 +227,6 @@ var juxWeb = (function (exports) {
|
|
|
172
227
|
return result;
|
|
173
228
|
};
|
|
174
229
|
|
|
175
|
-
const juxWhite = '#FFF';
|
|
176
|
-
const juxDarkGrey = '#282828';
|
|
177
|
-
const juxDimmedDarkGrey = '#28282822';
|
|
178
|
-
const juxDimmedBlack = '#00000088';
|
|
179
|
-
const juxLightGreen = '#20B03D';
|
|
180
|
-
const juxMediumGreen = '#0D631E';
|
|
181
|
-
|
|
182
|
-
const onKeyDown = (ev, el, persitent, onClose) => {
|
|
183
|
-
if (ev.key === 'Escape') {
|
|
184
|
-
if (persitent) {
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
close(el, onClose);
|
|
188
|
-
}
|
|
189
|
-
else if (ev.key === 'Enter') {
|
|
190
|
-
if (ev.target.id === 'members-textarea') {
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
el.dispatchEvent(new CustomEvent('ok'));
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
const close = (el, onClose) => {
|
|
197
|
-
el.remove();
|
|
198
|
-
if (onClose) {
|
|
199
|
-
onClose();
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
const attachEventHandlers = (el, persitent, onClose) => {
|
|
203
|
-
const cancelButton = el.querySelector('.cancel');
|
|
204
|
-
cancelButton === null || cancelButton === void 0 ? void 0 : cancelButton.addEventListener('click', (_e) => {
|
|
205
|
-
el.dispatchEvent(new CustomEvent('cancel'));
|
|
206
|
-
if (el.hasAttribute('dont-remove')) {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
close(el, onClose);
|
|
210
|
-
});
|
|
211
|
-
const closeButton = el.querySelector('.close');
|
|
212
|
-
if (closeButton) {
|
|
213
|
-
closeButton.addEventListener('click', (_e) => {
|
|
214
|
-
close(el, onClose);
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
const okButton = el.querySelector('.ok');
|
|
218
|
-
okButton === null || okButton === void 0 ? void 0 : okButton.addEventListener('click', (_e) => {
|
|
219
|
-
el.dispatchEvent(new CustomEvent('ok'));
|
|
220
|
-
});
|
|
221
|
-
el.removeEventListener('keydown', (ev) => onKeyDown(ev, el, persitent, () => onClose));
|
|
222
|
-
el.addEventListener('keydown', (ev) => onKeyDown(ev, el, persitent, () => onClose));
|
|
223
|
-
el === null || el === void 0 ? void 0 : el.addEventListener('click', (e) => {
|
|
224
|
-
if (e.target === el) {
|
|
225
|
-
if (persitent) {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
close(el, onClose);
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
};
|
|
232
|
-
// TODO: Mudar construtor para usar essa interface
|
|
233
|
-
// interface JuxModalOptions {
|
|
234
|
-
// title?: string,
|
|
235
|
-
// btns?: string[],
|
|
236
|
-
// content?: string,
|
|
237
|
-
// isPersistent?: boolean,
|
|
238
|
-
// isBusy?: boolean,
|
|
239
|
-
// body?: HTMLElement,
|
|
240
|
-
// okTxt?: string,
|
|
241
|
-
// cancelTxt?: string,
|
|
242
|
-
// onClose?: any,
|
|
243
|
-
// titleStyle?: string,
|
|
244
|
-
// }
|
|
245
|
-
const applyWrapperStyle = (wrapper) => {
|
|
246
|
-
wrapper.style.alignItems = 'center';
|
|
247
|
-
wrapper.style.backgroundColor = juxWhite;
|
|
248
|
-
wrapper.style.borderRadius = '.3125rem';
|
|
249
|
-
wrapper.style.boxShadow = `0 0 1.33rem ${juxDimmedBlack}`;
|
|
250
|
-
wrapper.style.boxSizing = 'content-box';
|
|
251
|
-
wrapper.style.display = 'flex';
|
|
252
|
-
wrapper.style.flexDirection = 'column';
|
|
253
|
-
wrapper.style.justifyContent = 'flex-start';
|
|
254
|
-
wrapper.style.margin = '0';
|
|
255
|
-
wrapper.style.maxHeight = '88%';
|
|
256
|
-
wrapper.style.maxWidth = '40%';
|
|
257
|
-
wrapper.style.minWidth = '20%';
|
|
258
|
-
wrapper.style.padding = '2.8rem';
|
|
259
|
-
wrapper.style.position = 'relative';
|
|
260
|
-
};
|
|
261
|
-
const applyModalStyle = (modal) => {
|
|
262
|
-
modal.style.alignItems = 'center';
|
|
263
|
-
modal.style.backgroundColor = juxDimmedBlack;
|
|
264
|
-
modal.style.display = 'flex';
|
|
265
|
-
modal.style.height = '100vh';
|
|
266
|
-
modal.style.justifyContent = 'center';
|
|
267
|
-
modal.style.left = '0';
|
|
268
|
-
modal.style.overflow = 'hidden';
|
|
269
|
-
modal.style.position = 'fixed';
|
|
270
|
-
modal.style.top = '0';
|
|
271
|
-
modal.style.width = '100%';
|
|
272
|
-
modal.style.zIndex = '9999';
|
|
273
|
-
};
|
|
274
|
-
const applyHeaderStyle = (header) => {
|
|
275
|
-
header.style.alignItems = 'center';
|
|
276
|
-
header.style.color = juxMediumGreen;
|
|
277
|
-
header.style.flexDirection = 'row';
|
|
278
|
-
header.style.fontSize = '16px';
|
|
279
|
-
header.style.fontWeight = '700';
|
|
280
|
-
header.style.justifyContent = 'space-between';
|
|
281
|
-
header.style.margin = '0';
|
|
282
|
-
header.style.display = 'flex';
|
|
283
|
-
header.style.position = 'relative';
|
|
284
|
-
header.style.width = '100%';
|
|
285
|
-
};
|
|
286
|
-
const applyJuxModalContentStyle = (el) => {
|
|
287
|
-
el.style.display = 'flex';
|
|
288
|
-
el.style.position = 'relative';
|
|
289
|
-
el.style.width = '100%';
|
|
290
|
-
el.style.flexFlow = 'column';
|
|
291
|
-
el.style.marginTop = '1.33rem';
|
|
292
|
-
el.style.fontSize = '14px';
|
|
293
|
-
el.style.rowGap = '8px';
|
|
294
|
-
};
|
|
295
|
-
const applyFooterStyle = (footer) => {
|
|
296
|
-
footer.style.display = 'flex';
|
|
297
|
-
footer.style.width = '100%';
|
|
298
|
-
footer.style.justifyContent = 'flex-end';
|
|
299
|
-
footer.style.alignItems = 'center';
|
|
300
|
-
footer.style.gap = '0.75rem';
|
|
301
|
-
footer.style.marginTop = '1.5rem';
|
|
302
|
-
footer.style.paddingTop = '1rem';
|
|
303
|
-
};
|
|
304
|
-
const applyModalButtonStyle = (btn) => {
|
|
305
|
-
btn.style.display = 'inline-flex';
|
|
306
|
-
btn.style.alignItems = 'center';
|
|
307
|
-
btn.style.justifyContent = 'center';
|
|
308
|
-
btn.style.height = '36px';
|
|
309
|
-
btn.style.minWidth = '88px';
|
|
310
|
-
btn.style.padding = '0 16px';
|
|
311
|
-
btn.style.background = 'rgb(255, 255, 255)';
|
|
312
|
-
btn.style.border = '1px solid rgb(160, 160, 160)';
|
|
313
|
-
btn.style.borderRadius = '4px';
|
|
314
|
-
btn.style.boxShadow = '0 1px 2px rgba(0,0,0,0.15)';
|
|
315
|
-
btn.style.color = 'rgb(68, 68, 68)';
|
|
316
|
-
btn.style.fontSize = '14px';
|
|
317
|
-
btn.style.fontWeight = '500';
|
|
318
|
-
btn.style.whiteSpace = 'nowrap';
|
|
319
|
-
btn.style.cursor = 'pointer';
|
|
320
|
-
};
|
|
321
|
-
const juxModal = (title, btns = ['ok', 'cancel'], content = '', persistent = false, busy = false, body, okTxt = getTranslation('alert-ok-btn-txt'), cancelTxt = getTranslation('alert-cancel-btn-txt'), onClose, titleStyle) => {
|
|
322
|
-
const result = document.createElement('jux-modal');
|
|
323
|
-
applyModalStyle(result);
|
|
324
|
-
const wrapper = document.createElement('modal-wrapper');
|
|
325
|
-
applyWrapperStyle(wrapper);
|
|
326
|
-
// START close
|
|
327
|
-
const closeBtn = document.createElement('button');
|
|
328
|
-
if (!persistent) {
|
|
329
|
-
closeBtn.className = 'close';
|
|
330
|
-
closeBtn.setAttribute('aria-label', getTranslation('close'));
|
|
331
|
-
}
|
|
332
|
-
// END close
|
|
333
|
-
// START header
|
|
334
|
-
const header = document.createElement('modal-header');
|
|
335
|
-
applyHeaderStyle(header);
|
|
336
|
-
if (title) {
|
|
337
|
-
if (titleStyle) {
|
|
338
|
-
header.classList.add(titleStyle);
|
|
339
|
-
}
|
|
340
|
-
const h3 = document.createElement('h3');
|
|
341
|
-
h3.textContent = title;
|
|
342
|
-
h3.style.margin = '0';
|
|
343
|
-
header.appendChild(h3);
|
|
344
|
-
}
|
|
345
|
-
// END header
|
|
346
|
-
// START content
|
|
347
|
-
const modalContent = document.createElement('jux-modal-content');
|
|
348
|
-
applyJuxModalContentStyle(modalContent);
|
|
349
|
-
if (content) {
|
|
350
|
-
modalContent.innerHTML = content;
|
|
351
|
-
}
|
|
352
|
-
else if (body) {
|
|
353
|
-
modalContent.appendChild(body);
|
|
354
|
-
}
|
|
355
|
-
// END content
|
|
356
|
-
// START footer
|
|
357
|
-
const footer = document.createElement('modal-footer');
|
|
358
|
-
applyFooterStyle(footer);
|
|
359
|
-
if (btns.includes('cancel')) {
|
|
360
|
-
const cancelBtn = document.createElement('button');
|
|
361
|
-
cancelBtn.classList.add('secondary-button', 'modal-button', 'action', 'cancel-btn', 'cancel');
|
|
362
|
-
applyModalButtonStyle(cancelBtn);
|
|
363
|
-
const cancelText = document.createElement('button-text');
|
|
364
|
-
cancelText.textContent = cancelTxt;
|
|
365
|
-
const cancelSpinner = document.createElement('loading-spinner');
|
|
366
|
-
if (!busy)
|
|
367
|
-
cancelSpinner.style.display = 'none';
|
|
368
|
-
cancelBtn.append(cancelText, cancelSpinner);
|
|
369
|
-
footer.appendChild(cancelBtn);
|
|
370
|
-
}
|
|
371
|
-
if (btns.includes('ok')) {
|
|
372
|
-
const okBtn = document.createElement('button');
|
|
373
|
-
okBtn.classList.add('primary-button', 'modal-button', 'action', 'ok');
|
|
374
|
-
applyModalButtonStyle(okBtn);
|
|
375
|
-
const okText = document.createElement('button-text');
|
|
376
|
-
okText.textContent = okTxt;
|
|
377
|
-
const okSpinner = document.createElement('loading-spinner');
|
|
378
|
-
if (!busy)
|
|
379
|
-
okSpinner.style.display = 'none';
|
|
380
|
-
okBtn.append(okText, okSpinner);
|
|
381
|
-
footer.appendChild(okBtn);
|
|
382
|
-
}
|
|
383
|
-
// END footer
|
|
384
|
-
if (footer.hasChildNodes()) {
|
|
385
|
-
wrapper.append(closeBtn, header, modalContent, footer);
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
wrapper.append(closeBtn, header, modalContent);
|
|
389
|
-
}
|
|
390
|
-
result.appendChild(wrapper);
|
|
391
|
-
if (!persistent) {
|
|
392
|
-
result.querySelector('.close').focus();
|
|
393
|
-
}
|
|
394
|
-
else {
|
|
395
|
-
if (btns.includes('ok')) {
|
|
396
|
-
result.querySelector('.ok').focus();
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
attachEventHandlers(result, persistent, onClose);
|
|
400
|
-
return result;
|
|
401
|
-
};
|
|
402
|
-
|
|
403
230
|
/******************************************************************************
|
|
404
231
|
Copyright (c) Microsoft Corporation.
|
|
405
232
|
|
|
@@ -786,103 +613,384 @@ var juxWeb = (function (exports) {
|
|
|
786
613
|
// @ts-ignore
|
|
787
614
|
options.body = content;
|
|
788
615
|
}
|
|
789
|
-
return apiRequest(endpoint, options, onSuccess, onError, onRedirect, requestType, handleUnauthorized);
|
|
790
|
-
};
|
|
791
|
-
const get = (endpoint, onSuccess, onError, onRedirect, handleUnauthorized) => {
|
|
792
|
-
const options = {
|
|
793
|
-
method: 'GET',
|
|
794
|
-
headers: {
|
|
795
|
-
'Accept': 'application/json',
|
|
796
|
-
'Content-Type': 'application/json',
|
|
797
|
-
}
|
|
798
|
-
};
|
|
799
|
-
return apiRequest(endpoint, options, onSuccess, onError, onRedirect, 'query', handleUnauthorized);
|
|
800
|
-
};
|
|
801
|
-
const backendPost = (endpoint, postContent, onJsonResponse, onHelpMessage, handleUnauthorized) => {
|
|
802
|
-
post(endpoint, postContent, onJsonResponse, onHelpMessage, null, 'command', handleUnauthorized);
|
|
803
|
-
};
|
|
804
|
-
const backendGet = (endpoint, params, onJsonResponse, onHelpMessage, handleUnauthorized) => {
|
|
805
|
-
if (params) {
|
|
806
|
-
endpoint += '?';
|
|
807
|
-
Object.keys(params).forEach((k, i) => {
|
|
808
|
-
if (i > 0)
|
|
809
|
-
endpoint += '&';
|
|
810
|
-
endpoint += `${k}=${params[k]}`;
|
|
811
|
-
});
|
|
616
|
+
return apiRequest(endpoint, options, onSuccess, onError, onRedirect, requestType, handleUnauthorized);
|
|
617
|
+
};
|
|
618
|
+
const get = (endpoint, onSuccess, onError, onRedirect, handleUnauthorized) => {
|
|
619
|
+
const options = {
|
|
620
|
+
method: 'GET',
|
|
621
|
+
headers: {
|
|
622
|
+
'Accept': 'application/json',
|
|
623
|
+
'Content-Type': 'application/json',
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
return apiRequest(endpoint, options, onSuccess, onError, onRedirect, 'query', handleUnauthorized);
|
|
627
|
+
};
|
|
628
|
+
const backendPost = (endpoint, postContent, onJsonResponse, onHelpMessage, handleUnauthorized) => {
|
|
629
|
+
post(endpoint, postContent, onJsonResponse, onHelpMessage, null, 'command', handleUnauthorized);
|
|
630
|
+
};
|
|
631
|
+
const backendGet = (endpoint, params, onJsonResponse, onHelpMessage, handleUnauthorized) => {
|
|
632
|
+
if (params) {
|
|
633
|
+
endpoint += '?';
|
|
634
|
+
Object.keys(params).forEach((k, i) => {
|
|
635
|
+
if (i > 0)
|
|
636
|
+
endpoint += '&';
|
|
637
|
+
endpoint += `${k}=${params[k]}`;
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
get(endpoint, onJsonResponse, onHelpMessage, null, handleUnauthorized);
|
|
641
|
+
};
|
|
642
|
+
const requestMagicLink = (data, onJsonResponse, onUnauthorized) => {
|
|
643
|
+
const { email, token } = data;
|
|
644
|
+
const url = getMagicAuthReqUrl() +
|
|
645
|
+
encodeURIComponent(email) +
|
|
646
|
+
'&destination=' +
|
|
647
|
+
extractTokenFromWindowLocation('destination') +
|
|
648
|
+
'&token=' +
|
|
649
|
+
token;
|
|
650
|
+
const options = {};
|
|
651
|
+
backendRequest(url, options, onJsonResponse, console.error, undefined, // ← use undefined instead of null
|
|
652
|
+
'query', onUnauthorized);
|
|
653
|
+
};
|
|
654
|
+
const openMagicLink = (magicToken, onJsonResponse, onHelpMessage) => {
|
|
655
|
+
backendRequest(getMagicAuthUrl() + magicToken, {}, onJsonResponse, onHelpMessage);
|
|
656
|
+
};
|
|
657
|
+
const googleLogin = (token, onLogin, onLoginError) => {
|
|
658
|
+
const url = getBackendUrl() + 'auth-google?google-id-token=' + token;
|
|
659
|
+
backendRequest(url, {}, onLogin, onLoginError);
|
|
660
|
+
};
|
|
661
|
+
const microsoftLogin = (token, onLogin, onLoginError) => {
|
|
662
|
+
const url = getBackendUrl() + 'auth-microsoft?access-token=' + token;
|
|
663
|
+
backendRequest(url, {}, onLogin, onLoginError);
|
|
664
|
+
};
|
|
665
|
+
const getSSOAuthorizationEndpoint = (onSuccess, onError) => {
|
|
666
|
+
backendGet('openid/authorization-endpoint', null, onSuccess, onError);
|
|
667
|
+
};
|
|
668
|
+
const validateSSOToken = (token, redirectUri, onLogin, onError, handleUnauthorized) => {
|
|
669
|
+
backendGet('openid/callback', { code: token, 'redirect-uri': redirectUri }, onLogin, onError, handleUnauthorized);
|
|
670
|
+
};
|
|
671
|
+
const authPasswordLogin = (credentials, onLogin, onLoginError, handleUnauthorized) => {
|
|
672
|
+
backendPost('auth-password', credentials, onLogin, onLoginError, handleUnauthorized);
|
|
673
|
+
};
|
|
674
|
+
const getMXData = (domainName) => __awaiter$2(void 0, void 0, void 0, function* () {
|
|
675
|
+
try {
|
|
676
|
+
const records = yield fetch(`https://dns.google.com/resolve?name=${domainName}&type=MX`, {
|
|
677
|
+
method: 'GET',
|
|
678
|
+
mode: 'cors'
|
|
679
|
+
});
|
|
680
|
+
if (!records.ok) {
|
|
681
|
+
console.log('response was not ok');
|
|
682
|
+
return null;
|
|
683
|
+
}
|
|
684
|
+
const recordsJson = yield records.json();
|
|
685
|
+
const answer = recordsJson.Answer;
|
|
686
|
+
if (!answer) {
|
|
687
|
+
return null;
|
|
688
|
+
}
|
|
689
|
+
return Array.from(answer).map((a) => a.data);
|
|
690
|
+
}
|
|
691
|
+
catch (error) {
|
|
692
|
+
console.error('Fetch failed: ', error);
|
|
693
|
+
return null;
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
// TODO: find a better way to import external scripts
|
|
698
|
+
const script$1 = document.createElement('script');
|
|
699
|
+
script$1.type = 'text/javascript';
|
|
700
|
+
script$1.src = 'https://www.google.com/recaptcha/api.js?render=explicit';
|
|
701
|
+
document.head.appendChild(script$1);
|
|
702
|
+
const googleCaptcha = () => {
|
|
703
|
+
const result = document.createElement('google-captcha');
|
|
704
|
+
const notifyCaptchaChange = () => result.dispatchEvent(new Event('captcha-change'));
|
|
705
|
+
const renderCaptcha = () => grecaptcha.ready(() => {
|
|
706
|
+
grecaptcha.render(result, {
|
|
707
|
+
sitekey: process.env.GOOGLE_CAPTCHA_KEY,
|
|
708
|
+
callback: (token) => {
|
|
709
|
+
result.setAttribute('token', token);
|
|
710
|
+
notifyCaptchaChange();
|
|
711
|
+
},
|
|
712
|
+
'expired-callback': () => {
|
|
713
|
+
result.removeAttribute('token');
|
|
714
|
+
notifyCaptchaChange();
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
result.dispatchEvent(new Event('captcha-rendered'));
|
|
718
|
+
});
|
|
719
|
+
if (typeof grecaptcha === 'undefined') {
|
|
720
|
+
script$1.addEventListener('load', renderCaptcha, { once: true });
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
renderCaptcha();
|
|
724
|
+
}
|
|
725
|
+
return result;
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
const juxWhite = '#FFF';
|
|
729
|
+
const juxDarkGrey = '#282828';
|
|
730
|
+
const juxDimmedBlack = '#00000088';
|
|
731
|
+
const juxLightGreen = '#20B03D';
|
|
732
|
+
const juxMediumGreen = '#0D631E';
|
|
733
|
+
|
|
734
|
+
const onKeyDown = (ev, el, persitent, onClose) => {
|
|
735
|
+
if (ev.key === 'Escape') {
|
|
736
|
+
if (persitent) {
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
close(el, onClose);
|
|
740
|
+
}
|
|
741
|
+
else if (ev.key === 'Enter') {
|
|
742
|
+
if (ev.target.id === 'members-textarea') {
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
el.dispatchEvent(new CustomEvent('ok'));
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
const close = (el, onClose) => {
|
|
749
|
+
el.remove();
|
|
750
|
+
if (onClose) {
|
|
751
|
+
onClose();
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
const attachEventHandlers = (el, persitent, onClose) => {
|
|
755
|
+
const cancelButton = el.querySelector('.cancel');
|
|
756
|
+
cancelButton === null || cancelButton === void 0 ? void 0 : cancelButton.addEventListener('click', (_e) => {
|
|
757
|
+
el.dispatchEvent(new CustomEvent('cancel'));
|
|
758
|
+
if (el.hasAttribute('dont-remove')) {
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
close(el, onClose);
|
|
762
|
+
});
|
|
763
|
+
const closeButton = el.querySelector('.close');
|
|
764
|
+
if (closeButton) {
|
|
765
|
+
closeButton.addEventListener('click', (_e) => {
|
|
766
|
+
close(el, onClose);
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
const okButton = el.querySelector('.ok');
|
|
770
|
+
okButton === null || okButton === void 0 ? void 0 : okButton.addEventListener('click', (_e) => {
|
|
771
|
+
el.dispatchEvent(new CustomEvent('ok'));
|
|
772
|
+
});
|
|
773
|
+
el.removeEventListener('keydown', (ev) => onKeyDown(ev, el, persitent, () => onClose));
|
|
774
|
+
el.addEventListener('keydown', (ev) => onKeyDown(ev, el, persitent, () => onClose));
|
|
775
|
+
el === null || el === void 0 ? void 0 : el.addEventListener('click', (e) => {
|
|
776
|
+
if (e.target === el) {
|
|
777
|
+
if (persitent) {
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
close(el, onClose);
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
};
|
|
784
|
+
// TODO: Mudar construtor para usar essa interface
|
|
785
|
+
// interface JuxModalOptions {
|
|
786
|
+
// title?: string,
|
|
787
|
+
// btns?: string[],
|
|
788
|
+
// content?: string,
|
|
789
|
+
// isPersistent?: boolean,
|
|
790
|
+
// isBusy?: boolean,
|
|
791
|
+
// body?: HTMLElement,
|
|
792
|
+
// okTxt?: string,
|
|
793
|
+
// cancelTxt?: string,
|
|
794
|
+
// onClose?: any,
|
|
795
|
+
// titleStyle?: string,
|
|
796
|
+
// }
|
|
797
|
+
const applyWrapperStyle = (wrapper) => {
|
|
798
|
+
wrapper.style.alignItems = 'center';
|
|
799
|
+
wrapper.style.backgroundColor = juxWhite;
|
|
800
|
+
wrapper.style.borderRadius = '.3125rem';
|
|
801
|
+
wrapper.style.boxShadow = `0 0 1.33rem ${juxDimmedBlack}`;
|
|
802
|
+
wrapper.style.boxSizing = 'content-box';
|
|
803
|
+
wrapper.style.display = 'flex';
|
|
804
|
+
wrapper.style.flexDirection = 'column';
|
|
805
|
+
wrapper.style.justifyContent = 'flex-start';
|
|
806
|
+
wrapper.style.margin = '0';
|
|
807
|
+
wrapper.style.maxHeight = '88%';
|
|
808
|
+
wrapper.style.maxWidth = '40%';
|
|
809
|
+
wrapper.style.minWidth = '20%';
|
|
810
|
+
wrapper.style.padding = '2.8rem';
|
|
811
|
+
wrapper.style.position = 'relative';
|
|
812
|
+
};
|
|
813
|
+
const applyModalStyle = (modal) => {
|
|
814
|
+
modal.style.alignItems = 'center';
|
|
815
|
+
modal.style.backgroundColor = juxDimmedBlack;
|
|
816
|
+
modal.style.display = 'flex';
|
|
817
|
+
modal.style.height = '100vh';
|
|
818
|
+
modal.style.justifyContent = 'center';
|
|
819
|
+
modal.style.left = '0';
|
|
820
|
+
modal.style.overflow = 'hidden';
|
|
821
|
+
modal.style.position = 'fixed';
|
|
822
|
+
modal.style.top = '0';
|
|
823
|
+
modal.style.width = '100%';
|
|
824
|
+
modal.style.zIndex = '9999';
|
|
825
|
+
};
|
|
826
|
+
const applyHeaderStyle = (header) => {
|
|
827
|
+
header.style.alignItems = 'center';
|
|
828
|
+
header.style.color = juxMediumGreen;
|
|
829
|
+
header.style.flexDirection = 'row';
|
|
830
|
+
header.style.fontSize = '16px';
|
|
831
|
+
header.style.fontWeight = '700';
|
|
832
|
+
header.style.justifyContent = 'space-between';
|
|
833
|
+
header.style.margin = '0';
|
|
834
|
+
header.style.display = 'flex';
|
|
835
|
+
header.style.position = 'relative';
|
|
836
|
+
header.style.width = '100%';
|
|
837
|
+
};
|
|
838
|
+
const applyJuxModalContentStyle = (el) => {
|
|
839
|
+
el.style.display = 'flex';
|
|
840
|
+
el.style.position = 'relative';
|
|
841
|
+
el.style.width = '100%';
|
|
842
|
+
el.style.flexFlow = 'column';
|
|
843
|
+
el.style.marginTop = '1.33rem';
|
|
844
|
+
el.style.fontSize = '14px';
|
|
845
|
+
el.style.rowGap = '8px';
|
|
846
|
+
};
|
|
847
|
+
const applyFooterStyle = (footer) => {
|
|
848
|
+
footer.style.display = 'flex';
|
|
849
|
+
footer.style.width = '100%';
|
|
850
|
+
footer.style.justifyContent = 'flex-end';
|
|
851
|
+
footer.style.alignItems = 'center';
|
|
852
|
+
footer.style.gap = '0.75rem';
|
|
853
|
+
footer.style.marginTop = '1.5rem';
|
|
854
|
+
footer.style.paddingTop = '1rem';
|
|
855
|
+
};
|
|
856
|
+
const applyModalButtonStyle = (btn) => {
|
|
857
|
+
btn.style.display = 'inline-flex';
|
|
858
|
+
btn.style.alignItems = 'center';
|
|
859
|
+
btn.style.justifyContent = 'center';
|
|
860
|
+
btn.style.height = '36px';
|
|
861
|
+
btn.style.minWidth = '88px';
|
|
862
|
+
btn.style.padding = '0 16px';
|
|
863
|
+
btn.style.background = 'rgb(255, 255, 255)';
|
|
864
|
+
btn.style.border = '1px solid rgb(160, 160, 160)';
|
|
865
|
+
btn.style.borderRadius = '4px';
|
|
866
|
+
btn.style.boxShadow = '0 1px 2px rgba(0,0,0,0.15)';
|
|
867
|
+
btn.style.color = 'rgb(68, 68, 68)';
|
|
868
|
+
btn.style.fontSize = '14px';
|
|
869
|
+
btn.style.fontWeight = '500';
|
|
870
|
+
btn.style.whiteSpace = 'nowrap';
|
|
871
|
+
btn.style.cursor = 'pointer';
|
|
872
|
+
};
|
|
873
|
+
const juxModal = (title, btns = ['ok', 'cancel'], content = '', persistent = false, busy = false, body, okTxt = getTranslation('alert-ok-btn-txt'), cancelTxt = getTranslation('alert-cancel-btn-txt'), onClose, titleStyle) => {
|
|
874
|
+
const result = document.createElement('jux-modal');
|
|
875
|
+
applyModalStyle(result);
|
|
876
|
+
const wrapper = document.createElement('modal-wrapper');
|
|
877
|
+
applyWrapperStyle(wrapper);
|
|
878
|
+
// START close
|
|
879
|
+
const closeBtn = document.createElement('button');
|
|
880
|
+
if (!persistent) {
|
|
881
|
+
closeBtn.className = 'close';
|
|
882
|
+
closeBtn.setAttribute('aria-label', getTranslation('close'));
|
|
883
|
+
}
|
|
884
|
+
// END close
|
|
885
|
+
// START header
|
|
886
|
+
const header = document.createElement('modal-header');
|
|
887
|
+
applyHeaderStyle(header);
|
|
888
|
+
if (title) {
|
|
889
|
+
if (titleStyle) {
|
|
890
|
+
header.classList.add(titleStyle);
|
|
891
|
+
}
|
|
892
|
+
const h3 = document.createElement('h3');
|
|
893
|
+
h3.textContent = title;
|
|
894
|
+
h3.style.margin = '0';
|
|
895
|
+
header.appendChild(h3);
|
|
896
|
+
}
|
|
897
|
+
// END header
|
|
898
|
+
// START content
|
|
899
|
+
const modalContent = document.createElement('jux-modal-content');
|
|
900
|
+
applyJuxModalContentStyle(modalContent);
|
|
901
|
+
if (content) {
|
|
902
|
+
modalContent.innerHTML = content;
|
|
903
|
+
}
|
|
904
|
+
else if (body) {
|
|
905
|
+
modalContent.appendChild(body);
|
|
906
|
+
}
|
|
907
|
+
// END content
|
|
908
|
+
// START footer
|
|
909
|
+
const footer = document.createElement('modal-footer');
|
|
910
|
+
applyFooterStyle(footer);
|
|
911
|
+
if (btns.includes('cancel')) {
|
|
912
|
+
const cancelBtn = document.createElement('button');
|
|
913
|
+
cancelBtn.classList.add('secondary-button', 'modal-button', 'action', 'cancel-btn', 'cancel');
|
|
914
|
+
applyModalButtonStyle(cancelBtn);
|
|
915
|
+
const cancelText = document.createElement('button-text');
|
|
916
|
+
cancelText.textContent = cancelTxt;
|
|
917
|
+
const cancelSpinner = document.createElement('loading-spinner');
|
|
918
|
+
if (!busy)
|
|
919
|
+
cancelSpinner.style.display = 'none';
|
|
920
|
+
cancelBtn.append(cancelText, cancelSpinner);
|
|
921
|
+
footer.appendChild(cancelBtn);
|
|
922
|
+
}
|
|
923
|
+
if (btns.includes('ok')) {
|
|
924
|
+
const okBtn = document.createElement('button');
|
|
925
|
+
okBtn.classList.add('primary-button', 'modal-button', 'action', 'ok');
|
|
926
|
+
applyModalButtonStyle(okBtn);
|
|
927
|
+
const okText = document.createElement('button-text');
|
|
928
|
+
okText.textContent = okTxt;
|
|
929
|
+
const okSpinner = document.createElement('loading-spinner');
|
|
930
|
+
if (!busy)
|
|
931
|
+
okSpinner.style.display = 'none';
|
|
932
|
+
okBtn.append(okText, okSpinner);
|
|
933
|
+
footer.appendChild(okBtn);
|
|
934
|
+
}
|
|
935
|
+
// END footer
|
|
936
|
+
if (footer.hasChildNodes()) {
|
|
937
|
+
wrapper.append(closeBtn, header, modalContent, footer);
|
|
812
938
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
const requestMagicLink = (data, onJsonResponse, onUnauthorized) => {
|
|
816
|
-
const { email, token } = data;
|
|
817
|
-
const url = getMagicAuthReqUrl() +
|
|
818
|
-
encodeURIComponent(email) +
|
|
819
|
-
'&destination=' +
|
|
820
|
-
extractTokenFromWindowLocation('destination') +
|
|
821
|
-
'&token=' +
|
|
822
|
-
token;
|
|
823
|
-
const options = {};
|
|
824
|
-
backendRequest(url, options, onJsonResponse, console.error, undefined, // ← use undefined instead of null
|
|
825
|
-
'query', onUnauthorized);
|
|
826
|
-
};
|
|
827
|
-
const openMagicLink = (magicToken, onJsonResponse, onHelpMessage) => {
|
|
828
|
-
backendRequest(getMagicAuthUrl() + magicToken, {}, onJsonResponse, onHelpMessage);
|
|
829
|
-
};
|
|
830
|
-
const googleLogin = (token, onLogin, onLoginError) => {
|
|
831
|
-
const url = getBackendUrl() + 'auth-google?google-id-token=' + token;
|
|
832
|
-
backendRequest(url, {}, onLogin, onLoginError);
|
|
833
|
-
};
|
|
834
|
-
const microsoftLogin = (token, onLogin, onLoginError) => {
|
|
835
|
-
const url = getBackendUrl() + 'auth-microsoft?access-token=' + token;
|
|
836
|
-
backendRequest(url, {}, onLogin, onLoginError);
|
|
837
|
-
};
|
|
838
|
-
const getSSOAuthorizationEndpoint = (onSuccess, onError) => {
|
|
839
|
-
backendGet('openid/authorization-endpoint', null, onSuccess, onError);
|
|
840
|
-
};
|
|
841
|
-
const validateSSOToken = (token, redirectUri, onLogin, onError, handleUnauthorized) => {
|
|
842
|
-
backendGet('openid/callback', { code: token, 'redirect-uri': redirectUri }, onLogin, onError, handleUnauthorized);
|
|
843
|
-
};
|
|
844
|
-
const authPasswordLogin = (credentials, onLogin, onLoginError, handleUnauthorized) => {
|
|
845
|
-
backendPost('auth-password', credentials, onLogin, onLoginError, handleUnauthorized);
|
|
846
|
-
};
|
|
847
|
-
const getMXData = (domainName) => __awaiter$2(void 0, void 0, void 0, function* () {
|
|
848
|
-
try {
|
|
849
|
-
const records = yield fetch(`https://dns.google.com/resolve?name=${domainName}&type=MX`, {
|
|
850
|
-
method: 'GET',
|
|
851
|
-
mode: 'cors'
|
|
852
|
-
});
|
|
853
|
-
if (!records.ok) {
|
|
854
|
-
console.log('response was not ok');
|
|
855
|
-
return null;
|
|
856
|
-
}
|
|
857
|
-
const recordsJson = yield records.json();
|
|
858
|
-
const answer = recordsJson.Answer;
|
|
859
|
-
if (!answer) {
|
|
860
|
-
return null;
|
|
861
|
-
}
|
|
862
|
-
return Array.from(answer).map((a) => a.data);
|
|
939
|
+
else {
|
|
940
|
+
wrapper.append(closeBtn, header, modalContent);
|
|
863
941
|
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
942
|
+
result.appendChild(wrapper);
|
|
943
|
+
if (!persistent) {
|
|
944
|
+
result.querySelector('.close').focus();
|
|
867
945
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
document.head.appendChild(script$1);
|
|
875
|
-
const googleCaptcha = () => {
|
|
876
|
-
const result = document.createElement('google-captcha');
|
|
877
|
-
window.submitCaptcha = (token) => result.setAttribute('token', token);
|
|
878
|
-
result.className = 'g-recaptcha';
|
|
879
|
-
// @ts-ignore
|
|
880
|
-
result.setAttribute('data-sitekey', process.env.GOOGLE_CAPTCHA_KEY);
|
|
881
|
-
result.setAttribute('data-callback', 'submitCaptcha');
|
|
882
|
-
grecaptcha.render(result);
|
|
946
|
+
else {
|
|
947
|
+
if (btns.includes('ok')) {
|
|
948
|
+
result.querySelector('.ok').focus();
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
attachEventHandlers(result, persistent, onClose);
|
|
883
952
|
return result;
|
|
884
953
|
};
|
|
885
954
|
|
|
955
|
+
const loginFieldClass = 'jux-login-field';
|
|
956
|
+
const addLoginFieldStyles = () => {
|
|
957
|
+
if (document.querySelector(`style[data-${loginFieldClass}]`))
|
|
958
|
+
return;
|
|
959
|
+
const style = document.createElement('style');
|
|
960
|
+
style.setAttribute(`data-${loginFieldClass}`, '');
|
|
961
|
+
style.textContent = `
|
|
962
|
+
.${loginFieldClass}:hover {
|
|
963
|
+
outline: 1px solid #999 !important;
|
|
964
|
+
outline-offset: -1px;
|
|
965
|
+
}
|
|
966
|
+
.${loginFieldClass}:focus {
|
|
967
|
+
outline: 2px solid #3943B7 !important;
|
|
968
|
+
outline-offset: -2px;
|
|
969
|
+
}
|
|
970
|
+
`;
|
|
971
|
+
document.head.appendChild(style);
|
|
972
|
+
};
|
|
973
|
+
const applyTextFieldStyle = (field) => {
|
|
974
|
+
addLoginFieldStyles();
|
|
975
|
+
field.classList.add(loginFieldClass);
|
|
976
|
+
field.style.backgroundColor = '#fff';
|
|
977
|
+
field.style.border = '1px solid #ccc';
|
|
978
|
+
field.style.borderRadius = '8px';
|
|
979
|
+
field.style.boxShadow = 'inset 0 2px 3px #28282822';
|
|
980
|
+
field.style.boxSizing = 'border-box';
|
|
981
|
+
field.style.color = '#444';
|
|
982
|
+
field.style.cursor = 'text';
|
|
983
|
+
field.style.fontFamily = 'Helvetica, Arial, sans-serif';
|
|
984
|
+
field.style.fontSize = '16px';
|
|
985
|
+
field.style.height = '40px';
|
|
986
|
+
field.style.lineHeight = '38px';
|
|
987
|
+
field.style.margin = '0';
|
|
988
|
+
field.style.outline = 'none';
|
|
989
|
+
field.style.overflow = 'hidden';
|
|
990
|
+
field.style.padding = '0 12px';
|
|
991
|
+
field.style.width = '100%';
|
|
992
|
+
};
|
|
993
|
+
|
|
886
994
|
const socialLoginModal = (userEmail, mailExchanger, token, onUserLogin, onReturn, backgroundImage, currentPage, clientBody, closeMagicLinkModal, handlers) => {
|
|
887
995
|
const result = document.createElement('social-login-modal');
|
|
888
996
|
const email = document.createElement('p');
|
|
@@ -956,77 +1064,118 @@ var juxWeb = (function (exports) {
|
|
|
956
1064
|
closeMagicLinkModal();
|
|
957
1065
|
});
|
|
958
1066
|
const applyMagicEmailFieldStyle = (el) => {
|
|
1067
|
+
el.style.alignItems = 'center';
|
|
959
1068
|
el.style.display = 'flex';
|
|
960
|
-
el.style.flexFlow = '
|
|
1069
|
+
el.style.flexFlow = 'row';
|
|
1070
|
+
el.style.gap = '0';
|
|
961
1071
|
el.style.marginTop = '8px';
|
|
962
|
-
el.style.rowGap = '8px';
|
|
963
1072
|
el.style.width = '100%';
|
|
964
1073
|
};
|
|
965
|
-
const
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1074
|
+
const applyCaptchaStyle = (captcha) => {
|
|
1075
|
+
const captchaFrameWidth = 304;
|
|
1076
|
+
const captchaHeight = 78;
|
|
1077
|
+
const contentWidth = 356;
|
|
1078
|
+
const horizontalInset = 1;
|
|
1079
|
+
const scale = (contentWidth - horizontalInset * 2) / captchaFrameWidth;
|
|
1080
|
+
captcha.style.height = `${captchaHeight * scale}px`;
|
|
1081
|
+
captcha.style.overflow = 'visible';
|
|
1082
|
+
captcha.style.width = '100%';
|
|
1083
|
+
const applyWidgetStyle = () => {
|
|
1084
|
+
const widget = captcha.firstElementChild;
|
|
1085
|
+
widget.style.marginLeft = `${horizontalInset}px`;
|
|
1086
|
+
widget.style.width = `${captchaFrameWidth}px`;
|
|
1087
|
+
widget.style.transform = `scale(${scale})`;
|
|
1088
|
+
widget.style.transformOrigin = 'top left';
|
|
1089
|
+
};
|
|
1090
|
+
if (captcha.firstElementChild) {
|
|
1091
|
+
applyWidgetStyle();
|
|
1092
|
+
}
|
|
1093
|
+
else {
|
|
1094
|
+
captcha.addEventListener('captcha-rendered', applyWidgetStyle, { once: true });
|
|
1095
|
+
}
|
|
976
1096
|
};
|
|
977
1097
|
const applyBtnStyle = (btn) => {
|
|
978
|
-
btn.style.alignSelf = 'flex-end';
|
|
979
1098
|
btn.style.backgroundColor = juxLightGreen;
|
|
980
1099
|
btn.style.border = `2px solid ${juxLightGreen}`;
|
|
981
1100
|
btn.style.borderRadius = '8px';
|
|
1101
|
+
btn.style.boxSizing = 'border-box';
|
|
982
1102
|
btn.style.color = juxWhite;
|
|
983
1103
|
btn.style.cursor = 'pointer';
|
|
984
1104
|
btn.style.display = 'inline-block';
|
|
1105
|
+
btn.style.fontSize = '16px';
|
|
985
1106
|
btn.style.fontWeight = '700';
|
|
986
1107
|
btn.style.height = '40px';
|
|
987
1108
|
btn.style.lineHeight = '1';
|
|
988
|
-
btn.style.marginLeft = '10px';
|
|
989
1109
|
btn.style.padding = '10px 16px';
|
|
990
1110
|
btn.style.position = 'relative';
|
|
991
1111
|
};
|
|
1112
|
+
const captchaModal = (onVerified, onClose) => {
|
|
1113
|
+
const body = document.createElement('captcha-modal-body');
|
|
1114
|
+
body.style.width = '356px';
|
|
1115
|
+
const modal = juxModal('Security check', [], '', false, false, body, '', '', onClose);
|
|
1116
|
+
modal.id = 'magic-email-captcha-modal';
|
|
1117
|
+
const wrapper = modal.querySelector('modal-wrapper');
|
|
1118
|
+
wrapper.style.maxWidth = '356px';
|
|
1119
|
+
wrapper.style.minWidth = '356px';
|
|
1120
|
+
wrapper.style.width = '356px';
|
|
1121
|
+
modal.querySelector('modal-header h3').style.color = juxDarkGrey;
|
|
1122
|
+
document.body.appendChild(modal);
|
|
1123
|
+
const captcha = googleCaptcha();
|
|
1124
|
+
applyCaptchaStyle(captcha);
|
|
1125
|
+
captcha.addEventListener('captcha-change', () => {
|
|
1126
|
+
const token = captcha.getAttribute('token');
|
|
1127
|
+
if (!token)
|
|
1128
|
+
return;
|
|
1129
|
+
modal.remove();
|
|
1130
|
+
onVerified(token);
|
|
1131
|
+
});
|
|
1132
|
+
body.appendChild(captcha);
|
|
1133
|
+
return modal;
|
|
1134
|
+
};
|
|
992
1135
|
const magicEmailField = (onUserLogin, onReturn, backgroundImage, currentPage, clientBody, closeMagicLinkModal, loginTypes, handlers) => {
|
|
993
1136
|
const result = document.createElement('magic-email-field');
|
|
994
1137
|
applyMagicEmailFieldStyle(result);
|
|
995
|
-
const captcha = googleCaptcha();
|
|
996
1138
|
const input = document.createElement('input');
|
|
997
1139
|
input.id = 'mail-magic';
|
|
998
1140
|
input.type = 'text';
|
|
999
|
-
input.
|
|
1000
|
-
input
|
|
1001
|
-
|
|
1002
|
-
input.
|
|
1003
|
-
|
|
1004
|
-
onMagicLinkRequest(captcha.getAttribute('token'), input, onUserLogin, onReturn, backgroundImage, currentPage, clientBody, closeMagicLinkModal, loginTypes, handlers);
|
|
1005
|
-
}
|
|
1006
|
-
});
|
|
1141
|
+
input.placeholder = 'Email';
|
|
1142
|
+
applyTextFieldStyle(input);
|
|
1143
|
+
input.style.borderRadius = '8px 0 0 8px';
|
|
1144
|
+
input.style.flex = '1';
|
|
1145
|
+
input.style.minWidth = '0';
|
|
1007
1146
|
const btn = document.createElement('button');
|
|
1008
1147
|
applyBtnStyle(btn);
|
|
1009
1148
|
btn.id = 'send-magic';
|
|
1010
1149
|
btn.className = 'primary-button';
|
|
1011
|
-
btn.addEventListener('click', (_ev) => onMagicLinkRequest(captcha.getAttribute('token'), input, onUserLogin, onReturn, backgroundImage, currentPage, clientBody, closeMagicLinkModal, loginTypes, handlers));
|
|
1012
1150
|
btn.textContent = getTranslation('send-magic');
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1151
|
+
btn.style.borderRadius = '0 8px 8px 0';
|
|
1152
|
+
btn.style.margin = '0';
|
|
1153
|
+
let openCaptchaModal = null;
|
|
1154
|
+
const requestMagicLink = (token) => onMagicLinkRequest(token, input, onUserLogin, onReturn, backgroundImage, currentPage, clientBody, closeMagicLinkModal, loginTypes, handlers);
|
|
1155
|
+
btn.addEventListener('click', () => {
|
|
1156
|
+
if (input.value.includes('-test@')) {
|
|
1157
|
+
requestMagicLink(null);
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
if (openCaptchaModal === null || openCaptchaModal === void 0 ? void 0 : openCaptchaModal.isConnected)
|
|
1161
|
+
return;
|
|
1162
|
+
openCaptchaModal = captchaModal((token) => {
|
|
1163
|
+
openCaptchaModal = null;
|
|
1164
|
+
requestMagicLink(token);
|
|
1165
|
+
}, () => openCaptchaModal = null);
|
|
1166
|
+
});
|
|
1167
|
+
const updateButtonState = () => {
|
|
1168
|
+
btn.disabled = !isValidEmail(input.value);
|
|
1169
|
+
btn.style.cursor = btn.disabled ? 'not-allowed' : 'pointer';
|
|
1170
|
+
btn.style.opacity = btn.disabled ? '0.5' : '1';
|
|
1171
|
+
};
|
|
1172
|
+
input.addEventListener('input', updateButtonState);
|
|
1173
|
+
input.addEventListener('keydown', (ev) => {
|
|
1174
|
+
if (ev.key === 'Enter' && !btn.disabled)
|
|
1175
|
+
btn.click();
|
|
1176
|
+
});
|
|
1177
|
+
updateButtonState();
|
|
1178
|
+
result.append(input, btn);
|
|
1030
1179
|
return result;
|
|
1031
1180
|
};
|
|
1032
1181
|
|
|
@@ -1045,6 +1194,8 @@ var juxWeb = (function (exports) {
|
|
|
1045
1194
|
container.style.justifyContent = 'center';
|
|
1046
1195
|
container.style.margin = '0 auto';
|
|
1047
1196
|
container.style.paddingTop = '0';
|
|
1197
|
+
container.style.paddingInline = '36px';
|
|
1198
|
+
container.style.boxSizing = 'border-box';
|
|
1048
1199
|
};
|
|
1049
1200
|
const applyBtnsContainerStyles = (container) => {
|
|
1050
1201
|
container.style.display = 'flex';
|
|
@@ -1072,6 +1223,78 @@ var juxWeb = (function (exports) {
|
|
|
1072
1223
|
return result;
|
|
1073
1224
|
};
|
|
1074
1225
|
|
|
1226
|
+
class JuxWebGlobal {
|
|
1227
|
+
setCurrentUser(newUser) {
|
|
1228
|
+
this._currentUser = newUser;
|
|
1229
|
+
}
|
|
1230
|
+
getCurrentUser() {
|
|
1231
|
+
return this._currentUser;
|
|
1232
|
+
}
|
|
1233
|
+
setBackendToken(token) {
|
|
1234
|
+
this._backendToken = token;
|
|
1235
|
+
}
|
|
1236
|
+
getBackendToken() {
|
|
1237
|
+
return this._backendToken;
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
const resetJuxWebGlobal = () => {
|
|
1242
|
+
window.juxWebGlobal = new JuxWebGlobal();
|
|
1243
|
+
};
|
|
1244
|
+
const getCurrentUser = () => {
|
|
1245
|
+
var _a;
|
|
1246
|
+
return (_a = window.juxWebGlobal) === null || _a === void 0 ? void 0 : _a.getCurrentUser();
|
|
1247
|
+
};
|
|
1248
|
+
|
|
1249
|
+
const setBackendToken = (token) => {
|
|
1250
|
+
var _a;
|
|
1251
|
+
(_a = window.juxWebGlobal) === null || _a === void 0 ? void 0 : _a.setBackendToken(token);
|
|
1252
|
+
if (token)
|
|
1253
|
+
setLocalStorageItem('token', token);
|
|
1254
|
+
};
|
|
1255
|
+
const clearSession = () => {
|
|
1256
|
+
removeLocalStorageItem('token');
|
|
1257
|
+
resetJuxWebGlobal();
|
|
1258
|
+
};
|
|
1259
|
+
const onTokenAcquired = (token, onUserLogin) => {
|
|
1260
|
+
setBackendToken(token);
|
|
1261
|
+
onUserLogin();
|
|
1262
|
+
};
|
|
1263
|
+
|
|
1264
|
+
const applyLoginTokenStyle = (textarea) => {
|
|
1265
|
+
applyTextFieldStyle(textarea);
|
|
1266
|
+
textarea.style.resize = 'none';
|
|
1267
|
+
textarea.style.setProperty('-webkit-text-security', 'disc');
|
|
1268
|
+
};
|
|
1269
|
+
const loginTokenTextarea = (onUserLogin, onLoginError) => {
|
|
1270
|
+
const juxWebGlobal = window.juxWebGlobal;
|
|
1271
|
+
const textarea = document.createElement('textarea');
|
|
1272
|
+
textarea.id = 'input-login-token';
|
|
1273
|
+
textarea.autocomplete = 'off';
|
|
1274
|
+
textarea.placeholder = 'Paste sign-in token';
|
|
1275
|
+
textarea.rows = 1;
|
|
1276
|
+
textarea.spellcheck = false;
|
|
1277
|
+
textarea.setAttribute('aria-label', 'Sign-in token');
|
|
1278
|
+
applyLoginTokenStyle(textarea);
|
|
1279
|
+
let loginInProgress = false;
|
|
1280
|
+
textarea.addEventListener('input', () => {
|
|
1281
|
+
const loginToken = textarea.value.trim();
|
|
1282
|
+
if (loginToken.length !== 16 || loginInProgress)
|
|
1283
|
+
return;
|
|
1284
|
+
loginInProgress = true;
|
|
1285
|
+
juxWebGlobal.setBackendToken(loginToken);
|
|
1286
|
+
backendGet('profile', null, (res) => {
|
|
1287
|
+
juxWebGlobal.setCurrentUser(res);
|
|
1288
|
+
onTokenAcquired(loginToken, onUserLogin);
|
|
1289
|
+
}, (err) => {
|
|
1290
|
+
loginInProgress = false;
|
|
1291
|
+
juxWebGlobal.setBackendToken('');
|
|
1292
|
+
onLoginError(err);
|
|
1293
|
+
});
|
|
1294
|
+
});
|
|
1295
|
+
return textarea;
|
|
1296
|
+
};
|
|
1297
|
+
|
|
1075
1298
|
const authPasswordRow = (type, autoCompleteValue) => {
|
|
1076
1299
|
const result = document.createElement(`${type}-row`);
|
|
1077
1300
|
result.style.display = 'flex';
|
|
@@ -1135,20 +1358,56 @@ var juxWeb = (function (exports) {
|
|
|
1135
1358
|
});
|
|
1136
1359
|
return result;
|
|
1137
1360
|
};
|
|
1138
|
-
const onEmailLoginRequest = (clientApp, loginPage, onUserLogin, backgroundImage, loginTypes, handlers) => {
|
|
1139
|
-
const onReturn = () => clientApp.appendChild(loginPage);
|
|
1140
|
-
loginPage.appendChild(magicLinkModal(onUserLogin, onReturn, backgroundImage, loginPage, clientApp, loginTypes, handlers));
|
|
1141
|
-
};
|
|
1142
1361
|
const appendLoginTypes = (loginPage, btnsContainer, clientApp, onUserLogin, onLoginError, loginTypes, backgroundImg, explanation, handleSSOLogin, handlers) => {
|
|
1143
1362
|
const upperLoginTypes = loginTypes.map(str => str.toUpperCase());
|
|
1363
|
+
if (upperLoginTypes.length === 0) {
|
|
1364
|
+
applyFormattedTranslation(explanation, 'sign-in-no-login-type');
|
|
1365
|
+
btnsContainer.replaceChildren();
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1144
1368
|
const onlyAuth = upperLoginTypes.length > 0 &&
|
|
1145
1369
|
upperLoginTypes.every(type => type === 'AUTH-PASSWORD');
|
|
1146
|
-
|
|
1370
|
+
const onlyEmail = upperLoginTypes.every(type => type === 'EMAIL');
|
|
1371
|
+
applyFormattedTranslation(explanation, 'sign-in-explanation');
|
|
1372
|
+
const showLoginTypes = () => {
|
|
1373
|
+
btnsContainer.replaceChildren();
|
|
1374
|
+
appendLoginTypes(loginPage, btnsContainer, clientApp, onUserLogin, onLoginError, loginTypes, backgroundImg, explanation, handleSSOLogin, handlers);
|
|
1375
|
+
};
|
|
1376
|
+
const showEmailLogin = () => {
|
|
1377
|
+
btnsContainer.replaceChildren();
|
|
1378
|
+
applyFormattedTranslation(explanation, 'magic-link-request-title');
|
|
1379
|
+
const subtitle = document.createElement('magic-link-request-subtitle');
|
|
1380
|
+
subtitle.style.fontSize = '14px';
|
|
1381
|
+
subtitle.style.lineHeight = '20px';
|
|
1382
|
+
subtitle.style.marginLeft = '2px';
|
|
1383
|
+
subtitle.style.marginTop = '12px';
|
|
1384
|
+
subtitle.style.width = 'calc(100% - 2px)';
|
|
1385
|
+
subtitle.textContent = getTranslation('magic-link-request-subtitle');
|
|
1386
|
+
const onReturn = () => {
|
|
1387
|
+
showLoginTypes();
|
|
1388
|
+
clientApp.appendChild(loginPage);
|
|
1389
|
+
};
|
|
1390
|
+
const content = document.createElement('email-login-content');
|
|
1391
|
+
content.style.alignItems = 'center';
|
|
1392
|
+
content.style.display = 'flex';
|
|
1393
|
+
content.style.flexDirection = 'column';
|
|
1394
|
+
content.style.width = '356px';
|
|
1395
|
+
const tokenInput = loginTokenTextarea(onUserLogin, onLoginError);
|
|
1396
|
+
tokenInput.style.marginTop = '24px';
|
|
1397
|
+
content.append(subtitle, magicEmailField(onUserLogin, onReturn, backgroundImg, loginPage, clientApp, () => { }, upperLoginTypes, handlers), tokenInput);
|
|
1398
|
+
btnsContainer.appendChild(content);
|
|
1399
|
+
if (!onlyEmail)
|
|
1400
|
+
btnsContainer.appendChild(backButton('Back', showLoginTypes));
|
|
1401
|
+
};
|
|
1402
|
+
if (onlyEmail) {
|
|
1403
|
+
showEmailLogin();
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1147
1406
|
if (upperLoginTypes.includes('AUTH-PASSWORD2') || onlyAuth) {
|
|
1148
1407
|
btnsContainer.replaceChildren();
|
|
1149
1408
|
btnsContainer.appendChild(authPasswordForm(clientApp, loginPage, onUserLogin, onLoginError, backgroundImg, handlers));
|
|
1150
1409
|
upperLoginTypes.pop();
|
|
1151
|
-
explanation
|
|
1410
|
+
applyFormattedTranslation(explanation, 'sign-in-email');
|
|
1152
1411
|
if (!onlyAuth) {
|
|
1153
1412
|
btnsContainer.appendChild(backButton('Back', () => {
|
|
1154
1413
|
btnsContainer.replaceChildren();
|
|
@@ -1172,7 +1431,7 @@ var juxWeb = (function (exports) {
|
|
|
1172
1431
|
btnsContainer.appendChild(loginButton('LINKEDIN', () => console.log('login with Linkedin')));
|
|
1173
1432
|
}
|
|
1174
1433
|
if (upperLoginTypes.includes('EMAIL')) {
|
|
1175
|
-
btnsContainer.appendChild(loginButton('EMAIL',
|
|
1434
|
+
btnsContainer.appendChild(loginButton('EMAIL', showEmailLogin));
|
|
1176
1435
|
}
|
|
1177
1436
|
if (upperLoginTypes.includes('AUTH-PASSWORD')) {
|
|
1178
1437
|
upperLoginTypes.push('AUTH-PASSWORD2');
|
|
@@ -1187,7 +1446,7 @@ var juxWeb = (function (exports) {
|
|
|
1187
1446
|
const salutation = document.createElement('sign-in-salutation');
|
|
1188
1447
|
salutation.textContent = getTranslation('sign-in-salutation');
|
|
1189
1448
|
const explanation = document.createElement('sign-in-explanation');
|
|
1190
|
-
explanation
|
|
1449
|
+
applyFormattedTranslation(explanation, 'sign-in-explanation');
|
|
1191
1450
|
const msg = document.createElement('sign-in-msg');
|
|
1192
1451
|
msg.textContent = getTranslation('sign-in-msg-general');
|
|
1193
1452
|
content.push(salutation, explanation, msg);
|
|
@@ -14565,44 +14824,6 @@ var juxWeb = (function (exports) {
|
|
|
14565
14824
|
document.body.style.pointerEvents = 'auto';
|
|
14566
14825
|
};
|
|
14567
14826
|
|
|
14568
|
-
class JuxWebGlobal {
|
|
14569
|
-
setCurrentUser(newUser) {
|
|
14570
|
-
this._currentUser = newUser;
|
|
14571
|
-
}
|
|
14572
|
-
getCurrentUser() {
|
|
14573
|
-
return this._currentUser;
|
|
14574
|
-
}
|
|
14575
|
-
setBackendToken(token) {
|
|
14576
|
-
this._backendToken = token;
|
|
14577
|
-
}
|
|
14578
|
-
getBackendToken() {
|
|
14579
|
-
return this._backendToken;
|
|
14580
|
-
}
|
|
14581
|
-
}
|
|
14582
|
-
|
|
14583
|
-
const resetJuxWebGlobal = () => {
|
|
14584
|
-
window.juxWebGlobal = new JuxWebGlobal();
|
|
14585
|
-
};
|
|
14586
|
-
const getCurrentUser = () => {
|
|
14587
|
-
var _a;
|
|
14588
|
-
return (_a = window.juxWebGlobal) === null || _a === void 0 ? void 0 : _a.getCurrentUser();
|
|
14589
|
-
};
|
|
14590
|
-
|
|
14591
|
-
const setBackendToken = (token) => {
|
|
14592
|
-
var _a;
|
|
14593
|
-
(_a = window.juxWebGlobal) === null || _a === void 0 ? void 0 : _a.setBackendToken(token);
|
|
14594
|
-
if (token)
|
|
14595
|
-
setLocalStorageItem('token', token);
|
|
14596
|
-
};
|
|
14597
|
-
const clearSession = () => {
|
|
14598
|
-
removeLocalStorageItem('token');
|
|
14599
|
-
resetJuxWebGlobal();
|
|
14600
|
-
};
|
|
14601
|
-
const onTokenAcquired = (token, onUserLogin) => {
|
|
14602
|
-
setBackendToken(token);
|
|
14603
|
-
onUserLogin();
|
|
14604
|
-
};
|
|
14605
|
-
|
|
14606
14827
|
// TODO: find a better way to import external scripts
|
|
14607
14828
|
const script = document.createElement('script');
|
|
14608
14829
|
script.type = 'text/javascript';
|
|
@@ -14838,7 +15059,7 @@ var juxWeb = (function (exports) {
|
|
|
14838
15059
|
email.style.marginBottom = '10px';
|
|
14839
15060
|
const howTo = document.createElement('p');
|
|
14840
15061
|
howTo.id = 'magic-link-how-to';
|
|
14841
|
-
howTo
|
|
15062
|
+
applyFormattedTranslation(howTo, howTo.id);
|
|
14842
15063
|
howTo.style.padding = '0 30px';
|
|
14843
15064
|
howTo.style.textAlign = 'center';
|
|
14844
15065
|
const btn = document.createElement('button');
|
|
@@ -14873,7 +15094,7 @@ var juxWeb = (function (exports) {
|
|
|
14873
15094
|
email.style.marginBottom = '10px';
|
|
14874
15095
|
const info = document.createElement('p');
|
|
14875
15096
|
info.id = 'magic-link-fail-info';
|
|
14876
|
-
info
|
|
15097
|
+
applyFormattedTranslation(info, failInfo || info.id);
|
|
14877
15098
|
info.style.padding = '0 30px';
|
|
14878
15099
|
info.style.textAlign = 'center';
|
|
14879
15100
|
const back = document.createElement('a');
|
|
@@ -14951,9 +15172,9 @@ var juxWeb = (function (exports) {
|
|
|
14951
15172
|
window.juxWebGlobal.fetchUserBackendUrl = fetchUserBackendUrl;
|
|
14952
15173
|
window.juxWebGlobal.magicLinkRequestEndpoint = magicLinkRequestEndpoint;
|
|
14953
15174
|
window.juxWebGlobal.magicLinkAuthEndpoint = magicLinkAuthEndpoint;
|
|
14954
|
-
const supportedLoginTypesArray = Array.isArray(supportedLoginTypes)
|
|
15175
|
+
const supportedLoginTypesArray = (Array.isArray(supportedLoginTypes)
|
|
14955
15176
|
? supportedLoginTypes
|
|
14956
|
-
: [supportedLoginTypes];
|
|
15177
|
+
: [supportedLoginTypes]).filter((loginType) => typeof loginType === 'string' && loginType.trim().length > 0);
|
|
14957
15178
|
const signInToken = extractTokenFromWindowLocation('sign-in') || extractTokenFromWindowLocation('magic-link');
|
|
14958
15179
|
if (signInToken) {
|
|
14959
15180
|
const onOpenMagicLink = () => {
|
|
@@ -15080,6 +15301,22 @@ var juxWeb = (function (exports) {
|
|
|
15080
15301
|
onRequestMagicLink();
|
|
15081
15302
|
};
|
|
15082
15303
|
|
|
15304
|
+
const magicLinkModal = (onUserLogin, onReturn, backgroundImage, currentPage, clientBody, loginTypes, handlers) => {
|
|
15305
|
+
const result = document.createElement('magic-link-modal');
|
|
15306
|
+
const subtitle = document.createElement('magic-link-request-subtitle');
|
|
15307
|
+
subtitle.style.fontSize = '14px';
|
|
15308
|
+
subtitle.textContent = getTranslation('magic-link-request-subtitle');
|
|
15309
|
+
const body = document.createElement('magic-link-request-body');
|
|
15310
|
+
body.append(subtitle, magicEmailField(onUserLogin, onReturn, backgroundImage, currentPage, clientBody, () => result.remove(), loginTypes, handlers));
|
|
15311
|
+
const modal = juxModal(getTranslation('magic-link-request-title'), [], '', false, false, body, '', '', () => result.remove());
|
|
15312
|
+
modal.setAttribute('data-cy', 'magic-link-modal');
|
|
15313
|
+
result.appendChild(modal);
|
|
15314
|
+
const wrapper = modal.querySelector('modal-wrapper');
|
|
15315
|
+
wrapper.style.maxWidth = '360px';
|
|
15316
|
+
wrapper.style.width = '100%';
|
|
15317
|
+
return result;
|
|
15318
|
+
};
|
|
15319
|
+
|
|
15083
15320
|
class JuxEvent extends Event {
|
|
15084
15321
|
constructor(type, method, endpoint, onResult, params, onError, onRedirect, extras) {
|
|
15085
15322
|
super('jux-event', { bubbles: true, cancelable: true, composed: true });
|
|
@@ -15102,6 +15339,8 @@ var juxWeb = (function (exports) {
|
|
|
15102
15339
|
|
|
15103
15340
|
exports.clearSession = clearSession;
|
|
15104
15341
|
exports.command = command;
|
|
15342
|
+
exports.createFormattedParagraph = createFormattedParagraph;
|
|
15343
|
+
exports.formatTextToMarkdown = formatTextToMarkdown;
|
|
15105
15344
|
exports.getCurrentUser = getCurrentUser;
|
|
15106
15345
|
exports.getTranslation = getTranslation;
|
|
15107
15346
|
exports.handleJuxEvent = handleJuxEvent;
|