@crowdin/app-project-module 2.2.0 → 2.4.0
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/out/middlewares/ui-module.js +1 -2
- package/out/modules/about.d.ts +4 -0
- package/out/modules/about.js +25 -3
- package/out/static/css/styles.css +2 -342
- package/out/static/ui/about.bundle.js +542 -0
- package/out/static/ui/about.bundle.js.map +1 -0
- package/out/static/ui/error.bundle.js +120 -2
- package/out/static/ui/error.bundle.js.map +1 -1
- package/out/static/ui/form.bundle.js +164 -12
- package/out/static/ui/form.bundle.js.map +1 -1
- package/out/static/ui/install.bundle.js +8 -2
- package/out/static/ui/install.bundle.js.map +1 -1
- package/out/static/ui/login.bundle.js +425 -35
- package/out/static/ui/login.bundle.js.map +1 -1
- package/out/static/ui/main.bundle.js +1798 -1377
- package/out/static/ui/main.bundle.js.map +1 -1
- package/out/static/ui/oauth.bundle.js +8 -2
- package/out/static/ui/oauth.bundle.js.map +1 -1
- package/out/static/ui/subscription.bundle.js +542 -0
- package/out/static/ui/subscription.bundle.js.map +1 -0
- package/out/storage/drizzle/postgresql/migrations/0002_equal_skrulls.sql +3 -0
- package/out/storage/drizzle/postgresql/migrations/meta/0002_snapshot.json +646 -0
- package/out/storage/drizzle/postgresql/migrations/meta/_journal.json +7 -0
- package/out/storage/drizzle/postgresql/schema.js +2 -1
- package/out/storage/drizzle/sqlite/migrations/0001_new_rhodey.sql +26 -0
- package/out/storage/drizzle/sqlite/migrations/meta/0001_snapshot.json +687 -0
- package/out/storage/drizzle/sqlite/migrations/meta/_journal.json +7 -0
- package/out/storage/drizzle/sqlite/schema.js +2 -1
- package/out/util/jsx-renderer.d.ts +2 -1
- package/out/util/jsx-renderer.js +8 -8
- package/out/views/FormPage.js +2 -2
- package/out/views/index.d.ts +0 -2
- package/out/views/index.js +1 -5
- package/out/views/layout/Head.js +0 -10
- package/package.json +5 -2
- package/out/static/css/about.css +0 -128
- package/out/static/css/crowdin-ui-colors.css +0 -115
- package/out/static/js/dependent.js +0 -315
- package/out/static/js/main.js +0 -96
- package/out/static/js/polyfills/fetch.js +0 -494
- package/out/static/js/polyfills/promise.js +0 -375
- package/out/views/AboutPage.d.ts +0 -10
- package/out/views/AboutPage.js +0 -88
- package/out/views/SubscriptionPage.d.ts +0 -7
- package/out/views/SubscriptionPage.js +0 -26
|
@@ -518,80 +518,1140 @@
|
|
|
518
518
|
|
|
519
519
|
var clientExports = requireClient();
|
|
520
520
|
|
|
521
|
+
/// <reference path="../types.d.ts" />
|
|
522
|
+
const postPromises = {};
|
|
523
|
+
let isInitialized = false;
|
|
524
|
+
let origin = null;
|
|
525
|
+
let clientId = null;
|
|
526
|
+
let restParams = '';
|
|
527
|
+
function parseJson(value) {
|
|
528
|
+
try {
|
|
529
|
+
return JSON.parse(value);
|
|
530
|
+
}
|
|
531
|
+
catch {
|
|
532
|
+
return undefined;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function handleMessage(event) {
|
|
536
|
+
if (event.origin !== window.location.origin || typeof event.data !== 'string') {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const eventData = parseJson(event.data);
|
|
540
|
+
if (!(eventData === null || eventData === void 0 ? void 0 : eventData.uid)) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const postPromise = postPromises[eventData.uid];
|
|
544
|
+
if (postPromise) {
|
|
545
|
+
delete postPromises[eventData.uid];
|
|
546
|
+
if (postPromise.timer) {
|
|
547
|
+
clearTimeout(postPromise.timer);
|
|
548
|
+
}
|
|
549
|
+
postPromise.resolve(eventData.data);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
function initializeCrowdinIframeContext() {
|
|
553
|
+
if (isInitialized) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
557
|
+
origin = urlParams.get('origin');
|
|
558
|
+
clientId = urlParams.get('client_id');
|
|
559
|
+
restParams = window.location.search;
|
|
560
|
+
JSON.parse(window.name);
|
|
561
|
+
window.addEventListener('message', handleMessage);
|
|
562
|
+
isInitialized = true;
|
|
563
|
+
}
|
|
564
|
+
function ensureInitialized() {
|
|
565
|
+
if (!isInitialized) {
|
|
566
|
+
initializeCrowdinIframeContext();
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function showToast(message) {
|
|
570
|
+
if (message) {
|
|
571
|
+
const toasts = document.querySelector('crowdin-toasts');
|
|
572
|
+
if (toasts && toasts.pushToasts) {
|
|
573
|
+
toasts.pushToasts([message]);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
function reloadLocation() {
|
|
578
|
+
ensureInitialized();
|
|
579
|
+
window.location.href =
|
|
580
|
+
window.location.protocol + '//' + window.location.host + window.location.pathname + restParams;
|
|
581
|
+
}
|
|
582
|
+
function catchRejection(e, message) {
|
|
583
|
+
var _a;
|
|
584
|
+
// session expired
|
|
585
|
+
if (e.code && e.code === 401) {
|
|
586
|
+
reloadLocation();
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
// payment required
|
|
590
|
+
if (e.code && e.code === 402 && ((_a = window.app) === null || _a === void 0 ? void 0 : _a.subscriptionModal.current)) {
|
|
591
|
+
if (window.app.subscriptionLink) {
|
|
592
|
+
window.app.subscriptionLink.current = e.message || message;
|
|
593
|
+
}
|
|
594
|
+
window.app.openModal(window.app.subscriptionModal.current);
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
showToast(e.message || message);
|
|
598
|
+
}
|
|
599
|
+
function checkResponse(response) {
|
|
600
|
+
return new Promise((resolve, reject) => {
|
|
601
|
+
if (response.status === 204) {
|
|
602
|
+
return resolve(undefined);
|
|
603
|
+
}
|
|
604
|
+
response
|
|
605
|
+
.json()
|
|
606
|
+
.then((res) => {
|
|
607
|
+
if (![200, 201, 202, 304].includes(response.status)) {
|
|
608
|
+
reject(res);
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
if (res.message) {
|
|
612
|
+
setTimeout(() => showToast(res.message), 100);
|
|
613
|
+
}
|
|
614
|
+
resolve(res);
|
|
615
|
+
}
|
|
616
|
+
})
|
|
617
|
+
.catch((e) => {
|
|
618
|
+
reject(e);
|
|
619
|
+
});
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
function checkOrigin() {
|
|
623
|
+
ensureInitialized();
|
|
624
|
+
return new Promise((resolve) => {
|
|
625
|
+
AP.getJwtToken((jwtToken) => {
|
|
626
|
+
restParams = `?origin=${origin}&client_id=${clientId}&jwtToken=${jwtToken}`;
|
|
627
|
+
resolve(restParams);
|
|
628
|
+
});
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function readPageProps() {
|
|
633
|
+
const element = document.getElementById('__PAGE_PROPS__');
|
|
634
|
+
return JSON.parse((element === null || element === void 0 ? void 0 : element.textContent) || '{}');
|
|
635
|
+
}
|
|
636
|
+
|
|
521
637
|
var reactExports = requireReact();
|
|
522
638
|
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
639
|
+
const dependencyShowClassName = 'dependency-show';
|
|
640
|
+
const events = ['input', 'change'];
|
|
641
|
+
function useFieldDependencies(refreshKey) {
|
|
642
|
+
const cleanupRef = reactExports.useRef(() => undefined);
|
|
643
|
+
const refreshDependencies = reactExports.useCallback(() => {
|
|
644
|
+
cleanupRef.current();
|
|
645
|
+
cleanupRef.current = initializeFieldDependencies();
|
|
646
|
+
}, []);
|
|
647
|
+
reactExports.useEffect(() => {
|
|
648
|
+
refreshDependencies();
|
|
649
|
+
return () => {
|
|
650
|
+
cleanupRef.current();
|
|
651
|
+
cleanupRef.current = () => undefined;
|
|
652
|
+
};
|
|
653
|
+
}, [refreshDependencies, refreshKey]);
|
|
654
|
+
return refreshDependencies;
|
|
655
|
+
}
|
|
656
|
+
function initializeFieldDependencies(root = document) {
|
|
657
|
+
const cleanupCallbacks = [];
|
|
658
|
+
const fields = Array.from(root.querySelectorAll('[data-dependency]'));
|
|
659
|
+
fields.forEach((field) => {
|
|
660
|
+
const dependency = field.dataset.dependency;
|
|
661
|
+
if (!dependency) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
try {
|
|
665
|
+
const conditions = JSON.parse(dependency);
|
|
666
|
+
applyDependencyState(field, conditions);
|
|
667
|
+
cleanupCallbacks.push(...bindDependencyListeners(field, conditions));
|
|
668
|
+
}
|
|
669
|
+
catch (e) {
|
|
670
|
+
console.error('[Dependencies] Error parsing conditions for field:', field, e);
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
return () => {
|
|
674
|
+
cleanupCallbacks.forEach((cleanup) => cleanup());
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
function bindDependencyListeners(field, conditions) {
|
|
678
|
+
const cleanupCallbacks = [];
|
|
679
|
+
conditions.forEach((rules) => {
|
|
680
|
+
Object.keys(rules).forEach((selector) => {
|
|
681
|
+
const element = document.querySelector(selector);
|
|
682
|
+
if (!element) {
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
events.forEach((event) => {
|
|
686
|
+
const listener = () => applyDependencyState(field, conditions);
|
|
687
|
+
element.addEventListener(event, listener);
|
|
688
|
+
cleanupCallbacks.push(() => element.removeEventListener(event, listener));
|
|
689
|
+
});
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
return cleanupCallbacks;
|
|
693
|
+
}
|
|
694
|
+
function applyDependencyState(field, conditions) {
|
|
695
|
+
if (checkConditions(conditions)) {
|
|
696
|
+
field.classList.add(dependencyShowClassName);
|
|
527
697
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
698
|
+
else {
|
|
699
|
+
field.classList.remove(dependencyShowClassName);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
function checkConditions(conditions) {
|
|
703
|
+
return conditions.every((conditionObj) => {
|
|
704
|
+
const selectors = Object.keys(conditionObj);
|
|
705
|
+
return selectors.every((selector) => evaluateDependencyRule(selector, conditionObj[selector]));
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
function evaluateDependencyRule(selector, condition) {
|
|
709
|
+
const type = condition.type;
|
|
710
|
+
const currentValue = getValue(selector);
|
|
711
|
+
const checkValue = typeof condition.value === 'undefined' ? false : condition.value;
|
|
712
|
+
let minValue = typeof condition.min === 'undefined' ? false : Number.parseInt(String(condition.min), 10);
|
|
713
|
+
let maxValue = typeof condition.max === 'undefined' ? false : Number.parseInt(String(condition.max), 10);
|
|
714
|
+
const allowEmpty = typeof condition.empty === 'undefined' ? false : condition.empty;
|
|
715
|
+
const isEmpty = !allowEmpty && currentValue.length < 1;
|
|
716
|
+
const likeSelector = typeof condition.like === 'undefined' ? false : condition.like;
|
|
717
|
+
const likeSelectorValue = getValue(likeSelector);
|
|
718
|
+
const regExpPattern = typeof condition.pattern === 'undefined' ? false : condition.pattern;
|
|
719
|
+
const regExpModifier = typeof condition.modifier === 'undefined' ? 'gi' : condition.modifier;
|
|
720
|
+
const sign = typeof condition.sign === 'undefined' ? false : condition.sign;
|
|
721
|
+
const strict = typeof condition.strict === 'undefined' ? false : condition.strict;
|
|
722
|
+
const emptyTypes = ['empty', 'blank'];
|
|
723
|
+
const notEmptyTypes = ['!empty', 'notEmpty', 'not-empty', 'notempty'];
|
|
724
|
+
const equalTypes = ['equal', '=', '==', '==='];
|
|
725
|
+
const notEqualTypes = ['!equal', '!=', '!==', '!===', 'notEqual', 'not-equal', 'notequal'];
|
|
726
|
+
const regularExpressionTypes = ['regexp', 'exp', 'expression', 'match'];
|
|
727
|
+
if (type && emptyTypes.includes(type)) {
|
|
728
|
+
return currentValue.length < 1;
|
|
729
|
+
}
|
|
730
|
+
if (type && notEmptyTypes.includes(type)) {
|
|
731
|
+
return currentValue.length > 0;
|
|
732
|
+
}
|
|
733
|
+
if (type && equalTypes.includes(type)) {
|
|
734
|
+
if (isEmpty) {
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
if (likeSelector) {
|
|
738
|
+
return strict
|
|
739
|
+
? likeSelectorValue.every((value) => currentValue.includes(value))
|
|
740
|
+
: likeSelectorValue.some((value) => currentValue.includes(value));
|
|
741
|
+
}
|
|
742
|
+
if (strict) {
|
|
743
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
744
|
+
return checkValue.every((value) => currentValue.includes(value));
|
|
745
|
+
}
|
|
746
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
747
|
+
return currentValue.includes(checkValue);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
752
|
+
return checkValue.some((value) => currentValue.includes(value));
|
|
753
|
+
}
|
|
754
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
755
|
+
return currentValue.includes(checkValue);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
if (type && notEqualTypes.includes(type)) {
|
|
760
|
+
if (isEmpty) {
|
|
761
|
+
return false;
|
|
762
|
+
}
|
|
763
|
+
if (likeSelector) {
|
|
764
|
+
return strict
|
|
765
|
+
? likeSelectorValue.every((value) => !currentValue.includes(value))
|
|
766
|
+
: likeSelectorValue.some((value) => !currentValue.includes(value));
|
|
767
|
+
}
|
|
768
|
+
if (strict) {
|
|
769
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
770
|
+
return checkValue.every((value) => !currentValue.includes(value));
|
|
771
|
+
}
|
|
772
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
773
|
+
return !currentValue.includes(checkValue);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
778
|
+
return checkValue.some((value) => !currentValue.includes(value));
|
|
779
|
+
}
|
|
780
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
781
|
+
return !currentValue.includes(checkValue);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
if (type && regularExpressionTypes.includes(type) && regExpPattern) {
|
|
786
|
+
if (isEmpty) {
|
|
787
|
+
return false;
|
|
788
|
+
}
|
|
789
|
+
const exp = new RegExp(regExpPattern, regExpModifier);
|
|
790
|
+
return currentValue.every((value) => exp.test(String(value)));
|
|
791
|
+
}
|
|
792
|
+
if (type === 'length') {
|
|
793
|
+
if (isEmpty) {
|
|
794
|
+
return false;
|
|
795
|
+
}
|
|
796
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
797
|
+
minValue = Number.parseInt(String(checkValue[0]), 10);
|
|
798
|
+
maxValue = typeof checkValue[1] === 'undefined' ? false : Number.parseInt(String(checkValue[1]), 10);
|
|
799
|
+
}
|
|
800
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
801
|
+
minValue = Number.parseInt(String(checkValue), 10);
|
|
802
|
+
maxValue = false;
|
|
803
|
+
}
|
|
804
|
+
const minBoundary = minValue === false ? 0 : minValue;
|
|
805
|
+
const maxBoundary = maxValue === false ? 0 : maxValue;
|
|
806
|
+
return currentValue.every((value) => {
|
|
807
|
+
const valueLength = String(value).length;
|
|
808
|
+
if (!maxValue) {
|
|
809
|
+
return valueLength >= minBoundary;
|
|
810
|
+
}
|
|
811
|
+
if (!minValue) {
|
|
812
|
+
return valueLength <= maxBoundary;
|
|
813
|
+
}
|
|
814
|
+
return valueLength >= minBoundary && valueLength <= maxBoundary;
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
if (type === 'range') {
|
|
818
|
+
if (isEmpty) {
|
|
819
|
+
return false;
|
|
820
|
+
}
|
|
821
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
822
|
+
minValue = Number.parseInt(String(checkValue[0]), 10);
|
|
823
|
+
maxValue = typeof checkValue[1] === 'undefined' ? false : Number.parseInt(String(checkValue[1]), 10);
|
|
824
|
+
}
|
|
825
|
+
const minBoundary = minValue === false ? 0 : minValue;
|
|
826
|
+
const maxBoundary = maxValue === false ? 0 : maxValue;
|
|
827
|
+
return currentValue.every((value) => {
|
|
828
|
+
const numericValue = Number.parseInt(String(value), 10);
|
|
829
|
+
if (!maxValue) {
|
|
830
|
+
return numericValue > minBoundary;
|
|
831
|
+
}
|
|
832
|
+
if (!minValue) {
|
|
833
|
+
return numericValue < maxBoundary;
|
|
834
|
+
}
|
|
835
|
+
return numericValue > minBoundary && numericValue < maxBoundary;
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
if (type === 'compare' && sign && checkValue) {
|
|
839
|
+
if (isEmpty) {
|
|
840
|
+
return false;
|
|
841
|
+
}
|
|
842
|
+
const numericCheckValue = Number.parseInt(String(checkValue), 10);
|
|
843
|
+
switch (sign) {
|
|
844
|
+
case '<':
|
|
845
|
+
return currentValue.every((value) => Number.parseInt(String(value), 10) < numericCheckValue);
|
|
846
|
+
case '<=':
|
|
847
|
+
return currentValue.every((value) => Number.parseInt(String(value), 10) <= numericCheckValue);
|
|
848
|
+
case '>':
|
|
849
|
+
return currentValue.every((value) => Number.parseInt(String(value), 10) > numericCheckValue);
|
|
850
|
+
case '>=':
|
|
851
|
+
return currentValue.every((value) => Number.parseInt(String(value), 10) >= numericCheckValue);
|
|
852
|
+
case '=':
|
|
853
|
+
case '==':
|
|
854
|
+
return currentValue.every((value) => Number.parseInt(String(value), 10) === numericCheckValue);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
return false;
|
|
858
|
+
}
|
|
859
|
+
function getValue(selector) {
|
|
860
|
+
const values = [];
|
|
861
|
+
if (selector && document.querySelector(selector)) {
|
|
862
|
+
const inputType = document.querySelector(selector).tagName.toLowerCase();
|
|
863
|
+
let currentSelector = selector;
|
|
864
|
+
if (inputType === 'crowdin-select') {
|
|
865
|
+
currentSelector = `${selector} option:checked`;
|
|
866
|
+
}
|
|
867
|
+
if (inputType === 'crowdin-checkbox') {
|
|
868
|
+
currentSelector = `${selector}:not(input)`;
|
|
869
|
+
}
|
|
870
|
+
document.querySelectorAll(currentSelector).forEach((element) => {
|
|
871
|
+
const value = element.value || element.checked;
|
|
872
|
+
values.push(value);
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
return values.filter((value) => value !== '');
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
const IntegrationView = ({ appComponentRef, userErrorsTableRef, name, isErrorLogsVisible, syncNewElements, withCronSync, webhooks, integrationOneLevelFetching, integrationSearchListener, integrationPagination, filtering, integrationButtonMenuItems, crowdinButtonMenuItems, }) => {
|
|
879
|
+
var _a, _b;
|
|
880
|
+
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { style: { display: isErrorLogsVisible ? 'none' : undefined }, children: jsxRuntimeExports.jsx("crowdin-simple-integration", { ref: appComponentRef, "async-progress": true, ...((syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.crowdin) ? { 'skip-crowdin-auto-schedule': true } : {}), ...((syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration) ? { 'skip-integration-auto-schedule': true } : {}), ...((withCronSync === null || withCronSync === void 0 ? void 0 : withCronSync.crowdin) || (webhooks === null || webhooks === void 0 ? void 0 : webhooks.crowdin) ? { 'crowdin-schedule': 'true' } : {}), ...((withCronSync === null || withCronSync === void 0 ? void 0 : withCronSync.integration) || (webhooks === null || webhooks === void 0 ? void 0 : webhooks.integration) ? { 'integration-schedule': 'true' } : {}), ...(integrationOneLevelFetching ? { 'integration-one-level-fetching': 'true' } : {}), ...(integrationSearchListener ? { 'allow-integration-filter-change-listener': 'true' } : {}), ...(integrationPagination ? { 'integration-load-more-files': 'true' } : {}), "integration-name": name, "integration-logo": "logo.png", ...(((_a = integrationButtonMenuItems === null || integrationButtonMenuItems === void 0 ? void 0 : integrationButtonMenuItems.length) !== null && _a !== void 0 ? _a : 0) > 0
|
|
881
|
+
? { 'integration-button-menu-items': integrationButtonMenuItems }
|
|
882
|
+
: {}), ...(((_b = crowdinButtonMenuItems === null || crowdinButtonMenuItems === void 0 ? void 0 : crowdinButtonMenuItems.length) !== null && _b !== void 0 ? _b : 0) > 0
|
|
883
|
+
? { 'crowdin-button-menu-items': crowdinButtonMenuItems }
|
|
884
|
+
: {}), ...((filtering === null || filtering === void 0 ? void 0 : filtering.crowdinLanguages) ? { 'crowdin-filter': true } : {}), ...((filtering === null || filtering === void 0 ? void 0 : filtering.integrationFilterConfig)
|
|
885
|
+
? {
|
|
886
|
+
'integration-filter': true,
|
|
887
|
+
'integration-filter-config': filtering.integrationFilterConfig,
|
|
888
|
+
}
|
|
889
|
+
: {}) }) }), jsxRuntimeExports.jsxs("div", { id: "user-errors", style: { display: isErrorLogsVisible ? undefined : 'none' }, children: [jsxRuntimeExports.jsx("crowdin-show-as-table", { ref: userErrorsTableRef, "is-loading": true, id: "user-errors-table", "is-searchable": true, "total-records": "25", "search-placeholder": "Search something" }), jsxRuntimeExports.jsx("crowdin-alert", { children: "This table displays the most recent error logs from the past month. Logs older than one month will be automatically deleted." })] })] }));
|
|
890
|
+
};
|
|
891
|
+
|
|
892
|
+
const TopBar = ({ notice, isNoticeVisible, checkSubscription, subscriptionInfo, isErrorLogsVisible, isManager, infoModal, hasSettings, isOwner, onCloseNotice, onShowIntegration, onShowErrorLogs, onShowPermissions, onOpenInfoModal, onOpenSettings, onLogout, }) => {
|
|
893
|
+
return (jsxRuntimeExports.jsxs("div", { className: "mb-2.5 text-right", children: [notice && (jsxRuntimeExports.jsxs("crowdin-alert", { id: "notice", title: notice.title, ...(!notice.icon ? { 'no-icon': 'true' } : {}), ...(notice.type ? { type: notice.type } : {}), style: { display: isNoticeVisible ? 'block' : 'none', marginBottom: '12px' }, children: [jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center", children: jsxRuntimeExports.jsx("p", { className: "m-0", dangerouslySetInnerHTML: { __html: notice.content } }) }), notice.close && (jsxRuntimeExports.jsx("crowdin-button", { onClick: () => onCloseNotice('notice'), class: "absolute top-0 right-0", icon: true, children: "close" }))] })), checkSubscription && (jsxRuntimeExports.jsx("crowdin-alert", { id: "subscription-info", "no-icon": "true", type: "warning", style: { display: subscriptionInfo ? 'block' : 'none', marginBottom: '12px' }, children: jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center", children: [jsxRuntimeExports.jsx("p", { className: "m-0", children: subscriptionInfo ? `Your trial expires in ${subscriptionInfo.daysLeft} days.` : '' }), jsxRuntimeExports.jsx("crowdin-button", { class: "ml-2", primary: true, onClick: () => {
|
|
894
|
+
if (subscriptionInfo === null || subscriptionInfo === void 0 ? void 0 : subscriptionInfo.subscribeLink) {
|
|
895
|
+
window.open(subscriptionInfo.subscribeLink, '_blank', 'noopener,noreferrer');
|
|
896
|
+
}
|
|
897
|
+
}, children: "Subscribe" })] }) })), jsxRuntimeExports.jsxs("div", { id: "buttons", className: "flex w-full items-center justify-between", children: [jsxRuntimeExports.jsxs("div", { className: "mr-auto", children: [jsxRuntimeExports.jsx("span", { style: { display: isErrorLogsVisible ? undefined : 'none' }, children: jsxRuntimeExports.jsx("crowdin-button", { id: "show-integration-btn", "icon-before": "arrow_back", onClick: onShowIntegration, children: "Integration" }) }), jsxRuntimeExports.jsx("span", { style: { display: isErrorLogsVisible ? 'none' : undefined }, children: jsxRuntimeExports.jsx("crowdin-button", { id: "show-error-logs-btn", "icon-before": "list", onClick: onShowErrorLogs, children: "Error logs" }) })] }), isManager && (jsxRuntimeExports.jsx("crowdin-button", { "icon-before": "link", onClick: onShowPermissions, children: "Share" })), infoModal && (jsxRuntimeExports.jsx("crowdin-button", { "icon-before": "info", onClick: onOpenInfoModal, children: infoModal.title })), hasSettings && (jsxRuntimeExports.jsx("crowdin-button", { "icon-before": "settings", onClick: onOpenSettings, children: "Settings" })), jsxRuntimeExports.jsx("crowdin-button", { ...(!isOwner ? { disabled: true, title: 'Only the owner can log out' } : {}), "icon-before": "account_circle", onClick: onLogout, children: "Log out" })] })] }));
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
const EMPTY_PERMISSION_VALUE = '―';
|
|
901
|
+
const getDefaultScheduleModalState = () => ({
|
|
902
|
+
type: null,
|
|
903
|
+
showNewFiles: true,
|
|
904
|
+
showAllFolderFiles: false,
|
|
905
|
+
newFiles: false,
|
|
906
|
+
newFilesClearSelection: false,
|
|
907
|
+
selectedFiles: true,
|
|
908
|
+
allFolderFiles: false,
|
|
909
|
+
});
|
|
910
|
+
const JOB_TYPE = {
|
|
911
|
+
updateCrowdin: 'updateCrowdin',
|
|
912
|
+
updateIntegration: 'updateIntegration',
|
|
913
|
+
updateTargetLanguages: 'updateTargetLanguages',
|
|
914
|
+
integrationSyncSettingsSave: 'integrationSyncSettingsSave',
|
|
915
|
+
crowdinSyncSettingsSave: 'crowdinSyncSettingsSave',
|
|
916
|
+
integrationSettingsSave: 'integrationSettingsSave',
|
|
917
|
+
};
|
|
918
|
+
const JOB_STATUS = {
|
|
919
|
+
created: 'created',
|
|
920
|
+
inProgress: 'inProgress',
|
|
921
|
+
failed: 'failed',
|
|
922
|
+
canceled: 'canceled',
|
|
923
|
+
finished: 'finished',
|
|
924
|
+
};
|
|
925
|
+
const FOLDER_TYPE = '0';
|
|
926
|
+
const FILE_TYPE = '1';
|
|
927
|
+
const BRANCH_TYPE = '2';
|
|
928
|
+
|
|
929
|
+
function isFolder(e) {
|
|
930
|
+
return !e.type && (e.nodeType === undefined || e.nodeType === FOLDER_TYPE || e.nodeType === BRANCH_TYPE);
|
|
931
|
+
}
|
|
932
|
+
function openModal(modal) {
|
|
933
|
+
if (!modal) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
modal.style.display = 'block';
|
|
937
|
+
modal.open();
|
|
938
|
+
}
|
|
939
|
+
function closeModal(modal) {
|
|
940
|
+
if (!modal) {
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
modal.style.display = 'none';
|
|
944
|
+
modal.close();
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/// <reference path="../../../../ui/types.d.ts" />
|
|
948
|
+
function usePermissions({ userId, hasOrganization, permissionsModalRef }) {
|
|
949
|
+
const usersSelectRef = reactExports.useRef(null);
|
|
950
|
+
const [isLoading, setIsLoading] = reactExports.useState(false);
|
|
951
|
+
const [permissionUserOptions, setPermissionUserOptions] = reactExports.useState([]);
|
|
952
|
+
const [permissionsSelectedValue, setPermissionsSelectedValue] = reactExports.useState('[]');
|
|
953
|
+
const [permissionsSummary, setPermissionsSummary] = reactExports.useState(null);
|
|
954
|
+
const [isPermissionsConfirmVisible, setIsPermissionsConfirmVisible] = reactExports.useState(false);
|
|
955
|
+
reactExports.useEffect(() => {
|
|
956
|
+
if (usersSelectRef.current) {
|
|
957
|
+
usersSelectRef.current.value = permissionsSelectedValue;
|
|
958
|
+
}
|
|
959
|
+
}, [permissionUserOptions, permissionsSelectedValue]);
|
|
960
|
+
// crowdin-users-select doesn't trigger onChange reliably, using native event listener instead
|
|
961
|
+
reactExports.useEffect(() => {
|
|
962
|
+
const selectElement = usersSelectRef.current;
|
|
963
|
+
if (!selectElement) {
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
const handleChange = () => checkUsers();
|
|
967
|
+
selectElement.addEventListener('change', handleChange);
|
|
968
|
+
return () => selectElement.removeEventListener('change', handleChange);
|
|
969
|
+
}, []);
|
|
970
|
+
function getUserFullName(user) {
|
|
971
|
+
if (user.full_name) {
|
|
972
|
+
return user.full_name;
|
|
973
|
+
}
|
|
974
|
+
const ownerFullName = user.name || ((user.first_name || '') + ' ' + (user.last_name || '')).trim();
|
|
975
|
+
return !!ownerFullName && (user === null || user === void 0 ? void 0 : user.login) !== ownerFullName ? `${ownerFullName} (${user === null || user === void 0 ? void 0 : user.login})` : user === null || user === void 0 ? void 0 : user.login;
|
|
976
|
+
}
|
|
977
|
+
function hideConfirmUsersBlock() {
|
|
978
|
+
var _a;
|
|
979
|
+
setIsPermissionsConfirmVisible(false);
|
|
980
|
+
(_a = permissionsModalRef.current) === null || _a === void 0 ? void 0 : _a.setAttribute('body-overflow-unset', true);
|
|
981
|
+
}
|
|
982
|
+
function showConfirmUsersBlock() {
|
|
983
|
+
var _a;
|
|
984
|
+
setIsPermissionsConfirmVisible(true);
|
|
985
|
+
(_a = permissionsModalRef.current) === null || _a === void 0 ? void 0 : _a.removeAttribute('body-overflow-unset');
|
|
986
|
+
}
|
|
987
|
+
async function showPermissionsDialog() {
|
|
988
|
+
hideConfirmUsersBlock();
|
|
989
|
+
openModal(permissionsModalRef.current);
|
|
990
|
+
setIsLoading(true);
|
|
991
|
+
setPermissionsSelectedValue('[]');
|
|
992
|
+
try {
|
|
993
|
+
const [managers, users] = await Promise.all([
|
|
994
|
+
new Promise((resolve) => {
|
|
995
|
+
checkOrigin()
|
|
996
|
+
.then((restParams) => fetch('api/users' + restParams))
|
|
997
|
+
.then(checkResponse)
|
|
998
|
+
.then((res) => resolve(JSON.stringify(res.data.managers)));
|
|
999
|
+
}),
|
|
1000
|
+
new Promise((resolve) => {
|
|
1001
|
+
AP.getUsers((res) => {
|
|
1002
|
+
const users = Object.values(res).filter((user) => user.id !== Number(userId));
|
|
1003
|
+
resolve(users);
|
|
1004
|
+
});
|
|
1005
|
+
}),
|
|
1006
|
+
]);
|
|
1007
|
+
const parsedManagers = (JSON.parse(managers) || []);
|
|
1008
|
+
const validUserIds = new Set(users.map((user) => `${user.id}`));
|
|
1009
|
+
const filteredManagers = parsedManagers.filter((id) => validUserIds.has(id));
|
|
1010
|
+
setPermissionUserOptions(users.map((user) => ({
|
|
1011
|
+
id: String(user.id),
|
|
1012
|
+
label: getUserFullName(user),
|
|
1013
|
+
})));
|
|
1014
|
+
setPermissionsSelectedValue(JSON.stringify(filteredManagers));
|
|
1015
|
+
}
|
|
1016
|
+
catch (e) {
|
|
1017
|
+
catchRejection(e, "Can't fetch users");
|
|
1018
|
+
}
|
|
1019
|
+
finally {
|
|
1020
|
+
setTimeout(() => setIsLoading(false), 500);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
async function checkUsers() {
|
|
1024
|
+
setIsLoading(true);
|
|
1025
|
+
const select = usersSelectRef.current;
|
|
1026
|
+
if (select.value === '[]') {
|
|
1027
|
+
hideConfirmUsersBlock();
|
|
1028
|
+
setTimeout(() => setIsLoading(false), 500);
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
const users = JSON.parse(select.value);
|
|
1032
|
+
const user_ids = users.filter((id) => parseInt(id));
|
|
1033
|
+
const emails = users.filter((id) => !parseInt(id));
|
|
1034
|
+
try {
|
|
1035
|
+
const [appManagers, checkUsersResponse, allUsers] = await Promise.all([
|
|
1036
|
+
new Promise((resolve) => {
|
|
1037
|
+
checkOrigin()
|
|
1038
|
+
.then((restParams) => fetch('api/users' + restParams))
|
|
1039
|
+
.then(checkResponse)
|
|
1040
|
+
.then((usersResponse) => resolve(usersResponse.data.managers));
|
|
1041
|
+
}),
|
|
1042
|
+
new Promise((resolve) => {
|
|
1043
|
+
AP.validateUsers({ user_ids, emails }, (res) => resolve(res.data));
|
|
1044
|
+
}),
|
|
1045
|
+
new Promise((resolve) => {
|
|
1046
|
+
AP.getUsers((res) => resolve(res));
|
|
1047
|
+
}),
|
|
1048
|
+
]);
|
|
1049
|
+
const newUserEmails = checkUsersResponse.newUserEmails.map((email) => ({ name: email }));
|
|
1050
|
+
const newProjectManagers = [
|
|
1051
|
+
...newUserEmails,
|
|
1052
|
+
...checkUsersResponse.newProjectManagers.map((user) => ({ name: getUserFullName(user) })),
|
|
1053
|
+
];
|
|
1054
|
+
const newApplicationAccessUsers = [
|
|
1055
|
+
...newUserEmails,
|
|
1056
|
+
...checkUsersResponse.newApplicationAccessUsers.map((user) => ({
|
|
1057
|
+
name: getUserFullName(user),
|
|
1058
|
+
})),
|
|
1059
|
+
];
|
|
1060
|
+
const newApplicationManagers = [
|
|
1061
|
+
...newUserEmails,
|
|
1062
|
+
...Object.values(allUsers)
|
|
1063
|
+
.filter((user) => users.some((id) => +id === user.id) && !appManagers.some((id) => +id === user.id))
|
|
1064
|
+
.map((user) => ({ name: getUserFullName(user) })),
|
|
1065
|
+
];
|
|
1066
|
+
prepareUsersConfirmBlock({
|
|
1067
|
+
...checkUsersResponse,
|
|
1068
|
+
newUserEmails,
|
|
1069
|
+
newProjectManagers,
|
|
1070
|
+
newApplicationAccessUsers,
|
|
1071
|
+
newApplicationManagers,
|
|
1072
|
+
});
|
|
1073
|
+
}
|
|
1074
|
+
catch (e) {
|
|
1075
|
+
catchRejection(e, (e === null || e === void 0 ? void 0 : e.error) || "Can't invite users");
|
|
1076
|
+
}
|
|
1077
|
+
finally {
|
|
1078
|
+
setTimeout(() => setIsLoading(false), 500);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
function inviteUsers() {
|
|
1082
|
+
setIsLoading(true);
|
|
1083
|
+
const select = usersSelectRef.current;
|
|
1084
|
+
const users = JSON.parse(select.value);
|
|
1085
|
+
const user_ids = users.filter((id) => parseInt(id));
|
|
1086
|
+
const emails = users.filter((id) => !parseInt(id));
|
|
1087
|
+
AP.inviteUsers({ user_ids, emails }, async (res) => {
|
|
1088
|
+
var _a;
|
|
1089
|
+
if (!res.success) {
|
|
1090
|
+
catchRejection(res, ((_a = res === null || res === void 0 ? void 0 : res.error) === null || _a === void 0 ? void 0 : _a.message) || "Can't invite users");
|
|
1091
|
+
setTimeout(() => setIsLoading(false), 500);
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
try {
|
|
1095
|
+
const restParams = await checkOrigin();
|
|
1096
|
+
const inviteRes = await checkResponse(await fetch('api/invite-users' + restParams, {
|
|
1097
|
+
method: 'POST',
|
|
1098
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1099
|
+
body: JSON.stringify(res.data),
|
|
1100
|
+
}));
|
|
1101
|
+
if (!inviteRes.success) {
|
|
1102
|
+
catchRejection(inviteRes, (inviteRes === null || inviteRes === void 0 ? void 0 : inviteRes.message) || "Can't invite users");
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1105
|
+
showToast('Users successfully updated');
|
|
1106
|
+
hideConfirmUsersBlock();
|
|
1107
|
+
closeModal(permissionsModalRef.current);
|
|
1108
|
+
}
|
|
1109
|
+
catch (e) {
|
|
1110
|
+
catchRejection(e, (e === null || e === void 0 ? void 0 : e.error) || "Can't invite users");
|
|
1111
|
+
}
|
|
1112
|
+
finally {
|
|
1113
|
+
setTimeout(() => setIsLoading(false), 500);
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
function prepareUsersConfirmBlock(usersData) {
|
|
1118
|
+
showConfirmUsersBlock();
|
|
1119
|
+
const toNames = (users = []) => users.map((user) => user.name);
|
|
1120
|
+
const applicationSettingsDescription = 'This can be configured in organization settings (Apps section).';
|
|
1121
|
+
const hasApplicationAccessUsers = usersData.newApplicationAccessUsers.length > 0;
|
|
1122
|
+
setPermissionsSummary({
|
|
1123
|
+
...(hasOrganization
|
|
1124
|
+
? {
|
|
1125
|
+
organization: {
|
|
1126
|
+
status: usersData.newUserEmails.length
|
|
1127
|
+
? usersData.inviteRestricted
|
|
1128
|
+
? 'actionRequired'
|
|
1129
|
+
: 'willBeRegistered'
|
|
1130
|
+
: 'granted',
|
|
1131
|
+
users: toNames(usersData.newUserEmails),
|
|
1132
|
+
description: usersData.inviteRestricted
|
|
1133
|
+
? 'New user invitations are restricted to administrators.'
|
|
1134
|
+
: '',
|
|
1135
|
+
isWarning: usersData.inviteRestricted,
|
|
1136
|
+
},
|
|
1137
|
+
}
|
|
1138
|
+
: {}),
|
|
1139
|
+
project: {
|
|
1140
|
+
status: usersData.newProjectManagers.length ? 'willBeGranted' : 'granted',
|
|
1141
|
+
users: toNames(usersData.newProjectManagers),
|
|
1142
|
+
},
|
|
1143
|
+
applicationSettings: {
|
|
1144
|
+
status: hasApplicationAccessUsers
|
|
1145
|
+
? usersData.isAdmin
|
|
1146
|
+
? 'willBeGranted'
|
|
1147
|
+
: 'actionRequired'
|
|
1148
|
+
: 'granted',
|
|
1149
|
+
users: toNames(usersData.newApplicationAccessUsers),
|
|
1150
|
+
description: hasApplicationAccessUsers
|
|
1151
|
+
? usersData.isAdmin
|
|
1152
|
+
? applicationSettingsDescription
|
|
1153
|
+
: `${applicationSettingsDescription} Only organization admins have permission to update this setting.`
|
|
1154
|
+
: applicationSettingsDescription,
|
|
1155
|
+
isWarning: hasApplicationAccessUsers && !usersData.isAdmin,
|
|
1156
|
+
},
|
|
1157
|
+
applicationCredentials: {
|
|
1158
|
+
status: usersData.newApplicationManagers.length ? 'willBeGranted' : 'granted',
|
|
1159
|
+
users: toNames(usersData.newApplicationManagers),
|
|
1160
|
+
},
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1163
|
+
return {
|
|
1164
|
+
usersSelectRef,
|
|
1165
|
+
isLoading,
|
|
1166
|
+
permissionUserOptions,
|
|
1167
|
+
permissionsSelectedValue,
|
|
1168
|
+
permissionsSummary,
|
|
1169
|
+
isPermissionsConfirmVisible,
|
|
1170
|
+
showPermissionsDialog,
|
|
1171
|
+
inviteUsers,
|
|
535
1172
|
};
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
/// <reference path="../../../../ui/types.d.ts" />
|
|
1176
|
+
function useSchedule({ appComponent, config, scheduleModalRef, withCronSync, webhooks, syncNewElements, integrationOneLevelFetching, hasLoadMoreElements, updateSyncSettings, }) {
|
|
1177
|
+
const selectedFilesCheckboxRef = reactExports.useRef(null);
|
|
1178
|
+
const allFolderFilesCheckboxRef = reactExports.useRef(null);
|
|
1179
|
+
const newFilesCheckboxRef = reactExports.useRef(null);
|
|
1180
|
+
const syncData = reactExports.useRef(null);
|
|
1181
|
+
const [scheduleModalState, setScheduleModalState] = reactExports.useState(getDefaultScheduleModalState);
|
|
1182
|
+
const [isScheduleSaveDisabled, setIsScheduleSaveDisabled] = reactExports.useState(false);
|
|
1183
|
+
reactExports.useEffect(() => {
|
|
1184
|
+
syncScheduleCheckbox(selectedFilesCheckboxRef.current, {
|
|
1185
|
+
checked: scheduleModalState.selectedFiles,
|
|
1186
|
+
});
|
|
1187
|
+
syncScheduleCheckbox(allFolderFilesCheckboxRef.current, {
|
|
1188
|
+
checked: scheduleModalState.allFolderFiles,
|
|
1189
|
+
hidden: !scheduleModalState.showAllFolderFiles,
|
|
1190
|
+
});
|
|
1191
|
+
syncScheduleCheckbox(newFilesCheckboxRef.current, {
|
|
1192
|
+
checked: scheduleModalState.newFiles,
|
|
1193
|
+
hidden: !scheduleModalState.showNewFiles,
|
|
1194
|
+
clearSelection: scheduleModalState.newFilesClearSelection,
|
|
1195
|
+
});
|
|
1196
|
+
}, [scheduleModalState]);
|
|
1197
|
+
reactExports.useEffect(() => {
|
|
1198
|
+
if (!withCronSync && !webhooks) {
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
const listeners = {
|
|
1202
|
+
integrationScheduleSync: setIntegrationScheduleSync,
|
|
1203
|
+
crowdinScheduleSync: setCrowdinScheduleSync,
|
|
1204
|
+
crowdinDisableSync: disableCrowdinSync,
|
|
1205
|
+
integrationDisableSync: disableIntegrationSync,
|
|
1206
|
+
};
|
|
1207
|
+
for (const [event, handler] of Object.entries(listeners)) {
|
|
1208
|
+
document.body.addEventListener(event, handler);
|
|
1209
|
+
}
|
|
1210
|
+
return () => {
|
|
1211
|
+
for (const [event, handler] of Object.entries(listeners)) {
|
|
1212
|
+
document.body.removeEventListener(event, handler);
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
}, []);
|
|
1216
|
+
function syncScheduleCheckbox(checkbox, { checked, hidden = false, clearSelection = false, }) {
|
|
1217
|
+
if (!checkbox) {
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
1220
|
+
checkbox.checked = checked;
|
|
1221
|
+
checkbox.value = checked;
|
|
1222
|
+
if (hidden) {
|
|
1223
|
+
checkbox.setAttribute('hidden', '');
|
|
1224
|
+
}
|
|
1225
|
+
else {
|
|
1226
|
+
checkbox.removeAttribute('hidden');
|
|
1227
|
+
}
|
|
1228
|
+
if (clearSelection) {
|
|
1229
|
+
checkbox.setAttribute('clear-selection', '');
|
|
1230
|
+
}
|
|
1231
|
+
else {
|
|
1232
|
+
checkbox.removeAttribute('clear-selection');
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
async function hasFolder(selectedFiles) {
|
|
1236
|
+
let found;
|
|
1237
|
+
if (Array.isArray(selectedFiles)) {
|
|
1238
|
+
found = selectedFiles.find((file) => file.node_type === FOLDER_TYPE || file.node_type === BRANCH_TYPE);
|
|
1239
|
+
}
|
|
1240
|
+
else {
|
|
1241
|
+
const files = await appComponent.current.getCrowdinFilesData();
|
|
1242
|
+
const folders = files.filter((file) => file.node_type === FOLDER_TYPE || file.node_type === BRANCH_TYPE);
|
|
1243
|
+
found = folders.find((folder) => selectedFiles.hasOwnProperty(folder.id));
|
|
1244
|
+
}
|
|
1245
|
+
return found !== undefined;
|
|
1246
|
+
}
|
|
1247
|
+
function getIntegrationFoldersToExpand(allData, syncedFiles) {
|
|
1248
|
+
return Array.isArray(allData)
|
|
1249
|
+
? allData
|
|
1250
|
+
.filter((node) => node.node_type === FOLDER_TYPE &&
|
|
1251
|
+
!syncedFiles.find((syncedFile) => syncedFile.parent_id === node.id))
|
|
1252
|
+
.map((node) => ({ ...node, nodeType: node.node_type, parentId: node.parent_id }))
|
|
1253
|
+
: [];
|
|
1254
|
+
}
|
|
1255
|
+
async function openScheduleModal(type, options = {}) {
|
|
1256
|
+
var _a, _b, _c, _d;
|
|
1257
|
+
const { showAllFolderFiles = false, showNewFiles = true } = options;
|
|
1258
|
+
let newFileStatus = 'unChecked';
|
|
1259
|
+
const integrationSyncFolders = ((await ((_b = (_a = appComponent.current) === null || _a === void 0 ? void 0 : _a.getIntegrationScheduleSync) === null || _b === void 0 ? void 0 : _b.call(_a, true))) || []).filter((elements) => elements.node_type === FOLDER_TYPE);
|
|
1260
|
+
const integrationFiles = (_c = appComponent.current) === null || _c === void 0 ? void 0 : _c.querySelector('#integration-files');
|
|
1261
|
+
const selectedIntegrationFolders = ((await ((_d = integrationFiles === null || integrationFiles === void 0 ? void 0 : integrationFiles.getSelected) === null || _d === void 0 ? void 0 : _d.call(integrationFiles, true))) || []).filter((elements) => elements.node_type === FOLDER_TYPE);
|
|
1262
|
+
for (let i = 0; i < selectedIntegrationFolders.length; i++) {
|
|
1263
|
+
const selectedElement = selectedIntegrationFolders[i];
|
|
1264
|
+
const found = integrationSyncFolders.some((integrationElement) => integrationElement.id === selectedElement.id);
|
|
1265
|
+
if (found) {
|
|
1266
|
+
newFileStatus = 'checked';
|
|
1267
|
+
}
|
|
1268
|
+
else if (!found && newFileStatus === 'checked') {
|
|
1269
|
+
newFileStatus = 'clear-selection';
|
|
1270
|
+
break;
|
|
1271
|
+
}
|
|
1272
|
+
else {
|
|
1273
|
+
newFileStatus = 'unChecked';
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
setScheduleModalState({
|
|
1277
|
+
type,
|
|
1278
|
+
showAllFolderFiles,
|
|
1279
|
+
showNewFiles,
|
|
1280
|
+
newFiles: showNewFiles && newFileStatus === 'checked',
|
|
1281
|
+
newFilesClearSelection: showNewFiles && newFileStatus === 'clear-selection',
|
|
1282
|
+
selectedFiles: true,
|
|
1283
|
+
allFolderFiles: false,
|
|
1284
|
+
});
|
|
1285
|
+
setIsScheduleSaveDisabled(false);
|
|
1286
|
+
openModal(scheduleModalRef.current);
|
|
1287
|
+
}
|
|
1288
|
+
function onChangeAutoSynchronizationOptions() {
|
|
1289
|
+
var _a, _b, _c;
|
|
1290
|
+
const nextState = {
|
|
1291
|
+
newFiles: scheduleModalState.showNewFiles ? !!((_a = newFilesCheckboxRef.current) === null || _a === void 0 ? void 0 : _a.checked) : false,
|
|
1292
|
+
selectedFiles: !!((_b = selectedFilesCheckboxRef.current) === null || _b === void 0 ? void 0 : _b.checked),
|
|
1293
|
+
allFolderFiles: scheduleModalState.showAllFolderFiles
|
|
1294
|
+
? !!((_c = allFolderFilesCheckboxRef.current) === null || _c === void 0 ? void 0 : _c.checked)
|
|
1295
|
+
: false,
|
|
1296
|
+
};
|
|
1297
|
+
setScheduleModalState((currentState) => ({
|
|
1298
|
+
...currentState,
|
|
1299
|
+
...nextState,
|
|
1300
|
+
newFilesClearSelection: false,
|
|
1301
|
+
}));
|
|
1302
|
+
setIsScheduleSaveDisabled(!nextState.newFiles && !nextState.selectedFiles && !nextState.allFolderFiles);
|
|
1303
|
+
}
|
|
1304
|
+
async function saveScheduleSync() {
|
|
1305
|
+
const { type, newFiles: newFile, selectedFiles, allFolderFiles } = scheduleModalState;
|
|
1306
|
+
if (type === 'crowdin') {
|
|
1307
|
+
const crowdinFiles = await appComponent.current.getCrowdinFilesData();
|
|
1308
|
+
const syncedFileIds = Object.keys(syncData.current);
|
|
1309
|
+
const crowdinFolderIds = crowdinFiles
|
|
1310
|
+
.filter((file) => file.node_type === FOLDER_TYPE || file.node_type === BRANCH_TYPE)
|
|
1311
|
+
.filter((file) => syncedFileIds.includes(String(file.id)))
|
|
1312
|
+
.map((file) => String(file.id));
|
|
1313
|
+
appComponent.current.setCrowdinScheduleSync(syncData.current, newFile, selectedFiles);
|
|
1314
|
+
appComponent.current.setCrowdinFilesHasSyncOption(true);
|
|
1315
|
+
const syncedFiles = await appComponent.current.getCrowdinScheduleSync(true);
|
|
1316
|
+
appComponent.current.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
1317
|
+
updateSyncSettings(syncedFiles, 'schedule', 'crowdin', [], crowdinFolderIds);
|
|
1318
|
+
}
|
|
1319
|
+
else if (type === 'integration') {
|
|
1320
|
+
if (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration) {
|
|
1321
|
+
appComponent.current.setIntegrationScheduleSync(syncData.current, newFile, selectedFiles);
|
|
1322
|
+
}
|
|
1323
|
+
else {
|
|
1324
|
+
appComponent.current.setIntegrationScheduleSync(syncData.current);
|
|
1325
|
+
}
|
|
1326
|
+
appComponent.current.setIntegrationFilesHasSyncOption(true);
|
|
1327
|
+
const syncedFiles = await appComponent.current.getIntegrationScheduleSync(true);
|
|
1328
|
+
appComponent.current.setAttribute('is-integration-sync-settings-in-progress', true);
|
|
1329
|
+
if (integrationOneLevelFetching) {
|
|
1330
|
+
updateSyncSettings(syncedFiles, 'schedule', 'integration', selectedFiles ? getIntegrationFoldersToExpand(syncData.current, syncedFiles) : []);
|
|
1331
|
+
}
|
|
1332
|
+
else {
|
|
1333
|
+
if (allFolderFiles) {
|
|
1334
|
+
const integrationExpandedFolders = syncData.current
|
|
1335
|
+
.filter((file) => file.node_type === FOLDER_TYPE)
|
|
1336
|
+
.map((file) => ({ ...file, nodeType: file.node_type, parentId: file.parent_id }));
|
|
1337
|
+
updateSyncSettings(syncedFiles, 'schedule', 'integration', integrationExpandedFolders);
|
|
1338
|
+
}
|
|
1339
|
+
else {
|
|
1340
|
+
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
closeModal(scheduleModalRef.current);
|
|
1345
|
+
}
|
|
1346
|
+
async function setIntegrationScheduleSync(e) {
|
|
1347
|
+
var _a;
|
|
1348
|
+
if (e.detail.length === 0) {
|
|
1349
|
+
showToast('Select templates which will be pushed to Crowdin');
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
let syncedFiles;
|
|
1353
|
+
if (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration) {
|
|
1354
|
+
const newIntegrationFiles = (_a = config.current) === null || _a === void 0 ? void 0 : _a['new-integration-files'];
|
|
1355
|
+
syncData.current = e.detail;
|
|
1356
|
+
const isFolder = await hasFolder(e.detail);
|
|
1357
|
+
const shouldShowModal = isFolder && !newIntegrationFiles;
|
|
1358
|
+
const showNewFiles = true;
|
|
1359
|
+
const showAllFolderFiles = hasLoadMoreElements.current;
|
|
1360
|
+
if (shouldShowModal) {
|
|
1361
|
+
await openScheduleModal('integration', { showNewFiles, showAllFolderFiles });
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
appComponent.current.setIntegrationScheduleSync(e.detail);
|
|
1365
|
+
appComponent.current.setIntegrationFilesHasSyncOption(true);
|
|
1366
|
+
syncedFiles = await appComponent.current.getIntegrationScheduleSync(true);
|
|
1367
|
+
}
|
|
1368
|
+
else {
|
|
1369
|
+
syncData.current = e.detail;
|
|
1370
|
+
const isFolder = await hasFolder(e.detail);
|
|
1371
|
+
if (hasLoadMoreElements.current && isFolder) {
|
|
1372
|
+
await openScheduleModal('integration', { showNewFiles: false, showAllFolderFiles: true });
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
syncedFiles = await appComponent.current.getIntegrationScheduleSync();
|
|
1376
|
+
}
|
|
1377
|
+
appComponent.current.setAttribute('is-integration-sync-settings-in-progress', true);
|
|
1378
|
+
if (integrationOneLevelFetching) {
|
|
1379
|
+
updateSyncSettings(syncedFiles, 'schedule', 'integration', getIntegrationFoldersToExpand(e.detail, syncedFiles));
|
|
1380
|
+
}
|
|
1381
|
+
else {
|
|
1382
|
+
if (hasLoadMoreElements.current) {
|
|
1383
|
+
const integrationExpandedFolders = e.detail
|
|
1384
|
+
.filter((file) => file.node_type === FOLDER_TYPE)
|
|
1385
|
+
.map((file) => ({ ...file, nodeType: file.node_type, parentId: file.parent_id }));
|
|
1386
|
+
updateSyncSettings(syncedFiles, 'schedule', 'integration', integrationExpandedFolders);
|
|
1387
|
+
}
|
|
1388
|
+
else {
|
|
1389
|
+
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
async function setCrowdinScheduleSync(e) {
|
|
1394
|
+
var _a;
|
|
1395
|
+
if (e.detail.length === 0) {
|
|
1396
|
+
showToast('Select templates which will be pushed to Crowdin');
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
let syncedFiles;
|
|
1400
|
+
if (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.crowdin) {
|
|
1401
|
+
const newCrowdinFiles = (_a = config.current) === null || _a === void 0 ? void 0 : _a['new-crowdin-files'];
|
|
1402
|
+
syncData.current = e.detail;
|
|
1403
|
+
const isFolder = await hasFolder(e.detail);
|
|
1404
|
+
if (isFolder && !newCrowdinFiles) {
|
|
1405
|
+
await openScheduleModal('crowdin');
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
appComponent.current.setCrowdinScheduleSync(e.detail);
|
|
1409
|
+
appComponent.current.setCrowdinFilesHasSyncOption(true);
|
|
1410
|
+
syncedFiles = await appComponent.current.getCrowdinScheduleSync(true);
|
|
1411
|
+
}
|
|
1412
|
+
else {
|
|
1413
|
+
syncedFiles = await appComponent.current.getCrowdinScheduleSync();
|
|
1414
|
+
}
|
|
1415
|
+
appComponent.current.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
1416
|
+
updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
|
|
1417
|
+
}
|
|
1418
|
+
async function disableIntegrationSync(e) {
|
|
1419
|
+
if (e.detail.length === 0) {
|
|
1420
|
+
showToast('Select templates which will be pushed to Crowdin');
|
|
1421
|
+
return;
|
|
1422
|
+
}
|
|
1423
|
+
appComponent.current.setAttribute('is-integration-sync-settings-in-progress', true);
|
|
1424
|
+
const syncedFiles = (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration)
|
|
1425
|
+
? await appComponent.current.getIntegrationScheduleSync(true)
|
|
1426
|
+
: await appComponent.current.getIntegrationScheduleSync();
|
|
1427
|
+
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
1428
|
+
}
|
|
1429
|
+
async function disableCrowdinSync(e) {
|
|
1430
|
+
if (e.detail.length === 0) {
|
|
1431
|
+
showToast('Select templates which will be pushed to Crowdin');
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
appComponent.current.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
1435
|
+
const syncedFiles = (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.crowdin)
|
|
1436
|
+
? await appComponent.current.getCrowdinScheduleSync(true)
|
|
1437
|
+
: await appComponent.current.getCrowdinScheduleSync();
|
|
1438
|
+
updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
|
|
1439
|
+
}
|
|
1440
|
+
return {
|
|
1441
|
+
selectedFilesCheckboxRef,
|
|
1442
|
+
allFolderFilesCheckboxRef,
|
|
1443
|
+
newFilesCheckboxRef,
|
|
1444
|
+
scheduleModalState,
|
|
1445
|
+
isScheduleSaveDisabled,
|
|
1446
|
+
onChangeAutoSynchronizationOptions,
|
|
1447
|
+
saveScheduleSync,
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
/// <reference path="../../../../ui/types.d.ts" />
|
|
1452
|
+
function useSettings({ configurationFields, config, settingsModalRef, reloadOnConfigSave, refreshDependencies, checkJob, getCrowdinData, getIntegrationData, refreshAutoSyncPausedIndicatorsAndWarning, }) {
|
|
1453
|
+
const settingsFieldRefs = reactExports.useRef({});
|
|
1454
|
+
const [isLoading, setIsLoading] = reactExports.useState(false);
|
|
1455
|
+
const [isSettingsSaveDisabled, setIsSettingsSaveDisabled] = reactExports.useState(false);
|
|
1456
|
+
function triggerEvent(el, type) {
|
|
1457
|
+
const e = document.createEvent('HTMLEvents');
|
|
1458
|
+
e.initEvent(type, false, true);
|
|
1459
|
+
el.dispatchEvent(e);
|
|
1460
|
+
}
|
|
1461
|
+
function parseCrowdinSelectValue(value) {
|
|
1462
|
+
if (Array.isArray(value)) {
|
|
1463
|
+
return value;
|
|
1464
|
+
}
|
|
1465
|
+
if (value === undefined || value === null || value === '') {
|
|
1466
|
+
return [];
|
|
1467
|
+
}
|
|
1468
|
+
try {
|
|
1469
|
+
const parsedValue = JSON.parse(value);
|
|
1470
|
+
return Array.isArray(parsedValue) ? parsedValue : [parsedValue];
|
|
1471
|
+
}
|
|
1472
|
+
catch {
|
|
1473
|
+
return [value];
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
function registerSettingsField(key) {
|
|
1477
|
+
return (element) => {
|
|
1478
|
+
if (!key) {
|
|
1479
|
+
return;
|
|
1480
|
+
}
|
|
1481
|
+
if (element) {
|
|
1482
|
+
settingsFieldRefs.current[key] = element;
|
|
1483
|
+
}
|
|
1484
|
+
else {
|
|
1485
|
+
delete settingsFieldRefs.current[key];
|
|
1486
|
+
}
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
function settingsFieldChange(eventOrElement) {
|
|
1490
|
+
var _a, _b;
|
|
1491
|
+
const el = (eventOrElement === null || eventOrElement === void 0 ? void 0 : eventOrElement.currentTarget) || (eventOrElement === null || eventOrElement === void 0 ? void 0 : eventOrElement.target) || eventOrElement;
|
|
1492
|
+
(_a = el === null || el === void 0 ? void 0 : el.removeAttribute) === null || _a === void 0 ? void 0 : _a.call(el, 'error');
|
|
1493
|
+
(_b = el === null || el === void 0 ? void 0 : el.removeAttribute) === null || _b === void 0 ? void 0 : _b.call(el, 'error-text');
|
|
1494
|
+
}
|
|
1495
|
+
function fillSettingsForm() {
|
|
1496
|
+
Object.entries(config.current).forEach(([key, value]) => {
|
|
1497
|
+
const el = settingsFieldRefs.current[key];
|
|
1498
|
+
if (el && (value || el.tagName.toLowerCase() === 'crowdin-checkbox')) {
|
|
1499
|
+
if (el.tagName.toLowerCase() === 'crowdin-select') {
|
|
1500
|
+
if (el.hasAttribute('is-multi')) {
|
|
1501
|
+
el.value = JSON.stringify(value);
|
|
1502
|
+
}
|
|
1503
|
+
else {
|
|
1504
|
+
el.value = JSON.stringify([value]);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
else if (el.tagName.toLowerCase() === 'crowdin-checkbox') {
|
|
1508
|
+
el.checked = !!value;
|
|
1509
|
+
}
|
|
1510
|
+
else if (el.tagName.toLowerCase() === 'crowdin-textarea') {
|
|
1511
|
+
el.value = value;
|
|
1512
|
+
el.setValue(value);
|
|
1513
|
+
}
|
|
1514
|
+
else {
|
|
1515
|
+
el.value = value;
|
|
1516
|
+
}
|
|
1517
|
+
triggerEvent(el, 'change');
|
|
1518
|
+
}
|
|
1519
|
+
});
|
|
1520
|
+
setTimeout(refreshDependencies, 100);
|
|
1521
|
+
}
|
|
1522
|
+
async function saveSettings() {
|
|
1523
|
+
var _a, _b, _c, _d;
|
|
1524
|
+
setIsLoading(true);
|
|
1525
|
+
const configReq = {};
|
|
1526
|
+
configurationFields === null || configurationFields === void 0 ? void 0 : configurationFields.forEach((tab) => {
|
|
1527
|
+
tab.fields.forEach((field) => {
|
|
1528
|
+
if (!field.key) {
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
const el = settingsFieldRefs.current[field.key];
|
|
1532
|
+
if (!el) {
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
const tagName = el.tagName.toLowerCase();
|
|
1536
|
+
if (tagName === 'crowdin-select') {
|
|
1537
|
+
const value = parseCrowdinSelectValue(el.value);
|
|
1538
|
+
configReq[field.key] = el.hasAttribute('is-multi') ? value : value[0];
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1541
|
+
if (tagName === 'crowdin-checkbox') {
|
|
1542
|
+
configReq[field.key] = !!el.checked;
|
|
1543
|
+
return;
|
|
1544
|
+
}
|
|
1545
|
+
configReq[field.key] = el.value;
|
|
1546
|
+
});
|
|
1547
|
+
});
|
|
1548
|
+
let isValidationError = false;
|
|
1549
|
+
let isSettingsSaveJobPending = false;
|
|
1550
|
+
let isSettingsSaveFailed = false;
|
|
1551
|
+
setIsSettingsSaveDisabled(true);
|
|
1552
|
+
try {
|
|
1553
|
+
const restParams = await checkOrigin();
|
|
1554
|
+
const res = await checkResponse(await fetch('api/settings' + restParams, {
|
|
1555
|
+
method: 'POST',
|
|
1556
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1557
|
+
body: JSON.stringify({ config: configReq }),
|
|
1558
|
+
}));
|
|
1559
|
+
if (res === null || res === void 0 ? void 0 : res.jobId) {
|
|
1560
|
+
isSettingsSaveJobPending = true;
|
|
1561
|
+
checkJob({
|
|
1562
|
+
jobId: res.jobId,
|
|
1563
|
+
jobType: JOB_TYPE.integrationSettingsSave,
|
|
1564
|
+
onSuccess: () => {
|
|
1565
|
+
showToast('Settings successfully saved');
|
|
1566
|
+
config.current = configReq;
|
|
1567
|
+
refreshAutoSyncPausedIndicatorsAndWarning().catch((e) => catchRejection(e, "Can't fetch sync settings warning"));
|
|
1568
|
+
},
|
|
1569
|
+
onError: () => {
|
|
1570
|
+
isSettingsSaveFailed = true;
|
|
1571
|
+
showToast("Can't save settings");
|
|
1572
|
+
},
|
|
1573
|
+
onFinally: () => {
|
|
1574
|
+
setTimeout(() => setIsLoading(false), 500);
|
|
1575
|
+
setIsSettingsSaveDisabled(false);
|
|
1576
|
+
if (!isValidationError && !isSettingsSaveFailed) {
|
|
1577
|
+
closeModal(settingsModalRef.current);
|
|
1578
|
+
if (reloadOnConfigSave) {
|
|
1579
|
+
getIntegrationData({ hardReload: true });
|
|
1580
|
+
getCrowdinData();
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
},
|
|
1584
|
+
});
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
showToast('Settings successfully saved');
|
|
1588
|
+
config.current = configReq;
|
|
1589
|
+
refreshAutoSyncPausedIndicatorsAndWarning().catch((e) => catchRejection(e, "Can't fetch sync settings warning"));
|
|
1590
|
+
}
|
|
1591
|
+
catch (e) {
|
|
1592
|
+
if ((e === null || e === void 0 ? void 0 : e.error) && ((_a = e === null || e === void 0 ? void 0 : e.error) === null || _a === void 0 ? void 0 : _a.type) === 'validation_error') {
|
|
1593
|
+
Object.keys((_b = e === null || e === void 0 ? void 0 : e.error) === null || _b === void 0 ? void 0 : _b.details).forEach((key) => {
|
|
1594
|
+
var _a;
|
|
1595
|
+
const el = settingsFieldRefs.current[key];
|
|
1596
|
+
if (el) {
|
|
1597
|
+
el.setAttribute('error', 'true');
|
|
1598
|
+
el.setAttribute('error-text', (_a = e === null || e === void 0 ? void 0 : e.error) === null || _a === void 0 ? void 0 : _a.details[key]);
|
|
1599
|
+
}
|
|
1600
|
+
});
|
|
1601
|
+
isValidationError = true;
|
|
1602
|
+
showToast(((_d = (_c = e === null || e === void 0 ? void 0 : e.error) === null || _c === void 0 ? void 0 : _c.details) === null || _d === void 0 ? void 0 : _d.message) || "Can't save settings");
|
|
1603
|
+
setIsSettingsSaveDisabled(false);
|
|
1604
|
+
return;
|
|
1605
|
+
}
|
|
1606
|
+
catchRejection(e, "Can't save settings");
|
|
1607
|
+
}
|
|
1608
|
+
finally {
|
|
1609
|
+
if (isSettingsSaveJobPending) {
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
setTimeout(() => setIsLoading(false), 500);
|
|
1613
|
+
setIsSettingsSaveDisabled(false);
|
|
1614
|
+
if (!isValidationError) {
|
|
1615
|
+
closeModal(settingsModalRef.current);
|
|
1616
|
+
if (reloadOnConfigSave) {
|
|
1617
|
+
getIntegrationData({ hardReload: true });
|
|
1618
|
+
getCrowdinData();
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
554
1622
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
const branchType = '2';
|
|
563
|
-
const JOB_TYPE = {
|
|
564
|
-
updateCrowdin: 'updateCrowdin',
|
|
565
|
-
updateIntegration: 'updateIntegration',
|
|
566
|
-
updateTargetLanguages: 'updateTargetLanguages',
|
|
567
|
-
integrationSyncSettingsSave: 'integrationSyncSettingsSave',
|
|
568
|
-
crowdinSyncSettingsSave: 'crowdinSyncSettingsSave',
|
|
569
|
-
integrationSettingsSave: 'integrationSettingsSave',
|
|
1623
|
+
return {
|
|
1624
|
+
isLoading,
|
|
1625
|
+
isSettingsSaveDisabled,
|
|
1626
|
+
fillSettingsForm,
|
|
1627
|
+
saveSettings,
|
|
1628
|
+
registerSettingsField,
|
|
1629
|
+
settingsFieldChange,
|
|
570
1630
|
};
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
canceled: 'canceled',
|
|
576
|
-
finished: 'finished',
|
|
577
|
-
};
|
|
578
|
-
const silentJobs = [JOB_TYPE.integrationSettingsSave];
|
|
579
|
-
const appComponent = reactExports.useRef(null);
|
|
580
|
-
const subscriptionModal = reactExports.useRef(null);
|
|
581
|
-
const languageModal = reactExports.useRef(null);
|
|
582
|
-
const usersSelectRef = reactExports.useRef(null);
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
/// <reference path="../../../../ui/types.d.ts" />
|
|
1634
|
+
function useSyncOperations({ appComponent, asyncProgressRef, config, name, integrationOneLevelFetching, integrationSearchListener, integrationPagination, withCronSync, webhooks, progressiveCrowdinFilesLoading, asyncProgress, syncNewElements, }) {
|
|
583
1635
|
const crowdinFilesToUpdateTargetLanguages = reactExports.useRef([]);
|
|
584
1636
|
const asyncJobs = reactExports.useRef({});
|
|
585
1637
|
const project = reactExports.useRef({});
|
|
586
1638
|
const crowdinData = reactExports.useRef([]);
|
|
587
1639
|
const fileToSync = reactExports.useRef([]);
|
|
588
|
-
const syncData = reactExports.useRef(null);
|
|
589
|
-
const subscriptionLink = reactExports.useRef('');
|
|
590
1640
|
const hasLoadMoreElements = reactExports.useRef(false);
|
|
591
1641
|
const savedIntegrationData = reactExports.useRef(null);
|
|
592
1642
|
const currentOpenedFolders = reactExports.useRef(null);
|
|
1643
|
+
const languageModal = reactExports.useRef(null);
|
|
1644
|
+
const languageSelectRef = reactExports.useRef(null);
|
|
1645
|
+
const [languageModalState, setLanguageModalState] = reactExports.useState(null);
|
|
1646
|
+
const silentJobs = [JOB_TYPE.integrationSettingsSave];
|
|
1647
|
+
reactExports.useEffect(() => {
|
|
1648
|
+
var _a;
|
|
1649
|
+
if (!languageModalState || !((_a = languageSelectRef.current) === null || _a === void 0 ? void 0 : _a.setValue)) {
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
languageSelectRef.current.setValue(languageModalState.languages.map((language) => language.id));
|
|
1653
|
+
}, [languageModalState]);
|
|
593
1654
|
reactExports.useEffect(() => {
|
|
594
|
-
// Event listeners
|
|
595
1655
|
const listeners = {
|
|
596
1656
|
refreshFilesList: (e) => {
|
|
597
1657
|
if (e.detail.refreshIntegration) {
|
|
@@ -616,34 +1676,20 @@
|
|
|
616
1676
|
cancelAsyncAction: (e) => {
|
|
617
1677
|
cancelJob(e.detail);
|
|
618
1678
|
},
|
|
619
|
-
keydown: (event) => {
|
|
620
|
-
if (event.keyCode === 27) {
|
|
621
|
-
const permissions = document.getElementById('permissions-modal');
|
|
622
|
-
// not sure where we get users from here
|
|
623
|
-
// @ts-ignore
|
|
624
|
-
if (users) {
|
|
625
|
-
closeModal(permissions);
|
|
626
|
-
}
|
|
627
|
-
const infoModalEl = document.getElementById('info-modal');
|
|
628
|
-
if (infoModalEl) {
|
|
629
|
-
closeModal(infoModalEl);
|
|
630
|
-
}
|
|
631
|
-
const settingsModal = document.getElementById('settings-modal');
|
|
632
|
-
if (settingsModal) {
|
|
633
|
-
closeModal(settingsModal);
|
|
634
|
-
}
|
|
635
|
-
if (languageModal.current) {
|
|
636
|
-
closeModal(languageModal.current);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
},
|
|
640
1679
|
loadMoreClick: async (e) => {
|
|
1680
|
+
var _a;
|
|
641
1681
|
const loadMoreFile = e.detail;
|
|
642
|
-
const fileComponent =
|
|
1682
|
+
const fileComponent = (_a = appComponent.current) === null || _a === void 0 ? void 0 : _a.querySelector('#integration-files');
|
|
1683
|
+
if (!fileComponent) {
|
|
1684
|
+
return;
|
|
1685
|
+
}
|
|
643
1686
|
await fileComponent.setLoadMoreLoading(loadMoreFile.id, true);
|
|
644
|
-
|
|
1687
|
+
try {
|
|
1688
|
+
await getIntegrationData({ parentId: e.detail.parent_id, paginationData: e.detail.pagination });
|
|
1689
|
+
}
|
|
1690
|
+
finally {
|
|
645
1691
|
await fileComponent.setLoadMoreLoading(loadMoreFile.id, false);
|
|
646
|
-
}
|
|
1692
|
+
}
|
|
647
1693
|
},
|
|
648
1694
|
};
|
|
649
1695
|
if (integrationSearchListener) {
|
|
@@ -666,64 +1712,18 @@
|
|
|
666
1712
|
getIntegrationData({ page: e.detail.page });
|
|
667
1713
|
};
|
|
668
1714
|
}
|
|
669
|
-
if (withCronSync || webhooks) {
|
|
670
|
-
listeners['integrationScheduleSync'] = setIntegrationScheduleSync;
|
|
671
|
-
listeners['crowdinScheduleSync'] = setCrowdinScheduleSync;
|
|
672
|
-
listeners['crowdinDisableSync'] = disableCrowdinSync;
|
|
673
|
-
listeners['integrationDisableSync'] = disableIntegrationSync;
|
|
674
|
-
}
|
|
675
1715
|
for (const [event, handler] of Object.entries(listeners)) {
|
|
676
1716
|
document.body.addEventListener(event, handler);
|
|
677
1717
|
}
|
|
678
|
-
// Initial data fetch
|
|
679
1718
|
getCrowdinData();
|
|
680
1719
|
getIntegrationData({});
|
|
681
1720
|
getActiveJobs();
|
|
682
|
-
if (checkSubscription) {
|
|
683
|
-
getSubscriptionInfo();
|
|
684
|
-
}
|
|
685
|
-
if (notice) {
|
|
686
|
-
const noticeEl = document.getElementById('notice');
|
|
687
|
-
checkAlert(noticeEl, 'notice');
|
|
688
|
-
}
|
|
689
1721
|
return () => {
|
|
690
1722
|
for (const [event, handler] of Object.entries(listeners)) {
|
|
691
1723
|
document.body.removeEventListener(event, handler);
|
|
692
1724
|
}
|
|
693
1725
|
};
|
|
694
1726
|
}, []);
|
|
695
|
-
// Expose centralized API to global scope for main.js compatibility
|
|
696
|
-
reactExports.useEffect(() => {
|
|
697
|
-
window.app = {
|
|
698
|
-
subscriptionModal: subscriptionModal,
|
|
699
|
-
subscriptionLink: subscriptionLink,
|
|
700
|
-
openModal: openModal,
|
|
701
|
-
};
|
|
702
|
-
return () => {
|
|
703
|
-
delete window.app;
|
|
704
|
-
};
|
|
705
|
-
}, []);
|
|
706
|
-
// crowdin-users-select doesn't trigger onChange reliably, using native event listener instead
|
|
707
|
-
reactExports.useEffect(() => {
|
|
708
|
-
const selectElement = usersSelectRef.current;
|
|
709
|
-
if (selectElement) {
|
|
710
|
-
const handleChange = () => {
|
|
711
|
-
checkUsers();
|
|
712
|
-
};
|
|
713
|
-
selectElement.addEventListener('change', handleChange);
|
|
714
|
-
return () => {
|
|
715
|
-
selectElement.removeEventListener('change', handleChange);
|
|
716
|
-
};
|
|
717
|
-
}
|
|
718
|
-
}, []);
|
|
719
|
-
function integrationLogout() {
|
|
720
|
-
checkOrigin()
|
|
721
|
-
.then((queryParams) => fetch(`api/logout${queryParams}`, { method: 'POST' }))
|
|
722
|
-
.then(checkResponse)
|
|
723
|
-
.then(reloadLocation)
|
|
724
|
-
.then(() => localStorage.removeItem(`revised_${name}`))
|
|
725
|
-
.catch((e) => catchRejection(e, e.error || 'Looks like you are not logged in'));
|
|
726
|
-
}
|
|
727
1727
|
function transformCrowdinItemToTree(e) {
|
|
728
1728
|
const item = {
|
|
729
1729
|
parent_id: e.parentId ? e.parentId : '0',
|
|
@@ -736,22 +1736,21 @@
|
|
|
736
1736
|
};
|
|
737
1737
|
if (e.type) {
|
|
738
1738
|
item.type = e.type;
|
|
739
|
-
item.node_type =
|
|
1739
|
+
item.node_type = FILE_TYPE;
|
|
740
1740
|
item.failed = e.failed;
|
|
741
1741
|
item.excludedTargetLanguages = e.excludedTargetLanguages;
|
|
742
1742
|
}
|
|
743
1743
|
else {
|
|
744
|
-
item.node_type = e.nodeType ||
|
|
1744
|
+
item.node_type = e.nodeType || FOLDER_TYPE;
|
|
745
1745
|
}
|
|
746
1746
|
return item;
|
|
747
1747
|
}
|
|
748
|
-
function getCrowdinData() {
|
|
749
|
-
var _a;
|
|
1748
|
+
async function getCrowdinData() {
|
|
1749
|
+
var _a, _b, _c, _d, _f;
|
|
750
1750
|
(_a = appComponent.current) === null || _a === void 0 ? void 0 : _a.setAttribute('is-crowdin-loading', 'true');
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
.then((restParams) => {
|
|
1751
|
+
try {
|
|
1752
|
+
const restParams = await checkOrigin();
|
|
1753
|
+
if (progressiveCrowdinFilesLoading) {
|
|
755
1754
|
const dirPromise = fetch('api/crowdin/files' + restParams + '&mode=directories')
|
|
756
1755
|
.then(checkResponse)
|
|
757
1756
|
.then((directories) => {
|
|
@@ -761,15 +1760,14 @@
|
|
|
761
1760
|
(_a = appComponent.current) === null || _a === void 0 ? void 0 : _a.setCrowdinFilesData(dirTree);
|
|
762
1761
|
return dirTree;
|
|
763
1762
|
});
|
|
764
|
-
const
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
var _a, _b, _c;
|
|
1763
|
+
const [dirTree, files, projectData] = await Promise.all([
|
|
1764
|
+
dirPromise,
|
|
1765
|
+
fetch('api/crowdin/files' + restParams + '&mode=files').then(checkResponse),
|
|
1766
|
+
fetch('api/crowdin/project' + restParams).then(checkResponse),
|
|
1767
|
+
]);
|
|
770
1768
|
const fileTree = files.map(transformCrowdinItemToTree);
|
|
771
1769
|
crowdinData.current = [...dirTree, ...fileTree];
|
|
772
|
-
(
|
|
1770
|
+
(_b = appComponent.current) === null || _b === void 0 ? void 0 : _b.setCrowdinFilesData(crowdinData.current);
|
|
773
1771
|
project.current = projectData;
|
|
774
1772
|
const languagesSorted = project.current.targetLanguages
|
|
775
1773
|
.map((language) => ({
|
|
@@ -778,22 +1776,17 @@
|
|
|
778
1776
|
...language,
|
|
779
1777
|
}))
|
|
780
1778
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
781
|
-
if (project.current.inContext && ((
|
|
1779
|
+
if (project.current.inContext && ((_c = config.current) === null || _c === void 0 ? void 0 : _c.inContext)) {
|
|
782
1780
|
languagesSorted.push({ ...project.current.inContextPseudoLanguage, inContext: true });
|
|
783
1781
|
}
|
|
784
1782
|
setLanguagesForTranslation(languagesSorted);
|
|
785
|
-
(
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
const projectPromise = fetch('api/crowdin/project' + restParams).then(checkResponse);
|
|
793
|
-
return Promise.all([filesPromise, projectPromise]);
|
|
794
|
-
})
|
|
795
|
-
.then(([files, projectData]) => {
|
|
796
|
-
var _a;
|
|
1783
|
+
(_d = appComponent.current) === null || _d === void 0 ? void 0 : _d.setCrowdinLanguagesData(languagesSorted);
|
|
1784
|
+
}
|
|
1785
|
+
else {
|
|
1786
|
+
const [files, projectData] = await Promise.all([
|
|
1787
|
+
fetch('api/crowdin/files' + restParams).then(checkResponse),
|
|
1788
|
+
fetch('api/crowdin/project' + restParams).then(checkResponse),
|
|
1789
|
+
]);
|
|
797
1790
|
const tree = files.map(transformCrowdinItemToTree);
|
|
798
1791
|
crowdinData.current = tree;
|
|
799
1792
|
appComponent.current.setCrowdinFilesData(tree);
|
|
@@ -805,37 +1798,35 @@
|
|
|
805
1798
|
...language,
|
|
806
1799
|
}))
|
|
807
1800
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
808
|
-
if (project.current.inContext && ((
|
|
1801
|
+
if (project.current.inContext && ((_f = config.current) === null || _f === void 0 ? void 0 : _f.inContext)) {
|
|
809
1802
|
languagesSorted.push({ ...project.current.inContextPseudoLanguage, inContext: true });
|
|
810
1803
|
}
|
|
811
1804
|
setLanguagesForTranslation(languagesSorted);
|
|
812
1805
|
appComponent.current.setCrowdinLanguagesData(languagesSorted);
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
promise
|
|
816
|
-
.then(() => {
|
|
1806
|
+
}
|
|
817
1807
|
if (withCronSync || webhooks) {
|
|
818
|
-
|
|
1808
|
+
await getSyncSettings('crowdin');
|
|
819
1809
|
}
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
|
|
1810
|
+
}
|
|
1811
|
+
catch (e) {
|
|
1812
|
+
catchRejection(e, "Can't fetch Crowdin data");
|
|
1813
|
+
}
|
|
1814
|
+
finally {
|
|
1815
|
+
appComponent.current.setAttribute('is-crowdin-loading', false);
|
|
1816
|
+
}
|
|
823
1817
|
}
|
|
824
|
-
function getIntegrationData({ hardReload = false, parentId = '', search = '', page = 0, recursion = false, paginationData } = {}, recursionState = null) {
|
|
1818
|
+
async function getIntegrationData({ hardReload = false, parentId = '', search = '', page = 0, recursion = false, paginationData } = {}, recursionState = null) {
|
|
825
1819
|
if (!paginationData) {
|
|
826
1820
|
appComponent.current.setAttribute('is-integration-loading', true);
|
|
827
1821
|
}
|
|
828
1822
|
let recursionStateLocal = recursionState;
|
|
829
|
-
|
|
830
|
-
|
|
1823
|
+
try {
|
|
1824
|
+
const restParams = await checkOrigin();
|
|
831
1825
|
let url = `api/integration/data${restParams}&parent_id=${encodeURIComponent(parentId)}&search=${encodeURIComponent(search)}&page=${page}`;
|
|
832
1826
|
if (paginationData) {
|
|
833
1827
|
url += `&paginationData=${encodeURIComponent(JSON.stringify(paginationData))}`;
|
|
834
1828
|
}
|
|
835
|
-
|
|
836
|
-
})
|
|
837
|
-
.then(checkResponse)
|
|
838
|
-
.then(async (res) => {
|
|
1829
|
+
const res = await checkResponse(await fetch(url));
|
|
839
1830
|
const files = res.data;
|
|
840
1831
|
const stopPagination = res.stopPagination;
|
|
841
1832
|
const tree = files.map((e) => {
|
|
@@ -855,10 +1846,10 @@
|
|
|
855
1846
|
item.notSynced = e.notSynced;
|
|
856
1847
|
item.synced = e.synced;
|
|
857
1848
|
item.type = e.type;
|
|
858
|
-
item.node_type =
|
|
1849
|
+
item.node_type = FILE_TYPE;
|
|
859
1850
|
}
|
|
860
1851
|
else {
|
|
861
|
-
item.node_type = e.nodeType ||
|
|
1852
|
+
item.node_type = e.nodeType || FOLDER_TYPE;
|
|
862
1853
|
}
|
|
863
1854
|
return item;
|
|
864
1855
|
});
|
|
@@ -870,17 +1861,16 @@
|
|
|
870
1861
|
appComponent.current.setIntegrationFilesData(tree);
|
|
871
1862
|
}
|
|
872
1863
|
else if (tree.length) {
|
|
873
|
-
appComponent.current.pushIntegrationFilesData(tree).then(() => {
|
|
1864
|
+
appComponent.current.pushIntegrationFilesData(tree).then(async () => {
|
|
874
1865
|
if (parentId) {
|
|
875
|
-
appIntegrationFiles.getSelected()
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
});
|
|
1866
|
+
const selection = await appIntegrationFiles.getSelected();
|
|
1867
|
+
const selectedIds = selection === null || selection === void 0 ? void 0 : selection.filter((node) => node).map(({ id }) => id.toString());
|
|
1868
|
+
const filteredNodes = tree.filter((node) => !selectedIds.includes(node.id.toString()) &&
|
|
1869
|
+
selectedIds.includes(node.parent_id.toString()));
|
|
1870
|
+
if (filteredNodes === null || filteredNodes === void 0 ? void 0 : filteredNodes.length) {
|
|
1871
|
+
const filteredNodesId = filteredNodes.map(({ id }) => id.toString());
|
|
1872
|
+
await appIntegrationFiles.setSelected(filteredNodesId);
|
|
1873
|
+
}
|
|
884
1874
|
}
|
|
885
1875
|
});
|
|
886
1876
|
}
|
|
@@ -912,18 +1902,18 @@
|
|
|
912
1902
|
}
|
|
913
1903
|
const folderItems = files.filter(isFolder);
|
|
914
1904
|
if (folderItems.length === 0) {
|
|
915
|
-
return
|
|
1905
|
+
return;
|
|
916
1906
|
}
|
|
917
1907
|
folderItems.forEach((folder) => recursionStateLocal.openedFolders.add(folder.id));
|
|
918
|
-
const
|
|
1908
|
+
const openedFoldersNow = await appComponent.current.getIntegrationOpenedFolders();
|
|
919
1909
|
appComponent.current.setIntegrationOpenedFolders([
|
|
920
|
-
...
|
|
1910
|
+
...openedFoldersNow,
|
|
921
1911
|
...recursionStateLocal.openedFolders,
|
|
922
1912
|
]);
|
|
923
|
-
|
|
1913
|
+
await Promise.all(folderItems.map(async (folder) => {
|
|
924
1914
|
recursionStateLocal.calls++;
|
|
925
1915
|
try {
|
|
926
|
-
|
|
1916
|
+
await getIntegrationData({ parentId: folder.id, recursion: true }, recursionState);
|
|
927
1917
|
}
|
|
928
1918
|
finally {
|
|
929
1919
|
recursionStateLocal.calls--;
|
|
@@ -931,24 +1921,23 @@
|
|
|
931
1921
|
recursionStateLocal.setLoading(false);
|
|
932
1922
|
}
|
|
933
1923
|
}
|
|
934
|
-
});
|
|
935
|
-
return Promise.all(recursivePromises);
|
|
1924
|
+
}));
|
|
936
1925
|
}
|
|
937
|
-
})
|
|
938
|
-
.then(() => {
|
|
939
1926
|
if (withCronSync || webhooks) {
|
|
940
|
-
getSyncSettings('integration');
|
|
1927
|
+
await getSyncSettings('integration');
|
|
941
1928
|
}
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
|
|
1929
|
+
}
|
|
1930
|
+
catch (e) {
|
|
1931
|
+
catchRejection(e, `Can't fetch ${name} templates`);
|
|
1932
|
+
}
|
|
1933
|
+
finally {
|
|
945
1934
|
if (!recursionStateLocal && !recursion) {
|
|
946
1935
|
appComponent.current.setAttribute('is-integration-loading', false);
|
|
947
1936
|
}
|
|
948
1937
|
else if (recursionStateLocal && recursionStateLocal.calls === 0) {
|
|
949
1938
|
appComponent.current.setAttribute('is-integration-loading', false);
|
|
950
1939
|
}
|
|
951
|
-
}
|
|
1940
|
+
}
|
|
952
1941
|
}
|
|
953
1942
|
function isScheduleDisabled(currentConfig = config.current) {
|
|
954
1943
|
var _a;
|
|
@@ -965,10 +1954,7 @@
|
|
|
965
1954
|
if (currentScheduleDisabled === nextScheduleDisabled) {
|
|
966
1955
|
return null;
|
|
967
1956
|
}
|
|
968
|
-
return {
|
|
969
|
-
...item,
|
|
970
|
-
scheduleDisabled: nextScheduleDisabled,
|
|
971
|
-
};
|
|
1957
|
+
return { ...item, scheduleDisabled: nextScheduleDisabled };
|
|
972
1958
|
})
|
|
973
1959
|
.filter(Boolean);
|
|
974
1960
|
if (provider === 'crowdin') {
|
|
@@ -996,1176 +1982,695 @@
|
|
|
996
1982
|
async function refreshAutoSyncPausedIndicatorsAndWarning() {
|
|
997
1983
|
const [crowdinSyncSettings, integrationSyncSettings] = await Promise.all([
|
|
998
1984
|
fetchSyncSettingsFiles('crowdin'),
|
|
999
|
-
fetchSyncSettingsFiles('integration'),
|
|
1000
|
-
]);
|
|
1001
|
-
await applyAutoSyncPausedMarkers('crowdin', crowdinSyncSettings);
|
|
1002
|
-
await applyAutoSyncPausedMarkers('integration', integrationSyncSettings);
|
|
1003
|
-
if (isScheduleDisabled() && (crowdinSyncSettings.length || integrationSyncSettings.length)) {
|
|
1004
|
-
showToast('Auto Sync is configured for some files, but sync schedule is disabled in app settings.');
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
function getSyncSettings(provider) {
|
|
1008
|
-
checkOrigin()
|
|
1009
|
-
.then((restParams) => fetch(`/api/sync-settings/${provider}` + restParams))
|
|
1010
|
-
.then(checkResponse)
|
|
1011
|
-
.then(async (res) => {
|
|
1012
|
-
if (provider === 'crowdin') {
|
|
1013
|
-
if (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.crowdin) {
|
|
1014
|
-
appComponent.current.setCrowdinScheduleSync(res, true, true);
|
|
1015
|
-
}
|
|
1016
|
-
else {
|
|
1017
|
-
appComponent.current.setCrowdinScheduleSync(res);
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
else {
|
|
1021
|
-
if (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration) {
|
|
1022
|
-
appComponent.current.setIntegrationScheduleSync(res, true, true);
|
|
1023
|
-
}
|
|
1024
|
-
else {
|
|
1025
|
-
appComponent.current.setIntegrationScheduleSync(res);
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
await applyAutoSyncPausedMarkers(provider, res);
|
|
1029
|
-
})
|
|
1030
|
-
.catch((e) => catchRejection(e, "Can't fetch file progress"));
|
|
1031
|
-
}
|
|
1032
|
-
function getFileProgress(fileId) {
|
|
1033
|
-
checkOrigin()
|
|
1034
|
-
.then((restParams) => fetch(`api/crowdin/file-progress/${fileId}` + restParams))
|
|
1035
|
-
.then(checkResponse)
|
|
1036
|
-
.then((res) => appComponent.current.addCrowdinFileProgress(res))
|
|
1037
|
-
.catch((e) => catchRejection(e, "Can't fetch file progress"));
|
|
1038
|
-
}
|
|
1039
|
-
function uploadFilesToCrowdin(event, languages = []) {
|
|
1040
|
-
var _a, _b, _c, _d, _e;
|
|
1041
|
-
let files = [];
|
|
1042
|
-
let uploadTranslations = false;
|
|
1043
|
-
let forcePushSources = false;
|
|
1044
|
-
if (((_a = event.detail) === null || _a === void 0 ? void 0 : _a.action) === 'uploadTranslations') {
|
|
1045
|
-
files = event.detail.files;
|
|
1046
|
-
uploadTranslations = true;
|
|
1047
|
-
forcePushSources = true;
|
|
1048
|
-
}
|
|
1049
|
-
else if (((_b = event.detail) === null || _b === void 0 ? void 0 : _b.action) === 'excludedTargetLanguages') {
|
|
1050
|
-
fileToSync.current = event.detail.files;
|
|
1051
|
-
openLanguageModal();
|
|
1052
|
-
return;
|
|
1053
|
-
}
|
|
1054
|
-
else if (((_c = event.detail) === null || _c === void 0 ? void 0 : _c.action) === 'forcePushSources') {
|
|
1055
|
-
files = event.detail.files;
|
|
1056
|
-
forcePushSources = true;
|
|
1057
|
-
}
|
|
1058
|
-
else if (((_d = event.detail) === null || _d === void 0 ? void 0 : _d.action) === 'syncTranslationsToIntegration') {
|
|
1059
|
-
syncTranslationsToIntegration(event.detail.files);
|
|
1060
|
-
return;
|
|
1061
|
-
}
|
|
1062
|
-
else {
|
|
1063
|
-
files = event.detail;
|
|
1064
|
-
}
|
|
1065
|
-
if (languages.length > 0) {
|
|
1066
|
-
forcePushSources = true;
|
|
1067
|
-
}
|
|
1068
|
-
if (((_e = event.detail) === null || _e === void 0 ? void 0 : _e.length) === 0 || !event.detail) {
|
|
1069
|
-
showToast('Select templates which will be pushed to Crowdin');
|
|
1070
|
-
return;
|
|
1071
|
-
}
|
|
1072
|
-
appComponent.current.setAttribute('is-to-crowdin-process', true);
|
|
1073
|
-
let req;
|
|
1074
|
-
if (integrationOneLevelFetching) {
|
|
1075
|
-
req = files.map((f) => ({
|
|
1076
|
-
name: f.name,
|
|
1077
|
-
id: f.id,
|
|
1078
|
-
type: f.type,
|
|
1079
|
-
parentId: f.parent_id,
|
|
1080
|
-
nodeType: f.node_type,
|
|
1081
|
-
isUpdated: f.isUpdated,
|
|
1082
|
-
}));
|
|
1083
|
-
}
|
|
1084
|
-
else {
|
|
1085
|
-
req = files
|
|
1086
|
-
.filter((f) => f.node_type !== folderType)
|
|
1087
|
-
.map((f) => ({
|
|
1088
|
-
name: f.name,
|
|
1089
|
-
id: f.id,
|
|
1090
|
-
type: f.type,
|
|
1091
|
-
parentId: f.parent_id,
|
|
1092
|
-
isUpdated: f.isUpdated,
|
|
1093
|
-
}));
|
|
1094
|
-
}
|
|
1095
|
-
checkOrigin()
|
|
1096
|
-
.then((restParams) => fetch(`api/crowdin/update${restParams}&uploadTranslations=${uploadTranslations}&languages=${languages}&forcePushSources=${forcePushSources}`, {
|
|
1097
|
-
method: 'POST',
|
|
1098
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1099
|
-
body: JSON.stringify(req),
|
|
1100
|
-
}))
|
|
1101
|
-
.then(checkResponse)
|
|
1102
|
-
.then((res) => {
|
|
1103
|
-
checkJob({
|
|
1104
|
-
jobId: res === null || res === void 0 ? void 0 : res.jobId,
|
|
1105
|
-
jobType: JOB_TYPE.updateCrowdin,
|
|
1106
|
-
});
|
|
1107
|
-
})
|
|
1108
|
-
.catch((e) => catchRejection(e, "Can't upload templates to Crowdin"));
|
|
1109
|
-
}
|
|
1110
|
-
function getActiveJobs() {
|
|
1111
|
-
checkOrigin()
|
|
1112
|
-
.then((restParams) => fetch(`api/jobs${restParams}`))
|
|
1113
|
-
.then(checkResponse)
|
|
1114
|
-
.then((jobs) => {
|
|
1115
|
-
if (!Array.isArray(jobs)) {
|
|
1116
|
-
return;
|
|
1117
|
-
}
|
|
1118
|
-
jobs.forEach((job) => {
|
|
1119
|
-
switch (job.type) {
|
|
1120
|
-
case JOB_TYPE.updateCrowdin:
|
|
1121
|
-
case JOB_TYPE.updateTargetLanguages:
|
|
1122
|
-
appComponent.current.setAttribute('is-to-crowdin-process', true);
|
|
1123
|
-
break;
|
|
1124
|
-
case JOB_TYPE.updateIntegration:
|
|
1125
|
-
appComponent.current.setAttribute('is-to-integration-process', true);
|
|
1126
|
-
break;
|
|
1127
|
-
case JOB_TYPE.crowdinSyncSettingsSave:
|
|
1128
|
-
appComponent.current.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
1129
|
-
break;
|
|
1130
|
-
case JOB_TYPE.integrationSyncSettingsSave:
|
|
1131
|
-
appComponent.current.setAttribute('is-integration-sync-settings-in-progress', true);
|
|
1132
|
-
break;
|
|
1133
|
-
}
|
|
1134
|
-
checkJob({
|
|
1135
|
-
jobId: job.id,
|
|
1136
|
-
jobType: job.type,
|
|
1137
|
-
});
|
|
1138
|
-
});
|
|
1139
|
-
})
|
|
1140
|
-
.catch((e) => catchRejection(e, 'Sync status check failed'));
|
|
1141
|
-
}
|
|
1142
|
-
function cancelJob(jobId) {
|
|
1143
|
-
var _a;
|
|
1144
|
-
if ((_a = asyncJobs.current[jobId]) === null || _a === void 0 ? void 0 : _a.isFailed) {
|
|
1145
|
-
return;
|
|
1146
|
-
}
|
|
1147
|
-
checkOrigin()
|
|
1148
|
-
.then((restParams) => fetch('api/jobs' + restParams + '&jobId=' + jobId, {
|
|
1149
|
-
method: 'DELETE',
|
|
1150
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1151
|
-
}))
|
|
1152
|
-
.then(checkResponse)
|
|
1153
|
-
.then(() => showToast('Cancellation…'))
|
|
1154
|
-
.catch((e) => catchRejection(e, 'Sync cancellation failed'));
|
|
1155
|
-
}
|
|
1156
|
-
function checkJob({ jobId, jobType, onSuccess, onError, onFinally }) {
|
|
1157
|
-
switch (jobType) {
|
|
1158
|
-
case JOB_TYPE.updateCrowdin:
|
|
1159
|
-
case JOB_TYPE.updateTargetLanguages:
|
|
1160
|
-
if (!onFinally) {
|
|
1161
|
-
onFinally = () => {
|
|
1162
|
-
appComponent.current.setAttribute('is-to-crowdin-process', false);
|
|
1163
|
-
getCrowdinData();
|
|
1164
|
-
};
|
|
1165
|
-
}
|
|
1166
|
-
break;
|
|
1167
|
-
case JOB_TYPE.updateIntegration:
|
|
1168
|
-
if (!onFinally) {
|
|
1169
|
-
onFinally = () => appComponent.current.setAttribute('is-to-integration-process', false);
|
|
1170
|
-
}
|
|
1171
|
-
break;
|
|
1172
|
-
case JOB_TYPE.crowdinSyncSettingsSave:
|
|
1173
|
-
if (!onFinally) {
|
|
1174
|
-
onFinally = () => appComponent.current.setAttribute('is-crowdin-sync-settings-in-progress', false);
|
|
1175
|
-
}
|
|
1176
|
-
break;
|
|
1177
|
-
case JOB_TYPE.integrationSyncSettingsSave:
|
|
1178
|
-
if (!onFinally) {
|
|
1179
|
-
onFinally = () => appComponent.current.setAttribute('is-integration-sync-settings-in-progress', false);
|
|
1180
|
-
}
|
|
1181
|
-
break;
|
|
1985
|
+
fetchSyncSettingsFiles('integration'),
|
|
1986
|
+
]);
|
|
1987
|
+
await applyAutoSyncPausedMarkers('crowdin', crowdinSyncSettings);
|
|
1988
|
+
await applyAutoSyncPausedMarkers('integration', integrationSyncSettings);
|
|
1989
|
+
if (isScheduleDisabled() && (crowdinSyncSettings.length || integrationSyncSettings.length)) {
|
|
1990
|
+
showToast('Auto Sync is configured for some files, but sync schedule is disabled in app settings.');
|
|
1182
1991
|
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
const
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
title: job.title,
|
|
1195
|
-
progress,
|
|
1196
|
-
info,
|
|
1197
|
-
isFailed,
|
|
1198
|
-
},
|
|
1199
|
-
]);
|
|
1200
|
-
}
|
|
1201
|
-
if (isFailed) {
|
|
1202
|
-
if (onError) {
|
|
1203
|
-
onError();
|
|
1992
|
+
}
|
|
1993
|
+
async function getSyncSettings(provider) {
|
|
1994
|
+
try {
|
|
1995
|
+
const restParams = await checkOrigin();
|
|
1996
|
+
const res = await checkResponse(await fetch(`/api/sync-settings/${provider}` + restParams));
|
|
1997
|
+
if (provider === 'crowdin') {
|
|
1998
|
+
if (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.crowdin) {
|
|
1999
|
+
appComponent.current.setCrowdinScheduleSync(res, true, true);
|
|
2000
|
+
}
|
|
2001
|
+
else {
|
|
2002
|
+
appComponent.current.setCrowdinScheduleSync(res);
|
|
1204
2003
|
}
|
|
1205
|
-
}
|
|
1206
|
-
else if ([JOB_STATUS.created, JOB_STATUS.inProgress].includes(job.status) && job.progress < 100) {
|
|
1207
|
-
setTimeout(() => {
|
|
1208
|
-
checkJob({ jobId, jobType, onSuccess, onError, onFinally });
|
|
1209
|
-
}, asyncProgress.checkInterval);
|
|
1210
|
-
return;
|
|
1211
2004
|
}
|
|
1212
2005
|
else {
|
|
1213
|
-
if (
|
|
1214
|
-
|
|
2006
|
+
if (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration) {
|
|
2007
|
+
appComponent.current.setIntegrationScheduleSync(res, true, true);
|
|
2008
|
+
}
|
|
2009
|
+
else {
|
|
2010
|
+
appComponent.current.setIntegrationScheduleSync(res);
|
|
1215
2011
|
}
|
|
1216
2012
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
if (onFinally) {
|
|
1223
|
-
onFinally();
|
|
1224
|
-
}
|
|
1225
|
-
if (!silentJobs.find((type) => type === jobType)) {
|
|
1226
|
-
pushJobs([
|
|
1227
|
-
{
|
|
1228
|
-
id: jobId,
|
|
1229
|
-
isFailed: true,
|
|
1230
|
-
},
|
|
1231
|
-
]);
|
|
1232
|
-
}
|
|
1233
|
-
showToast('Sync status check failed');
|
|
1234
|
-
});
|
|
2013
|
+
await applyAutoSyncPausedMarkers(provider, res);
|
|
2014
|
+
}
|
|
2015
|
+
catch (e) {
|
|
2016
|
+
catchRejection(e, "Can't fetch file progress");
|
|
2017
|
+
}
|
|
1235
2018
|
}
|
|
1236
|
-
function
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
2019
|
+
async function getFileProgress(fileId) {
|
|
2020
|
+
try {
|
|
2021
|
+
const restParams = await checkOrigin();
|
|
2022
|
+
const res = await checkResponse(await fetch(`api/crowdin/file-progress/${fileId}` + restParams));
|
|
2023
|
+
appComponent.current.addCrowdinFileProgress(res);
|
|
1241
2024
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
pushJobs(jobs);
|
|
1245
|
-
}, 300);
|
|
2025
|
+
catch (e) {
|
|
2026
|
+
catchRejection(e, "Can't fetch file progress");
|
|
1246
2027
|
}
|
|
1247
2028
|
}
|
|
1248
|
-
function
|
|
1249
|
-
var _a, _b, _c, _d;
|
|
1250
|
-
let files =
|
|
1251
|
-
let
|
|
1252
|
-
|
|
2029
|
+
async function uploadFilesToCrowdin(event, languages = []) {
|
|
2030
|
+
var _a, _b, _c, _d, _f;
|
|
2031
|
+
let files = [];
|
|
2032
|
+
let uploadTranslations = false;
|
|
2033
|
+
let forcePushSources = false;
|
|
2034
|
+
if (((_a = event.detail) === null || _a === void 0 ? void 0 : _a.action) === 'uploadTranslations') {
|
|
1253
2035
|
files = event.detail.files;
|
|
1254
|
-
|
|
2036
|
+
uploadTranslations = true;
|
|
2037
|
+
forcePushSources = true;
|
|
1255
2038
|
}
|
|
1256
2039
|
else if (((_b = event.detail) === null || _b === void 0 ? void 0 : _b.action) === 'excludedTargetLanguages') {
|
|
1257
|
-
|
|
1258
|
-
|
|
2040
|
+
fileToSync.current = event.detail.files;
|
|
2041
|
+
openLanguageModal();
|
|
1259
2042
|
return;
|
|
1260
2043
|
}
|
|
1261
|
-
else if (((_c = event.detail) === null || _c === void 0 ? void 0 : _c.action) === '
|
|
1262
|
-
|
|
1263
|
-
|
|
2044
|
+
else if (((_c = event.detail) === null || _c === void 0 ? void 0 : _c.action) === 'forcePushSources') {
|
|
2045
|
+
files = event.detail.files;
|
|
2046
|
+
forcePushSources = true;
|
|
1264
2047
|
}
|
|
1265
|
-
else if (((_d = event.detail) === null || _d === void 0 ? void 0 : _d.action) === '
|
|
1266
|
-
|
|
2048
|
+
else if (((_d = event.detail) === null || _d === void 0 ? void 0 : _d.action) === 'syncTranslationsToIntegration') {
|
|
2049
|
+
syncTranslationsToIntegration(event.detail.files);
|
|
1267
2050
|
return;
|
|
1268
2051
|
}
|
|
1269
2052
|
else {
|
|
1270
2053
|
files = event.detail;
|
|
1271
2054
|
}
|
|
1272
|
-
if (
|
|
1273
|
-
|
|
1274
|
-
return;
|
|
2055
|
+
if (languages.length > 0) {
|
|
2056
|
+
forcePushSources = true;
|
|
1275
2057
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
Object.keys(files)
|
|
1279
|
-
.filter((id) => crowdinData.current.find((c) => c.id === id).node_type === fileType)
|
|
1280
|
-
.forEach((id) => (req[id] = files[id]));
|
|
1281
|
-
checkOrigin()
|
|
1282
|
-
.then((restParams) => fetch(`api/integration/update${restParams}&forcePushTranslations=${forcePushTranslations}`, {
|
|
1283
|
-
method: 'POST',
|
|
1284
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1285
|
-
body: JSON.stringify(req),
|
|
1286
|
-
}))
|
|
1287
|
-
.then(checkResponse)
|
|
1288
|
-
.then((res) => {
|
|
1289
|
-
checkJob({
|
|
1290
|
-
jobId: res === null || res === void 0 ? void 0 : res.jobId,
|
|
1291
|
-
jobType: JOB_TYPE.updateIntegration,
|
|
1292
|
-
});
|
|
1293
|
-
})
|
|
1294
|
-
.catch((e) => catchRejection(e, `Can't upload files to ${name}`));
|
|
1295
|
-
}
|
|
1296
|
-
function syncToCrowdinFromCrowdinFiles(files, uploadTranslations) {
|
|
1297
|
-
if (!files || Object.keys(files).length === 0) {
|
|
1298
|
-
showToast('Select files to sync');
|
|
2058
|
+
if (((_f = event.detail) === null || _f === void 0 ? void 0 : _f.length) === 0 || !event.detail) {
|
|
2059
|
+
showToast('Select templates which will be pushed to Crowdin');
|
|
1299
2060
|
return;
|
|
1300
2061
|
}
|
|
1301
2062
|
appComponent.current.setAttribute('is-to-crowdin-process', true);
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
.then(checkResponse)
|
|
1313
|
-
.then((res) => {
|
|
1314
|
-
checkJob({
|
|
1315
|
-
jobId: res === null || res === void 0 ? void 0 : res.jobId,
|
|
1316
|
-
jobType: JOB_TYPE.updateCrowdin,
|
|
1317
|
-
});
|
|
1318
|
-
})
|
|
1319
|
-
.catch((e) => catchRejection(e, "Can't sync files to Crowdin"));
|
|
1320
|
-
}
|
|
1321
|
-
function syncTranslationsToIntegration(files) {
|
|
1322
|
-
if (!files || files.length === 0) {
|
|
1323
|
-
showToast('Select files to sync');
|
|
1324
|
-
return;
|
|
1325
|
-
}
|
|
1326
|
-
appComponent.current.setAttribute('is-to-integration-process', true);
|
|
1327
|
-
const req = files
|
|
1328
|
-
.filter((f) => f.node_type !== folderType)
|
|
1329
|
-
.map((f) => ({
|
|
1330
|
-
name: f.name,
|
|
1331
|
-
id: f.id,
|
|
1332
|
-
type: f.type,
|
|
1333
|
-
parentId: f.parent_id,
|
|
1334
|
-
}));
|
|
1335
|
-
checkOrigin()
|
|
1336
|
-
.then((restParams) => fetch(`api/integration/update${restParams}&matchFromIntegration=true`, {
|
|
1337
|
-
method: 'POST',
|
|
1338
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1339
|
-
body: JSON.stringify(req),
|
|
1340
|
-
}))
|
|
1341
|
-
.then(checkResponse)
|
|
1342
|
-
.then((res) => {
|
|
1343
|
-
checkJob({
|
|
1344
|
-
jobId: res === null || res === void 0 ? void 0 : res.jobId,
|
|
1345
|
-
jobType: JOB_TYPE.updateIntegration,
|
|
1346
|
-
});
|
|
1347
|
-
})
|
|
1348
|
-
.catch((e) => catchRejection(e, `Can't sync translations to ${name}`));
|
|
1349
|
-
}
|
|
1350
|
-
function openLanguageModal() {
|
|
1351
|
-
openModal(languageModal.current);
|
|
1352
|
-
}
|
|
1353
|
-
function openLanguageModalForCrowdinFiles() {
|
|
1354
|
-
const languages = project.current.targetLanguages || [];
|
|
1355
|
-
const buttonHtml = `
|
|
1356
|
-
<crowdin-button id="update-crowdin-target-languages" outlined">
|
|
1357
|
-
Update Target Languages
|
|
1358
|
-
</crowdin-button>
|
|
1359
|
-
`;
|
|
1360
|
-
setTimeout(() => {
|
|
1361
|
-
const btn = document.querySelector('#update-crowdin-target-languages');
|
|
1362
|
-
if (btn) {
|
|
1363
|
-
btn.addEventListener('click', () => updateCrowdinFilesTargetLanguages());
|
|
1364
|
-
}
|
|
1365
|
-
}, 0);
|
|
1366
|
-
setLanguagesForTranslation(languages, buttonHtml);
|
|
1367
|
-
openModal(languageModal.current);
|
|
1368
|
-
}
|
|
1369
|
-
async function uploadFilesToCrowdinWithExcludedLanguages() {
|
|
1370
|
-
const languageSelect = document.querySelector('#language-select');
|
|
1371
|
-
const selectedLanguages = await languageSelect.getValue();
|
|
1372
|
-
closeModal(languageModal.current);
|
|
1373
|
-
uploadFilesToCrowdin({ detail: fileToSync.current }, selectedLanguages);
|
|
1374
|
-
}
|
|
1375
|
-
async function updateCrowdinFilesTargetLanguages() {
|
|
1376
|
-
const languageSelect = document.querySelector('#language-select');
|
|
1377
|
-
const selectedLanguages = await languageSelect.getValue();
|
|
1378
|
-
closeModal(languageModal.current);
|
|
1379
|
-
const fileIds = Object.keys(crowdinFilesToUpdateTargetLanguages.current).map((id) => parseInt(id, 10));
|
|
1380
|
-
if (fileIds.length === 0) {
|
|
1381
|
-
showToast('Select files to update');
|
|
1382
|
-
return;
|
|
2063
|
+
let req;
|
|
2064
|
+
if (integrationOneLevelFetching) {
|
|
2065
|
+
req = files.map((f) => ({
|
|
2066
|
+
name: f.name,
|
|
2067
|
+
id: f.id,
|
|
2068
|
+
type: f.type,
|
|
2069
|
+
parentId: f.parent_id,
|
|
2070
|
+
nodeType: f.node_type,
|
|
2071
|
+
isUpdated: f.isUpdated,
|
|
2072
|
+
}));
|
|
1383
2073
|
}
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
jobId: res === null || res === void 0 ? void 0 : res.jobId,
|
|
1395
|
-
jobType: JOB_TYPE.updateTargetLanguages,
|
|
1396
|
-
});
|
|
1397
|
-
})
|
|
1398
|
-
.catch((e) => catchRejection(e, "Can't update files target languages"));
|
|
1399
|
-
}
|
|
1400
|
-
async function setLanguagesForTranslation(languages, buttonHtml) {
|
|
1401
|
-
const defaultButtonHtml = `
|
|
1402
|
-
<crowdin-button id="upload-exclude-languages" outlined">
|
|
1403
|
-
<div class="integration-icon-button">
|
|
1404
|
-
<span>Sync to</span>
|
|
1405
|
-
<crowdin-logo is-icon/>
|
|
1406
|
-
</div>
|
|
1407
|
-
</crowdin-button>
|
|
1408
|
-
`;
|
|
1409
|
-
setTimeout(() => {
|
|
1410
|
-
const btn = document.querySelector('#upload-exclude-languages');
|
|
1411
|
-
if (btn) {
|
|
1412
|
-
btn.addEventListener('click', () => uploadFilesToCrowdinWithExcludedLanguages());
|
|
1413
|
-
}
|
|
1414
|
-
}, 0);
|
|
1415
|
-
const languageIds = languages.map((language) => language.id);
|
|
1416
|
-
if (languageModal.current) {
|
|
1417
|
-
let modalContent = `<div>
|
|
1418
|
-
<crowdin-select
|
|
1419
|
-
is-multi
|
|
1420
|
-
is-searchable
|
|
1421
|
-
is-position-fixed
|
|
1422
|
-
close-on-select="false"
|
|
1423
|
-
name="languages"
|
|
1424
|
-
id="language-select"
|
|
1425
|
-
label="Languages"
|
|
1426
|
-
>
|
|
1427
|
-
`;
|
|
1428
|
-
for (const language of languages) {
|
|
1429
|
-
modalContent += `<option value="${language.id}">${language.name}</option>`;
|
|
1430
|
-
}
|
|
1431
|
-
modalContent += `
|
|
1432
|
-
</crowdin-select>
|
|
1433
|
-
</div>
|
|
1434
|
-
<div slot="footer">
|
|
1435
|
-
${buttonHtml || defaultButtonHtml}
|
|
1436
|
-
</div>
|
|
1437
|
-
`;
|
|
1438
|
-
languageModal.current.innerHTML = modalContent;
|
|
1439
|
-
const select = document.querySelector('#language-select');
|
|
1440
|
-
await select.setValue(languageIds);
|
|
2074
|
+
else {
|
|
2075
|
+
req = files
|
|
2076
|
+
.filter((f) => f.node_type !== FOLDER_TYPE)
|
|
2077
|
+
.map((f) => ({
|
|
2078
|
+
name: f.name,
|
|
2079
|
+
id: f.id,
|
|
2080
|
+
type: f.type,
|
|
2081
|
+
parentId: f.parent_id,
|
|
2082
|
+
isUpdated: f.isUpdated,
|
|
2083
|
+
}));
|
|
1441
2084
|
}
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
if (user.full_name) {
|
|
1451
|
-
return user.full_name;
|
|
2085
|
+
try {
|
|
2086
|
+
const restParams = await checkOrigin();
|
|
2087
|
+
const res = await checkResponse(await fetch(`api/crowdin/update${restParams}&uploadTranslations=${uploadTranslations}&languages=${languages}&forcePushSources=${forcePushSources}`, {
|
|
2088
|
+
method: 'POST',
|
|
2089
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2090
|
+
body: JSON.stringify(req),
|
|
2091
|
+
}));
|
|
2092
|
+
checkJob({ jobId: res === null || res === void 0 ? void 0 : res.jobId, jobType: JOB_TYPE.updateCrowdin });
|
|
1452
2093
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
}
|
|
1456
|
-
function showPermissionsDialog() {
|
|
1457
|
-
const permissions = document.getElementById('permissions-modal');
|
|
1458
|
-
hideConfirmUsersBlock();
|
|
1459
|
-
openModal(permissions);
|
|
1460
|
-
setLoader('#permissions-modal');
|
|
1461
|
-
const select = document.getElementById('users');
|
|
1462
|
-
select.value = '[]';
|
|
1463
|
-
Promise.all([
|
|
1464
|
-
new Promise((resolve) => {
|
|
1465
|
-
checkOrigin()
|
|
1466
|
-
.then((restParams) => fetch('api/users' + restParams))
|
|
1467
|
-
.then(checkResponse)
|
|
1468
|
-
.then((res) => {
|
|
1469
|
-
resolve(JSON.stringify(res.data.managers));
|
|
1470
|
-
});
|
|
1471
|
-
}),
|
|
1472
|
-
new Promise((resolve) => {
|
|
1473
|
-
AP.getUsers((res) => {
|
|
1474
|
-
const users = Object.values(res).filter((user) => user.id !== Number(userId));
|
|
1475
|
-
resolve(users);
|
|
1476
|
-
});
|
|
1477
|
-
}),
|
|
1478
|
-
])
|
|
1479
|
-
.then(([managers, users]) => {
|
|
1480
|
-
const parsedManagers = (JSON.parse(managers) || []);
|
|
1481
|
-
const availableUsers = users;
|
|
1482
|
-
const validUserIds = new Set(availableUsers.map((user) => `${user.id}`));
|
|
1483
|
-
const filteredManagers = parsedManagers.filter((id) => validUserIds.has(id));
|
|
1484
|
-
select.innerHTML = availableUsers
|
|
1485
|
-
.map((user) => `<option value="${user.id}">${sanitizeHTML(getUserFullName(user))}</option>`)
|
|
1486
|
-
.join('');
|
|
1487
|
-
select.value = JSON.stringify(filteredManagers);
|
|
1488
|
-
})
|
|
1489
|
-
.catch((e) => catchRejection(e, "Can't fetch users"))
|
|
1490
|
-
.finally(() => unsetLoader('#permissions-modal'));
|
|
1491
|
-
}
|
|
1492
|
-
function showConfirmUsersBlock() {
|
|
1493
|
-
const confirmUsersBlock = document.querySelector('.confirm-users-block');
|
|
1494
|
-
confirmUsersBlock.classList.remove('hidden');
|
|
1495
|
-
const permissionsModal = document.getElementById('permissions-modal');
|
|
1496
|
-
permissionsModal.removeAttribute('body-overflow-unset');
|
|
1497
|
-
}
|
|
1498
|
-
function checkUsers() {
|
|
1499
|
-
setLoader('#permissions-modal');
|
|
1500
|
-
const select = document.getElementById('users');
|
|
1501
|
-
if (select.value === '[]') {
|
|
1502
|
-
hideConfirmUsersBlock();
|
|
1503
|
-
unsetLoader('#permissions-modal');
|
|
1504
|
-
return;
|
|
2094
|
+
catch (e) {
|
|
2095
|
+
catchRejection(e, "Can't upload templates to Crowdin");
|
|
1505
2096
|
}
|
|
1506
|
-
const users = JSON.parse(select.value);
|
|
1507
|
-
const user_ids = users.filter((id) => parseInt(id));
|
|
1508
|
-
const emails = users.filter((id) => !parseInt(id));
|
|
1509
|
-
const params = { user_ids, emails };
|
|
1510
|
-
Promise.all([
|
|
1511
|
-
new Promise((resolve) => {
|
|
1512
|
-
checkOrigin()
|
|
1513
|
-
.then((restParams) => fetch('api/users' + restParams))
|
|
1514
|
-
.then(checkResponse)
|
|
1515
|
-
.then((usersResponse) => {
|
|
1516
|
-
resolve(usersResponse.data.managers);
|
|
1517
|
-
});
|
|
1518
|
-
}),
|
|
1519
|
-
new Promise((resolve) => {
|
|
1520
|
-
AP.validateUsers(params, (res) => {
|
|
1521
|
-
resolve(res.data);
|
|
1522
|
-
});
|
|
1523
|
-
}),
|
|
1524
|
-
new Promise((resolve) => {
|
|
1525
|
-
AP.getUsers((res) => {
|
|
1526
|
-
resolve(res);
|
|
1527
|
-
});
|
|
1528
|
-
}),
|
|
1529
|
-
])
|
|
1530
|
-
.then(([appManagers, checkUsersResponse, allUsers]) => {
|
|
1531
|
-
const newUserEmails = checkUsersResponse.newUserEmails.map((email) => ({ name: email }));
|
|
1532
|
-
const newProjectManagers = [
|
|
1533
|
-
...newUserEmails,
|
|
1534
|
-
...checkUsersResponse.newProjectManagers.map((user) => ({
|
|
1535
|
-
name: getUserFullName(user),
|
|
1536
|
-
})),
|
|
1537
|
-
];
|
|
1538
|
-
const newApplicationAccessUsers = [
|
|
1539
|
-
...newUserEmails,
|
|
1540
|
-
...checkUsersResponse.newApplicationAccessUsers.map((user) => ({
|
|
1541
|
-
name: getUserFullName(user),
|
|
1542
|
-
})),
|
|
1543
|
-
];
|
|
1544
|
-
const newApplicationManagers = [
|
|
1545
|
-
...newUserEmails,
|
|
1546
|
-
...Object.values(allUsers)
|
|
1547
|
-
.filter((user) => users.some((id) => +id === user.id) && !appManagers.some((id) => +id === user.id))
|
|
1548
|
-
.map((user) => ({ name: getUserFullName(user) })),
|
|
1549
|
-
];
|
|
1550
|
-
prepareUsersConfirmBlock({
|
|
1551
|
-
...checkUsersResponse,
|
|
1552
|
-
newUserEmails,
|
|
1553
|
-
newProjectManagers,
|
|
1554
|
-
newApplicationAccessUsers,
|
|
1555
|
-
newApplicationManagers,
|
|
1556
|
-
});
|
|
1557
|
-
})
|
|
1558
|
-
.catch((e) => catchRejection(e, (e === null || e === void 0 ? void 0 : e.error) || "Can't invite users"))
|
|
1559
|
-
.finally(() => unsetLoader('#permissions-modal'));
|
|
1560
2097
|
}
|
|
1561
|
-
function
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
const emails = users.filter((id) => !parseInt(id));
|
|
1567
|
-
const params = { user_ids, emails };
|
|
1568
|
-
AP.inviteUsers(params, (res) => {
|
|
1569
|
-
var _a;
|
|
1570
|
-
if (!res.success) {
|
|
1571
|
-
catchRejection(res, ((_a = res === null || res === void 0 ? void 0 : res.error) === null || _a === void 0 ? void 0 : _a.message) || "Can't invite users");
|
|
1572
|
-
unsetLoader('#permissions-modal');
|
|
2098
|
+
async function getActiveJobs() {
|
|
2099
|
+
try {
|
|
2100
|
+
const restParams = await checkOrigin();
|
|
2101
|
+
const jobs = await checkResponse(await fetch(`api/jobs${restParams}`));
|
|
2102
|
+
if (!Array.isArray(jobs)) {
|
|
1573
2103
|
return;
|
|
1574
2104
|
}
|
|
1575
|
-
|
|
1576
|
-
.
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
});
|
|
1595
|
-
}
|
|
1596
|
-
function prepareUsersConfirmBlock(usersData) {
|
|
1597
|
-
showConfirmUsersBlock();
|
|
1598
|
-
const organizationInvite = document.querySelector('.organization-invite');
|
|
1599
|
-
const projectInvite = document.querySelector('.project-invite');
|
|
1600
|
-
const applicationCredentialsInvite = document.querySelector('.application-credentials-invite');
|
|
1601
|
-
const grantedElement = '<crowdin-p>―</crowdin-p>';
|
|
1602
|
-
const willGrantedElement = '<span class="badge badge-will-be-granted">Will Be Granted</span>';
|
|
1603
|
-
const notAvailableElement = '<span class="badge badge-not-available">Action Required</span>';
|
|
1604
|
-
// only in enterprise
|
|
1605
|
-
if (organizationInvite) {
|
|
1606
|
-
const organizationWillGrantElement = '<span class="badge badge-will-be-granted">Will Be Registered</span>';
|
|
1607
|
-
processUsersWhoWillBeInvitedToOrganization(organizationInvite, usersData, organizationWillGrantElement, grantedElement, notAvailableElement);
|
|
1608
|
-
}
|
|
1609
|
-
processUsersWhoWillBeInvited(projectInvite, usersData.newProjectManagers, willGrantedElement, grantedElement);
|
|
1610
|
-
processUsersWhoWillBeInvited(applicationCredentialsInvite, usersData.newApplicationManagers, willGrantedElement, grantedElement);
|
|
1611
|
-
processUsersWhoWillBeInvitedApplicationSettings(usersData, willGrantedElement, grantedElement, notAvailableElement);
|
|
1612
|
-
}
|
|
1613
|
-
function processUsersWhoWillBeInvitedToOrganization(element, usersData, willGrantedElement, alreadyGrantedMessage, notAvailableElement) {
|
|
1614
|
-
const tooltip = element.querySelector('.status');
|
|
1615
|
-
const description = element.querySelector('.permission-description');
|
|
1616
|
-
const userList = element.querySelector('.affected-users');
|
|
1617
|
-
description.classList.remove('text-warning');
|
|
1618
|
-
description.innerText = '';
|
|
1619
|
-
const users = usersData.newUserEmails;
|
|
1620
|
-
if (users.length) {
|
|
1621
|
-
if (usersData.inviteRestricted) {
|
|
1622
|
-
description.classList.add('text-warning');
|
|
1623
|
-
description.innerText = 'New user invitations are restricted to administrators.';
|
|
1624
|
-
tooltip.innerHTML = notAvailableElement;
|
|
1625
|
-
}
|
|
1626
|
-
else {
|
|
1627
|
-
tooltip.innerHTML = willGrantedElement;
|
|
1628
|
-
}
|
|
1629
|
-
let affectedUsers = '<ul>';
|
|
1630
|
-
for (const user of users) {
|
|
1631
|
-
affectedUsers += `<li><crowdin-p>${sanitizeHTML(user.name)}</crowdin-p></li>`;
|
|
1632
|
-
}
|
|
1633
|
-
affectedUsers += '</ul>';
|
|
1634
|
-
userList.innerHTML = affectedUsers;
|
|
2105
|
+
jobs.forEach((job) => {
|
|
2106
|
+
switch (job.type) {
|
|
2107
|
+
case JOB_TYPE.updateCrowdin:
|
|
2108
|
+
case JOB_TYPE.updateTargetLanguages:
|
|
2109
|
+
appComponent.current.setAttribute('is-to-crowdin-process', true);
|
|
2110
|
+
break;
|
|
2111
|
+
case JOB_TYPE.updateIntegration:
|
|
2112
|
+
appComponent.current.setAttribute('is-to-integration-process', true);
|
|
2113
|
+
break;
|
|
2114
|
+
case JOB_TYPE.crowdinSyncSettingsSave:
|
|
2115
|
+
appComponent.current.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
2116
|
+
break;
|
|
2117
|
+
case JOB_TYPE.integrationSyncSettingsSave:
|
|
2118
|
+
appComponent.current.setAttribute('is-integration-sync-settings-in-progress', true);
|
|
2119
|
+
break;
|
|
2120
|
+
default:
|
|
2121
|
+
}
|
|
2122
|
+
checkJob({ jobId: job.id, jobType: job.type });
|
|
2123
|
+
});
|
|
1635
2124
|
}
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
userList.innerHTML = alreadyGrantedMessage;
|
|
2125
|
+
catch (e) {
|
|
2126
|
+
catchRejection(e, 'Sync status check failed');
|
|
1639
2127
|
}
|
|
1640
2128
|
}
|
|
1641
|
-
function
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
tooltip.innerHTML = grantMessage;
|
|
1646
|
-
let affectedUsers = '<ul>';
|
|
1647
|
-
for (const user of users) {
|
|
1648
|
-
affectedUsers += `<li><crowdin-p>${sanitizeHTML(user.name)}</crowdin-p></li>`;
|
|
1649
|
-
}
|
|
1650
|
-
affectedUsers += '</ul>';
|
|
1651
|
-
userList.innerHTML = affectedUsers;
|
|
2129
|
+
async function cancelJob(jobId) {
|
|
2130
|
+
var _a;
|
|
2131
|
+
if ((_a = asyncJobs.current[jobId]) === null || _a === void 0 ? void 0 : _a.isFailed) {
|
|
2132
|
+
return;
|
|
1652
2133
|
}
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
const tooltip = applicationSettingsInvite.querySelector('.status');
|
|
1661
|
-
const description = applicationSettingsInvite.querySelector('.permission-description');
|
|
1662
|
-
const userList = applicationSettingsInvite.querySelector('.affected-users');
|
|
1663
|
-
let descriptionMessage = 'This can be configured in organization settings (Apps section).';
|
|
1664
|
-
description.classList.remove('text-warning');
|
|
1665
|
-
description.innerText = descriptionMessage;
|
|
1666
|
-
let affectedUsers = '<ul>';
|
|
1667
|
-
if (!usersData.newApplicationAccessUsers.length) {
|
|
1668
|
-
tooltip.innerHTML = grantedElement;
|
|
1669
|
-
userList.innerHTML = grantedElement;
|
|
2134
|
+
try {
|
|
2135
|
+
const restParams = await checkOrigin();
|
|
2136
|
+
await checkResponse(await fetch('api/jobs' + restParams + '&jobId=' + jobId, {
|
|
2137
|
+
method: 'DELETE',
|
|
2138
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2139
|
+
}));
|
|
2140
|
+
showToast('Cancellation…');
|
|
1670
2141
|
}
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
tooltip.innerHTML = willGrantedElement;
|
|
1674
|
-
for (const user of usersData.newApplicationAccessUsers) {
|
|
1675
|
-
affectedUsers += `<li><crowdin-p>${sanitizeHTML(user.name)}</crowdin-p></li>`;
|
|
1676
|
-
}
|
|
1677
|
-
userList.innerHTML = affectedUsers + '</ul>';
|
|
1678
|
-
}
|
|
1679
|
-
else {
|
|
1680
|
-
descriptionMessage += ' Only organization admins have permission to update this setting.';
|
|
1681
|
-
description.classList.add('text-warning');
|
|
1682
|
-
description.innerText = descriptionMessage;
|
|
1683
|
-
tooltip.innerHTML = notAvailableElement;
|
|
1684
|
-
for (const user of usersData.newApplicationAccessUsers) {
|
|
1685
|
-
affectedUsers += `<li><crowdin-p>${sanitizeHTML(user.name)}</crowdin-p></li>`;
|
|
1686
|
-
}
|
|
1687
|
-
userList.innerHTML = affectedUsers + '</ul>';
|
|
1688
|
-
}
|
|
2142
|
+
catch (e) {
|
|
2143
|
+
catchRejection(e, 'Sync cancellation failed');
|
|
1689
2144
|
}
|
|
1690
2145
|
}
|
|
1691
|
-
function
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
}
|
|
1701
|
-
function triggerEvent(el, type) {
|
|
1702
|
-
const e = document.createEvent('HTMLEvents');
|
|
1703
|
-
e.initEvent(type, false, true);
|
|
1704
|
-
el.dispatchEvent(e);
|
|
1705
|
-
}
|
|
1706
|
-
function fillSettingsForm() {
|
|
1707
|
-
Object.entries(config.current).forEach(([key, value]) => {
|
|
1708
|
-
const el = document.getElementById(`${key}-settings`);
|
|
1709
|
-
if (el && (value || el.tagName.toLowerCase() === 'crowdin-checkbox')) {
|
|
1710
|
-
if (el.tagName.toLowerCase() === 'crowdin-select') {
|
|
1711
|
-
if (el.hasAttribute('is-multi')) {
|
|
1712
|
-
el.value = JSON.stringify(value);
|
|
1713
|
-
}
|
|
1714
|
-
else {
|
|
1715
|
-
el.value = JSON.stringify([value]);
|
|
1716
|
-
}
|
|
2146
|
+
async function checkJob({ jobId, jobType, onSuccess, onError, onFinally }) {
|
|
2147
|
+
switch (jobType) {
|
|
2148
|
+
case JOB_TYPE.updateCrowdin:
|
|
2149
|
+
case JOB_TYPE.updateTargetLanguages:
|
|
2150
|
+
if (!onFinally) {
|
|
2151
|
+
onFinally = () => {
|
|
2152
|
+
appComponent.current.setAttribute('is-to-crowdin-process', false);
|
|
2153
|
+
getCrowdinData();
|
|
2154
|
+
};
|
|
1717
2155
|
}
|
|
1718
|
-
|
|
1719
|
-
|
|
2156
|
+
break;
|
|
2157
|
+
case JOB_TYPE.updateIntegration:
|
|
2158
|
+
if (!onFinally) {
|
|
2159
|
+
onFinally = () => appComponent.current.setAttribute('is-to-integration-process', false);
|
|
1720
2160
|
}
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
2161
|
+
break;
|
|
2162
|
+
case JOB_TYPE.crowdinSyncSettingsSave:
|
|
2163
|
+
if (!onFinally) {
|
|
2164
|
+
onFinally = () => appComponent.current.setAttribute('is-crowdin-sync-settings-in-progress', false);
|
|
1724
2165
|
}
|
|
1725
|
-
|
|
1726
|
-
|
|
2166
|
+
break;
|
|
2167
|
+
case JOB_TYPE.integrationSyncSettingsSave:
|
|
2168
|
+
if (!onFinally) {
|
|
2169
|
+
onFinally = () => appComponent.current.setAttribute('is-integration-sync-settings-in-progress', false);
|
|
1727
2170
|
}
|
|
1728
|
-
|
|
2171
|
+
break;
|
|
2172
|
+
}
|
|
2173
|
+
try {
|
|
2174
|
+
const restParams = await checkOrigin();
|
|
2175
|
+
const job = await checkResponse(await fetch('api/jobs' + restParams + '&jobId=' + jobId));
|
|
2176
|
+
const isFailed = [JOB_STATUS.failed, JOB_STATUS.canceled].includes(job.status);
|
|
2177
|
+
const progress = isFailed || JOB_STATUS.finished === job.status ? 100 : job.progress;
|
|
2178
|
+
const info = JOB_STATUS.canceled === job.status ? `Cancelled\n${job.info || ''}` : job.info;
|
|
2179
|
+
if (!silentJobs.find((type) => type === jobType)) {
|
|
2180
|
+
pushJobs([{ id: job.id, title: job.title, progress, info, isFailed }]);
|
|
1729
2181
|
}
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
if (window.initializeDependencies) {
|
|
1734
|
-
window.initializeDependencies();
|
|
1735
|
-
}
|
|
1736
|
-
}, 100);
|
|
1737
|
-
}
|
|
1738
|
-
function saveSettings() {
|
|
1739
|
-
const settingsSaveBtn = document.getElementById('settings-save-btn');
|
|
1740
|
-
setLoader('#settings-modal');
|
|
1741
|
-
const settingsElements = Array.from(document.querySelectorAll('#modal-content crowdin-tabs > div'));
|
|
1742
|
-
const tags = ['crowdin-checkbox', 'crowdin-select', 'crowdin-input', 'crowdin-textarea'];
|
|
1743
|
-
const configReq = {};
|
|
1744
|
-
settingsElements.forEach((tab) => {
|
|
1745
|
-
const formElements = Array.from(tab.querySelectorAll('.crowdin-form > *'));
|
|
1746
|
-
formElements
|
|
1747
|
-
.filter((e) => tags.includes(e.tagName.toLowerCase()))
|
|
1748
|
-
.forEach((e) => {
|
|
1749
|
-
const key = e.getAttribute('_key');
|
|
1750
|
-
let value;
|
|
1751
|
-
if (e.tagName.toLowerCase() === 'crowdin-select') {
|
|
1752
|
-
value = JSON.parse(e.value);
|
|
1753
|
-
if (!e.hasAttribute('is-multi')) {
|
|
1754
|
-
value = value.length > 0 ? value[0] : undefined;
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
|
-
else if (e.tagName.toLowerCase() === 'crowdin-checkbox') {
|
|
1758
|
-
value = !!e.checked;
|
|
1759
|
-
}
|
|
1760
|
-
else {
|
|
1761
|
-
value = e.value;
|
|
2182
|
+
if (isFailed) {
|
|
2183
|
+
if (onError) {
|
|
2184
|
+
onError();
|
|
1762
2185
|
}
|
|
1763
|
-
configReq[key] = value;
|
|
1764
|
-
});
|
|
1765
|
-
});
|
|
1766
|
-
let isValidationError = false;
|
|
1767
|
-
let isSettingsSaveJobPending = false;
|
|
1768
|
-
let isSettingsSaveFailed = false;
|
|
1769
|
-
settingsSaveBtn.setAttribute('disabled', true);
|
|
1770
|
-
checkOrigin()
|
|
1771
|
-
.then((restParams) => fetch('api/settings' + restParams, {
|
|
1772
|
-
method: 'POST',
|
|
1773
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1774
|
-
body: JSON.stringify({ config: configReq }),
|
|
1775
|
-
}))
|
|
1776
|
-
.then(checkResponse)
|
|
1777
|
-
.then((res) => {
|
|
1778
|
-
if (res === null || res === void 0 ? void 0 : res.jobId) {
|
|
1779
|
-
isSettingsSaveJobPending = true;
|
|
1780
|
-
checkJob({
|
|
1781
|
-
jobId: res.jobId,
|
|
1782
|
-
jobType: JOB_TYPE.integrationSettingsSave,
|
|
1783
|
-
onSuccess: () => {
|
|
1784
|
-
showToast('Settings successfully saved');
|
|
1785
|
-
config.current = configReq;
|
|
1786
|
-
refreshAutoSyncPausedIndicatorsAndWarning().catch((e) => catchRejection(e, "Can't fetch sync settings warning"));
|
|
1787
|
-
},
|
|
1788
|
-
onError: () => {
|
|
1789
|
-
isSettingsSaveFailed = true;
|
|
1790
|
-
showToast("Can't save settings");
|
|
1791
|
-
},
|
|
1792
|
-
onFinally: () => {
|
|
1793
|
-
unsetLoader('#settings-modal');
|
|
1794
|
-
settingsSaveBtn.removeAttribute('disabled');
|
|
1795
|
-
if (!isValidationError && !isSettingsSaveFailed) {
|
|
1796
|
-
const settingsModal = document.getElementById('settings-modal');
|
|
1797
|
-
closeModal(settingsModal);
|
|
1798
|
-
if (reloadOnConfigSave) {
|
|
1799
|
-
getIntegrationData({ hardReload: true });
|
|
1800
|
-
getCrowdinData();
|
|
1801
|
-
}
|
|
1802
|
-
}
|
|
1803
|
-
},
|
|
1804
|
-
});
|
|
1805
|
-
return;
|
|
1806
|
-
}
|
|
1807
|
-
showToast('Settings successfully saved');
|
|
1808
|
-
config.current = configReq;
|
|
1809
|
-
refreshAutoSyncPausedIndicatorsAndWarning().catch((e) => catchRejection(e, "Can't fetch sync settings warning"));
|
|
1810
|
-
})
|
|
1811
|
-
.catch((e) => {
|
|
1812
|
-
var _a, _b, _c, _d;
|
|
1813
|
-
if ((e === null || e === void 0 ? void 0 : e.error) && ((_a = e === null || e === void 0 ? void 0 : e.error) === null || _a === void 0 ? void 0 : _a.type) === 'validation_error') {
|
|
1814
|
-
Object.keys((_b = e === null || e === void 0 ? void 0 : e.error) === null || _b === void 0 ? void 0 : _b.details).forEach((key) => {
|
|
1815
|
-
var _a;
|
|
1816
|
-
const el = document.getElementById(`${key}-settings`);
|
|
1817
|
-
if (el) {
|
|
1818
|
-
el.setAttribute('error', 'true');
|
|
1819
|
-
el.setAttribute('error-text', (_a = e === null || e === void 0 ? void 0 : e.error) === null || _a === void 0 ? void 0 : _a.details[key]);
|
|
1820
|
-
}
|
|
1821
|
-
});
|
|
1822
|
-
isValidationError = true;
|
|
1823
|
-
showToast(((_d = (_c = e === null || e === void 0 ? void 0 : e.error) === null || _c === void 0 ? void 0 : _c.details) === null || _d === void 0 ? void 0 : _d.message) || "Can't save settings");
|
|
1824
|
-
settingsSaveBtn.removeAttribute('disabled');
|
|
1825
|
-
return;
|
|
1826
2186
|
}
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
.finally(() => {
|
|
1830
|
-
if (isSettingsSaveJobPending) {
|
|
2187
|
+
else if ([JOB_STATUS.created, JOB_STATUS.inProgress].includes(job.status) && job.progress < 100) {
|
|
2188
|
+
setTimeout(() => checkJob({ jobId, jobType, onSuccess, onError, onFinally }), asyncProgress.checkInterval);
|
|
1831
2189
|
return;
|
|
1832
2190
|
}
|
|
1833
|
-
unsetLoader('#settings-modal');
|
|
1834
|
-
settingsSaveBtn.removeAttribute('disabled');
|
|
1835
|
-
if (!isValidationError) {
|
|
1836
|
-
const settingsModal = document.getElementById('settings-modal');
|
|
1837
|
-
closeModal(settingsModal);
|
|
1838
|
-
if (reloadOnConfigSave) {
|
|
1839
|
-
getIntegrationData({ hardReload: true });
|
|
1840
|
-
getCrowdinData();
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
});
|
|
1844
|
-
}
|
|
1845
|
-
function getIntegrationFoldersToExpand(allData, syncedFiles) {
|
|
1846
|
-
return Array.isArray(allData)
|
|
1847
|
-
? allData
|
|
1848
|
-
.filter((node) => node.node_type === folderType &&
|
|
1849
|
-
!syncedFiles.find((syncedFile) => syncedFile.parent_id === node.id))
|
|
1850
|
-
.map((node) => ({
|
|
1851
|
-
...node,
|
|
1852
|
-
nodeType: node.node_type,
|
|
1853
|
-
parentId: node.parent_id,
|
|
1854
|
-
}))
|
|
1855
|
-
: [];
|
|
1856
|
-
}
|
|
1857
|
-
async function saveScheduleSync() {
|
|
1858
|
-
const scheduleModal = document.getElementById('confirm-schedule-modal');
|
|
1859
|
-
const newFile = scheduleModal.querySelector('#new-files').checked || false;
|
|
1860
|
-
const selectedFiles = scheduleModal.querySelector('#selected-files').checked || false;
|
|
1861
|
-
const allFolderFiles = scheduleModal.querySelector('#all-folder-files').checked || false;
|
|
1862
|
-
const type = scheduleModal.getAttribute('data-type');
|
|
1863
|
-
if (type === 'crowdin') {
|
|
1864
|
-
const crowdinFiles = await appComponent.current.getCrowdinFilesData();
|
|
1865
|
-
const syncedFileIds = Object.keys(syncData.current);
|
|
1866
|
-
const crowdinFolderIds = crowdinFiles
|
|
1867
|
-
.filter((file) => file.node_type === folderType || file.node_type === branchType)
|
|
1868
|
-
.filter((file) => syncedFileIds.includes(String(file.id)))
|
|
1869
|
-
.map((file) => String(file.id));
|
|
1870
|
-
appComponent.current.setCrowdinScheduleSync(syncData.current, newFile, selectedFiles);
|
|
1871
|
-
appComponent.current.setCrowdinFilesHasSyncOption(true);
|
|
1872
|
-
const syncedFiles = await appComponent.current.getCrowdinScheduleSync(true);
|
|
1873
|
-
appComponent.current.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
1874
|
-
updateSyncSettings(syncedFiles, 'schedule', 'crowdin', [], crowdinFolderIds);
|
|
1875
|
-
}
|
|
1876
|
-
else if (type === 'integration') {
|
|
1877
|
-
if (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration) {
|
|
1878
|
-
appComponent.current.setIntegrationScheduleSync(syncData.current, newFile, selectedFiles);
|
|
1879
|
-
}
|
|
1880
|
-
else {
|
|
1881
|
-
appComponent.current.setIntegrationScheduleSync(syncData.current);
|
|
1882
|
-
}
|
|
1883
|
-
appComponent.current.setIntegrationFilesHasSyncOption(true);
|
|
1884
|
-
const syncedFiles = await appComponent.current.getIntegrationScheduleSync(true);
|
|
1885
|
-
appComponent.current.setAttribute('is-integration-sync-settings-in-progress', true);
|
|
1886
|
-
if (integrationOneLevelFetching) {
|
|
1887
|
-
updateSyncSettings(syncedFiles, 'schedule', 'integration', selectedFiles ? getIntegrationFoldersToExpand(syncData.current, syncedFiles) : []);
|
|
1888
|
-
}
|
|
1889
2191
|
else {
|
|
1890
|
-
if (
|
|
1891
|
-
|
|
1892
|
-
.filter((file) => file.node_type === folderType)
|
|
1893
|
-
.map((file) => ({
|
|
1894
|
-
...file,
|
|
1895
|
-
nodeType: file.node_type,
|
|
1896
|
-
parentId: file.parent_id,
|
|
1897
|
-
}));
|
|
1898
|
-
updateSyncSettings(syncedFiles, 'schedule', 'integration', integrationExpandedFolders);
|
|
1899
|
-
}
|
|
1900
|
-
else {
|
|
1901
|
-
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
2192
|
+
if (onSuccess) {
|
|
2193
|
+
onSuccess(job);
|
|
1902
2194
|
}
|
|
1903
2195
|
}
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
}
|
|
1907
|
-
async function openScheduleModal(type, options = {}) {
|
|
1908
|
-
var _a, _b;
|
|
1909
|
-
const scheduleModal = document.getElementById('confirm-schedule-modal');
|
|
1910
|
-
const { showAllFolderFiles = false, showNewFiles = true } = options;
|
|
1911
|
-
const newFile = scheduleModal.querySelector('#new-files');
|
|
1912
|
-
const selectedFiles = scheduleModal.querySelector('#selected-files');
|
|
1913
|
-
const allFolderFiles = scheduleModal.querySelector('#all-folder-files');
|
|
1914
|
-
let newFileStatus = 'unChecked';
|
|
1915
|
-
const integrationSyncFolders = ((await ((_a = document.querySelector('crowdin-simple-integration')) === null || _a === void 0 ? void 0 : _a.getIntegrationScheduleSync(true))) ||
|
|
1916
|
-
[]).filter((elements) => elements.node_type === '0');
|
|
1917
|
-
const selectedIntegrationFolders = ((await ((_b = document.getElementById('integration-files')) === null || _b === void 0 ? void 0 : _b.getSelected(true))) || []).filter((elements) => elements.node_type === '0');
|
|
1918
|
-
for (let i = 0; i < selectedIntegrationFolders.length; i++) {
|
|
1919
|
-
const selectedElement = selectedIntegrationFolders[i];
|
|
1920
|
-
const found = integrationSyncFolders.some((integrationElement) => integrationElement.id === selectedElement.id);
|
|
1921
|
-
if (found) {
|
|
1922
|
-
newFileStatus = 'checked';
|
|
1923
|
-
}
|
|
1924
|
-
else if (!found && newFileStatus === 'checked') {
|
|
1925
|
-
newFileStatus = 'clear-selection';
|
|
1926
|
-
break;
|
|
1927
|
-
}
|
|
1928
|
-
else {
|
|
1929
|
-
newFileStatus = 'unChecked';
|
|
2196
|
+
if (onFinally) {
|
|
2197
|
+
onFinally(job);
|
|
1930
2198
|
}
|
|
1931
2199
|
}
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
newFile[newFileStatus] = true;
|
|
1936
|
-
newFile.value = true;
|
|
1937
|
-
newFile.removeAttribute('clear-selection');
|
|
1938
|
-
}
|
|
1939
|
-
else if (newFileStatus === 'clear-selection') {
|
|
1940
|
-
newFile.checked = false;
|
|
1941
|
-
newFile.value = false;
|
|
1942
|
-
newFile.setAttribute(newFileStatus, '');
|
|
2200
|
+
catch (_e) {
|
|
2201
|
+
if (onFinally) {
|
|
2202
|
+
onFinally();
|
|
1943
2203
|
}
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
newFile.value = false;
|
|
1947
|
-
newFile.removeAttribute('clear-selection');
|
|
2204
|
+
if (!silentJobs.find((type) => type === jobType)) {
|
|
2205
|
+
pushJobs([{ id: jobId, isFailed: true }]);
|
|
1948
2206
|
}
|
|
2207
|
+
showToast('Sync status check failed');
|
|
1949
2208
|
}
|
|
1950
|
-
else {
|
|
1951
|
-
newFile.setAttribute('hidden', '');
|
|
1952
|
-
newFile.checked = false;
|
|
1953
|
-
}
|
|
1954
|
-
if (showAllFolderFiles) {
|
|
1955
|
-
allFolderFiles.removeAttribute('hidden');
|
|
1956
|
-
allFolderFiles.checked = false;
|
|
1957
|
-
allFolderFiles.value = false;
|
|
1958
|
-
}
|
|
1959
|
-
else {
|
|
1960
|
-
allFolderFiles.setAttribute('hidden', '');
|
|
1961
|
-
allFolderFiles.checked = false;
|
|
1962
|
-
}
|
|
1963
|
-
selectedFiles.checked = true;
|
|
1964
|
-
selectedFiles.value = true;
|
|
1965
|
-
scheduleModal.querySelector('#save-schedule-sync').setAttribute('disabled', false);
|
|
1966
|
-
scheduleModal.setAttribute('data-type', type);
|
|
1967
|
-
openModal(scheduleModal);
|
|
1968
2209
|
}
|
|
1969
|
-
function
|
|
1970
|
-
const
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
const allFolderFiles = document.getElementById('all-folder-files').checked || false;
|
|
1975
|
-
const buttonSaveScheduleSync = document.getElementById('save-schedule-sync');
|
|
1976
|
-
if (newFilesStatus || selectedFiles || allFolderFiles) {
|
|
1977
|
-
buttonSaveScheduleSync.removeAttribute('disabled');
|
|
2210
|
+
function pushJobs(jobs) {
|
|
2211
|
+
const el = asyncProgressRef.current;
|
|
2212
|
+
if (el && el.pushJobs) {
|
|
2213
|
+
el.pushJobs(jobs);
|
|
2214
|
+
jobs.forEach((job) => (asyncJobs.current[job.id] = job));
|
|
1978
2215
|
}
|
|
1979
2216
|
else {
|
|
1980
|
-
|
|
2217
|
+
setTimeout(() => pushJobs(jobs), 300);
|
|
1981
2218
|
}
|
|
1982
2219
|
}
|
|
1983
|
-
async function
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
2220
|
+
async function uploadFilesToIntegration(event) {
|
|
2221
|
+
var _a, _b, _c, _d;
|
|
2222
|
+
let files = {};
|
|
2223
|
+
let forcePushTranslations = false;
|
|
2224
|
+
if (((_a = event.detail) === null || _a === void 0 ? void 0 : _a.action) === 'forcePushTranslations') {
|
|
2225
|
+
files = event.detail.files;
|
|
2226
|
+
forcePushTranslations = true;
|
|
1987
2227
|
}
|
|
1988
|
-
else {
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2228
|
+
else if (((_b = event.detail) === null || _b === void 0 ? void 0 : _b.action) === 'excludedTargetLanguages') {
|
|
2229
|
+
crowdinFilesToUpdateTargetLanguages.current = event.detail.files;
|
|
2230
|
+
openLanguageModalForCrowdinFiles();
|
|
2231
|
+
return;
|
|
1992
2232
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
async function setIntegrationScheduleSync(e) {
|
|
1996
|
-
var _a;
|
|
1997
|
-
if (e.detail.length === 0) {
|
|
1998
|
-
showToast('Select templates which will be pushed to Crowdin');
|
|
2233
|
+
else if (((_c = event.detail) === null || _c === void 0 ? void 0 : _c.action) === 'syncSourcesToCrowdin') {
|
|
2234
|
+
syncToCrowdinFromCrowdinFiles(event.detail.files, false);
|
|
1999
2235
|
return;
|
|
2000
2236
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
syncData.current = e.detail;
|
|
2005
|
-
const isFolder = await hasFolder(e.detail);
|
|
2006
|
-
const shouldShowModal = isFolder && !newIntegrationFiles;
|
|
2007
|
-
const showNewFiles = true; // завжди показуємо New files коли є syncNewElements.integration
|
|
2008
|
-
const showAllFolderFiles = hasLoadMoreElements.current; // показуємо All files якщо є hasLoadMoreElements
|
|
2009
|
-
if (shouldShowModal) {
|
|
2010
|
-
await openScheduleModal('integration', { showNewFiles, showAllFolderFiles });
|
|
2011
|
-
return;
|
|
2012
|
-
}
|
|
2013
|
-
appComponent.current.setIntegrationScheduleSync(e.detail);
|
|
2014
|
-
appComponent.current.setIntegrationFilesHasSyncOption(true);
|
|
2015
|
-
syncedFiles = await appComponent.current.getIntegrationScheduleSync(true);
|
|
2237
|
+
else if (((_d = event.detail) === null || _d === void 0 ? void 0 : _d.action) === 'syncTranslationsToCrowdin') {
|
|
2238
|
+
syncToCrowdinFromCrowdinFiles(event.detail.files, true);
|
|
2239
|
+
return;
|
|
2016
2240
|
}
|
|
2017
2241
|
else {
|
|
2018
|
-
|
|
2019
|
-
const isFolder = await hasFolder(e.detail);
|
|
2020
|
-
if (hasLoadMoreElements.current && isFolder) {
|
|
2021
|
-
await openScheduleModal('integration', { showNewFiles: false, showAllFolderFiles: true });
|
|
2022
|
-
return;
|
|
2023
|
-
}
|
|
2024
|
-
syncedFiles = await appComponent.current.getIntegrationScheduleSync();
|
|
2242
|
+
files = event.detail;
|
|
2025
2243
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2244
|
+
if (Object.keys(event.detail).length === 0 || !event.detail) {
|
|
2245
|
+
showToast(`Select files which will be uploaded to ${name}`);
|
|
2246
|
+
return;
|
|
2029
2247
|
}
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2248
|
+
appComponent.current.setAttribute('is-to-integration-process', true);
|
|
2249
|
+
const req = {};
|
|
2250
|
+
Object.keys(files)
|
|
2251
|
+
.filter((id) => crowdinData.current.find((c) => c.id === id).node_type === FILE_TYPE)
|
|
2252
|
+
.forEach((id) => (req[id] = files[id]));
|
|
2253
|
+
try {
|
|
2254
|
+
const restParams = await checkOrigin();
|
|
2255
|
+
const res = await checkResponse(await fetch(`api/integration/update${restParams}&forcePushTranslations=${forcePushTranslations}`, {
|
|
2256
|
+
method: 'POST',
|
|
2257
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2258
|
+
body: JSON.stringify(req),
|
|
2259
|
+
}));
|
|
2260
|
+
checkJob({ jobId: res === null || res === void 0 ? void 0 : res.jobId, jobType: JOB_TYPE.updateIntegration });
|
|
2261
|
+
}
|
|
2262
|
+
catch (e) {
|
|
2263
|
+
catchRejection(e, `Can't upload files to ${name}`);
|
|
2044
2264
|
}
|
|
2045
2265
|
}
|
|
2046
|
-
async function
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
showToast('Select templates which will be pushed to Crowdin');
|
|
2266
|
+
async function syncToCrowdinFromCrowdinFiles(files, uploadTranslations) {
|
|
2267
|
+
if (!files || Object.keys(files).length === 0) {
|
|
2268
|
+
showToast('Select files to sync');
|
|
2050
2269
|
return;
|
|
2051
2270
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2271
|
+
appComponent.current.setAttribute('is-to-crowdin-process', true);
|
|
2272
|
+
const req = {};
|
|
2273
|
+
Object.keys(files)
|
|
2274
|
+
.filter((id) => { var _a; return ((_a = crowdinData.current.find((c) => c.id === id)) === null || _a === void 0 ? void 0 : _a.node_type) === FILE_TYPE; })
|
|
2275
|
+
.forEach((id) => (req[id] = files[id]));
|
|
2276
|
+
try {
|
|
2277
|
+
const restParams = await checkOrigin();
|
|
2278
|
+
const res = await checkResponse(await fetch(`api/crowdin/update${restParams}&matchFromCrowdin=true&uploadTranslations=${uploadTranslations}`, {
|
|
2279
|
+
method: 'POST',
|
|
2280
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2281
|
+
body: JSON.stringify(req),
|
|
2282
|
+
}));
|
|
2283
|
+
checkJob({ jobId: res === null || res === void 0 ? void 0 : res.jobId, jobType: JOB_TYPE.updateCrowdin });
|
|
2064
2284
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2285
|
+
catch (e) {
|
|
2286
|
+
catchRejection(e, "Can't sync files to Crowdin");
|
|
2067
2287
|
}
|
|
2068
|
-
appComponent.current.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
2069
|
-
updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
|
|
2070
2288
|
}
|
|
2071
|
-
async function
|
|
2072
|
-
if (
|
|
2073
|
-
showToast('Select
|
|
2289
|
+
async function syncTranslationsToIntegration(files) {
|
|
2290
|
+
if (!files || files.length === 0) {
|
|
2291
|
+
showToast('Select files to sync');
|
|
2074
2292
|
return;
|
|
2075
2293
|
}
|
|
2076
|
-
appComponent.current.setAttribute('is-integration-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2294
|
+
appComponent.current.setAttribute('is-to-integration-process', true);
|
|
2295
|
+
const req = files
|
|
2296
|
+
.filter((f) => f.node_type !== FOLDER_TYPE)
|
|
2297
|
+
.map((f) => ({ name: f.name, id: f.id, type: f.type, parentId: f.parent_id }));
|
|
2298
|
+
try {
|
|
2299
|
+
const restParams = await checkOrigin();
|
|
2300
|
+
const res = await checkResponse(await fetch(`api/integration/update${restParams}&matchFromIntegration=true`, {
|
|
2301
|
+
method: 'POST',
|
|
2302
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2303
|
+
body: JSON.stringify(req),
|
|
2304
|
+
}));
|
|
2305
|
+
checkJob({ jobId: res === null || res === void 0 ? void 0 : res.jobId, jobType: JOB_TYPE.updateIntegration });
|
|
2080
2306
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2307
|
+
catch (e) {
|
|
2308
|
+
catchRejection(e, `Can't sync translations to ${name}`);
|
|
2083
2309
|
}
|
|
2084
|
-
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
2085
2310
|
}
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2311
|
+
function openLanguageModal() {
|
|
2312
|
+
setLanguageModalState((state) => {
|
|
2313
|
+
var _a, _b;
|
|
2314
|
+
return ({
|
|
2315
|
+
languages: (_b = (_a = state === null || state === void 0 ? void 0 : state.languages) !== null && _a !== void 0 ? _a : project.current.targetLanguages) !== null && _b !== void 0 ? _b : [],
|
|
2316
|
+
action: 'syncToCrowdin',
|
|
2317
|
+
});
|
|
2318
|
+
});
|
|
2319
|
+
openModal(languageModal.current);
|
|
2320
|
+
}
|
|
2321
|
+
function openLanguageModalForCrowdinFiles() {
|
|
2322
|
+
setLanguageModalState((state) => {
|
|
2323
|
+
var _a, _b;
|
|
2324
|
+
return ({
|
|
2325
|
+
languages: (_b = (_a = state === null || state === void 0 ? void 0 : state.languages) !== null && _a !== void 0 ? _a : project.current.targetLanguages) !== null && _b !== void 0 ? _b : [],
|
|
2326
|
+
action: 'updateCrowdinTargetLanguages',
|
|
2327
|
+
});
|
|
2328
|
+
});
|
|
2329
|
+
openModal(languageModal.current);
|
|
2330
|
+
}
|
|
2331
|
+
async function uploadFilesToCrowdinWithExcludedLanguages() {
|
|
2332
|
+
const selectedLanguages = await languageSelectRef.current.getValue();
|
|
2333
|
+
closeModal(languageModal.current);
|
|
2334
|
+
uploadFilesToCrowdin({ detail: fileToSync.current }, selectedLanguages);
|
|
2335
|
+
}
|
|
2336
|
+
async function updateCrowdinFilesTargetLanguages() {
|
|
2337
|
+
const selectedLanguages = await languageSelectRef.current.getValue();
|
|
2338
|
+
closeModal(languageModal.current);
|
|
2339
|
+
const fileIds = Object.keys(crowdinFilesToUpdateTargetLanguages.current).map((id) => parseInt(id, 10));
|
|
2340
|
+
if (fileIds.length === 0) {
|
|
2341
|
+
showToast('Select files to update');
|
|
2089
2342
|
return;
|
|
2090
2343
|
}
|
|
2091
|
-
appComponent.current.setAttribute('is-crowdin-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2344
|
+
appComponent.current.setAttribute('is-to-crowdin-process', true);
|
|
2345
|
+
try {
|
|
2346
|
+
const restParams = await checkOrigin();
|
|
2347
|
+
const res = await checkResponse(await fetch(`api/crowdin/files-target-languages${restParams}`, {
|
|
2348
|
+
method: 'POST',
|
|
2349
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2350
|
+
body: JSON.stringify({ fileIds, languages: selectedLanguages }),
|
|
2351
|
+
}));
|
|
2352
|
+
checkJob({ jobId: res === null || res === void 0 ? void 0 : res.jobId, jobType: JOB_TYPE.updateTargetLanguages });
|
|
2095
2353
|
}
|
|
2096
|
-
|
|
2097
|
-
|
|
2354
|
+
catch (e) {
|
|
2355
|
+
catchRejection(e, "Can't update files target languages");
|
|
2098
2356
|
}
|
|
2099
|
-
updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
|
|
2100
2357
|
}
|
|
2101
|
-
function
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2358
|
+
function setLanguagesForTranslation(languages, action = 'syncToCrowdin') {
|
|
2359
|
+
setLanguageModalState({ languages, action });
|
|
2360
|
+
}
|
|
2361
|
+
async function updateSyncSettings(files, type, provider, expandIntegrationFolders = [], folderIds = []) {
|
|
2362
|
+
try {
|
|
2363
|
+
const restParams = await checkOrigin();
|
|
2364
|
+
const res = await checkResponse(await fetch('api/sync-settings' + restParams, {
|
|
2365
|
+
method: 'POST',
|
|
2366
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2367
|
+
body: JSON.stringify({
|
|
2368
|
+
files,
|
|
2369
|
+
type,
|
|
2370
|
+
provider,
|
|
2371
|
+
expandIntegrationFolders,
|
|
2372
|
+
hasLoadMoreElements: hasLoadMoreElements.current,
|
|
2373
|
+
folderIds,
|
|
2374
|
+
}),
|
|
2375
|
+
}));
|
|
2117
2376
|
checkJob({
|
|
2118
2377
|
jobId: res === null || res === void 0 ? void 0 : res.jobId,
|
|
2119
2378
|
jobType: JOB_TYPE[`${provider}SyncSettingsSave`],
|
|
2120
2379
|
});
|
|
2121
|
-
}
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2380
|
+
}
|
|
2381
|
+
catch (e) {
|
|
2382
|
+
catchRejection(e, "Can't save schedule sync settings");
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
return {
|
|
2386
|
+
getCrowdinData,
|
|
2387
|
+
getIntegrationData,
|
|
2388
|
+
checkJob,
|
|
2389
|
+
cancelJob,
|
|
2390
|
+
getActiveJobs,
|
|
2391
|
+
updateSyncSettings,
|
|
2392
|
+
refreshAutoSyncPausedIndicatorsAndWarning,
|
|
2393
|
+
uploadFilesToCrowdin,
|
|
2394
|
+
uploadFilesToIntegration,
|
|
2395
|
+
updateCrowdinFilesTargetLanguages,
|
|
2396
|
+
uploadFilesToCrowdinWithExcludedLanguages,
|
|
2397
|
+
languageModalState,
|
|
2398
|
+
languageModalRef: languageModal,
|
|
2399
|
+
languageSelectRef,
|
|
2400
|
+
crowdinData,
|
|
2401
|
+
hasLoadMoreElements,
|
|
2402
|
+
};
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
const ExcludedLanguagesModal = ({ modalRef, languageSelectRef, languageModalState, onUpdateTargetLanguages, onSyncToCrowdin, }) => {
|
|
2406
|
+
return (jsxRuntimeExports.jsx("crowdin-modal", { ref: modalRef, style: { display: 'none' }, "modal-width": "50", "modal-title": "Select Target Languages for Translation", id: "excluded-languages", children: languageModalState && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { children: jsxRuntimeExports.jsx("crowdin-select", { ref: languageSelectRef, "is-multi": true, "is-searchable": true, "is-position-fixed": true, "close-on-select": "false", name: "languages", id: "language-select", label: "Languages", children: languageModalState.languages.map((language) => (jsxRuntimeExports.jsx("option", { value: language.id, children: language.name }, language.id))) }) }), jsxRuntimeExports.jsxs("div", { slot: "footer", children: [jsxRuntimeExports.jsx("span", { hidden: languageModalState.action !== 'updateCrowdinTargetLanguages', children: jsxRuntimeExports.jsx("crowdin-button", { id: "update-crowdin-target-languages", outlined: true, onClick: onUpdateTargetLanguages, children: "Update Target Languages" }) }), jsxRuntimeExports.jsx("span", { hidden: languageModalState.action !== 'syncToCrowdin', children: jsxRuntimeExports.jsx("crowdin-button", { id: "upload-exclude-languages", outlined: true, onClick: onSyncToCrowdin, children: jsxRuntimeExports.jsxs("div", { className: "inline-flex items-center gap-1", children: [jsxRuntimeExports.jsx("span", { children: "Sync to" }), jsxRuntimeExports.jsx("crowdin-logo", { "is-icon": true })] }) }) })] })] })) }));
|
|
2407
|
+
};
|
|
2408
|
+
|
|
2409
|
+
const InfoModal = ({ modalRef, infoModal }) => {
|
|
2410
|
+
return (jsxRuntimeExports.jsx("crowdin-modal", { ref: modalRef, style: { display: 'none' }, id: "info-modal", "modal-width": "50", "modal-title": infoModal.title, "close-button-title": "Close", children: jsxRuntimeExports.jsx("div", { dangerouslySetInnerHTML: { __html: infoModal.content } }) }));
|
|
2411
|
+
};
|
|
2412
|
+
|
|
2413
|
+
function renderPermissionStatus(status) {
|
|
2414
|
+
switch (status) {
|
|
2415
|
+
case 'willBeGranted':
|
|
2416
|
+
return (jsxRuntimeExports.jsx("span", { className: "inline-block cursor-default rounded-[15px] bg-[var(--crowdin-info)] px-3 py-1 text-center text-xs font-medium text-[var(--crowdin-white)]", children: "Will Be Granted" }));
|
|
2417
|
+
case 'willBeRegistered':
|
|
2418
|
+
return (jsxRuntimeExports.jsx("span", { className: "inline-block cursor-default rounded-[15px] bg-[var(--crowdin-info)] px-3 py-1 text-center text-xs font-medium text-[var(--crowdin-white)]", children: "Will Be Registered" }));
|
|
2419
|
+
case 'actionRequired':
|
|
2420
|
+
return (jsxRuntimeExports.jsx("span", { className: "inline-block cursor-default rounded-[15px] bg-[var(--crowdin-warning-bg)] px-3 py-1 text-center text-xs font-medium text-[var(--crowdin-warning)]", children: "Action Required" }));
|
|
2421
|
+
case 'granted':
|
|
2422
|
+
default:
|
|
2423
|
+
return jsxRuntimeExports.jsx("crowdin-p", { children: EMPTY_PERMISSION_VALUE });
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
function renderPermissionUsers(row) {
|
|
2427
|
+
if (!row || row.users.length === 0) {
|
|
2428
|
+
return row ? renderPermissionStatus(row.status) : null;
|
|
2429
|
+
}
|
|
2430
|
+
return (jsxRuntimeExports.jsx("ul", { className: "m-0 list-none p-0", children: row.users.map((user) => (jsxRuntimeExports.jsx("li", { className: "mb-1 text-sm last:mb-0", children: jsxRuntimeExports.jsx("crowdin-p", { children: user }) }, user))) }));
|
|
2431
|
+
}
|
|
2432
|
+
function renderPermissionRowDescription(row) {
|
|
2433
|
+
if (!(row === null || row === void 0 ? void 0 : row.description)) {
|
|
2434
|
+
return null;
|
|
2435
|
+
}
|
|
2436
|
+
return (jsxRuntimeExports.jsx("div", { className: row.isWarning
|
|
2437
|
+
? 'mt-1 text-xs text-[var(--crowdin-warning)]'
|
|
2438
|
+
: 'mt-1 text-xs text-[var(--crowdin-text-muted)]', children: row.description }));
|
|
2439
|
+
}
|
|
2440
|
+
const PermissionsModal = ({ modalRef, usersSelectRef, isLoading, permissionUserOptions, isConfirmVisible, permissionsSummary, hasOrganization, zenModeUrl, onSave, }) => {
|
|
2441
|
+
return (jsxRuntimeExports.jsxs("crowdin-modal", { ref: modalRef, style: { display: 'none' }, id: "permissions-modal", "modal-title": "Share", "close-button-title": "Close", "close-button": true, "body-overflow-unset": true, children: [jsxRuntimeExports.jsx("div", { className: isLoading ? 'absolute inset-0 z-[4] flex items-center justify-center bg-white/30' : 'hidden', children: jsxRuntimeExports.jsx("crowdin-progress-indicator", {}) }), jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsx("div", { children: jsxRuntimeExports.jsx("crowdin-users-select", { ref: usersSelectRef, "allow-new-options": true, "is-multi": true, "is-searchable": true, id: "users", label: "Users", "help-text": "Search for members by name, username, email, or invite new ones using their email.", "is-position-fixed": true, children: permissionUserOptions.map((option) => (jsxRuntimeExports.jsx("option", { value: option.id, children: option.label }, option.id))) }, "users") }), jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsx("div", { className: isConfirmVisible ? 'mt-4' : 'hidden', children: jsxRuntimeExports.jsxs("table", { className: "w-full border-separate border-spacing-0", children: [jsxRuntimeExports.jsx("thead", { children: jsxRuntimeExports.jsxs("tr", { children: [jsxRuntimeExports.jsx("th", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left text-sm", style: { width: '40%' }, children: "Access" }), jsxRuntimeExports.jsx("th", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left text-sm", style: { width: '35%' }, children: "Users" }), jsxRuntimeExports.jsx("th", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-right text-sm", style: { width: '20%' }, children: "Upcoming changes" })] }) }), jsxRuntimeExports.jsxs("tbody", { children: [hasOrganization && (jsxRuntimeExports.jsxs("tr", { children: [jsxRuntimeExports.jsxs("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left align-top", children: [jsxRuntimeExports.jsx("crowdin-p", { children: "Registration in Organization" }), renderPermissionRowDescription(permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.organization)] }), jsxRuntimeExports.jsx("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left align-top", children: renderPermissionUsers(permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.organization) }), jsxRuntimeExports.jsx("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-right align-top", children: (permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.organization) &&
|
|
2442
|
+
renderPermissionStatus(permissionsSummary.organization.status) })] })), jsxRuntimeExports.jsxs("tr", { children: [jsxRuntimeExports.jsx("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left align-top", children: jsxRuntimeExports.jsx("crowdin-p", { children: "Project Manager Access" }) }), jsxRuntimeExports.jsx("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left align-top", children: renderPermissionUsers(permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.project) }), jsxRuntimeExports.jsx("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-right align-top", children: (permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.project) &&
|
|
2443
|
+
renderPermissionStatus(permissionsSummary.project.status) })] }), jsxRuntimeExports.jsxs("tr", { children: [jsxRuntimeExports.jsxs("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left align-top", children: [jsxRuntimeExports.jsx("crowdin-p", { children: "Application Visibility Access" }), renderPermissionRowDescription(permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.applicationSettings)] }), jsxRuntimeExports.jsx("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left align-top", children: renderPermissionUsers(permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.applicationSettings) }), jsxRuntimeExports.jsx("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-right align-top", children: (permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.applicationSettings) &&
|
|
2444
|
+
renderPermissionStatus(permissionsSummary.applicationSettings.status) })] }), jsxRuntimeExports.jsxs("tr", { children: [jsxRuntimeExports.jsxs("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left align-top", children: [jsxRuntimeExports.jsx("crowdin-p", { children: "Access to the Integration" }), jsxRuntimeExports.jsx("div", { className: "mt-1 text-xs text-[var(--crowdin-text-muted)]", children: "This provides access to sync files and modify the current integration settings." })] }), jsxRuntimeExports.jsx("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-left align-top", children: renderPermissionUsers(permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.applicationCredentials) }), jsxRuntimeExports.jsx("td", { className: "border-b border-[var(--crowdin-border-color)] p-4 text-right align-top", children: (permissionsSummary === null || permissionsSummary === void 0 ? void 0 : permissionsSummary.applicationCredentials) &&
|
|
2445
|
+
renderPermissionStatus(permissionsSummary.applicationCredentials.status) })] })] })] }) }), zenModeUrl && (jsxRuntimeExports.jsx("div", { className: "mt-4", children: jsxRuntimeExports.jsx("crowdin-input", { "with-fixed-height": true, label: "Zen Mode link", "help-text": "This focused view allows you to concentrate solely on the Integrations section, eliminating other distractions.", value: zenModeUrl, name: "zenModeLink", "with-copy-button": true }) }))] })] }), jsxRuntimeExports.jsx("div", { slot: "footer", children: jsxRuntimeExports.jsx("crowdin-button", { id: "confirm-users-btn", outlined: true, onClick: onSave, children: "Save" }) })] }));
|
|
2446
|
+
};
|
|
2447
|
+
|
|
2448
|
+
const ScheduleModal = ({ modalRef, selectedFilesCheckboxRef, allFolderFilesCheckboxRef, newFilesCheckboxRef, scheduleModalState, isSaveDisabled, onChangeOptions, onSave, }) => {
|
|
2449
|
+
return (jsxRuntimeExports.jsxs("crowdin-modal", { ref: modalRef, style: { display: 'none' }, id: "confirm-schedule-modal", "modal-width": "50", "modal-title": "Synchronization options", "close-button-title": "Close", "close-button": "true", "body-overflow-unset": true, children: [jsxRuntimeExports.jsx("crowdin-checkbox", { ref: selectedFilesCheckboxRef, id: "selected-files", name: "selected-files", label: "Selected files", class: "hydrated", checked: scheduleModalState.selectedFiles, value: String(scheduleModalState.selectedFiles), onChange: onChangeOptions }), jsxRuntimeExports.jsx("crowdin-checkbox", { ref: allFolderFilesCheckboxRef, id: "all-folder-files", name: "all-folder-files", label: "All files in the folder", class: "hydrated", hidden: !scheduleModalState.showAllFolderFiles, checked: scheduleModalState.allFolderFiles, value: String(scheduleModalState.allFolderFiles), onChange: onChangeOptions }), jsxRuntimeExports.jsx("crowdin-checkbox", { ref: newFilesCheckboxRef, id: "new-files", name: "new-files", label: "New files", class: "hydrated", hidden: !scheduleModalState.showNewFiles, checked: scheduleModalState.newFiles, value: String(scheduleModalState.newFiles), ...(scheduleModalState.newFilesClearSelection ? { 'clear-selection': '' } : {}), onChange: onChangeOptions }), jsxRuntimeExports.jsx("div", { slot: "footer", children: jsxRuntimeExports.jsx("crowdin-button", { outlined: true, id: "save-schedule-sync", disabled: isSaveDisabled, onClick: onSave, children: "Save" }) })] }));
|
|
2450
|
+
};
|
|
2451
|
+
|
|
2452
|
+
function renderConfigField(field, settingsFieldChange, registerSettingsField, suffix = 'settings') {
|
|
2453
|
+
var _a;
|
|
2454
|
+
if (!field.key) {
|
|
2455
|
+
return field.labelHtml ? (jsxRuntimeExports.jsx("crowdin-p", { ...(field.dependencySettings ? { 'data-dependency': field.dependencySettings } : {}), dangerouslySetInnerHTML: { __html: field.labelHtml } })) : (jsxRuntimeExports.jsx("crowdin-p", { ...(field.dependencySettings ? { 'data-dependency': field.dependencySettings } : {}), children: field.label }));
|
|
2456
|
+
}
|
|
2457
|
+
const commonProps = {
|
|
2458
|
+
id: `${field.key}-${suffix}`,
|
|
2459
|
+
_key: field.key,
|
|
2460
|
+
label: field.label,
|
|
2461
|
+
...(field.helpText ? { 'help-text': field.helpText } : {}),
|
|
2462
|
+
...(field.helpTextHtml ? { 'help-text-html': field.helpTextHtml } : {}),
|
|
2463
|
+
...(field.dependencySettings ? { 'data-dependency': field.dependencySettings } : {}),
|
|
2464
|
+
};
|
|
2465
|
+
switch (field.type) {
|
|
2466
|
+
case 'checkbox':
|
|
2467
|
+
return (jsxRuntimeExports.jsx("crowdin-checkbox", { ref: registerSettingsField(field.key), ...commonProps, value: "false", "use-switch": true, ...(field.defaultValue === true ? { checked: String(field.defaultValue) } : {}), onChange: settingsFieldChange }));
|
|
2468
|
+
case 'select':
|
|
2469
|
+
return (jsxRuntimeExports.jsx("crowdin-select", { ref: registerSettingsField(field.key), ...commonProps, ...(field.isMulti ? { 'is-multi': true, 'close-on-select': 'false' } : {}), ...(field.isSearchable ? { 'is-searchable': true } : {}), "is-position-fixed": true, onChange: settingsFieldChange, children: (_a = field.options) === null || _a === void 0 ? void 0 : _a.map((option) => {
|
|
2470
|
+
const isSelected = Array.isArray(field.defaultValue)
|
|
2471
|
+
? field.defaultValue.includes(option.value)
|
|
2472
|
+
: field.defaultValue === option.value;
|
|
2473
|
+
return (jsxRuntimeExports.jsx("option", { value: option.value, ...(isSelected ? { selected: true } : {}), children: option.label }, option.value));
|
|
2474
|
+
}) }));
|
|
2475
|
+
case 'text':
|
|
2476
|
+
return (jsxRuntimeExports.jsx("crowdin-input", { ref: registerSettingsField(field.key), ...commonProps, "with-fixed-height": true, value: field.defaultValue || '', onChange: settingsFieldChange }));
|
|
2477
|
+
case 'textarea':
|
|
2478
|
+
return (jsxRuntimeExports.jsx("crowdin-textarea", { ref: registerSettingsField(field.key), ...commonProps, value: field.defaultValue || '', onChange: settingsFieldChange }));
|
|
2479
|
+
case 'notice':
|
|
2480
|
+
return (jsxRuntimeExports.jsx("crowdin-alert", { ...(field.noticeType ? { type: field.noticeType } : {}), ...(field.label ? { title: field.label } : {}), ...(field.noIcon ? { 'no-icon': String(field.noIcon) } : {}), ...(field.dependencySettings ? { 'data-dependency': field.dependencySettings } : {}), dangerouslySetInnerHTML: { __html: field.helpTextHtml || field.helpText || '' } }));
|
|
2481
|
+
default:
|
|
2482
|
+
return null;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
const SettingsModal = ({ modalRef, isLoading, configurationFields, isSaveDisabled, settingsFieldChange, registerSettingsField, onSave, }) => {
|
|
2486
|
+
return (jsxRuntimeExports.jsxs("crowdin-modal", { ref: modalRef, style: { display: 'none' }, id: "settings-modal", "modal-width": "65", "modal-title": "Settings", "close-button-title": "Close", children: [jsxRuntimeExports.jsx("div", { className: isLoading ? 'absolute inset-0 z-[4] flex items-center justify-center bg-white/30' : 'hidden', children: jsxRuntimeExports.jsx("crowdin-progress-indicator", {}) }), jsxRuntimeExports.jsx("div", { id: "modal-content", children: jsxRuntimeExports.jsx("crowdin-tabs", { "tabs-config": JSON.stringify(configurationFields.map((f) => f.name)), "active-tab": "1", children: configurationFields.map((tab, tabIndex) => (jsxRuntimeExports.jsx("div", { slot: `tab-${tabIndex + 1}`, children: jsxRuntimeExports.jsx("div", { children: tab.fields.map((field, fieldIndex) => (jsxRuntimeExports.jsxs(reactExports.Fragment, { children: [renderConfigField(field, settingsFieldChange, registerSettingsField), jsxRuntimeExports.jsx("div", { style: { padding: '8px' }, ...(field.dependencySettings
|
|
2487
|
+
? { 'data-dependency': field.dependencySettings }
|
|
2488
|
+
: {}) })] }, field.key || `${tabIndex}-${fieldIndex}`))) }) }, tabIndex))) }) }), jsxRuntimeExports.jsx("div", { slot: "footer", children: jsxRuntimeExports.jsx("crowdin-button", { id: "settings-save-btn", outlined: true, disabled: isSaveDisabled, onClick: onSave, children: "Save" }) })] }));
|
|
2489
|
+
};
|
|
2490
|
+
|
|
2491
|
+
const SubscriptionModal = ({ modalRef, subscriptionLink, name, onLogout }) => {
|
|
2492
|
+
return (jsxRuntimeExports.jsxs("crowdin-modal", { ref: modalRef, style: { display: 'none' }, id: "subscription-modal", "modal-width": "50", "close-button": "false", children: [jsxRuntimeExports.jsx("div", { children: jsxRuntimeExports.jsxs("crowdin-alert", { type: "warning", children: ["Subscribe to continue using the ", name, " app."] }) }), jsxRuntimeExports.jsxs("div", { slot: "footer", children: [jsxRuntimeExports.jsx("crowdin-button", { primary: true, onClick: () => { var _a; return window.open((_a = subscriptionLink.current) !== null && _a !== void 0 ? _a : '', '_blank', 'noopener,noreferrer'); }, children: "Subscribe" }), jsxRuntimeExports.jsx("crowdin-button", { outlined: true, onClick: () => window.open('https://crowdin.com/contacts', '_blank', 'noopener,noreferrer'), children: "Contact us" }), jsxRuntimeExports.jsx("crowdin-button", { class: "ml-2.5", secondary: true, onClick: onLogout, children: "Log out" })] })] }));
|
|
2493
|
+
};
|
|
2494
|
+
|
|
2495
|
+
function isJSON(string) {
|
|
2496
|
+
try {
|
|
2497
|
+
JSON.parse(string);
|
|
2498
|
+
return true;
|
|
2499
|
+
}
|
|
2500
|
+
catch (e) {
|
|
2501
|
+
return false;
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
function getUserErrorDetail(error) {
|
|
2505
|
+
const data = JSON.parse(error.data);
|
|
2506
|
+
const preClassName = 'block rounded bg-[#eceff1] p-4 text-[87.5%] text-[#212529]';
|
|
2507
|
+
const rows = [
|
|
2508
|
+
{ label: 'Action', value: error.action },
|
|
2509
|
+
{
|
|
2510
|
+
label: 'Message',
|
|
2511
|
+
value: isJSON(error.message) ? jsxRuntimeExports.jsx("pre", { className: preClassName, children: error.message }) : error.message,
|
|
2512
|
+
},
|
|
2513
|
+
{ label: 'Date/time', value: error.formattedDate },
|
|
2514
|
+
];
|
|
2515
|
+
if (data.requestParams) {
|
|
2516
|
+
rows.push({ label: 'Method', value: data.requestParams.method });
|
|
2517
|
+
}
|
|
2518
|
+
if (data.responseData) {
|
|
2519
|
+
rows.push({
|
|
2520
|
+
label: 'Response Data',
|
|
2521
|
+
value: jsxRuntimeExports.jsx("pre", { className: preClassName, children: JSON.stringify(data.responseData, null, 2) }),
|
|
2136
2522
|
});
|
|
2137
2523
|
}
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2524
|
+
if (data.appData) {
|
|
2525
|
+
if (Array.isArray(data.appData)) {
|
|
2526
|
+
rows.push({
|
|
2527
|
+
label: 'App Data',
|
|
2528
|
+
value: jsxRuntimeExports.jsx("pre", { className: preClassName, children: JSON.stringify(data.appData, null, 2) }),
|
|
2529
|
+
});
|
|
2530
|
+
}
|
|
2531
|
+
else if (typeof data.appData === 'object') {
|
|
2532
|
+
for (const key in data.appData) {
|
|
2533
|
+
rows.push({
|
|
2534
|
+
label: key.charAt(0).toUpperCase() + key.slice(1),
|
|
2535
|
+
value: jsxRuntimeExports.jsx("pre", { className: preClassName, children: JSON.stringify(data.appData[key], null, 2) }),
|
|
2536
|
+
});
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
else {
|
|
2540
|
+
rows.push({ label: 'App Data', value: data.appData });
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
return (jsxRuntimeExports.jsx("div", { className: "-m-6 h-auto max-h-[579px] overflow-auto", children: jsxRuntimeExports.jsx("table", { className: "w-full border-separate border-spacing-0", children: jsxRuntimeExports.jsx("tbody", { children: rows.map((row) => (jsxRuntimeExports.jsxs("tr", { children: [jsxRuntimeExports.jsx("td", { className: "min-w-[200px] p-2 px-6 align-top font-medium", children: row.label }), jsxRuntimeExports.jsx("td", { className: "break-all bg-[var(--crowdin-primary-blue-gray,#f6f6f6)] p-2 px-6 text-[var(--crowdin-body-color,rgba(38,50,56,0.87))]", children: row.value })] }, row.label))) }) }) }));
|
|
2544
|
+
}
|
|
2545
|
+
const UserErrorDetailModal = ({ modalRef, selectedUserError }) => {
|
|
2546
|
+
return (jsxRuntimeExports.jsx("crowdin-modal", { ref: modalRef, style: { display: 'none' }, id: "user-error-detail", "close-button-title": "Close", "close-button": "true", children: selectedUserError && getUserErrorDetail(selectedUserError) }));
|
|
2547
|
+
};
|
|
2548
|
+
|
|
2549
|
+
const MainPage = (props) => {
|
|
2550
|
+
const { name, userId, notice, checkSubscription, isManager, isOwner, infoModal, configurationFields, config: configString, syncNewElements, withCronSync, webhooks, integrationOneLevelFetching, integrationSearchListener, integrationPagination, excludedTargetLanguages, filtering, hasOrganization, zenModeUrl, asyncProgress = { checkInterval: 3000 }, reloadOnConfigSave, progressiveCrowdinFilesLoading, integrationButtonMenuItems, crowdinButtonMenuItems, } = props;
|
|
2551
|
+
const config = reactExports.useRef(configString ? JSON.parse(configString.replace(/\\n/g, '\\\\n')) : {});
|
|
2552
|
+
const appComponent = reactExports.useRef(null);
|
|
2553
|
+
const asyncProgressRef = reactExports.useRef(null);
|
|
2554
|
+
const infoModalRef = reactExports.useRef(null);
|
|
2555
|
+
const subscriptionModal = reactExports.useRef(null);
|
|
2556
|
+
const settingsModalRef = reactExports.useRef(null);
|
|
2557
|
+
const scheduleModalRef = reactExports.useRef(null);
|
|
2558
|
+
const permissionsModalRef = reactExports.useRef(null);
|
|
2559
|
+
const userErrorsTableRef = reactExports.useRef(null);
|
|
2560
|
+
const userErrorDetailModalRef = reactExports.useRef(null);
|
|
2561
|
+
const subscriptionLink = reactExports.useRef('');
|
|
2562
|
+
const refreshDependencies = useFieldDependencies(configurationFields);
|
|
2563
|
+
const [isNoticeVisible, setIsNoticeVisible] = reactExports.useState(false);
|
|
2564
|
+
const [subscriptionInfo, setSubscriptionInfo] = reactExports.useState(null);
|
|
2565
|
+
const [isErrorLogsVisible, setIsErrorLogsVisible] = reactExports.useState(false);
|
|
2566
|
+
const [selectedUserError, setSelectedUserError] = reactExports.useState(null);
|
|
2567
|
+
const syncOps = useSyncOperations({
|
|
2568
|
+
appComponent,
|
|
2569
|
+
asyncProgressRef,
|
|
2570
|
+
config,
|
|
2571
|
+
name,
|
|
2572
|
+
integrationOneLevelFetching,
|
|
2573
|
+
integrationSearchListener,
|
|
2574
|
+
integrationPagination,
|
|
2575
|
+
withCronSync,
|
|
2576
|
+
webhooks,
|
|
2577
|
+
progressiveCrowdinFilesLoading,
|
|
2578
|
+
asyncProgress,
|
|
2579
|
+
syncNewElements,
|
|
2580
|
+
});
|
|
2581
|
+
const permissions = usePermissions({
|
|
2582
|
+
userId,
|
|
2583
|
+
hasOrganization,
|
|
2584
|
+
permissionsModalRef,
|
|
2585
|
+
});
|
|
2586
|
+
const settings = useSettings({
|
|
2587
|
+
configurationFields,
|
|
2588
|
+
config,
|
|
2589
|
+
settingsModalRef,
|
|
2590
|
+
reloadOnConfigSave,
|
|
2591
|
+
refreshDependencies,
|
|
2592
|
+
checkJob: syncOps.checkJob,
|
|
2593
|
+
getCrowdinData: syncOps.getCrowdinData,
|
|
2594
|
+
getIntegrationData: syncOps.getIntegrationData,
|
|
2595
|
+
refreshAutoSyncPausedIndicatorsAndWarning: syncOps.refreshAutoSyncPausedIndicatorsAndWarning,
|
|
2596
|
+
});
|
|
2597
|
+
const schedule = useSchedule({
|
|
2598
|
+
appComponent,
|
|
2599
|
+
config,
|
|
2600
|
+
scheduleModalRef,
|
|
2601
|
+
withCronSync,
|
|
2602
|
+
webhooks,
|
|
2603
|
+
syncNewElements,
|
|
2604
|
+
integrationOneLevelFetching,
|
|
2605
|
+
hasLoadMoreElements: syncOps.hasLoadMoreElements,
|
|
2606
|
+
updateSyncSettings: syncOps.updateSyncSettings,
|
|
2607
|
+
});
|
|
2608
|
+
reactExports.useEffect(() => {
|
|
2609
|
+
const handleKeydown = (event) => {
|
|
2610
|
+
if (event.keyCode === 27) {
|
|
2611
|
+
closeModal(permissionsModalRef.current);
|
|
2612
|
+
closeModal(infoModalRef.current);
|
|
2613
|
+
closeModal(settingsModalRef.current);
|
|
2614
|
+
closeModal(scheduleModalRef.current);
|
|
2615
|
+
if (syncOps.languageModalRef.current) {
|
|
2616
|
+
closeModal(syncOps.languageModalRef.current);
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
};
|
|
2620
|
+
document.body.addEventListener('keydown', handleKeydown);
|
|
2621
|
+
return () => document.body.removeEventListener('keydown', handleKeydown);
|
|
2622
|
+
}, []);
|
|
2623
|
+
// Expose centralized API to global scope for main.js compatibility
|
|
2624
|
+
reactExports.useEffect(() => {
|
|
2625
|
+
window.app = {
|
|
2626
|
+
subscriptionModal,
|
|
2627
|
+
subscriptionLink,
|
|
2628
|
+
openModal,
|
|
2629
|
+
};
|
|
2630
|
+
return () => {
|
|
2631
|
+
delete window.app;
|
|
2632
|
+
};
|
|
2633
|
+
}, []);
|
|
2634
|
+
reactExports.useEffect(() => {
|
|
2635
|
+
setIsNoticeVisible(Boolean(notice) && localStorage.getItem('revised_notice') !== '1');
|
|
2636
|
+
if (checkSubscription) {
|
|
2637
|
+
getSubscriptionInfo();
|
|
2638
|
+
}
|
|
2639
|
+
}, []);
|
|
2640
|
+
async function getSubscriptionInfo() {
|
|
2641
|
+
const restParams = await checkOrigin();
|
|
2642
|
+
const res = await checkResponse(await fetch('api/subscription-info' + restParams));
|
|
2643
|
+
if (res.showInfo) {
|
|
2644
|
+
subscriptionLink.current = res.subscribeLink;
|
|
2645
|
+
setSubscriptionInfo({ daysLeft: res.daysLeft, subscribeLink: res.subscribeLink });
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
async function integrationLogout() {
|
|
2649
|
+
try {
|
|
2650
|
+
const queryParams = await checkOrigin();
|
|
2651
|
+
await checkResponse(await fetch(`api/logout${queryParams}`, { method: 'POST' }));
|
|
2652
|
+
reloadLocation();
|
|
2653
|
+
localStorage.removeItem(`revised_${name}`);
|
|
2654
|
+
}
|
|
2655
|
+
catch (e) {
|
|
2656
|
+
catchRejection(e, e.error || 'Looks like you are not logged in');
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
function closeAlert(suffix) {
|
|
2660
|
+
setIsNoticeVisible(false);
|
|
2661
|
+
localStorage.setItem(`revised_${suffix !== null && suffix !== void 0 ? suffix : name}`, '1');
|
|
2662
|
+
}
|
|
2663
|
+
async function showErrorLogs() {
|
|
2664
|
+
setIsErrorLogsVisible(true);
|
|
2665
|
+
try {
|
|
2666
|
+
const restParams = await checkOrigin();
|
|
2667
|
+
const res = await checkResponse(await fetch('api/user-errors' + restParams));
|
|
2668
|
+
const table = userErrorsTableRef.current;
|
|
2669
|
+
const clickRow = (_field, _index, item) => {
|
|
2670
|
+
setSelectedUserError(item);
|
|
2671
|
+
openModal(userErrorDetailModalRef.current);
|
|
2168
2672
|
};
|
|
2673
|
+
const formatDate = (_field, _index, item) => item.formattedDate;
|
|
2169
2674
|
if (table.setTableConfig) {
|
|
2170
2675
|
table.setTableConfig({
|
|
2171
2676
|
defaultSortingColumn: 'createdAt',
|
|
@@ -2178,114 +2683,30 @@
|
|
|
2178
2683
|
clickFn: clickRow,
|
|
2179
2684
|
formatFn: formatDate,
|
|
2180
2685
|
},
|
|
2181
|
-
{
|
|
2182
|
-
|
|
2183
|
-
name: 'Action',
|
|
2184
|
-
clickFn: clickRow,
|
|
2185
|
-
},
|
|
2186
|
-
{
|
|
2187
|
-
field: 'message',
|
|
2188
|
-
name: 'Message',
|
|
2189
|
-
clickFn: clickRow,
|
|
2190
|
-
},
|
|
2686
|
+
{ field: 'action', name: 'Action', clickFn: clickRow },
|
|
2687
|
+
{ field: 'message', name: 'Message', clickFn: clickRow },
|
|
2191
2688
|
],
|
|
2192
2689
|
});
|
|
2193
2690
|
}
|
|
2194
2691
|
table.setTableData(JSON.stringify(res));
|
|
2195
2692
|
table.setAttribute('is-loading', false);
|
|
2196
|
-
})
|
|
2197
|
-
.catch((e) => catchRejection(e, "Can't fetch error logs"));
|
|
2198
|
-
}
|
|
2199
|
-
function showIntegration() {
|
|
2200
|
-
document.getElementById('show-error-logs-btn').classList.remove('hidden');
|
|
2201
|
-
document.getElementById('show-integration-btn').classList.add('hidden');
|
|
2202
|
-
appComponent.current.classList.remove('hidden');
|
|
2203
|
-
document.getElementById('user-errors').classList.add('hidden');
|
|
2204
|
-
}
|
|
2205
|
-
function isJSON(string) {
|
|
2206
|
-
try {
|
|
2207
|
-
JSON.parse(string);
|
|
2208
|
-
return true;
|
|
2209
2693
|
}
|
|
2210
2694
|
catch (e) {
|
|
2211
|
-
|
|
2695
|
+
catchRejection(e, "Can't fetch error logs");
|
|
2212
2696
|
}
|
|
2213
2697
|
}
|
|
2214
|
-
function
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
else {
|
|
2222
|
-
html += `<tr><td>Message</td><td>${sanitizeHTML(error.message)}</td></tr>`;
|
|
2223
|
-
}
|
|
2224
|
-
html += `<tr><td>Date/time</td><td>${sanitizeHTML(error.formattedDate)}</td></tr>`;
|
|
2225
|
-
if (data.requestParams) {
|
|
2226
|
-
html += `<tr><td>Method</td><td>${sanitizeHTML(data.requestParams.method)}</td></tr>`;
|
|
2227
|
-
}
|
|
2228
|
-
if (data.responseData) {
|
|
2229
|
-
html += `<tr><td>Response Data</td><td><pre>${sanitizeHTML(JSON.stringify(data.responseData, null, 2))}</pre></td></tr>`;
|
|
2230
|
-
}
|
|
2231
|
-
if (data.appData) {
|
|
2232
|
-
if (Array.isArray(data.appData)) {
|
|
2233
|
-
html += `<tr><td>App Data</td><td><pre>${sanitizeHTML(JSON.stringify(data.appData, null, 2))}</pre></td></tr>`;
|
|
2234
|
-
}
|
|
2235
|
-
else if (typeof data.appData === 'object') {
|
|
2236
|
-
for (const key in data.appData) {
|
|
2237
|
-
html += `<tr><td>${sanitizeHTML(key.charAt(0).toUpperCase() + key.slice(1))}</td><td><pre>${sanitizeHTML(JSON.stringify(data.appData[key], null, 2))}</pre></td></tr>`;
|
|
2238
|
-
}
|
|
2239
|
-
}
|
|
2240
|
-
else {
|
|
2241
|
-
html += `<tr><td>App Data</td><td>${sanitizeHTML(data.appData)}</td></tr>`;
|
|
2242
|
-
}
|
|
2243
|
-
}
|
|
2244
|
-
html += '</table></div>';
|
|
2245
|
-
return html;
|
|
2246
|
-
}
|
|
2247
|
-
function sanitizeHTML(str) {
|
|
2248
|
-
const tempDiv = document.createElement('div');
|
|
2249
|
-
tempDiv.textContent = str;
|
|
2250
|
-
return tempDiv.innerHTML;
|
|
2251
|
-
}
|
|
2252
|
-
function openModal(modal) {
|
|
2253
|
-
modal.style.display = 'block';
|
|
2254
|
-
modal.open();
|
|
2255
|
-
}
|
|
2256
|
-
function closeModal(modal) {
|
|
2257
|
-
modal.style.display = 'none';
|
|
2258
|
-
modal.close();
|
|
2259
|
-
}
|
|
2260
|
-
function settingsFieldChange(el) {
|
|
2261
|
-
el.removeAttribute('error');
|
|
2262
|
-
el.removeAttribute('error-text');
|
|
2263
|
-
}
|
|
2264
|
-
function isFolder(e) {
|
|
2265
|
-
return !e.type && (e.nodeType === undefined || e.nodeType === folderType || e.nodeType === branchType);
|
|
2266
|
-
}
|
|
2267
|
-
return (jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsxs("div", { className: "i_w", children: [jsxRuntimeExports.jsxs("div", { className: "top", children: [notice && (jsxRuntimeExports.jsxs("crowdin-alert", { id: "notice", title: notice.title, ...(!notice.icon ? { 'no-icon': 'true' } : {}), ...(notice.type ? { type: notice.type } : {}), style: { display: 'none', marginBottom: '12px' }, children: [jsxRuntimeExports.jsx("div", { className: "box-center", children: jsxRuntimeExports.jsx("p", { className: "m-0", dangerouslySetInnerHTML: { __html: notice.content } }) }), notice.close && (jsxRuntimeExports.jsx("crowdin-button", { onClick: (e) => closeAlert(e, 'notice'), class: "dismiss-alert", icon: true, children: "close" }))] })), checkSubscription && (jsxRuntimeExports.jsx("crowdin-alert", { id: "subscription-info", "no-icon": "true", type: "warning", style: { display: 'none', marginBottom: '12px' }, children: jsxRuntimeExports.jsxs("div", { className: "box-center", children: [jsxRuntimeExports.jsx("p", { className: "m-0" }), jsxRuntimeExports.jsx("crowdin-button", { class: "ml-1", primary: true, onClick: () => window.open(subscriptionLink.current, '_blank'), children: "Subscribe" })] }) })), jsxRuntimeExports.jsxs("div", { id: "buttons", children: [jsxRuntimeExports.jsx("crowdin-button", { id: "show-integration-btn", class: "hidden", "icon-before": "arrow_back", onClick: () => showIntegration(), children: "Integration" }), jsxRuntimeExports.jsx("crowdin-button", { id: "show-error-logs-btn", "icon-before": "list", onClick: () => showErrorLogs(), children: "Error logs" }), isManager && (jsxRuntimeExports.jsx("crowdin-button", { "icon-before": "link", onClick: () => showPermissionsDialog(), children: "Share" })), infoModal && (jsxRuntimeExports.jsx("crowdin-button", { "icon-before": "info", onClick: () => {
|
|
2268
|
-
const infoModalEl = document.getElementById('info-modal');
|
|
2269
|
-
openModal(infoModalEl);
|
|
2270
|
-
}, children: infoModal.title })), configurationFields && (jsxRuntimeExports.jsx("crowdin-button", { "icon-before": "settings", onClick: () => {
|
|
2271
|
-
const settingsModal = document.getElementById('settings-modal');
|
|
2272
|
-
openModal(settingsModal);
|
|
2273
|
-
fillSettingsForm();
|
|
2274
|
-
}, children: "Settings" })), jsxRuntimeExports.jsx("crowdin-button", { ...(!isOwner ? { disabled: true, title: 'Only the owner can log out' } : {}), "icon-before": "account_circle", onClick: () => integrationLogout(), children: "Log out" })] })] }), jsxRuntimeExports.jsx("crowdin-simple-integration", { ref: appComponent, "async-progress": true, ...((syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.crowdin) ? { 'skip-crowdin-auto-schedule': true } : {}), ...((syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration) ? { 'skip-integration-auto-schedule': true } : {}), ...((withCronSync === null || withCronSync === void 0 ? void 0 : withCronSync.crowdin) || (webhooks === null || webhooks === void 0 ? void 0 : webhooks.crowdin) ? { 'crowdin-schedule': 'true' } : {}), ...((withCronSync === null || withCronSync === void 0 ? void 0 : withCronSync.integration) || (webhooks === null || webhooks === void 0 ? void 0 : webhooks.integration) ? { 'integration-schedule': 'true' } : {}), ...(integrationOneLevelFetching ? { 'integration-one-level-fetching': 'true' } : {}), ...(integrationSearchListener ? { 'allow-integration-filter-change-listener': 'true' } : {}), ...(integrationPagination ? { 'integration-load-more-files': 'true' } : {}), "integration-name": name, "integration-logo": "logo.png", ...(((_a = integrationButtonMenuItems === null || integrationButtonMenuItems === void 0 ? void 0 : integrationButtonMenuItems.length) !== null && _a !== void 0 ? _a : 0) > 0
|
|
2275
|
-
? { 'integration-button-menu-items': integrationButtonMenuItems }
|
|
2276
|
-
: {}), ...(((_b = crowdinButtonMenuItems === null || crowdinButtonMenuItems === void 0 ? void 0 : crowdinButtonMenuItems.length) !== null && _b !== void 0 ? _b : 0) > 0
|
|
2277
|
-
? { 'crowdin-button-menu-items': crowdinButtonMenuItems }
|
|
2278
|
-
: {}), ...((filtering === null || filtering === void 0 ? void 0 : filtering.crowdinLanguages) ? { 'crowdin-filter': true } : {}), ...((filtering === null || filtering === void 0 ? void 0 : filtering.integrationFilterConfig)
|
|
2279
|
-
? {
|
|
2280
|
-
'integration-filter': true,
|
|
2281
|
-
'integration-filter-config': filtering.integrationFilterConfig,
|
|
2282
|
-
}
|
|
2283
|
-
: {}) }), jsxRuntimeExports.jsxs("div", { id: "user-errors", className: "hidden", children: [jsxRuntimeExports.jsx("crowdin-show-as-table", { "is-loading": true, id: "user-errors-table", "is-searchable": true, "total-records": "25", "search-placeholder": "Search something" }), jsxRuntimeExports.jsx("crowdin-alert", { children: "This table displays the most recent error logs from the past month. Logs older than one month will be automatically deleted." })] })] }), jsxRuntimeExports.jsx("crowdin-toasts", {}), jsxRuntimeExports.jsx("crowdin-async-progress", { cancelAsyncAction: "" }), jsxRuntimeExports.jsxs("crowdin-modal", { ref: subscriptionModal, style: { display: 'none' }, id: "subscription-modal", "modal-width": "50", "close-button": "false", children: [jsxRuntimeExports.jsx("div", { children: jsxRuntimeExports.jsxs("crowdin-alert", { type: "warning", children: ["Subscribe to continue using the ", name, " app."] }) }), jsxRuntimeExports.jsxs("div", { slot: "footer", children: [jsxRuntimeExports.jsx("crowdin-button", { primary: true, onClick: () => window.open(subscriptionLink.current, '_blank'), children: "Subscribe" }), jsxRuntimeExports.jsx("crowdin-button", { outlined: true, onClick: () => window.open('https://crowdin.com/contacts', '_blank'), children: "Contact us" }), jsxRuntimeExports.jsx("crowdin-button", { class: "ml-10", secondary: true, onClick: () => integrationLogout(), children: "Log out" })] })] }), jsxRuntimeExports.jsxs("crowdin-modal", { style: { display: 'none' }, id: "permissions-modal", "modal-title": "Share", "close-button-title": "Close", "close-button": true, "body-overflow-unset": true, children: [jsxRuntimeExports.jsx("div", { className: "loader hidden", children: jsxRuntimeExports.jsx("crowdin-progress-indicator", {}) }), jsxRuntimeExports.jsxs("div", { className: "permissions-modal-content", children: [jsxRuntimeExports.jsx("div", { className: "select-users-block", children: jsxRuntimeExports.jsx("crowdin-users-select", { ref: usersSelectRef, "allow-new-options": true, "is-multi": true, "is-searchable": true, id: "users", label: "Users", "help-text": "Search for members by name, username, email, or invite new ones using their email.", "is-position-fixed": true }, "users") }), jsxRuntimeExports.jsxs("div", { className: "select-users-info", children: [jsxRuntimeExports.jsx("div", { className: "confirm-users-block mt-2 hidden", children: jsxRuntimeExports.jsxs("table", { children: [jsxRuntimeExports.jsx("thead", { children: jsxRuntimeExports.jsxs("tr", { children: [jsxRuntimeExports.jsx("th", { style: { width: '40%' }, children: "Access" }), jsxRuntimeExports.jsx("th", { style: { width: '35%' }, children: "Users" }), jsxRuntimeExports.jsx("th", { className: "status", style: { width: '20%' }, children: "Upcoming changes" })] }) }), jsxRuntimeExports.jsxs("tbody", { children: [hasOrganization && (jsxRuntimeExports.jsxs("tr", { className: "organization-invite", children: [jsxRuntimeExports.jsxs("td", { children: [jsxRuntimeExports.jsx("crowdin-p", { children: "Registration in Organization" }), jsxRuntimeExports.jsx("div", { className: "permission-description" })] }), jsxRuntimeExports.jsx("td", { className: "affected-users" }), jsxRuntimeExports.jsx("td", { className: "status" })] })), jsxRuntimeExports.jsxs("tr", { className: "project-invite", children: [jsxRuntimeExports.jsx("td", { children: jsxRuntimeExports.jsx("crowdin-p", { children: "Project Manager Access" }) }), jsxRuntimeExports.jsx("td", { className: "affected-users" }), jsxRuntimeExports.jsx("td", { className: "status" })] }), jsxRuntimeExports.jsxs("tr", { className: "application-settings-invite", children: [jsxRuntimeExports.jsxs("td", { children: [jsxRuntimeExports.jsx("crowdin-p", { children: "Application Visibility Access" }), jsxRuntimeExports.jsx("div", { className: "permission-description" })] }), jsxRuntimeExports.jsx("td", { className: "affected-users" }), jsxRuntimeExports.jsx("td", { className: "status" })] }), jsxRuntimeExports.jsxs("tr", { className: "application-credentials-invite", children: [jsxRuntimeExports.jsxs("td", { children: [jsxRuntimeExports.jsx("crowdin-p", { children: "Access to the Integration" }), jsxRuntimeExports.jsx("div", { className: "permission-description", children: "This provides access to sync files and modify the current integration settings." })] }), jsxRuntimeExports.jsx("td", { className: "affected-users" }), jsxRuntimeExports.jsx("td", { className: "status" })] })] })] }) }), zenModeUrl && (jsxRuntimeExports.jsx("div", { className: "mt-2", children: jsxRuntimeExports.jsx("crowdin-input", { "with-fixed-height": true, label: "Zen Mode link", "help-text": "This focused view allows you to concentrate solely on the Integrations section, eliminating other distractions.", value: zenModeUrl, name: "zenModeLink", "with-copy-button": true }) }))] })] }), jsxRuntimeExports.jsx("div", { slot: "footer", children: jsxRuntimeExports.jsx("crowdin-button", { id: "confirm-users-btn", outlined: true, onClick: () => inviteUsers(), children: "Save" }) })] }), excludedTargetLanguages && (jsxRuntimeExports.jsx("crowdin-modal", { ref: languageModal, "modal-width": "50", "modal-title": "Select Target Languages for Translation", id: "excluded-languages" })), infoModal && (jsxRuntimeExports.jsx("crowdin-modal", { style: { display: 'none' }, id: "info-modal", "modal-width": "50", "modal-title": infoModal.title, "close-button-title": "Close", children: jsxRuntimeExports.jsx("div", { dangerouslySetInnerHTML: { __html: infoModal.content } }) })), configurationFields && (jsxRuntimeExports.jsxs("crowdin-modal", { style: { display: 'none' }, id: "settings-modal", "modal-width": "65", "modal-title": "Settings", "close-button-title": "Close", children: [jsxRuntimeExports.jsx("div", { className: "loader hidden", children: jsxRuntimeExports.jsx("crowdin-progress-indicator", {}) }), jsxRuntimeExports.jsx("div", { id: "modal-content", children: jsxRuntimeExports.jsx("crowdin-tabs", { "tabs-config": JSON.stringify(configurationFields.map((f) => f.name)), "active-tab": "1", children: configurationFields.map((tab, tabIndex) => (jsxRuntimeExports.jsx("div", { slot: `tab-${tabIndex + 1}`, children: jsxRuntimeExports.jsx("div", { className: "crowdin-form", children: tab.fields.map((field) => (jsxRuntimeExports.jsxs(reactExports.Fragment, { children: [renderConfigField(field, settingsFieldChange), jsxRuntimeExports.jsx("div", { style: { padding: '8px' }, ...(field.dependencySettings
|
|
2284
|
-
? { 'data-dependency': field.dependencySettings }
|
|
2285
|
-
: {}) })] }, field.key))) }) }, tabIndex))) }) }), jsxRuntimeExports.jsx("div", { slot: "footer", children: jsxRuntimeExports.jsx("crowdin-button", { id: "settings-save-btn", outlined: true, onClick: () => saveSettings(), children: "Save" }) })] })), ((syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.crowdin) || (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration)) && (jsxRuntimeExports.jsxs("crowdin-modal", { style: { display: 'none' }, id: "confirm-schedule-modal", "modal-width": "50", "modal-title": "Synchronization options", "close-button-title": "Close", "close-button": "true", "body-overflow-unset": true, children: [jsxRuntimeExports.jsx("crowdin-checkbox", { id: "selected-files", name: "selected-files", label: "Selected files", class: "hydrated", onChange: () => onChangeAutoSynchronizationOptions() }), jsxRuntimeExports.jsx("crowdin-checkbox", { id: "all-folder-files", name: "all-folder-files", label: "All files in the folder", class: "hydrated", hidden: true, onChange: () => onChangeAutoSynchronizationOptions() }), jsxRuntimeExports.jsx("crowdin-checkbox", { id: "new-files", name: "new-files", label: "New files", class: "hydrated", onChange: () => onChangeAutoSynchronizationOptions() }), jsxRuntimeExports.jsx("div", { slot: "footer", children: jsxRuntimeExports.jsx("crowdin-button", { outlined: true, id: "save-schedule-sync", onClick: () => saveScheduleSync(), children: "Save" }) })] })), jsxRuntimeExports.jsx("crowdin-modal", { style: { display: 'none' }, id: "user-error-detail", "close-button-title": "Close", "close-button": "true" })] }));
|
|
2698
|
+
function showIntegration() {
|
|
2699
|
+
setIsErrorLogsVisible(false);
|
|
2700
|
+
}
|
|
2701
|
+
return (jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsxs("div", { className: "mx-auto max-w-[1420px] px-6 py-4", children: [jsxRuntimeExports.jsx(TopBar, { notice: notice, isNoticeVisible: isNoticeVisible, checkSubscription: checkSubscription, subscriptionInfo: subscriptionInfo, isErrorLogsVisible: isErrorLogsVisible, isManager: isManager, infoModal: infoModal, hasSettings: !!configurationFields, isOwner: isOwner, onCloseNotice: closeAlert, onShowIntegration: showIntegration, onShowErrorLogs: showErrorLogs, onShowPermissions: permissions.showPermissionsDialog, onOpenInfoModal: () => openModal(infoModalRef.current), onOpenSettings: () => {
|
|
2702
|
+
openModal(settingsModalRef.current);
|
|
2703
|
+
settings.fillSettingsForm();
|
|
2704
|
+
}, onLogout: integrationLogout }), jsxRuntimeExports.jsx(IntegrationView, { appComponentRef: appComponent, userErrorsTableRef: userErrorsTableRef, name: name, isErrorLogsVisible: isErrorLogsVisible, syncNewElements: syncNewElements, withCronSync: withCronSync, webhooks: webhooks, integrationOneLevelFetching: integrationOneLevelFetching, integrationSearchListener: integrationSearchListener, integrationPagination: integrationPagination, filtering: filtering, integrationButtonMenuItems: integrationButtonMenuItems, crowdinButtonMenuItems: crowdinButtonMenuItems })] }), jsxRuntimeExports.jsx("crowdin-toasts", {}), jsxRuntimeExports.jsx("crowdin-async-progress", { ref: asyncProgressRef, cancelAsyncAction: "" }), jsxRuntimeExports.jsx(SubscriptionModal, { modalRef: subscriptionModal, subscriptionLink: subscriptionLink, name: name, onLogout: integrationLogout }), jsxRuntimeExports.jsx(PermissionsModal, { modalRef: permissionsModalRef, usersSelectRef: permissions.usersSelectRef, isLoading: permissions.isLoading, permissionUserOptions: permissions.permissionUserOptions, isConfirmVisible: permissions.isPermissionsConfirmVisible, permissionsSummary: permissions.permissionsSummary, hasOrganization: hasOrganization, zenModeUrl: zenModeUrl, onSave: permissions.inviteUsers }), excludedTargetLanguages && (jsxRuntimeExports.jsx(ExcludedLanguagesModal, { modalRef: syncOps.languageModalRef, languageSelectRef: syncOps.languageSelectRef, languageModalState: syncOps.languageModalState, onUpdateTargetLanguages: syncOps.updateCrowdinFilesTargetLanguages, onSyncToCrowdin: syncOps.uploadFilesToCrowdinWithExcludedLanguages })), infoModal && jsxRuntimeExports.jsx(InfoModal, { modalRef: infoModalRef, infoModal: infoModal }), configurationFields && (jsxRuntimeExports.jsx(SettingsModal, { modalRef: settingsModalRef, isLoading: settings.isLoading, configurationFields: configurationFields, isSaveDisabled: settings.isSettingsSaveDisabled, settingsFieldChange: settings.settingsFieldChange, registerSettingsField: settings.registerSettingsField, onSave: settings.saveSettings })), ((syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.crowdin) || (syncNewElements === null || syncNewElements === void 0 ? void 0 : syncNewElements.integration)) && (jsxRuntimeExports.jsx(ScheduleModal, { modalRef: scheduleModalRef, selectedFilesCheckboxRef: schedule.selectedFilesCheckboxRef, allFolderFilesCheckboxRef: schedule.allFolderFilesCheckboxRef, newFilesCheckboxRef: schedule.newFilesCheckboxRef, scheduleModalState: schedule.scheduleModalState, isSaveDisabled: schedule.isScheduleSaveDisabled, onChangeOptions: schedule.onChangeAutoSynchronizationOptions, onSave: schedule.saveScheduleSync })), jsxRuntimeExports.jsx(UserErrorDetailModal, { modalRef: userErrorDetailModalRef, selectedUserError: selectedUserError })] }));
|
|
2286
2705
|
};
|
|
2287
2706
|
|
|
2288
|
-
|
|
2707
|
+
initializeCrowdinIframeContext();
|
|
2708
|
+
const props = readPageProps();
|
|
2709
|
+
clientExports.createRoot(document.getElementById('root')).render(jsxRuntimeExports.jsx(MainPage, { ...props }));
|
|
2289
2710
|
|
|
2290
2711
|
})();
|
|
2291
2712
|
//# sourceMappingURL=main.bundle.js.map
|