@crowdin/app-project-module 0.48.0 → 0.50.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/modules/integration/util/defaults.js +15 -0
- package/package.json +11 -11
- package/out/static/css/styles.css +0 -235
- package/out/static/js/dependent.js +0 -306
- package/out/static/js/form.js +0 -112
- package/out/static/js/main.js +0 -94
- package/out/static/js/polyfills/fetch.js +0 -494
- package/out/static/js/polyfills/promise.js +0 -375
- package/out/views/error.handlebars +0 -31
- package/out/views/form.handlebars +0 -30
- package/out/views/install.handlebars +0 -16
- package/out/views/login.handlebars +0 -250
- package/out/views/main.handlebars +0 -1153
- package/out/views/oauth.handlebars +0 -4
- package/out/views/partials/head.handlebars +0 -48
- package/out/views/subscription.handlebars +0 -26
|
@@ -1,1153 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
{{> head}}
|
|
4
|
-
|
|
5
|
-
<body>
|
|
6
|
-
<div class="i_w">
|
|
7
|
-
<div class="top">
|
|
8
|
-
{{#if notice}}
|
|
9
|
-
<crowdin-alert
|
|
10
|
-
id="notice"
|
|
11
|
-
title="{{notice.title}}"
|
|
12
|
-
{{#unless notice.icon}}
|
|
13
|
-
no-icon="true"
|
|
14
|
-
{{/unless}}
|
|
15
|
-
{{#if notice.type}}
|
|
16
|
-
type={{notice.type}}
|
|
17
|
-
{{/if}}
|
|
18
|
-
style="display: none; margin-bottom: 12px;"
|
|
19
|
-
>
|
|
20
|
-
<div class="box-center">
|
|
21
|
-
<p class="m-0">{{{notice.content}}}</p>
|
|
22
|
-
</div>
|
|
23
|
-
{{#if notice.close}}
|
|
24
|
-
<crowdin-button onclick="closeAlert(this, 'notice')" class="dismiss-alert" icon>close</crowdin-button>
|
|
25
|
-
{{/if}}
|
|
26
|
-
</crowdin-alert>
|
|
27
|
-
{{/if}}
|
|
28
|
-
{{#if checkSubscription}}
|
|
29
|
-
<crowdin-alert id="subscription-info" no-icon="true" type="warning" style="display: none; margin-bottom: 12px;">
|
|
30
|
-
<div class="box-center">
|
|
31
|
-
<p class="m-0"></p>
|
|
32
|
-
<crowdin-button class="ml-1" primary onclick="window.open(subscriptionLink,'_blank')">Subscribe</crowdin-button>
|
|
33
|
-
</div>
|
|
34
|
-
</crowdin-alert>
|
|
35
|
-
{{/if}}
|
|
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>
|
|
39
|
-
{{#if infoModal}}
|
|
40
|
-
<crowdin-button icon-before="info" onclick="infoModal.open();">{{infoModal.title}}</crowdin-button>
|
|
41
|
-
{{/if}}
|
|
42
|
-
{{#if configurationFields}}
|
|
43
|
-
<crowdin-button icon-before="settings" onclick="settingsModal.open();fillSettingsForm();">Settings</crowdin-button>
|
|
44
|
-
{{/if}}
|
|
45
|
-
<crowdin-button icon-before="account_circle" onclick="integrationLogout()">Log out</crowdin-button>
|
|
46
|
-
</div>
|
|
47
|
-
{{#if uploadTranslations}}
|
|
48
|
-
<crowdin-alert id="translation-info" no-icon="true" style="display: none;">
|
|
49
|
-
<div class="box-center">
|
|
50
|
-
<p class="info-text">
|
|
51
|
-
We recommend importing existing translations into your Crowdin project for newly uploaded source content.
|
|
52
|
-
Please note that translations imported for non-key-value formats may require additional review.
|
|
53
|
-
Read more about <crowdin-a href="https://support.crowdin.com/uploading-translations/" target="_blank">Uploading Translations</crowdin-a>.
|
|
54
|
-
</p>
|
|
55
|
-
</div>
|
|
56
|
-
<crowdin-button onclick="closeAlert(this)" class="dismiss-alert" icon>close</crowdin-button>
|
|
57
|
-
</crowdin-alert>
|
|
58
|
-
{{/if}}
|
|
59
|
-
</div>
|
|
60
|
-
<crowdin-simple-integration
|
|
61
|
-
async-progress
|
|
62
|
-
{{#if syncNewElements.crowdin}}
|
|
63
|
-
skip-crowdin-auto-schedule
|
|
64
|
-
{{/if}}
|
|
65
|
-
{{#if syncNewElements.integration}}
|
|
66
|
-
skip-integration-auto-schedule
|
|
67
|
-
{{/if}}
|
|
68
|
-
{{#or withCronSync.crowdin webhooks.crowdin}}
|
|
69
|
-
crowdin-schedule="true"
|
|
70
|
-
{{/or}}
|
|
71
|
-
{{#or withCronSync.integration webhooks.integration}}
|
|
72
|
-
integration-schedule="true"
|
|
73
|
-
{{/or}}
|
|
74
|
-
{{#if integrationOneLevelFetching}}
|
|
75
|
-
integration-one-level-fetching="true"
|
|
76
|
-
{{/if}}
|
|
77
|
-
{{#if integrationSearchListener}}
|
|
78
|
-
allow-filter-change-listener="true"
|
|
79
|
-
{{/if}}
|
|
80
|
-
{{#if integrationPagination}}
|
|
81
|
-
integration-load-more-files="true"
|
|
82
|
-
{{/if}}
|
|
83
|
-
integration-name="{{name}}"
|
|
84
|
-
integration-logo="logo.png"
|
|
85
|
-
{{#if uploadTranslations}}
|
|
86
|
-
integration-button-menu-items='[{"label":"Upload Translations", "action":"uploadTranslations"}]'
|
|
87
|
-
{{/if}}
|
|
88
|
-
{{#if filtering.crowdinLanguages}}
|
|
89
|
-
crowdin-filter
|
|
90
|
-
{{/if}}
|
|
91
|
-
>
|
|
92
|
-
</crowdin-simple-integration>
|
|
93
|
-
<div id="user-errors" class="hidden">
|
|
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
|
-
<crowdin-alert>This table displays the most recent error logs from the past month. Logs older than one month will be automatically deleted.</crowdin-alert>
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
104
|
-
<crowdin-toasts></crowdin-toasts>
|
|
105
|
-
<crowdin-async-progress
|
|
106
|
-
cancelAsyncAction=""
|
|
107
|
-
></crowdin-async-progress>
|
|
108
|
-
<crowdin-modal id="subscription-modal" modal-width="50" close-button="false">
|
|
109
|
-
<div>
|
|
110
|
-
<crowdin-alert type="warning">Subscribe to continue using the {{name}} app.</crowdin-alert>
|
|
111
|
-
</div>
|
|
112
|
-
<div slot="footer">
|
|
113
|
-
<crowdin-button primary onclick="window.open(subscriptionLink,'_blank')">Subscribe</crowdin-button>
|
|
114
|
-
<crowdin-button outlined onclick="window.open('https://crowdin.com/contacts','_blank')">Contact us</crowdin-button>
|
|
115
|
-
<crowdin-button class="ml-10" secondary onclick="integrationLogout()">Log out</crowdin-button>
|
|
116
|
-
</div>
|
|
117
|
-
</crowdin-modal>
|
|
118
|
-
{{#if infoModal}}
|
|
119
|
-
<crowdin-modal id="info-modal" modal-width="50" modal-title="{{infoModal.title}}" close-button-title="Close">
|
|
120
|
-
<div>
|
|
121
|
-
{{{infoModal.content}}}
|
|
122
|
-
</div>
|
|
123
|
-
</crowdin-modal>
|
|
124
|
-
{{/if}}
|
|
125
|
-
{{#if configurationFields}}
|
|
126
|
-
<crowdin-modal
|
|
127
|
-
id="settings-modal"
|
|
128
|
-
body-overflow-unset="{{#checkLength configurationFields 3}}false{{else}}true{{/checkLength}}"
|
|
129
|
-
modal-width="50"
|
|
130
|
-
modal-title="Settings"
|
|
131
|
-
close-button-title="Close"
|
|
132
|
-
>
|
|
133
|
-
<div class="loader hidden">
|
|
134
|
-
<crowdin-progress-indicator></crowdin-progress-indicator>
|
|
135
|
-
</div>
|
|
136
|
-
<div id="modal-content">
|
|
137
|
-
{{#each configurationFields}}
|
|
138
|
-
{{#if key}}
|
|
139
|
-
{{#ifeq type "checkbox"}}
|
|
140
|
-
<crowdin-checkbox
|
|
141
|
-
id="{{key}}-settings"
|
|
142
|
-
key="{{key}}"
|
|
143
|
-
label="{{label}}"
|
|
144
|
-
value="false"
|
|
145
|
-
use-switch
|
|
146
|
-
{{#if helpText}}
|
|
147
|
-
help-text="{{helpText}}"
|
|
148
|
-
{{/if}}
|
|
149
|
-
{{#if helpTextHtml}}
|
|
150
|
-
help-text-html="{{helpTextHtml}}"
|
|
151
|
-
{{/if}}
|
|
152
|
-
{{#ifeq defaultValue true}}
|
|
153
|
-
checked="{{defaultValue}}"
|
|
154
|
-
{{/ifeq}}
|
|
155
|
-
{{#if dependencySettings}}
|
|
156
|
-
data-dependency="{{dependencySettings}}"
|
|
157
|
-
{{/if}}
|
|
158
|
-
>
|
|
159
|
-
</crowdin-checkbox>
|
|
160
|
-
{{/ifeq}}
|
|
161
|
-
{{#ifeq type "select"}}
|
|
162
|
-
<crowdin-select
|
|
163
|
-
{{#if isMulti}}
|
|
164
|
-
is-multi
|
|
165
|
-
close-on-select="false"
|
|
166
|
-
{{/if}}
|
|
167
|
-
{{#if isSearchable}}
|
|
168
|
-
is-searchable
|
|
169
|
-
{{/if}}
|
|
170
|
-
id="{{key}}-settings"
|
|
171
|
-
key="{{key}}"
|
|
172
|
-
label="{{label}}"
|
|
173
|
-
{{#if helpText}}
|
|
174
|
-
help-text="{{helpText}}"
|
|
175
|
-
{{/if}}
|
|
176
|
-
{{#if helpTextHtml}}
|
|
177
|
-
help-text-html="{{helpTextHtml}}"
|
|
178
|
-
{{/if}}
|
|
179
|
-
{{#if dependencySettings}}
|
|
180
|
-
data-dependency="{{dependencySettings}}"
|
|
181
|
-
{{/if}}
|
|
182
|
-
>
|
|
183
|
-
{{#each options}}
|
|
184
|
-
<option
|
|
185
|
-
{{#if ../defaultValue}}
|
|
186
|
-
{{#ifeq ../defaultValue value}} selected {{/ifeq}}
|
|
187
|
-
{{#in ../defaultValue value}} selected {{/in}}
|
|
188
|
-
{{/if}}
|
|
189
|
-
value="{{value}}">{{label}}
|
|
190
|
-
</option>
|
|
191
|
-
{{/each}}
|
|
192
|
-
</crowdin-select>
|
|
193
|
-
{{/ifeq}}
|
|
194
|
-
{{#ifeq type "text"}}
|
|
195
|
-
<crowdin-input
|
|
196
|
-
id="{{key}}-settings"
|
|
197
|
-
label="{{label}}"
|
|
198
|
-
key="{{key}}"
|
|
199
|
-
with-fixed-height
|
|
200
|
-
{{#if helpText}}
|
|
201
|
-
help-text="{{helpText}}"
|
|
202
|
-
{{/if}}
|
|
203
|
-
{{#if helpTextHtml}}
|
|
204
|
-
help-text-html="{{helpTextHtml}}"
|
|
205
|
-
{{/if}}
|
|
206
|
-
{{#if dependencySettings}}
|
|
207
|
-
data-dependency="{{dependencySettings}}"
|
|
208
|
-
{{/if}}
|
|
209
|
-
value="{{#if defaultValue}}{{defaultValue}}{{/if}}"
|
|
210
|
-
>
|
|
211
|
-
</crowdin-input>
|
|
212
|
-
{{/ifeq}}
|
|
213
|
-
{{#ifeq type "textarea"}}
|
|
214
|
-
<crowdin-textarea
|
|
215
|
-
id="{{key}}-settings"
|
|
216
|
-
label="{{label}}"
|
|
217
|
-
key="{{key}}"
|
|
218
|
-
{{#if helpText}}
|
|
219
|
-
help-text="{{helpText}}"
|
|
220
|
-
{{/if}}
|
|
221
|
-
{{#if helpTextHtml}}
|
|
222
|
-
help-text-html="{{helpTextHtml}}"
|
|
223
|
-
{{/if}}
|
|
224
|
-
{{#if dependencySettings}}
|
|
225
|
-
data-dependency="{{dependencySettings}}"
|
|
226
|
-
{{/if}}
|
|
227
|
-
value="{{#if defaultValue}}{{defaultValue}}{{/if}}">
|
|
228
|
-
</crowdin-textarea>
|
|
229
|
-
{{/ifeq}}
|
|
230
|
-
{{else}}
|
|
231
|
-
{{#if labelHtml}}
|
|
232
|
-
<crowdin-p
|
|
233
|
-
{{#if dependencySettings}}
|
|
234
|
-
data-dependency="{{dependencySettings}}"
|
|
235
|
-
{{/if}}
|
|
236
|
-
>
|
|
237
|
-
{{{labelHtml}}}
|
|
238
|
-
</crowdin-p>
|
|
239
|
-
{{else}}
|
|
240
|
-
<crowdin-p
|
|
241
|
-
{{#if dependencySettings}}
|
|
242
|
-
data-dependency="{{dependencySettings}}"
|
|
243
|
-
{{/if}}
|
|
244
|
-
>
|
|
245
|
-
{{label}}
|
|
246
|
-
</crowdin-p>
|
|
247
|
-
{{/if}}
|
|
248
|
-
{{/if}}
|
|
249
|
-
<div
|
|
250
|
-
style="padding: 8px"
|
|
251
|
-
{{#if dependencySettings}}
|
|
252
|
-
data-dependency="{{dependencySettings}}"
|
|
253
|
-
{{/if}}
|
|
254
|
-
></div>
|
|
255
|
-
{{/each}}
|
|
256
|
-
</div>
|
|
257
|
-
<div slot="footer">
|
|
258
|
-
<crowdin-button id="settings-save-btn" outlined onclick="saveSettings()">Save</crowdin-button>
|
|
259
|
-
</div>
|
|
260
|
-
</crowdin-modal>
|
|
261
|
-
{{/if}}
|
|
262
|
-
{{#or syncNewElements.crowdin syncNewElements.integration}}
|
|
263
|
-
<crowdin-modal
|
|
264
|
-
id="confirm-schedule-modal"
|
|
265
|
-
modal-width="50"
|
|
266
|
-
modal-title="Synchronization options"
|
|
267
|
-
close-button-title="Close"
|
|
268
|
-
close-button="true"
|
|
269
|
-
body-overflow-unset
|
|
270
|
-
>
|
|
271
|
-
<crowdin-checkbox
|
|
272
|
-
id="selected-files"
|
|
273
|
-
name="selected-files"
|
|
274
|
-
label="Selected files"
|
|
275
|
-
class="hydrated"
|
|
276
|
-
onchange="onChangeAutoSynchronizationOptions(this)"
|
|
277
|
-
>
|
|
278
|
-
</crowdin-checkbox>
|
|
279
|
-
<crowdin-checkbox
|
|
280
|
-
id="new-files"
|
|
281
|
-
name="new-files"
|
|
282
|
-
label="New files"
|
|
283
|
-
class="hydrated"
|
|
284
|
-
onchange="onChangeAutoSynchronizationOptions(this)"
|
|
285
|
-
>
|
|
286
|
-
</crowdin-checkbox>
|
|
287
|
-
<div slot="footer">
|
|
288
|
-
<crowdin-button outlined id="save-schedule-sync" onclick="saveScheduleSync()">Save</crowdin-button>
|
|
289
|
-
</div>
|
|
290
|
-
</crowdin-modal>
|
|
291
|
-
{{/or}}
|
|
292
|
-
|
|
293
|
-
<crowdin-modal
|
|
294
|
-
id="user-error-detail"
|
|
295
|
-
close-button-title="Close"
|
|
296
|
-
close-button="true"
|
|
297
|
-
>
|
|
298
|
-
</crowdin-modal>
|
|
299
|
-
</body>
|
|
300
|
-
<script type="text/javascript">
|
|
301
|
-
document.body.addEventListener('refreshFilesList', (e) => {
|
|
302
|
-
if (e.detail.refreshIntegration) {
|
|
303
|
-
getIntegrationData(true);
|
|
304
|
-
} else if (e.detail.refreshCrowdin) {
|
|
305
|
-
getCrowdinData();
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
document.body.addEventListener('crowdinFilesFolderToggled', (event) => {
|
|
309
|
-
if (event.detail.componentId === 'crowdin-files' && event.detail.isOpen && event.detail.type === '1') {
|
|
310
|
-
getFileProgress(event.detail.id);
|
|
311
|
-
}
|
|
312
|
-
{{#if integrationOneLevelFetching}}
|
|
313
|
-
if (event.detail.componentId === 'integration-files' && event.detail.isOpen) {
|
|
314
|
-
getIntegrationData(false, event.detail.id);
|
|
315
|
-
}
|
|
316
|
-
{{/if}}
|
|
317
|
-
});
|
|
318
|
-
document.body.addEventListener('uploadFilesToCrowdin', uploadFilesToCrowdin);
|
|
319
|
-
document.body.addEventListener('uploadFilesToIntegration', uploadFilesToIntegration);
|
|
320
|
-
document.body.addEventListener('cancelAsyncAction', (e) => {
|
|
321
|
-
cancelJob(e.detail);
|
|
322
|
-
});
|
|
323
|
-
{{#if integrationSearchListener}}
|
|
324
|
-
document.body.addEventListener("integrationFilterChange", (event) => {
|
|
325
|
-
getIntegrationData(false, 0, event.detail);
|
|
326
|
-
})
|
|
327
|
-
{{/if}}
|
|
328
|
-
const appComponent = document.querySelector('crowdin-simple-integration');
|
|
329
|
-
const subscriptionModal = document.getElementById('subscription-modal');
|
|
330
|
-
|
|
331
|
-
const folderType = '0';
|
|
332
|
-
const fileType = '1';
|
|
333
|
-
const branchType = '2';
|
|
334
|
-
|
|
335
|
-
const JOB_TYPE = {
|
|
336
|
-
updateCrowdin: 'updateCrowdin',
|
|
337
|
-
updateIntegration: 'updateIntegration',
|
|
338
|
-
integrationSyncSettingsSave: 'integrationSyncSettingsSave',
|
|
339
|
-
crowdinSyncSettingsSave: 'crowdinSyncSettingsSave',
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
const JOB_STATUS = {
|
|
343
|
-
created: 'created',
|
|
344
|
-
inProgress: 'inProgress',
|
|
345
|
-
failed: 'failed',
|
|
346
|
-
canceled: 'canceled',
|
|
347
|
-
finished: 'finished',
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
const silentJobs = [
|
|
351
|
-
JOB_TYPE.integrationSyncSettingsSave,
|
|
352
|
-
JOB_TYPE.crowdinSyncSettingsSave,
|
|
353
|
-
];
|
|
354
|
-
|
|
355
|
-
const asyncJobs = {};
|
|
356
|
-
|
|
357
|
-
let project = {};
|
|
358
|
-
let crowdinData = [];
|
|
359
|
-
|
|
360
|
-
getCrowdinData();
|
|
361
|
-
getIntegrationData();
|
|
362
|
-
getActiveJobs();
|
|
363
|
-
|
|
364
|
-
function integrationLogout() {
|
|
365
|
-
checkOrigin()
|
|
366
|
-
.then(queryParams => fetch(`api/logout${queryParams}`, { method: 'POST' }))
|
|
367
|
-
.then(checkResponse)
|
|
368
|
-
.then(reloadLocation)
|
|
369
|
-
.then(localStorage.removeItem('revised_{{name}}'))
|
|
370
|
-
.catch(e => catchRejection(e, 'Looks like you are not logged in'));
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
function getCrowdinData() {
|
|
374
|
-
appComponent.setAttribute('is-crowdin-loading', true);
|
|
375
|
-
checkOrigin()
|
|
376
|
-
.then(restParams => fetch('api/crowdin/files' + restParams))
|
|
377
|
-
.then(checkResponse)
|
|
378
|
-
.then((res) => {
|
|
379
|
-
const tree = res.map(e => {
|
|
380
|
-
const item = {
|
|
381
|
-
parent_id: e.parentId ? e.parentId : '0',
|
|
382
|
-
name: e.name,
|
|
383
|
-
id: e.id,
|
|
384
|
-
customContent: e.customContent,
|
|
385
|
-
labels: e.labels,
|
|
386
|
-
};
|
|
387
|
-
if (e.type) {
|
|
388
|
-
item.type = e.type;
|
|
389
|
-
item.node_type = fileType;
|
|
390
|
-
} else {
|
|
391
|
-
item.node_type = e.nodeType || folderType;
|
|
392
|
-
}
|
|
393
|
-
return item;
|
|
394
|
-
});
|
|
395
|
-
crowdinData = tree;
|
|
396
|
-
appComponent.setCrowdinFilesData(tree);
|
|
397
|
-
return checkOrigin();
|
|
398
|
-
})
|
|
399
|
-
.then(restParams => fetch('api/crowdin/project' + restParams))
|
|
400
|
-
.then(checkResponse)
|
|
401
|
-
.then((res) => {
|
|
402
|
-
project = res;
|
|
403
|
-
const languagesSorted = project.targetLanguages.sort((a, b) => a.name.localeCompare(b.name));
|
|
404
|
-
appComponent.setCrowdinLanguagesData(languagesSorted)
|
|
405
|
-
})
|
|
406
|
-
{{#or withCronSync webhooks}}
|
|
407
|
-
.then(() => getSyncSettings('crowdin'))
|
|
408
|
-
{{/or}}
|
|
409
|
-
.catch(e => catchRejection(e, 'Can\'t fetch Crowdin data'))
|
|
410
|
-
.finally(() => (appComponent.setAttribute('is-crowdin-loading', false)));
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
function getIntegrationData(hardReload = false, parentId = '', search = '', page = 0) {
|
|
414
|
-
appComponent.setAttribute('is-integration-loading', true);
|
|
415
|
-
checkOrigin()
|
|
416
|
-
.then(restParams => fetch(`api/integration/data${restParams}&parent_id=${encodeURIComponent(parentId)}&search=${encodeURIComponent(search)}&page=${page}`))
|
|
417
|
-
.then(checkResponse)
|
|
418
|
-
.then((res) => {
|
|
419
|
-
const files = res.data;
|
|
420
|
-
const stopPagination = res.stopPagination;
|
|
421
|
-
const tree = files.map(e => {
|
|
422
|
-
const item = {
|
|
423
|
-
parent_id: e.parentId ? e.parentId : '0',
|
|
424
|
-
name: e.name,
|
|
425
|
-
id: e.id,
|
|
426
|
-
customContent: e.customContent,
|
|
427
|
-
labels: e.labels,
|
|
428
|
-
};
|
|
429
|
-
if (e.type) {
|
|
430
|
-
item.type = e.type;
|
|
431
|
-
item.node_type = fileType;
|
|
432
|
-
} else {
|
|
433
|
-
item.node_type = e.nodeType || folderType;
|
|
434
|
-
}
|
|
435
|
-
return item;
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
const appIntegrationFiles = appComponent.querySelector('#integration-files');
|
|
439
|
-
if (hardReload) {
|
|
440
|
-
appComponent.setIntegrationFilesData(tree);
|
|
441
|
-
} else if (tree.length) {
|
|
442
|
-
appComponent.pushIntegrationFilesData(tree).then(() => {
|
|
443
|
-
appIntegrationFiles.getSelected().then(selection => {
|
|
444
|
-
selection = selection?.filter((node) => node);
|
|
445
|
-
if (!selection?.length) {
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
const selectedIds = selection.map(({id}) => id.toString());
|
|
450
|
-
tree.forEach((node) => {
|
|
451
|
-
selectedIds.includes(node.parent_id.toString()) && selectedIds.push(node.id.toString());
|
|
452
|
-
});
|
|
453
|
-
appIntegrationFiles.setSelected(selectedIds);
|
|
454
|
-
});
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
{{#if integrationPagination}}
|
|
458
|
-
if (stopPagination) {
|
|
459
|
-
appIntegrationFiles.setAttribute('load-more-disabled', true);
|
|
460
|
-
} else {
|
|
461
|
-
appIntegrationFiles.setAttribute('load-more-disabled', false);
|
|
462
|
-
}
|
|
463
|
-
{{/if}}
|
|
464
|
-
if (search) {
|
|
465
|
-
const openIds = files.filter(e => !e.type).map(e => e.id);
|
|
466
|
-
appComponent.setIntegrationOpenedFolders(openIds);
|
|
467
|
-
}
|
|
468
|
-
})
|
|
469
|
-
{{#or withCronSync webhooks}}
|
|
470
|
-
.then(() => getSyncSettings('integration'))
|
|
471
|
-
{{/or}}
|
|
472
|
-
.catch(e => catchRejection(e, 'Can\'t fetch {{name}} templates'))
|
|
473
|
-
.finally(() => (appComponent.setAttribute('is-integration-loading', false)));
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
function getSyncSettings(provider) {
|
|
477
|
-
checkOrigin()
|
|
478
|
-
.then(restParams => fetch(`/api/sync-settings/${provider}` + restParams))
|
|
479
|
-
.then(checkResponse)
|
|
480
|
-
.then((res) => {
|
|
481
|
-
if (provider === 'crowdin') {
|
|
482
|
-
{{#if syncNewElements.crowdin}}
|
|
483
|
-
appComponent.setCrowdinScheduleSync(res, true, true);
|
|
484
|
-
{{else}}
|
|
485
|
-
appComponent.setCrowdinScheduleSync(res);
|
|
486
|
-
{{/if}}
|
|
487
|
-
} else {
|
|
488
|
-
{{#if syncNewElements.integration}}
|
|
489
|
-
appComponent.setIntegrationScheduleSync(res, true, true);
|
|
490
|
-
{{else}}
|
|
491
|
-
appComponent.setIntegrationScheduleSync(res);
|
|
492
|
-
{{/if}}
|
|
493
|
-
|
|
494
|
-
}
|
|
495
|
-
})
|
|
496
|
-
.catch(e => catchRejection(e, 'Can\'t fetch file progress'));
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
function getFileProgress(fileId) {
|
|
500
|
-
checkOrigin()
|
|
501
|
-
.then(restParams => fetch(`api/crowdin/file-progress/${fileId}` + restParams))
|
|
502
|
-
.then(checkResponse)
|
|
503
|
-
.then((res) => (appComponent.addCrowdinFileProgress(res)))
|
|
504
|
-
.catch(e => catchRejection(e, 'Can\'t fetch file progress'));
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
function uploadFilesToCrowdin(event) {
|
|
508
|
-
let files = [];
|
|
509
|
-
let uploadTranslations = false;
|
|
510
|
-
if (event.detail.action === 'uploadTranslations') {
|
|
511
|
-
files = event.detail.files;
|
|
512
|
-
uploadTranslations = true;
|
|
513
|
-
} else {
|
|
514
|
-
files = event.detail;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
if (event.detail.length === 0) {
|
|
518
|
-
showToast('Select templates which will be pushed to Crowdin');
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
appComponent.setAttribute('is-to-crowdin-process', true);
|
|
522
|
-
let req;
|
|
523
|
-
{{#if integrationOneLevelFetching}}
|
|
524
|
-
req = files.map(f => ({
|
|
525
|
-
name: f.name,
|
|
526
|
-
id: f.id,
|
|
527
|
-
type: f.type,
|
|
528
|
-
parentId: f.parent_id,
|
|
529
|
-
nodeType: f.node_type
|
|
530
|
-
}));
|
|
531
|
-
{{else}}
|
|
532
|
-
req = files.filter(f => f.node_type !== folderType).map(f => ({
|
|
533
|
-
name: f.name,
|
|
534
|
-
id: f.id,
|
|
535
|
-
type: f.type,
|
|
536
|
-
parentId: f.parent_id
|
|
537
|
-
}));
|
|
538
|
-
{{/if}}
|
|
539
|
-
checkOrigin()
|
|
540
|
-
.then(restParams => fetch(`api/crowdin/update${restParams}&uploadTranslations=${uploadTranslations}`, {
|
|
541
|
-
method: 'POST',
|
|
542
|
-
headers: { 'Content-Type': 'application/json' },
|
|
543
|
-
body: JSON.stringify(req)
|
|
544
|
-
}))
|
|
545
|
-
.then(checkResponse)
|
|
546
|
-
.then((res) => {
|
|
547
|
-
checkJob({
|
|
548
|
-
jobId: res?.jobId,
|
|
549
|
-
jobType: JOB_TYPE.updateCrowdin,
|
|
550
|
-
})
|
|
551
|
-
})
|
|
552
|
-
.catch(e => catchRejection(e, 'Can\'t upload templates to Crowdin'))
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
function getActiveJobs() {
|
|
556
|
-
checkOrigin()
|
|
557
|
-
.then(restParams => fetch(`api/jobs${restParams}`))
|
|
558
|
-
.then(checkResponse)
|
|
559
|
-
.then((jobs) => {
|
|
560
|
-
if (!Array.isArray(jobs)) {
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
jobs.forEach((job) => {
|
|
565
|
-
switch (job.type) {
|
|
566
|
-
case JOB_TYPE.updateCrowdin:
|
|
567
|
-
appComponent.setAttribute('is-to-crowdin-process', true);
|
|
568
|
-
break;
|
|
569
|
-
case JOB_TYPE.updateIntegration:
|
|
570
|
-
appComponent.setAttribute('is-to-integration-process', true);
|
|
571
|
-
break;
|
|
572
|
-
case JOB_TYPE.crowdinSyncSettingsSave:
|
|
573
|
-
appComponent.setAttribute(`is-crowdin-sync-settings-in-progress`, true)
|
|
574
|
-
break;
|
|
575
|
-
case JOB_TYPE.integrationSyncSettingsSave:
|
|
576
|
-
appComponent.setAttribute(`is-integration-sync-settings-in-progress`, true)
|
|
577
|
-
break;
|
|
578
|
-
default:
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
checkJob({
|
|
582
|
-
jobId: job.id,
|
|
583
|
-
jobType: job.type,
|
|
584
|
-
})
|
|
585
|
-
})
|
|
586
|
-
})
|
|
587
|
-
.catch(e => catchRejection(e, 'Sync status check failed'))
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
function cancelJob(jobId) {
|
|
591
|
-
if (asyncJobs[jobId]?.isFailed) {
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
checkOrigin()
|
|
596
|
-
.then(restParams => fetch('api/jobs' + restParams + '&job_id=' + jobId, {
|
|
597
|
-
method: 'DELETE',
|
|
598
|
-
headers: { 'Content-Type': 'application/json' },
|
|
599
|
-
}))
|
|
600
|
-
.then(checkResponse)
|
|
601
|
-
.then(() => showToast('Cancellation…'))
|
|
602
|
-
.catch(e => catchRejection(e, 'Sync cancellation failed'));
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
function checkJob({jobId, jobType, onSuccess, onError, onFinally}) {
|
|
606
|
-
switch (jobType) {
|
|
607
|
-
case JOB_TYPE.updateCrowdin:
|
|
608
|
-
if (!onSuccess) {
|
|
609
|
-
onSuccess = ((job) => {
|
|
610
|
-
getCrowdinData();
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
if (!onFinally) {
|
|
615
|
-
onFinally = (() => appComponent.setAttribute('is-to-crowdin-process', false));
|
|
616
|
-
}
|
|
617
|
-
break;
|
|
618
|
-
case JOB_TYPE.updateIntegration:
|
|
619
|
-
if (!onFinally) {
|
|
620
|
-
onFinally = (() => appComponent.setAttribute('is-to-integration-process', false));
|
|
621
|
-
}
|
|
622
|
-
break;
|
|
623
|
-
case JOB_TYPE.crowdinSyncSettingsSave:
|
|
624
|
-
if (!onFinally) {
|
|
625
|
-
onFinally = (() => appComponent.setAttribute(`is-crowdin-sync-settings-in-progress`, false));
|
|
626
|
-
}
|
|
627
|
-
break;
|
|
628
|
-
case JOB_TYPE.integrationSyncSettingsSave:
|
|
629
|
-
if (!onFinally) {
|
|
630
|
-
onFinally = (() => appComponent.setAttribute(`is-integration-sync-settings-in-progress`, false));
|
|
631
|
-
}
|
|
632
|
-
break;
|
|
633
|
-
default:
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
checkOrigin()
|
|
637
|
-
.then(restParams => fetch('api/jobs' + restParams + '&job_id=' + jobId))
|
|
638
|
-
.then(checkResponse)
|
|
639
|
-
.then((job) => {
|
|
640
|
-
const isFailed = [JOB_STATUS.failed, JOB_STATUS.canceled].includes(job.status);
|
|
641
|
-
const progress = isFailed || JOB_STATUS.finished === job.status ? 100 : job.progress;
|
|
642
|
-
const info = JOB_STATUS.canceled === job.status ? `Cancelled\n${job.info || ''}` : job.info;
|
|
643
|
-
|
|
644
|
-
!silentJobs.find((type) => type === jobType) && pushJobs([ {
|
|
645
|
-
id: job.id,
|
|
646
|
-
title: job.title,
|
|
647
|
-
progress,
|
|
648
|
-
info,
|
|
649
|
-
isFailed,
|
|
650
|
-
} ]);
|
|
651
|
-
|
|
652
|
-
if (isFailed) {
|
|
653
|
-
onError && onError();
|
|
654
|
-
} else if ([JOB_STATUS.created, JOB_STATUS.inProgress].includes(job.status) && job.progress < 100) {
|
|
655
|
-
setTimeout(() => {
|
|
656
|
-
checkJob({jobId, jobType, onSuccess, onError, onFinally});
|
|
657
|
-
}, {{asyncProgress.checkInterval}});
|
|
658
|
-
return;
|
|
659
|
-
} else {
|
|
660
|
-
onSuccess && onSuccess(job);
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
onFinally && onFinally(job);
|
|
664
|
-
})
|
|
665
|
-
.catch((e) => {
|
|
666
|
-
onFinally && onFinally();
|
|
667
|
-
|
|
668
|
-
!silentJobs.find((type) => type === jobType) && pushJobs([ {
|
|
669
|
-
id: jobId,
|
|
670
|
-
isFailed: true,
|
|
671
|
-
} ]);
|
|
672
|
-
|
|
673
|
-
showToast('Sync status check failed');
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
function pushJobs(jobs) {
|
|
678
|
-
const el = document.querySelector('crowdin-async-progress');
|
|
679
|
-
if (el && el.pushJobs) {
|
|
680
|
-
el.pushJobs(jobs);
|
|
681
|
-
jobs.forEach((job) => (asyncJobs[job.id] = job));
|
|
682
|
-
} else {
|
|
683
|
-
setTimeout(() => {
|
|
684
|
-
pushJobs(jobs);
|
|
685
|
-
}, 300);
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
function uploadFilesToIntegration(e) {
|
|
690
|
-
if (Object.keys(e.detail).length === 0) {
|
|
691
|
-
showToast('Select files which will be uploaded to {{name}}');
|
|
692
|
-
return;
|
|
693
|
-
}
|
|
694
|
-
appComponent.setAttribute('is-to-integration-process', true);
|
|
695
|
-
const req = {};
|
|
696
|
-
Object.keys(e.detail)
|
|
697
|
-
.filter(id => crowdinData.find(c => c.id === id).node_type === fileType)
|
|
698
|
-
.forEach(id => (req[id] = e.detail[id]));
|
|
699
|
-
checkOrigin()
|
|
700
|
-
.then(restParams => fetch('api/integration/update' + restParams, {
|
|
701
|
-
method: 'POST',
|
|
702
|
-
headers: { 'Content-Type': 'application/json' },
|
|
703
|
-
body: JSON.stringify(req)
|
|
704
|
-
}))
|
|
705
|
-
.then(checkResponse)
|
|
706
|
-
.then((res) => {
|
|
707
|
-
checkJob({
|
|
708
|
-
jobId: res?.jobId,
|
|
709
|
-
jobType: JOB_TYPE.updateIntegration,
|
|
710
|
-
})
|
|
711
|
-
})
|
|
712
|
-
.catch(e => catchRejection(e, 'Can\'t upload files to {{name}}'))
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
{{#if configurationFields}}
|
|
716
|
-
const settingsModal = document.getElementById('settings-modal');
|
|
717
|
-
const settingsSaveBtn = document.getElementById('settings-save-btn');
|
|
718
|
-
let config = JSON.parse('{{{config}}}');
|
|
719
|
-
|
|
720
|
-
function triggerEvent(el, type) {
|
|
721
|
-
const e = document.createEvent('HTMLEvents');
|
|
722
|
-
e.initEvent(type, false, true);
|
|
723
|
-
el.dispatchEvent(e);
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
function fillSettingsForm() {
|
|
727
|
-
Object.entries(config).forEach(([key, value]) => {
|
|
728
|
-
const el = document.getElementById(`${key}-settings`);
|
|
729
|
-
if (el && (value || el.tagName.toLowerCase() === 'crowdin-checkbox')) {
|
|
730
|
-
if (el.tagName.toLowerCase() === 'crowdin-select') {
|
|
731
|
-
if (el.hasAttribute('is-multi')) {
|
|
732
|
-
el.value = JSON.stringify(value);
|
|
733
|
-
} else {
|
|
734
|
-
el.value = JSON.stringify([value]);
|
|
735
|
-
}
|
|
736
|
-
} else if (el.tagName.toLowerCase() === 'crowdin-checkbox') {
|
|
737
|
-
el.checked = !!value;
|
|
738
|
-
} else {
|
|
739
|
-
el.value = value;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
triggerEvent(el, 'change');
|
|
743
|
-
}
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
function saveSettings() {
|
|
748
|
-
setLoader();
|
|
749
|
-
const settingsElements = Array.from(document.getElementById('modal-content').children);
|
|
750
|
-
const tags = ['crowdin-checkbox', 'crowdin-select', 'crowdin-input'];
|
|
751
|
-
const configReq = {};
|
|
752
|
-
settingsElements
|
|
753
|
-
.filter(e => tags.includes(e.tagName.toLowerCase()))
|
|
754
|
-
.forEach(e => {
|
|
755
|
-
const key = e.getAttribute('key');
|
|
756
|
-
let value;
|
|
757
|
-
if (e.tagName.toLowerCase() === 'crowdin-select') {
|
|
758
|
-
value = JSON.parse(e.value);
|
|
759
|
-
if (!e.hasAttribute('is-multi')) {
|
|
760
|
-
value = value.length > 0 ? value[0] : undefined;
|
|
761
|
-
}
|
|
762
|
-
} else if (e.tagName.toLowerCase() === 'crowdin-checkbox') {
|
|
763
|
-
value = !!e.checked;
|
|
764
|
-
} else {
|
|
765
|
-
value = e.value;
|
|
766
|
-
}
|
|
767
|
-
configReq[key] = value;
|
|
768
|
-
});
|
|
769
|
-
settingsSaveBtn.setAttribute('disabled', true);
|
|
770
|
-
checkOrigin()
|
|
771
|
-
.then(restParams => fetch('api/settings' + restParams, {
|
|
772
|
-
method: 'POST',
|
|
773
|
-
headers: { 'Content-Type': 'application/json' },
|
|
774
|
-
body: JSON.stringify({ config: configReq })
|
|
775
|
-
}))
|
|
776
|
-
.then(checkResponse)
|
|
777
|
-
.then(() => {
|
|
778
|
-
showToast('Settings successfully saved');
|
|
779
|
-
config = configReq;
|
|
780
|
-
})
|
|
781
|
-
.catch(e => catchRejection(e, 'Can\'t save settings'))
|
|
782
|
-
.finally(() => {
|
|
783
|
-
unsetLoader();
|
|
784
|
-
settingsSaveBtn.removeAttribute('disabled');
|
|
785
|
-
settingsModal.close();
|
|
786
|
-
{{#if reloadOnConfigSave}}
|
|
787
|
-
getIntegrationData(true);
|
|
788
|
-
getCrowdinData();
|
|
789
|
-
{{/if}}
|
|
790
|
-
});
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
function setLoader() {
|
|
794
|
-
const loader = document.querySelector('#settings-modal .loader');
|
|
795
|
-
loader.classList.remove('hidden');
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
function unsetLoader() {
|
|
799
|
-
const loader = document.querySelector('#settings-modal .loader');
|
|
800
|
-
setTimeout(function() {
|
|
801
|
-
loader.classList.add('hidden');
|
|
802
|
-
}, 500)
|
|
803
|
-
}
|
|
804
|
-
{{else}}
|
|
805
|
-
const settingsModal = undefined;
|
|
806
|
-
{{/if}}
|
|
807
|
-
|
|
808
|
-
{{#if infoModal}}
|
|
809
|
-
const infoModal = document.getElementById('info-modal');
|
|
810
|
-
{{else}}
|
|
811
|
-
const infoModal = undefined;
|
|
812
|
-
{{/if}}
|
|
813
|
-
|
|
814
|
-
document.addEventListener('keydown', (event) => {
|
|
815
|
-
if (event.keyCode == 27) {
|
|
816
|
-
|
|
817
|
-
if (infoModal) {
|
|
818
|
-
infoModal.close();
|
|
819
|
-
}
|
|
820
|
-
if (settingsModal) {
|
|
821
|
-
settingsModal.close();
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
});
|
|
825
|
-
|
|
826
|
-
{{#if integrationPagination}}
|
|
827
|
-
document.body.addEventListener('fileListEnd', (e) => {
|
|
828
|
-
getIntegrationData(false, 0, '', e.detail.page)
|
|
829
|
-
})
|
|
830
|
-
{{/if}}
|
|
831
|
-
|
|
832
|
-
{{#or withCronSync webhooks}}
|
|
833
|
-
const scheduleModal = document.getElementById('confirm-schedule-modal');
|
|
834
|
-
let syncData;
|
|
835
|
-
|
|
836
|
-
document.body.addEventListener('integrationScheduleSync', setIntegrationScheduleSync);
|
|
837
|
-
document.body.addEventListener('crowdinScheduleSync', setCrowdinScheduleSync);
|
|
838
|
-
document.body.addEventListener('crowdinDisableSync', disableCrowdinSync);
|
|
839
|
-
document.body.addEventListener('integrationDisableSync', disableIntegrationSync);
|
|
840
|
-
|
|
841
|
-
function getIntegrationFoldersToExpand(allData, syncedFiles) {
|
|
842
|
-
return Array.isArray(allData)
|
|
843
|
-
? allData.filter(
|
|
844
|
-
node => (node.node_type === folderType && !syncedFiles.find((syncedFile) => syncedFile.parent_id === node.id))
|
|
845
|
-
).map(node => ({
|
|
846
|
-
...node,
|
|
847
|
-
nodeType: node.node_type,
|
|
848
|
-
parentId: node.parent_id,
|
|
849
|
-
}))
|
|
850
|
-
: [];
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
async function saveScheduleSync() {
|
|
854
|
-
const newFile = scheduleModal.querySelector('#new-files').checked || false;
|
|
855
|
-
const selectedFiles = scheduleModal.querySelector('#selected-files').checked || false;
|
|
856
|
-
|
|
857
|
-
const type = scheduleModal.getAttribute('data-type');
|
|
858
|
-
|
|
859
|
-
if (type === 'crowdin') {
|
|
860
|
-
appComponent.setCrowdinScheduleSync(syncData, newFile, selectedFiles);
|
|
861
|
-
const syncedFiles = await appComponent.getCrowdinScheduleSync(true);
|
|
862
|
-
appComponent.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
863
|
-
updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
|
|
864
|
-
} else if (type === 'integration') {
|
|
865
|
-
appComponent.setIntegrationScheduleSync(syncData, newFile, selectedFiles);
|
|
866
|
-
const syncedFiles = await appComponent.getIntegrationScheduleSync(true);
|
|
867
|
-
appComponent.setAttribute('is-integration-sync-settings-in-progress', true);
|
|
868
|
-
{{#if integrationOneLevelFetching}}
|
|
869
|
-
updateSyncSettings(
|
|
870
|
-
syncedFiles,
|
|
871
|
-
'schedule',
|
|
872
|
-
'integration',
|
|
873
|
-
selectedFiles ? getIntegrationFoldersToExpand(syncData, syncedFiles) : [],
|
|
874
|
-
);
|
|
875
|
-
{{else}}
|
|
876
|
-
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
877
|
-
{{/if}}
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
scheduleModal.close();
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
function openScheduleModal(type) {
|
|
884
|
-
const newFile = scheduleModal.querySelector('#new-files')
|
|
885
|
-
const selectedFiles = scheduleModal.querySelector('#selected-files');
|
|
886
|
-
|
|
887
|
-
newFile.checked = false;
|
|
888
|
-
newFile.value = false;
|
|
889
|
-
selectedFiles.checked = true;
|
|
890
|
-
selectedFiles.value = true;
|
|
891
|
-
scheduleModal.querySelector('#save-schedule-sync').setAttribute('disabled', false);
|
|
892
|
-
scheduleModal.setAttribute('data-type', type);
|
|
893
|
-
scheduleModal.open();
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
function onChangeAutoSynchronizationOptions() {
|
|
897
|
-
const newFiles = document.getElementById('new-files').checked || false;
|
|
898
|
-
const selectedFiles = document.getElementById('selected-files').checked || false;
|
|
899
|
-
const buttonSaveScheduleSync = document.getElementById('save-schedule-sync');
|
|
900
|
-
|
|
901
|
-
if (newFiles || selectedFiles) {
|
|
902
|
-
buttonSaveScheduleSync.removeAttribute('disabled');
|
|
903
|
-
} else {
|
|
904
|
-
buttonSaveScheduleSync.setAttribute('disabled', true);
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
async function hasFolder(selectedFiles) {
|
|
909
|
-
let isFolder;
|
|
910
|
-
if (Array.isArray(selectedFiles)) {
|
|
911
|
-
isFolder = selectedFiles.find((file) => file.node_type === folderType || file.node_type === branchType);
|
|
912
|
-
} else {
|
|
913
|
-
const files = await appComponent.getCrowdinFilesData();
|
|
914
|
-
const folders = files.filter((file) => file.node_type === folderType || file.node_type === branchType);
|
|
915
|
-
isFolder = folders.find((folder) => selectedFiles.hasOwnProperty(folder.id));
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
return isFolder !== undefined;
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
async function setIntegrationScheduleSync(e) {
|
|
922
|
-
if (e.detail.length === 0) {
|
|
923
|
-
showToast('Select templates which will be pushed to Crowdin');
|
|
924
|
-
return;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
{{#if syncNewElements.integration}}
|
|
928
|
-
syncData = e.detail;
|
|
929
|
-
const isFolder = await hasFolder(e.detail);
|
|
930
|
-
if (isFolder) {
|
|
931
|
-
openScheduleModal('integration');
|
|
932
|
-
return;
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
appComponent.setIntegrationScheduleSync(e.detail);
|
|
936
|
-
const syncedFiles = await appComponent.getIntegrationScheduleSync(true);
|
|
937
|
-
{{else}}
|
|
938
|
-
const syncedFiles = await appComponent.getIntegrationScheduleSync();
|
|
939
|
-
{{/if}}
|
|
940
|
-
|
|
941
|
-
appComponent.setAttribute('is-integration-sync-settings-in-progress', true);
|
|
942
|
-
{{#if integrationOneLevelFetching}}
|
|
943
|
-
updateSyncSettings(syncedFiles, 'schedule', 'integration', getIntegrationFoldersToExpand(e.detail, syncedFiles));
|
|
944
|
-
{{else}}
|
|
945
|
-
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
946
|
-
{{/if}}
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
async function setCrowdinScheduleSync(e) {
|
|
950
|
-
if (e.detail.length === 0) {
|
|
951
|
-
showToast('Select templates which will be pushed to Crowdin');
|
|
952
|
-
return;
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
{{#if syncNewElements.crowdin}}
|
|
956
|
-
syncData = e.detail;
|
|
957
|
-
const isFolder = await hasFolder(e.detail);
|
|
958
|
-
if (isFolder) {
|
|
959
|
-
openScheduleModal('crowdin');
|
|
960
|
-
return;
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
appComponent.setCrowdinScheduleSync(e.detail);
|
|
964
|
-
const syncedFiles = await appComponent.getCrowdinScheduleSync(true);
|
|
965
|
-
{{else}}
|
|
966
|
-
const syncedFiles = await appComponent.getCrowdinScheduleSync();
|
|
967
|
-
{{/if}}
|
|
968
|
-
appComponent.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
969
|
-
updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
async function disableIntegrationSync(e) {
|
|
973
|
-
if (e.detail.length === 0) {
|
|
974
|
-
showToast('Select templates which will be pushed to Crowdin');
|
|
975
|
-
return;
|
|
976
|
-
}
|
|
977
|
-
appComponent.setAttribute('is-integration-sync-settings-in-progress', true);
|
|
978
|
-
{{#if syncNewElements.integration}}
|
|
979
|
-
const syncedFiles = await appComponent.getIntegrationScheduleSync(true);
|
|
980
|
-
{{else}}
|
|
981
|
-
const syncedFiles = await appComponent.getIntegrationScheduleSync();
|
|
982
|
-
{{/if}}
|
|
983
|
-
|
|
984
|
-
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
async function disableCrowdinSync(e) {
|
|
988
|
-
if (e.detail.length === 0) {
|
|
989
|
-
showToast('Select templates which will be pushed to Crowdin');
|
|
990
|
-
return;
|
|
991
|
-
}
|
|
992
|
-
appComponent.setAttribute('is-crowdin-sync-settings-in-progress', true);
|
|
993
|
-
{{#if syncNewElements.crowdin}}
|
|
994
|
-
const syncedFiles = await appComponent.getCrowdinScheduleSync(true);
|
|
995
|
-
{{else}}
|
|
996
|
-
const syncedFiles = await appComponent.getCrowdinScheduleSync();
|
|
997
|
-
{{/if}}
|
|
998
|
-
|
|
999
|
-
updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
function updateSyncSettings(files, type, provider, expandIntegrationFolders = []) {
|
|
1003
|
-
checkOrigin()
|
|
1004
|
-
.then(restParams => fetch('api/sync-settings' + restParams, {
|
|
1005
|
-
method: 'POST',
|
|
1006
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1007
|
-
body: JSON.stringify({ files, type, provider, expandIntegrationFolders })
|
|
1008
|
-
}))
|
|
1009
|
-
.then(checkResponse)
|
|
1010
|
-
.then((res) => {
|
|
1011
|
-
checkJob({
|
|
1012
|
-
jobId: res?.jobId,
|
|
1013
|
-
jobType: JOB_TYPE[`${provider}SyncSettingsSave`],
|
|
1014
|
-
})
|
|
1015
|
-
})
|
|
1016
|
-
.catch(e => catchRejection(e, 'Can\'t save schedule sync settings'));
|
|
1017
|
-
}
|
|
1018
|
-
{{/or}}
|
|
1019
|
-
|
|
1020
|
-
{{#if checkSubscription}}
|
|
1021
|
-
const subscriptionInfo = document.getElementById('subscription-info');
|
|
1022
|
-
const subscriptionInfoText = subscriptionInfo.getElementsByTagName('p')[0];
|
|
1023
|
-
function getSubscriptionInfo() {
|
|
1024
|
-
checkOrigin()
|
|
1025
|
-
.then(restParams => fetch('api/subscription-info' + restParams))
|
|
1026
|
-
.then(checkResponse)
|
|
1027
|
-
.then((res) => {
|
|
1028
|
-
if (res.showInfo) {
|
|
1029
|
-
subscriptionLink = res.subscribeLink;
|
|
1030
|
-
subscriptionInfoText.textContent = `Your trial expires in ${res.daysLeft} days.`
|
|
1031
|
-
subscriptionInfo.style.display = 'block';
|
|
1032
|
-
}
|
|
1033
|
-
});
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
getSubscriptionInfo();
|
|
1037
|
-
{{/if}}
|
|
1038
|
-
|
|
1039
|
-
function checkAlert(alert, suffix) {
|
|
1040
|
-
const name = suffix ?? '{{name}}';
|
|
1041
|
-
const revised = localStorage.getItem(`revised_${name}`) === '1';
|
|
1042
|
-
if (!revised) {
|
|
1043
|
-
alert.style.display = 'block';
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
function closeAlert(el, suffix) {
|
|
1047
|
-
const name = suffix ?? '{{name}}';
|
|
1048
|
-
const alert = el.closest('crowdin-alert');
|
|
1049
|
-
alert.style.display = 'none';
|
|
1050
|
-
localStorage.setItem(`revised_${name}`, 1);
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
{{#if uploadTranslations}}
|
|
1054
|
-
const translationInfo = document.getElementById('translation-info');
|
|
1055
|
-
checkAlert(translationInfo);
|
|
1056
|
-
{{/if}}
|
|
1057
|
-
|
|
1058
|
-
{{#if notice}}
|
|
1059
|
-
const notice = document.getElementById('notice');
|
|
1060
|
-
checkAlert(notice, 'notice');
|
|
1061
|
-
{{/if}}
|
|
1062
|
-
|
|
1063
|
-
function showErrorLogs() {
|
|
1064
|
-
document.getElementById('show-error-logs-btn').classList.add('hidden');
|
|
1065
|
-
document.getElementById('show-integration-btn').classList.remove('hidden');
|
|
1066
|
-
|
|
1067
|
-
appComponent.classList.add('hidden');
|
|
1068
|
-
document.getElementById('user-errors').classList.remove('hidden');
|
|
1069
|
-
|
|
1070
|
-
checkOrigin()
|
|
1071
|
-
.then(restParams => fetch('api/user-errors' + restParams))
|
|
1072
|
-
.then(checkResponse)
|
|
1073
|
-
.then((res) => {
|
|
1074
|
-
const table = document.getElementById('user-errors-table');
|
|
1075
|
-
|
|
1076
|
-
const clickRow = (field, index, item) => {
|
|
1077
|
-
const modal = document.getElementById('user-error-detail');
|
|
1078
|
-
modal.open();
|
|
1079
|
-
modal.innerHTML = getUserErrorDetail(item);
|
|
1080
|
-
};
|
|
1081
|
-
|
|
1082
|
-
table.setTableConfig && table.setTableConfig({
|
|
1083
|
-
defaultSortingColumn: "createdAt",
|
|
1084
|
-
defaultSortingDir: "desc",
|
|
1085
|
-
headerFields: [
|
|
1086
|
-
{
|
|
1087
|
-
field: "createdAt",
|
|
1088
|
-
name: "Date",
|
|
1089
|
-
isSortable: true,
|
|
1090
|
-
clickFn: clickRow,
|
|
1091
|
-
},
|
|
1092
|
-
{
|
|
1093
|
-
field: "action",
|
|
1094
|
-
name: "Action",
|
|
1095
|
-
clickFn: clickRow,
|
|
1096
|
-
},
|
|
1097
|
-
{
|
|
1098
|
-
field: "message",
|
|
1099
|
-
name: "Message",
|
|
1100
|
-
clickFn: clickRow,
|
|
1101
|
-
}
|
|
1102
|
-
],
|
|
1103
|
-
});
|
|
1104
|
-
|
|
1105
|
-
table.setTableData(JSON.stringify(res));
|
|
1106
|
-
table.setAttribute(`is-loading`, false);
|
|
1107
|
-
})
|
|
1108
|
-
.catch(e => catchRejection(e, 'Can\'t fetch error logs'));
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
function showIntegration() {
|
|
1112
|
-
document.getElementById('show-error-logs-btn').classList.remove('hidden');
|
|
1113
|
-
document.getElementById('show-integration-btn').classList.add('hidden');
|
|
1114
|
-
|
|
1115
|
-
appComponent.classList.remove('hidden');
|
|
1116
|
-
document.getElementById('user-errors').classList.add('hidden');
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
function getUserErrorDetail(error) {
|
|
1120
|
-
const data = JSON.parse(error.data);
|
|
1121
|
-
|
|
1122
|
-
let html = '<div class="error-detail-table"><table>';
|
|
1123
|
-
html += `<tr><td>Action</td><td>${error.action}</td></tr>`;
|
|
1124
|
-
html += `<tr><td>Message</td><td>${error.message}</td></tr>`;
|
|
1125
|
-
html += `<tr><td>Date/time</td><td>${error.createdAt}</td></tr>`;
|
|
1126
|
-
|
|
1127
|
-
if (data.requestParams) {
|
|
1128
|
-
html += `<tr><td>Method</td><td>${data.requestParams.method}</td></tr>`;
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
if (data.responseData) {
|
|
1132
|
-
html += `<tr><td>Response Data</td><td><pre>${JSON.stringify(data.responseData, null, 2)}</pre></td></tr>`;
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
if (data.appData) {
|
|
1136
|
-
if (Array.isArray(data.appData)) {
|
|
1137
|
-
html += `<tr><td>App Data</td><td><pre>${JSON.stringify(data.appData, null, 2)}</pre></td></tr>`;
|
|
1138
|
-
} else if (typeof data.appData === 'object') {
|
|
1139
|
-
for (const key in data.appData) {
|
|
1140
|
-
html += `<tr><td>${key.charAt(0).toUpperCase() + key.slice(1)}</td><td><pre>${JSON.stringify(data.appData[key], null, 2)}</pre></td></tr>`;
|
|
1141
|
-
}
|
|
1142
|
-
} else {
|
|
1143
|
-
html += `<tr><td>App Data</td><td>${data.appData}</td></tr>`;
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
html += '</table></div>';
|
|
1148
|
-
|
|
1149
|
-
return html;
|
|
1150
|
-
}
|
|
1151
|
-
</script>
|
|
1152
|
-
|
|
1153
|
-
</html>
|