@crowdin/app-project-module 0.37.0 → 0.39.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/handlers/integration/crowdin-file-progress.js +15 -3
- package/out/handlers/integration/crowdin-files.js +17 -5
- package/out/handlers/integration/crowdin-update.js +15 -3
- package/out/handlers/integration/integration-data.js +19 -7
- package/out/handlers/integration/integration-login.js +14 -2
- package/out/handlers/integration/integration-logout.js +14 -2
- package/out/handlers/integration/integration-update.js +15 -3
- package/out/handlers/manifest.js +12 -0
- package/out/handlers/user-errors.d.ts +3 -0
- package/out/handlers/user-errors.js +40 -0
- package/out/index.js +5 -0
- package/out/models/index.d.ts +31 -2
- package/out/models/index.js +8 -8
- package/out/static/css/styles.css +49 -1
- package/out/storage/index.d.ts +4 -1
- package/out/storage/mysql.d.ts +4 -1
- package/out/storage/mysql.js +49 -0
- package/out/storage/postgre.d.ts +4 -1
- package/out/storage/postgre.js +49 -0
- package/out/storage/sqlite.d.ts +4 -1
- package/out/storage/sqlite.js +37 -0
- package/out/util/cron.js +2 -0
- package/out/util/logger.d.ts +7 -0
- package/out/util/logger.js +110 -4
- package/out/views/main.handlebars +188 -81
- package/package.json +3 -3
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
</div>
|
|
34
34
|
</crowdin-alert>
|
|
35
35
|
{{/if}}
|
|
36
|
-
<div>
|
|
36
|
+
<div id="buttons">
|
|
37
|
+
<crowdin-button id="show-integration-btn" class="hidden" icon-before="arrow_back" onclick="showIntegration();">Integration</crowdin-button>
|
|
38
|
+
<crowdin-button id="show-error-logs-btn" icon-before="list" onclick="showErrorLogs();">Error logs</crowdin-button>
|
|
37
39
|
{{#if infoModal}}
|
|
38
40
|
<crowdin-button icon-before="info" onclick="infoModal.open();">{{infoModal.title}}</crowdin-button>
|
|
39
41
|
{{/if}}
|
|
@@ -87,6 +89,16 @@
|
|
|
87
89
|
{{/if}}
|
|
88
90
|
>
|
|
89
91
|
</crowdin-simple-integration>
|
|
92
|
+
<div id="user-errors" class="hidden">
|
|
93
|
+
<crowdin-alert title="Error Logs">This table displays the most recent error logs from the past month. Logs older than one month will be automatically deleted.</crowdin-alert>
|
|
94
|
+
<crowdin-show-as-table
|
|
95
|
+
is-loading
|
|
96
|
+
id="user-errors-table"
|
|
97
|
+
is-searchable
|
|
98
|
+
total-records="25"
|
|
99
|
+
search-placeholder="Search something"
|
|
100
|
+
></crowdin-show-as-table>
|
|
101
|
+
</div>
|
|
90
102
|
</div>
|
|
91
103
|
<crowdin-toasts></crowdin-toasts>
|
|
92
104
|
<crowdin-modal id="subscription-modal" modal-width="50" close-button="false">
|
|
@@ -256,6 +268,13 @@
|
|
|
256
268
|
</div>
|
|
257
269
|
</crowdin-modal>
|
|
258
270
|
{{/or}}
|
|
271
|
+
|
|
272
|
+
<crowdin-modal
|
|
273
|
+
id="user-error-detail"
|
|
274
|
+
close-button-title="Close"
|
|
275
|
+
close-button="true"
|
|
276
|
+
>
|
|
277
|
+
</crowdin-modal>
|
|
259
278
|
</body>
|
|
260
279
|
<script type="text/javascript">
|
|
261
280
|
document.body.addEventListener('refreshFilesList', (e) => {
|
|
@@ -491,95 +510,94 @@
|
|
|
491
510
|
}
|
|
492
511
|
|
|
493
512
|
{{#if configurationFields}}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
513
|
+
const settingsModal = document.getElementById('settings-modal');
|
|
514
|
+
const settingsSaveBtn = document.getElementById('settings-save-btn');
|
|
515
|
+
let config = JSON.parse('{{{config}}}');
|
|
516
|
+
|
|
517
|
+
function triggerEvent(el, type) {
|
|
518
|
+
const e = document.createEvent('HTMLEvents');
|
|
519
|
+
e.initEvent(type, false, true);
|
|
520
|
+
el.dispatchEvent(e);
|
|
521
|
+
}
|
|
503
522
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
523
|
+
function fillSettingsForm() {
|
|
524
|
+
Object.entries(config).forEach(([key, value]) => {
|
|
525
|
+
const el = document.getElementById(`${key}-settings`);
|
|
526
|
+
if (el && (value || el.tagName.toLowerCase() === 'crowdin-checkbox')) {
|
|
527
|
+
if (el.tagName.toLowerCase() === 'crowdin-select') {
|
|
528
|
+
if (el.hasAttribute('is-multi')) {
|
|
529
|
+
el.value = JSON.stringify(value);
|
|
530
|
+
} else {
|
|
531
|
+
el.value = JSON.stringify([value]);
|
|
532
|
+
}
|
|
533
|
+
} else if (el.tagName.toLowerCase() === 'crowdin-checkbox') {
|
|
534
|
+
el.checked = !!value;
|
|
511
535
|
} else {
|
|
512
|
-
el.value =
|
|
536
|
+
el.value = value;
|
|
513
537
|
}
|
|
514
|
-
} else if (el.tagName.toLowerCase() === 'crowdin-checkbox') {
|
|
515
|
-
el.checked = !!value;
|
|
516
|
-
} else {
|
|
517
|
-
el.value = value;
|
|
518
|
-
}
|
|
519
538
|
|
|
520
|
-
|
|
521
|
-
}
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
function saveSettings() {
|
|
526
|
-
setLoader();
|
|
527
|
-
const settingsElements = Array.from(document.getElementById('modal-content').children);
|
|
528
|
-
const tags = ['crowdin-checkbox', 'crowdin-select', 'crowdin-input'];
|
|
529
|
-
const configReq = {};
|
|
530
|
-
settingsElements
|
|
531
|
-
.filter(e => tags.includes(e.tagName.toLowerCase()))
|
|
532
|
-
.forEach(e => {
|
|
533
|
-
const key = e.getAttribute('key');
|
|
534
|
-
let value;
|
|
535
|
-
if (e.tagName.toLowerCase() === 'crowdin-select') {
|
|
536
|
-
value = JSON.parse(e.value);
|
|
537
|
-
if (!e.hasAttribute('is-multi')) {
|
|
538
|
-
value = value.length > 0 ? value[0] : undefined;
|
|
539
|
-
}
|
|
540
|
-
} else if (e.tagName.toLowerCase() === 'crowdin-checkbox') {
|
|
541
|
-
value = !!e.checked;
|
|
542
|
-
} else {
|
|
543
|
-
value = e.value;
|
|
539
|
+
triggerEvent(el, 'change');
|
|
544
540
|
}
|
|
545
|
-
configReq[key] = value;
|
|
546
541
|
});
|
|
547
|
-
|
|
548
|
-
checkOrigin()
|
|
549
|
-
.then(restParams => fetch('api/settings' + restParams, {
|
|
550
|
-
method: 'POST',
|
|
551
|
-
headers: { 'Content-Type': 'application/json' },
|
|
552
|
-
body: JSON.stringify({ config: configReq })
|
|
553
|
-
}))
|
|
554
|
-
.then(checkResponse)
|
|
555
|
-
.then(() => {
|
|
556
|
-
showToast('Settings successfully saved');
|
|
557
|
-
config = configReq;
|
|
558
|
-
})
|
|
559
|
-
.catch(e => catchRejection(e, 'Can\'t save settings'))
|
|
560
|
-
.finally(() => {
|
|
561
|
-
unsetLoader();
|
|
562
|
-
settingsSaveBtn.removeAttribute('disabled');
|
|
563
|
-
settingsModal.close();
|
|
564
|
-
{{#if reloadOnConfigSave}}
|
|
565
|
-
getIntegrationData(true);
|
|
566
|
-
getCrowdinData();
|
|
567
|
-
{{/if}}
|
|
568
|
-
});
|
|
569
|
-
}
|
|
542
|
+
}
|
|
570
543
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
544
|
+
function saveSettings() {
|
|
545
|
+
setLoader();
|
|
546
|
+
const settingsElements = Array.from(document.getElementById('modal-content').children);
|
|
547
|
+
const tags = ['crowdin-checkbox', 'crowdin-select', 'crowdin-input'];
|
|
548
|
+
const configReq = {};
|
|
549
|
+
settingsElements
|
|
550
|
+
.filter(e => tags.includes(e.tagName.toLowerCase()))
|
|
551
|
+
.forEach(e => {
|
|
552
|
+
const key = e.getAttribute('key');
|
|
553
|
+
let value;
|
|
554
|
+
if (e.tagName.toLowerCase() === 'crowdin-select') {
|
|
555
|
+
value = JSON.parse(e.value);
|
|
556
|
+
if (!e.hasAttribute('is-multi')) {
|
|
557
|
+
value = value.length > 0 ? value[0] : undefined;
|
|
558
|
+
}
|
|
559
|
+
} else if (e.tagName.toLowerCase() === 'crowdin-checkbox') {
|
|
560
|
+
value = !!e.checked;
|
|
561
|
+
} else {
|
|
562
|
+
value = e.value;
|
|
563
|
+
}
|
|
564
|
+
configReq[key] = value;
|
|
565
|
+
});
|
|
566
|
+
settingsSaveBtn.setAttribute('disabled', true);
|
|
567
|
+
checkOrigin()
|
|
568
|
+
.then(restParams => fetch('api/settings' + restParams, {
|
|
569
|
+
method: 'POST',
|
|
570
|
+
headers: { 'Content-Type': 'application/json' },
|
|
571
|
+
body: JSON.stringify({ config: configReq })
|
|
572
|
+
}))
|
|
573
|
+
.then(checkResponse)
|
|
574
|
+
.then(() => {
|
|
575
|
+
showToast('Settings successfully saved');
|
|
576
|
+
config = configReq;
|
|
577
|
+
})
|
|
578
|
+
.catch(e => catchRejection(e, 'Can\'t save settings'))
|
|
579
|
+
.finally(() => {
|
|
580
|
+
unsetLoader();
|
|
581
|
+
settingsSaveBtn.removeAttribute('disabled');
|
|
582
|
+
settingsModal.close();
|
|
583
|
+
{{#if reloadOnConfigSave}}
|
|
584
|
+
getIntegrationData(true);
|
|
585
|
+
getCrowdinData();
|
|
586
|
+
{{/if}}
|
|
587
|
+
});
|
|
588
|
+
}
|
|
575
589
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
}, 500)
|
|
581
|
-
}
|
|
590
|
+
function setLoader() {
|
|
591
|
+
const loader = document.querySelector('#settings-modal .loader');
|
|
592
|
+
loader.classList.remove('hidden');
|
|
593
|
+
}
|
|
582
594
|
|
|
595
|
+
function unsetLoader() {
|
|
596
|
+
const loader = document.querySelector('#settings-modal .loader');
|
|
597
|
+
setTimeout(function() {
|
|
598
|
+
loader.classList.add('hidden');
|
|
599
|
+
}, 500)
|
|
600
|
+
}
|
|
583
601
|
{{else}}
|
|
584
602
|
const settingsModal = undefined;
|
|
585
603
|
{{/if}}
|
|
@@ -807,6 +825,95 @@
|
|
|
807
825
|
const notice = document.getElementById('notice');
|
|
808
826
|
checkAlert(notice, 'notice');
|
|
809
827
|
{{/if}}
|
|
828
|
+
|
|
829
|
+
function showErrorLogs() {
|
|
830
|
+
document.getElementById('show-error-logs-btn').classList.add('hidden');
|
|
831
|
+
document.getElementById('show-integration-btn').classList.remove('hidden');
|
|
832
|
+
|
|
833
|
+
appComponent.classList.add('hidden');
|
|
834
|
+
document.getElementById('user-errors').classList.remove('hidden');
|
|
835
|
+
|
|
836
|
+
checkOrigin()
|
|
837
|
+
.then(restParams => fetch('api/user-errors' + restParams))
|
|
838
|
+
.then(checkResponse)
|
|
839
|
+
.then((res) => {
|
|
840
|
+
const table = document.getElementById('user-errors-table');
|
|
841
|
+
|
|
842
|
+
const clickRow = (field, index, item) => {
|
|
843
|
+
const modal = document.getElementById('user-error-detail');
|
|
844
|
+
modal.open();
|
|
845
|
+
modal.innerHTML = getUserErrorDetail(item);
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
table.setTableConfig && table.setTableConfig({
|
|
849
|
+
defaultSortingColumn: "createdAt",
|
|
850
|
+
defaultSortingDir: "desc",
|
|
851
|
+
headerFields: [
|
|
852
|
+
{
|
|
853
|
+
field: "createdAt",
|
|
854
|
+
name: "Date",
|
|
855
|
+
isSortable: true,
|
|
856
|
+
clickFn: clickRow,
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
field: "action",
|
|
860
|
+
name: "Action",
|
|
861
|
+
clickFn: clickRow,
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
field: "message",
|
|
865
|
+
name: "Message",
|
|
866
|
+
clickFn: clickRow,
|
|
867
|
+
}
|
|
868
|
+
],
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
table.setTableData(JSON.stringify(res));
|
|
872
|
+
table.setAttribute(`is-loading`, false);
|
|
873
|
+
})
|
|
874
|
+
.catch(e => catchRejection(e, 'Can\'t fetch error logs'));
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
function showIntegration() {
|
|
878
|
+
document.getElementById('show-error-logs-btn').classList.remove('hidden');
|
|
879
|
+
document.getElementById('show-integration-btn').classList.add('hidden');
|
|
880
|
+
|
|
881
|
+
appComponent.classList.remove('hidden');
|
|
882
|
+
document.getElementById('user-errors').classList.add('hidden');
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
function getUserErrorDetail(error) {
|
|
886
|
+
const data = JSON.parse(error.data);
|
|
887
|
+
|
|
888
|
+
let html = '<div class="error-detail-table"><table>';
|
|
889
|
+
html += `<tr><td>Action</td><td>${error.action}</td></tr>`;
|
|
890
|
+
html += `<tr><td>Message</td><td>${error.message}</td></tr>`;
|
|
891
|
+
html += `<tr><td>Date/time</td><td>${error.createdAt}</td></tr>`;
|
|
892
|
+
|
|
893
|
+
if (data.requestParams) {
|
|
894
|
+
html += `<tr><td>Method</td><td>${data.requestParams.method}</td></tr>`;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
if (data.responseData) {
|
|
898
|
+
html += `<tr><td>Response Data</td><td><pre>${JSON.stringify(data.responseData, null, 2)}</pre></td></tr>`;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
if (data.appData) {
|
|
902
|
+
if (Array.isArray(data.appData)) {
|
|
903
|
+
html += `<tr><td>App Data</td><td><pre>${JSON.stringify(data.appData, null, 2)}</pre></td></tr>`;
|
|
904
|
+
} else if (typeof data.appData === 'object') {
|
|
905
|
+
for (const key in data.appData) {
|
|
906
|
+
html += `<tr><td>${key.charAt(0).toUpperCase() + key.slice(1)}</td><td><pre>${JSON.stringify(data.appData[key], null, 2)}</pre></td></tr>`;
|
|
907
|
+
}
|
|
908
|
+
} else {
|
|
909
|
+
html += `<tr><td>App Data</td><td>${data.appData}</td></tr>`;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
html += '</table></div>';
|
|
914
|
+
|
|
915
|
+
return html;
|
|
916
|
+
}
|
|
810
917
|
</script>
|
|
811
918
|
|
|
812
919
|
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crowdin/app-project-module",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.0",
|
|
4
4
|
"description": "Module that generates for you all common endpoints for serving standalone Crowdin App",
|
|
5
5
|
"main": "out/index.js",
|
|
6
6
|
"types": "out/index.d.ts",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@aws-sdk/client-s3": "^3.423.0",
|
|
18
18
|
"@aws-sdk/s3-request-presigner": "^3.423.0",
|
|
19
|
-
"@crowdin/crowdin-apps-functions": "0.
|
|
20
|
-
"@crowdin/logs-formatter": "^2.0.
|
|
19
|
+
"@crowdin/crowdin-apps-functions": "0.6.0",
|
|
20
|
+
"@crowdin/logs-formatter": "^2.0.6",
|
|
21
21
|
"@godaddy/terminus": "^4.12.1",
|
|
22
22
|
"@types/pg": "^8.10.3",
|
|
23
23
|
"amqplib": "^0.10.3",
|