@crowdin/app-project-module 0.41.0 → 0.41.2

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.
@@ -8,12 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
+ const lodash_uniqby_1 = __importDefault(require("lodash.uniqby"));
12
16
  const job_1 = require("../../models/job");
13
17
  const util_1 = require("../../util");
14
18
  const defaults_1 = require("../../util/defaults");
15
19
  const logger_1 = require("../../util/logger");
16
20
  const job_2 = require("../../util/job");
21
+ const files_1 = require("../../util/files");
17
22
  function handle(config, integration) {
18
23
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
19
24
  var _a, _b;
@@ -36,6 +41,11 @@ function handle(config, integration) {
36
41
  payload: req.body,
37
42
  res,
38
43
  jobCallback: (job) => __awaiter(this, void 0, void 0, function* () {
44
+ var _c;
45
+ if (req.body && ((_c = req.body) === null || _c === void 0 ? void 0 : _c.length)) {
46
+ req.body = yield (0, files_1.expandFilesTree)(req.body, req, integration, job);
47
+ req.body = (0, lodash_uniqby_1.default)(req.body, 'id');
48
+ }
39
49
  const result = yield integration.updateCrowdin({
40
50
  projectId,
41
51
  client: req.crowdinApiClient,
@@ -8,20 +8,51 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
+ const lodash_uniqby_1 = __importDefault(require("lodash.uniqby"));
12
16
  const util_1 = require("../../util");
13
17
  const cron_1 = require("../../util/cron");
14
18
  const file_snapshot_1 = require("../../util/file-snapshot");
19
+ const files_1 = require("../../util/files");
20
+ const job_1 = require("../../util/job");
15
21
  function handle(config, integration) {
16
22
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
17
- var _a;
18
- const { files, provider } = req.body;
19
- yield (0, cron_1.createOrUpdateSyncSettings)(config, req, files, provider);
20
- const appSettings = req.integrationSettings || {};
21
- if (((_a = integration.syncNewElements) === null || _a === void 0 ? void 0 : _a[provider]) && appSettings[`new-${provider}-files`]) {
22
- yield (0, file_snapshot_1.createOrUpdateFileSnapshot)(config, integration, req, provider);
23
- }
24
- res.status(204).end();
23
+ const { files, provider, expandIntegrationFolders } = req.body;
24
+ yield (0, job_1.runAsJob)({
25
+ integrationId: req.crowdinContext.clientId,
26
+ crowdinId: req.crowdinContext.crowdinId,
27
+ type: `${provider}SyncSettingsSave`,
28
+ title: 'Save sync settings',
29
+ payload: req.body,
30
+ res,
31
+ jobCallback: () => __awaiter(this, void 0, void 0, function* () {
32
+ var _a;
33
+ if (Array.isArray(expandIntegrationFolders) && expandIntegrationFolders.length) {
34
+ const allFiles = (yield (0, files_1.expandFilesTree)(expandIntegrationFolders, req, integration)).map((node) => ({
35
+ id: node.id,
36
+ name: node.name,
37
+ // eslint-disable-next-line @typescript-eslint/camelcase
38
+ node_type: node.nodeType,
39
+ // eslint-disable-next-line @typescript-eslint/camelcase
40
+ parent_id: node.parentId,
41
+ schedule: true,
42
+ sync: false,
43
+ type: node.type,
44
+ }));
45
+ yield (0, cron_1.createOrUpdateSyncSettings)(config, req, (0, lodash_uniqby_1.default)([...files, ...allFiles], 'id'), provider);
46
+ }
47
+ else {
48
+ yield (0, cron_1.createOrUpdateSyncSettings)(config, req, files, provider);
49
+ }
50
+ const appSettings = req.integrationSettings || {};
51
+ if (((_a = integration.syncNewElements) === null || _a === void 0 ? void 0 : _a[provider]) && appSettings[`new-${provider}-files`]) {
52
+ yield (0, file_snapshot_1.createOrUpdateFileSnapshot)(config, integration, req, provider);
53
+ }
54
+ }),
55
+ });
25
56
  }));
26
57
  }
27
58
  exports.default = handle;
@@ -199,7 +199,8 @@ export declare enum Scope {
199
199
  WEBHOOKS = "project.webhook",
200
200
  TRANSLATIONS = "project.translation",
201
201
  SCREENSHOTS = "project.screenshot",
202
- SECURITY_LOGS = "security-log"
202
+ SECURITY_LOGS = "security-log",
203
+ VENDORS = "vendor"
203
204
  }
204
205
  export interface IntegrationLogic {
205
206
  /**
@@ -589,6 +590,7 @@ export interface IntegrationFile {
589
590
  name: string;
590
591
  type: SourceFilesModel.FileType;
591
592
  parentId: string;
593
+ nodeType?: IntegrationTreeElementType;
592
594
  }
593
595
  export interface UpdateIntegrationRequest {
594
596
  [fileId: string]: string[];
@@ -25,6 +25,7 @@ var Scope;
25
25
  Scope["TRANSLATIONS"] = "project.translation";
26
26
  Scope["SCREENSHOTS"] = "project.screenshot";
27
27
  Scope["SECURITY_LOGS"] = "security-log";
28
+ Scope["VENDORS"] = "vendor";
28
29
  })(Scope = exports.Scope || (exports.Scope = {}));
29
30
  var AccountType;
30
31
  (function (AccountType) {
@@ -1,6 +1,8 @@
1
1
  export declare enum JobType {
2
2
  UPDATE_TO_CROWDIN = "updateCrowdin",
3
- UPDATE_TO_INTEGRATION = "updateIntegration"
3
+ UPDATE_TO_INTEGRATION = "updateIntegration",
4
+ CROWDIN_SYNC_SETTINGS_SAVE = "crowdinSyncSettingsSave",
5
+ INTEGRATION_SYNC_SETTINGS_SAVE = "integrationSyncSettingsSave"
4
6
  }
5
7
  export declare enum JobStatus {
6
8
  CREATED = "created",
package/out/models/job.js CHANGED
@@ -5,6 +5,8 @@ var JobType;
5
5
  (function (JobType) {
6
6
  JobType["UPDATE_TO_CROWDIN"] = "updateCrowdin";
7
7
  JobType["UPDATE_TO_INTEGRATION"] = "updateIntegration";
8
+ JobType["CROWDIN_SYNC_SETTINGS_SAVE"] = "crowdinSyncSettingsSave";
9
+ JobType["INTEGRATION_SYNC_SETTINGS_SAVE"] = "integrationSyncSettingsSave";
8
10
  })(JobType = exports.JobType || (exports.JobType = {}));
9
11
  var JobStatus;
10
12
  (function (JobStatus) {
@@ -1,7 +1,9 @@
1
1
  /// <reference types="node" />
2
- import { ProcessFileString, SkipIntegrationNodes, TreeItem } from '../models';
2
+ import { IntegrationFile, IntegrationLogic, IntegrationRequest, ProcessFileString, SkipIntegrationNodes, TreeItem } from '../models';
3
+ import { JobClient } from '../models/job';
3
4
  export declare const MAX_BODY_SIZE: number;
4
5
  export declare function storeFile(fileContent: Buffer, folder: string): Promise<string>;
5
6
  export declare function getFileContent(url: string): Promise<Buffer>;
6
7
  export declare function getFileStrings(url: string): Promise<ProcessFileString[]>;
7
8
  export declare function skipFilesByRegex(files: TreeItem[] | undefined, skipIntegrationNodes?: SkipIntegrationNodes): TreeItem[];
9
+ export declare function expandFilesTree(nodes: IntegrationFile[], req: IntegrationRequest, integration: IntegrationLogic, job?: JobClient): Promise<IntegrationFile[]>;
package/out/util/files.js CHANGED
@@ -12,10 +12,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.skipFilesByRegex = exports.getFileStrings = exports.getFileContent = exports.storeFile = exports.MAX_BODY_SIZE = void 0;
15
+ exports.expandFilesTree = exports.skipFilesByRegex = exports.getFileStrings = exports.getFileContent = exports.storeFile = exports.MAX_BODY_SIZE = void 0;
16
16
  const axios_1 = __importDefault(require("axios"));
17
17
  const fs_1 = __importDefault(require("fs"));
18
18
  const path_1 = __importDefault(require("path"));
19
+ const index_1 = require("./index");
20
+ const job_1 = require("../models/job");
19
21
  exports.MAX_BODY_SIZE = 4.9 * 1024 * 1024; //4.9mb
20
22
  function storeFile(fileContent, folder) {
21
23
  const fileName = `file${Date.now()}`;
@@ -63,3 +65,24 @@ function skipFilesByRegex(files, skipIntegrationNodes) {
63
65
  return files;
64
66
  }
65
67
  exports.skipFilesByRegex = skipFilesByRegex;
68
+ function expandFilesTree(nodes, req, integration, job) {
69
+ var _a;
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ if (job && job_1.JobStatus.CANCELED === ((_a = (yield job.get())) === null || _a === void 0 ? void 0 : _a.status)) {
72
+ throw new Error('Job canceled');
73
+ }
74
+ const files = nodes.filter((file) => file.nodeType === undefined || file.nodeType === '1');
75
+ const folders = nodes.filter((folder) => folder.nodeType === '0' && !nodes.find((node) => node.parentId === folder.id));
76
+ for (const { id } of folders) {
77
+ const integrationData = yield integration.getIntegrationFiles(req.integrationCredentials, req.integrationSettings, id);
78
+ const integrationTreeItems = (0, index_1.isExtendedResultType)(integrationData)
79
+ ? integrationData.data
80
+ : integrationData;
81
+ const checkNodes = integrationTreeItems.map((item) => (Object.assign(Object.assign({}, item), { nodeType: item.nodeType || ('type' in item ? '1' : '0') })));
82
+ const expandedResult = yield expandFilesTree(checkNodes, req, integration, job);
83
+ files.push(...expandedResult);
84
+ }
85
+ return files;
86
+ });
87
+ }
88
+ exports.expandFilesTree = expandFilesTree;
package/out/util/job.js CHANGED
@@ -16,6 +16,8 @@ const logger_1 = require("./logger");
16
16
  const blockingJobs = {
17
17
  [job_1.JobType.UPDATE_TO_CROWDIN]: [job_1.JobType.UPDATE_TO_CROWDIN, job_1.JobType.UPDATE_TO_INTEGRATION],
18
18
  [job_1.JobType.UPDATE_TO_INTEGRATION]: [job_1.JobType.UPDATE_TO_CROWDIN, job_1.JobType.UPDATE_TO_INTEGRATION],
19
+ [job_1.JobType.CROWDIN_SYNC_SETTINGS_SAVE]: [job_1.JobType.CROWDIN_SYNC_SETTINGS_SAVE],
20
+ [job_1.JobType.INTEGRATION_SYNC_SETTINGS_SAVE]: [job_1.JobType.INTEGRATION_SYNC_SETTINGS_SAVE],
19
21
  };
20
22
  function runAsJob({ integrationId, crowdinId, type, title, payload, res, jobCallback, onError, }) {
21
23
  return __awaiter(this, void 0, void 0, function* () {
@@ -25,7 +27,7 @@ function runAsJob({ integrationId, crowdinId, type, title, payload, res, jobCall
25
27
  const existingJob = activeJobs.find((job) => blockingJobs[type].includes(job.type));
26
28
  if (existingJob === null || existingJob === void 0 ? void 0 : existingJob.id) {
27
29
  if (res) {
28
- res.status(202).send({ jobId: existingJob.id, message: 'Job is already running' });
30
+ res.status(202).send({ jobId: existingJob.id, message: 'Another sync is running' });
29
31
  }
30
32
  return;
31
33
  }
@@ -137,20 +137,20 @@ function logError(e, context) {
137
137
  }
138
138
  exports.logError = logError;
139
139
  function errorOutputByType(error) {
140
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
140
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
141
141
  const message = error.message || error;
142
142
  if (isAxiosError(error)) {
143
- const request = error.config || error.data.config
143
+ const request = (error === null || error === void 0 ? void 0 : error.config) || ((_a = error.data) === null || _a === void 0 ? void 0 : _a.config)
144
144
  ? {
145
- url: ((_a = error.config) === null || _a === void 0 ? void 0 : _a.url) || ((_b = error.data) === null || _b === void 0 ? void 0 : _b.config.url),
146
- method: ((_c = error.config) === null || _c === void 0 ? void 0 : _c.method) || ((_d = error.data) === null || _d === void 0 ? void 0 : _d.config.method),
147
- data: ((_e = error.config) === null || _e === void 0 ? void 0 : _e.data) || ((_f = error.data) === null || _f === void 0 ? void 0 : _f.config.data),
145
+ url: ((_b = error.config) === null || _b === void 0 ? void 0 : _b.url) || ((_c = error.data) === null || _c === void 0 ? void 0 : _c.config.url),
146
+ method: ((_d = error.config) === null || _d === void 0 ? void 0 : _d.method) || ((_e = error.data) === null || _e === void 0 ? void 0 : _e.config.method),
147
+ data: ((_f = error.config) === null || _f === void 0 ? void 0 : _f.data) || ((_g = error.data) === null || _g === void 0 ? void 0 : _g.config.data),
148
148
  }
149
149
  : {};
150
- const response = error.response || error.data.response
150
+ const response = (error === null || error === void 0 ? void 0 : error.response) || ((_h = error.data) === null || _h === void 0 ? void 0 : _h.response)
151
151
  ? {
152
- data: ((_g = error.response) === null || _g === void 0 ? void 0 : _g.data) || ((_h = error.data) === null || _h === void 0 ? void 0 : _h.response.data),
153
- status: ((_j = error.response) === null || _j === void 0 ? void 0 : _j.status) || ((_k = error.data) === null || _k === void 0 ? void 0 : _k.response.status),
152
+ data: ((_j = error.response) === null || _j === void 0 ? void 0 : _j.data) || ((_k = error.data) === null || _k === void 0 ? void 0 : _k.response.data),
153
+ status: ((_l = error.response) === null || _l === void 0 ? void 0 : _l.status) || ((_m = error.data) === null || _m === void 0 ? void 0 : _m.response.status),
154
154
  }
155
155
  : {};
156
156
  console.error(message, { attributes: JSON.stringify({ request, response }) }, { backtrace: error.stack });
@@ -318,6 +318,8 @@
318
318
  const JOB_TYPE = {
319
319
  updateCrowdin: 'updateCrowdin',
320
320
  updateIntegration: 'updateIntegration',
321
+ integrationSyncSettingsSave: 'integrationSyncSettingsSave',
322
+ crowdinSyncSettingsSave: 'crowdinSyncSettingsSave',
321
323
  };
322
324
 
323
325
  const JOB_STATUS = {
@@ -328,6 +330,11 @@
328
330
  finished: 'finished',
329
331
  };
330
332
 
333
+ const silentJobs = [
334
+ JOB_TYPE.integrationSyncSettingsSave,
335
+ JOB_TYPE.crowdinSyncSettingsSave,
336
+ ];
337
+
331
338
  const asyncJobs = {};
332
339
 
333
340
  let project = {};
@@ -410,16 +417,31 @@
410
417
  }
411
418
  return item;
412
419
  });
420
+
421
+ const appIntegrationFiles = appComponent.querySelector('#integration-files');
413
422
  if (hardReload) {
414
423
  appComponent.setIntegrationFilesData(tree);
415
- } else {
416
- appComponent.pushIntegrationFilesData(tree);
424
+ } else if (tree.length) {
425
+ appComponent.pushIntegrationFilesData(tree).then(() => {
426
+ appIntegrationFiles.getSelected().then(selection => {
427
+ selection = selection?.filter((node) => node);
428
+ if (!selection?.length) {
429
+ return;
430
+ }
431
+
432
+ const selectedIds = selection.map(({id}) => id);
433
+ tree.forEach((node) => {
434
+ selectedIds.includes(node.parent_id) && selectedIds.push(node.id);
435
+ });
436
+ appIntegrationFiles.setSelected(selectedIds);
437
+ });
438
+ });
417
439
  }
418
440
  {{#if integrationPagination}}
419
441
  if (stopPagination) {
420
- appComponent.querySelector('#integration-files').setAttribute('load-more-disabled', true);
442
+ appIntegrationFiles.setAttribute('load-more-disabled', true);
421
443
  } else {
422
- appComponent.querySelector('#integration-files').setAttribute('load-more-disabled', false);
444
+ appIntegrationFiles.setAttribute('load-more-disabled', false);
423
445
  }
424
446
  {{/if}}
425
447
  if (search) {
@@ -530,6 +552,12 @@
530
552
  case JOB_TYPE.updateIntegration:
531
553
  appComponent.setAttribute('is-to-integration-process', true);
532
554
  break;
555
+ case JOB_TYPE.crowdinSyncSettingsSave:
556
+ appComponent.setAttribute(`is-crowdin-sync-settings-in-progress`, true)
557
+ break;
558
+ case JOB_TYPE.integrationSyncSettingsSave:
559
+ appComponent.setAttribute(`is-integration-sync-settings-in-progress`, true)
560
+ break;
533
561
  default:
534
562
  }
535
563
 
@@ -575,6 +603,16 @@
575
603
  onFinally = (() => appComponent.setAttribute('is-to-integration-process', false));
576
604
  }
577
605
  break;
606
+ case JOB_TYPE.crowdinSyncSettingsSave:
607
+ if (!onFinally) {
608
+ onFinally = (() => appComponent.setAttribute(`is-crowdin-sync-settings-in-progress`, false));
609
+ }
610
+ break;
611
+ case JOB_TYPE.integrationSyncSettingsSave:
612
+ if (!onFinally) {
613
+ onFinally = (() => appComponent.setAttribute(`is-integration-sync-settings-in-progress`, false));
614
+ }
615
+ break;
578
616
  default:
579
617
  }
580
618
 
@@ -586,7 +624,7 @@
586
624
  const progress = isFailed || JOB_STATUS.finished === job.status ? 100 : job.progress;
587
625
  const info = JOB_STATUS.canceled === job.status ? `Cancelled\n${job.info || ''}` : job.info;
588
626
 
589
- pushJobs([ {
627
+ !silentJobs.find((type) => type === jobType) && pushJobs([ {
590
628
  id: job.id,
591
629
  title: job.title,
592
630
  progress,
@@ -610,7 +648,7 @@
610
648
  .catch((e) => {
611
649
  onFinally && onFinally();
612
650
 
613
- pushJobs([ {
651
+ !silentJobs.find((type) => type === jobType) && pushJobs([ {
614
652
  id: jobId,
615
653
  isFailed: true,
616
654
  } ]);
@@ -783,6 +821,18 @@
783
821
  document.body.addEventListener('crowdinDisableSync', disableCrowdinSync);
784
822
  document.body.addEventListener('integrationDisableSync', disableIntegrationSync);
785
823
 
824
+ function getIntegrationFoldersToExpand(allData, syncedFiles) {
825
+ return Array.isArray(allData)
826
+ ? allData.filter(
827
+ node => (node.node_type === folderType && !syncedFiles.find((syncedFile) => syncedFile.parent_id === node.id))
828
+ ).map(node => ({
829
+ ...node,
830
+ nodeType: node.node_type,
831
+ parentId: node.parent_id,
832
+ }))
833
+ : [];
834
+ }
835
+
786
836
  async function saveScheduleSync() {
787
837
  const newFile = scheduleModal.querySelector('#new-files').checked || false;
788
838
  const selectedFiles = scheduleModal.querySelector('#selected-files').checked || false;
@@ -792,13 +842,22 @@
792
842
  if (type === 'crowdin') {
793
843
  appComponent.setCrowdinScheduleSync(syncData, newFile, selectedFiles);
794
844
  const syncedFiles = await appComponent.getCrowdinScheduleSync(true);
795
- appComponent.setAttribute('is-crowdin-loading', true);
845
+ appComponent.setAttribute('is-crowdin-sync-settings-in-progress', true);
796
846
  updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
797
847
  } else if (type === 'integration') {
798
848
  appComponent.setIntegrationScheduleSync(syncData, newFile, selectedFiles);
799
849
  const syncedFiles = await appComponent.getIntegrationScheduleSync(true);
800
- appComponent.setAttribute('is-integration-loading', true);
801
- updateSyncSettings(syncedFiles, 'schedule', 'integration');
850
+ appComponent.setAttribute('is-integration-sync-settings-in-progress', true);
851
+ {{#if integrationOneLevelFetching}}
852
+ updateSyncSettings(
853
+ syncedFiles,
854
+ 'schedule',
855
+ 'integration',
856
+ selectedFiles ? getIntegrationFoldersToExpand(syncData, syncedFiles) : [],
857
+ );
858
+ {{else}}
859
+ updateSyncSettings(syncedFiles, 'schedule', 'integration');
860
+ {{/if}}
802
861
  }
803
862
 
804
863
  scheduleModal.close();
@@ -861,8 +920,13 @@
861
920
  {{else}}
862
921
  const syncedFiles = await appComponent.getIntegrationScheduleSync();
863
922
  {{/if}}
864
- appComponent.setAttribute('is-integration-loading', true);
865
- updateSyncSettings(syncedFiles, 'schedule', 'integration');
923
+
924
+ appComponent.setAttribute('is-integration-sync-settings-in-progress', true);
925
+ {{#if integrationOneLevelFetching}}
926
+ updateSyncSettings(syncedFiles, 'schedule', 'integration', getIntegrationFoldersToExpand(e.detail, syncedFiles));
927
+ {{else}}
928
+ updateSyncSettings(syncedFiles, 'schedule', 'integration');
929
+ {{/if}}
866
930
  }
867
931
 
868
932
  async function setCrowdinScheduleSync(e) {
@@ -884,7 +948,7 @@
884
948
  {{else}}
885
949
  const syncedFiles = await appComponent.getCrowdinScheduleSync();
886
950
  {{/if}}
887
- appComponent.setAttribute('is-crowdin-loading', true);
951
+ appComponent.setAttribute('is-crowdin-sync-settings-in-progress', true);
888
952
  updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
889
953
  }
890
954
 
@@ -893,7 +957,7 @@
893
957
  showToast('Select templates which will be pushed to Crowdin');
894
958
  return;
895
959
  }
896
- appComponent.setAttribute('is-integration-loading', true);
960
+ appComponent.setAttribute('is-integration-sync-settings-in-progress', true);
897
961
  {{#if syncNewElements.integration}}
898
962
  const syncedFiles = await appComponent.getIntegrationScheduleSync(true);
899
963
  {{else}}
@@ -908,7 +972,7 @@
908
972
  showToast('Select templates which will be pushed to Crowdin');
909
973
  return;
910
974
  }
911
- appComponent.setAttribute('is-crowdin-loading', true);
975
+ appComponent.setAttribute('is-crowdin-sync-settings-in-progress', true);
912
976
  {{#if syncNewElements.crowdin}}
913
977
  const syncedFiles = await appComponent.getCrowdinScheduleSync(true);
914
978
  {{else}}
@@ -918,16 +982,21 @@
918
982
  updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
919
983
  }
920
984
 
921
- function updateSyncSettings(files, type, provider) {
985
+ function updateSyncSettings(files, type, provider, expandIntegrationFolders = []) {
922
986
  checkOrigin()
923
987
  .then(restParams => fetch('api/sync-settings' + restParams, {
924
988
  method: 'POST',
925
989
  headers: { 'Content-Type': 'application/json' },
926
- body: JSON.stringify({ files, type, provider })
990
+ body: JSON.stringify({ files, type, provider, expandIntegrationFolders })
927
991
  }))
928
992
  .then(checkResponse)
929
- .catch(e => catchRejection(e, 'Can\'t save schedule sync settings'))
930
- .finally(() => (appComponent.setAttribute(`is-${provider}-loading`, false)));
993
+ .then((res) => {
994
+ checkJob({
995
+ jobId: res?.jobId,
996
+ jobType: JOB_TYPE[`${provider}SyncSettingsSave`],
997
+ })
998
+ })
999
+ .catch(e => catchRejection(e, 'Can\'t save schedule sync settings'));
931
1000
  }
932
1001
  {{/or}}
933
1002
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.41.0",
3
+ "version": "0.41.2",
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",
@@ -17,12 +17,13 @@
17
17
  "@aws-sdk/client-s3": "^3.423.0",
18
18
  "@aws-sdk/s3-request-presigner": "^3.484.0",
19
19
  "@crowdin/crowdin-apps-functions": "0.6.0",
20
- "@crowdin/logs-formatter": "^2.1.2",
20
+ "@crowdin/logs-formatter": "^2.1.3",
21
21
  "@godaddy/terminus": "^4.12.1",
22
22
  "amqplib": "^0.10.3",
23
23
  "crypto-js": "^4.2.0",
24
24
  "express": "4.18.2",
25
25
  "express-handlebars": "^5.3.5",
26
+ "lodash.uniqby": "^4.7.0",
26
27
  "mysql2": "^2.3.3",
27
28
  "node-cron": "^3.0.2",
28
29
  "pg": "^8.11.3",
@@ -52,6 +53,7 @@
52
53
  "@types/express": "4.17.21",
53
54
  "@types/express-handlebars": "^5.3.1",
54
55
  "@types/jest": "^29.5.5",
56
+ "@types/lodash.uniqby": "^4.7.9",
55
57
  "@types/node": "^16.18.69",
56
58
  "@types/node-cron": "^3.0.9",
57
59
  "@types/pg": "^8.10.3",