@crowdin/app-project-module 0.10.2 → 0.11.1
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/README.md +1 -0
- package/out/handlers/custom-file-format/process.js +12 -2
- package/out/handlers/main.js +2 -0
- package/out/handlers/sync-settings-save.d.ts +3 -0
- package/out/handlers/sync-settings-save.js +27 -0
- package/out/handlers/sync-settings.d.ts +3 -0
- package/out/handlers/sync-settings.js +25 -0
- package/out/index.js +11 -0
- package/out/models/index.d.ts +26 -2
- package/out/storage/index.d.ts +6 -1
- package/out/storage/index.js +52 -1
- package/out/util/index.d.ts +1 -0
- package/out/util/index.js +69 -1
- package/out/views/login.handlebars +9 -1
- package/out/views/main.handlebars +95 -3
- package/out/views/partials/head.handlebars +4 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,9 +69,19 @@ function handleParseFile(baseUrl, dataFolder, config, file, req) {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
if (res.strings) {
|
|
72
|
-
|
|
72
|
+
let strings = res.strings;
|
|
73
|
+
if (config.autoUploadTranslations) {
|
|
74
|
+
strings = strings.map(string => {
|
|
75
|
+
const translations = {};
|
|
76
|
+
req.targetLanguages
|
|
77
|
+
.map(targetLanguage => targetLanguage.id)
|
|
78
|
+
.forEach(targetLanguage => (translations[targetLanguage] = { text: string.text }));
|
|
79
|
+
return Object.assign(Object.assign({}, string), { translations });
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const stringsJson = JSON.stringify(strings);
|
|
73
83
|
if (Buffer.byteLength(stringsJson, 'utf8') < MAX_BODY_SIZE) {
|
|
74
|
-
response.strings =
|
|
84
|
+
response.strings = strings;
|
|
75
85
|
}
|
|
76
86
|
else {
|
|
77
87
|
const storedFile = yield storeFile(stringsJson, dataFolder);
|
package/out/handlers/main.js
CHANGED
|
@@ -49,6 +49,8 @@ function handle(config, integration) {
|
|
|
49
49
|
options.config = JSON.stringify(req.integrationSettings || {});
|
|
50
50
|
}
|
|
51
51
|
options.infoModal = integration.infoModal;
|
|
52
|
+
options.withCronSync = integration.withCronSync;
|
|
53
|
+
options.withWebhookSync = integration.withWebhookSync;
|
|
52
54
|
return res.render(view, options);
|
|
53
55
|
}));
|
|
54
56
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
export default function handle(): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const util_1 = require("../util");
|
|
13
|
+
const storage_1 = require("../storage");
|
|
14
|
+
function handle() {
|
|
15
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
const { files, type, provider } = req.body;
|
|
17
|
+
const existingSettings = yield (0, storage_1.getSyncSettings)(req.crowdinContext.clientId, req.crowdinContext.crowdinId, type, provider);
|
|
18
|
+
if (existingSettings) {
|
|
19
|
+
yield (0, storage_1.updateSyncSettings)(JSON.stringify(files), req.crowdinContext.clientId, req.crowdinContext.crowdinId, type, provider);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
yield (0, storage_1.saveSyncSettings)(JSON.stringify(files), req.crowdinContext.clientId, req.crowdinContext.crowdinId, type, provider);
|
|
23
|
+
}
|
|
24
|
+
res.status(204).end();
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
exports.default = handle;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
export default function handle(): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const util_1 = require("../util");
|
|
13
|
+
const storage_1 = require("../storage");
|
|
14
|
+
function handle() {
|
|
15
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
let files = {};
|
|
17
|
+
const provider = req.params.provider;
|
|
18
|
+
const syncSettings = yield (0, storage_1.getSyncSettingsByProvider)(req.crowdinContext.clientId, provider);
|
|
19
|
+
if (syncSettings) {
|
|
20
|
+
files = JSON.parse(syncSettings.files) || [];
|
|
21
|
+
}
|
|
22
|
+
res.send(files);
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
exports.default = handle;
|
package/out/index.js
CHANGED
|
@@ -48,6 +48,8 @@ const integration_data_1 = __importDefault(require("./handlers/integration-data"
|
|
|
48
48
|
const integration_login_1 = __importDefault(require("./handlers/integration-login"));
|
|
49
49
|
const integration_logout_1 = __importDefault(require("./handlers/integration-logout"));
|
|
50
50
|
const integration_update_1 = __importDefault(require("./handlers/integration-update"));
|
|
51
|
+
const sync_settings_save_1 = __importDefault(require("./handlers/sync-settings-save"));
|
|
52
|
+
const sync_settings_1 = __importDefault(require("./handlers/sync-settings"));
|
|
51
53
|
const main_1 = __importDefault(require("./handlers/main"));
|
|
52
54
|
const manifest_1 = __importDefault(require("./handlers/manifest"));
|
|
53
55
|
const oauth_login_1 = __importDefault(require("./handlers/oauth-login"));
|
|
@@ -93,6 +95,8 @@ function addCrowdinEndpoints(app, config) {
|
|
|
93
95
|
app.get('/api/integration/data', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, integration_data_1.default)(integrationLogic));
|
|
94
96
|
app.post('/api/crowdin/update', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, crowdin_update_1.default)(config, integrationLogic));
|
|
95
97
|
app.post('/api/integration/update', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, integration_update_1.default)(config, integrationLogic));
|
|
98
|
+
app.get('/api/sync-settings/:provider', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, sync_settings_1.default)());
|
|
99
|
+
app.post('/api/sync-settings', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, sync_settings_save_1.default)());
|
|
96
100
|
if (integrationLogic.oauthLogin) {
|
|
97
101
|
app.get((0, util_1.getOauthRoute)(integrationLogic), (0, oauth_login_1.default)(config, integrationLogic));
|
|
98
102
|
}
|
|
@@ -101,6 +105,13 @@ function addCrowdinEndpoints(app, config) {
|
|
|
101
105
|
cron.schedule(job.expression, () => (0, util_1.runJob)(config, integrationLogic, job).catch(console.error));
|
|
102
106
|
});
|
|
103
107
|
}
|
|
108
|
+
if (integrationLogic.withCronSync) {
|
|
109
|
+
cron.schedule('0 * * * *', () => (0, util_1.filesCron)(config, integrationLogic, '1').catch(console.error));
|
|
110
|
+
cron.schedule('0 */3 * * *', () => (0, util_1.filesCron)(config, integrationLogic, '3').catch(console.error));
|
|
111
|
+
cron.schedule('0 */6 * * *', () => (0, util_1.filesCron)(config, integrationLogic, '6').catch(console.error));
|
|
112
|
+
cron.schedule('0 */12 * * *', () => (0, util_1.filesCron)(config, integrationLogic, '12').catch(console.error));
|
|
113
|
+
cron.schedule('0 0 * * *', () => (0, util_1.filesCron)(config, integrationLogic, '24').catch(console.error));
|
|
114
|
+
}
|
|
104
115
|
}
|
|
105
116
|
if (config.customFileFormat) {
|
|
106
117
|
app.post('/process', (0, process_1.default)(config.baseUrl, config.customFileFormat.filesFolder || config.dbFolder, config.customFileFormat));
|
package/out/models/index.d.ts
CHANGED
|
@@ -127,6 +127,14 @@ export interface IntegrationLogic {
|
|
|
127
127
|
* background jobs that will be executed for each crowdin project and user
|
|
128
128
|
*/
|
|
129
129
|
cronJobs?: CronJob[];
|
|
130
|
+
withCronSync?: {
|
|
131
|
+
crowdin: boolean;
|
|
132
|
+
integration: boolean;
|
|
133
|
+
};
|
|
134
|
+
withWebhookSync?: {
|
|
135
|
+
crowdin: boolean;
|
|
136
|
+
integration: boolean;
|
|
137
|
+
};
|
|
130
138
|
}
|
|
131
139
|
export interface ConfigurationField {
|
|
132
140
|
key: string;
|
|
@@ -321,9 +329,13 @@ export interface CustomFileFormatLogic {
|
|
|
321
329
|
*/
|
|
322
330
|
multilingual?: boolean;
|
|
323
331
|
/**
|
|
324
|
-
*
|
|
332
|
+
* Contains fileName and/or fileContent regular expressions used to detect file type when uploading a new source file via UI (or via API without specified type parameter). If the file matches regular expressions, it's labeled as a custom format file.
|
|
325
333
|
*/
|
|
326
334
|
signaturePatterns?: SignaturePatterns;
|
|
335
|
+
/**
|
|
336
|
+
* Flag to automatically upload translations
|
|
337
|
+
*/
|
|
338
|
+
autoUploadTranslations?: boolean;
|
|
327
339
|
/**
|
|
328
340
|
* Used for initial source file upload, source file update, and translation upload
|
|
329
341
|
*/
|
|
@@ -371,7 +383,12 @@ export interface ProcessFileString {
|
|
|
371
383
|
hasPlurals?: boolean;
|
|
372
384
|
labels?: string[];
|
|
373
385
|
text: string | SourceStringsModel.PluralText;
|
|
374
|
-
translations?:
|
|
386
|
+
translations?: StringTranslations;
|
|
387
|
+
}
|
|
388
|
+
export interface StringTranslations {
|
|
389
|
+
[language: string]: {
|
|
390
|
+
text: string | SourceStringsModel.PluralText;
|
|
391
|
+
};
|
|
375
392
|
}
|
|
376
393
|
export interface CustomMTLogic {
|
|
377
394
|
translate: (client: Crowdin, context: CrowdinContextInfo, projectId: number, source: string, target: string, strings: string[]) => Promise<string[]>;
|
|
@@ -411,3 +428,10 @@ export interface CrowdinAppUtilities {
|
|
|
411
428
|
client?: Crowdin;
|
|
412
429
|
}>;
|
|
413
430
|
}
|
|
431
|
+
export interface IntegrationSyncSettings {
|
|
432
|
+
id: string;
|
|
433
|
+
files?: any;
|
|
434
|
+
integrationId: string;
|
|
435
|
+
crowdinId: string;
|
|
436
|
+
provider: string;
|
|
437
|
+
}
|
package/out/storage/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CrowdinCredentials, IntegrationCredentials } from '../models';
|
|
1
|
+
import { CrowdinCredentials, IntegrationCredentials, IntegrationSyncSettings } from '../models';
|
|
2
2
|
export declare function connect(folder: string): Promise<void>;
|
|
3
3
|
export declare function saveCrowdinCredentials(credentials: CrowdinCredentials): Promise<void>;
|
|
4
4
|
export declare function updateCrowdinCredentials(credentials: CrowdinCredentials): Promise<void>;
|
|
@@ -15,3 +15,8 @@ export declare function saveMetadata(id: string, metadata: any): Promise<void>;
|
|
|
15
15
|
export declare function updateMetadata(id: string, metadata: any): Promise<void>;
|
|
16
16
|
export declare function getMetadata(id: string): Promise<any | undefined>;
|
|
17
17
|
export declare function deleteMetadata(id: string): Promise<void>;
|
|
18
|
+
export declare function getSyncSettingsByProvider(integrationId: string, provider: string): Promise<IntegrationSyncSettings | undefined>;
|
|
19
|
+
export declare function getAllSyncSettingsByType(type: string): Promise<IntegrationSyncSettings[]>;
|
|
20
|
+
export declare function saveSyncSettings(files: any, integrationId: string, crowdinId: string, type: string, provider: string): Promise<void>;
|
|
21
|
+
export declare function updateSyncSettings(files: any, integrationId: string, crowdinId: string, type: string, provider: string): Promise<void>;
|
|
22
|
+
export declare function getSyncSettings(integrationId: string, crowdinId: string, type: string, provider: string): Promise<IntegrationSyncSettings | undefined>;
|
package/out/storage/index.js
CHANGED
|
@@ -13,7 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
14
|
};
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.deleteMetadata = exports.getMetadata = exports.updateMetadata = exports.saveMetadata = exports.deleteIntegrationCredentials = exports.getAllIntegrationCredentials = exports.getIntegrationCredentials = exports.updateIntegrationConfig = exports.updateIntegrationCredentials = exports.saveIntegrationCredentials = exports.deleteCrowdinCredentials = exports.getAllCrowdinCredentials = exports.getCrowdinCredentials = exports.updateCrowdinCredentials = exports.saveCrowdinCredentials = exports.connect = void 0;
|
|
16
|
+
exports.getSyncSettings = exports.updateSyncSettings = exports.saveSyncSettings = exports.getAllSyncSettingsByType = exports.getSyncSettingsByProvider = exports.deleteMetadata = exports.getMetadata = exports.updateMetadata = exports.saveMetadata = exports.deleteIntegrationCredentials = exports.getAllIntegrationCredentials = exports.getIntegrationCredentials = exports.updateIntegrationConfig = exports.updateIntegrationCredentials = exports.saveIntegrationCredentials = exports.deleteCrowdinCredentials = exports.getAllCrowdinCredentials = exports.getCrowdinCredentials = exports.updateCrowdinCredentials = exports.saveCrowdinCredentials = exports.connect = void 0;
|
|
17
17
|
const path_1 = require("path");
|
|
18
18
|
const sqlite3_1 = __importDefault(require("sqlite3"));
|
|
19
19
|
let _res;
|
|
@@ -75,6 +75,17 @@ function connect(folder) {
|
|
|
75
75
|
);
|
|
76
76
|
`, []);
|
|
77
77
|
yield _run(`
|
|
78
|
+
create table if not exists sync_settings
|
|
79
|
+
(
|
|
80
|
+
id integer not null primary key autoincrement,
|
|
81
|
+
files varchar null,
|
|
82
|
+
integration_id varchar not null,
|
|
83
|
+
crowdin_id varchar not null,
|
|
84
|
+
type varchar not null,
|
|
85
|
+
provider varchar not null
|
|
86
|
+
);
|
|
87
|
+
`, []);
|
|
88
|
+
yield _run(`
|
|
78
89
|
create table if not exists app_metadata
|
|
79
90
|
(
|
|
80
91
|
id varchar not null primary key,
|
|
@@ -167,6 +178,7 @@ function deleteCrowdinCredentials(id) {
|
|
|
167
178
|
return __awaiter(this, void 0, void 0, function* () {
|
|
168
179
|
yield run('DELETE FROM crowdin_credentials where id = ?', [id]);
|
|
169
180
|
yield run('DELETE FROM integration_credentials where crowdin_id = ?', [id]);
|
|
181
|
+
yield run('DELETE FROM sync_settings WHERE crowdin_id = ?', [id]);
|
|
170
182
|
});
|
|
171
183
|
}
|
|
172
184
|
exports.deleteCrowdinCredentials = deleteCrowdinCredentials;
|
|
@@ -203,6 +215,7 @@ function getAllIntegrationCredentials(crowdinId) {
|
|
|
203
215
|
exports.getAllIntegrationCredentials = getAllIntegrationCredentials;
|
|
204
216
|
function deleteIntegrationCredentials(id) {
|
|
205
217
|
return run('DELETE FROM integration_credentials where id = ?', [id]);
|
|
218
|
+
return run('DELETE FROM sync_settings where integration_id = ?', [id]);
|
|
206
219
|
}
|
|
207
220
|
exports.deleteIntegrationCredentials = deleteIntegrationCredentials;
|
|
208
221
|
function saveMetadata(id, metadata) {
|
|
@@ -228,3 +241,41 @@ function deleteMetadata(id) {
|
|
|
228
241
|
});
|
|
229
242
|
}
|
|
230
243
|
exports.deleteMetadata = deleteMetadata;
|
|
244
|
+
function getSyncSettingsByProvider(integrationId, provider) {
|
|
245
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
246
|
+
const row = yield get('SELECT id, files, integration_id as integrationId, crowdin_id as crowdinId, type, provider FROM sync_settings WHERE integration_id = ? AND provider = ?', [integrationId, provider]);
|
|
247
|
+
if (row) {
|
|
248
|
+
return row;
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
exports.getSyncSettingsByProvider = getSyncSettingsByProvider;
|
|
253
|
+
function getAllSyncSettingsByType(type) {
|
|
254
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
255
|
+
return each('SELECT id, files, integration_id as integrationId, crowdin_id as crowdinId, type, provider FROM sync_settings WHERE type = ?', [type]);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
exports.getAllSyncSettingsByType = getAllSyncSettingsByType;
|
|
259
|
+
function saveSyncSettings(files, integrationId, crowdinId, type, provider) {
|
|
260
|
+
return run('INSERT INTO sync_settings(files, integration_id, crowdin_id, type, provider) VALUES (?, ?, ?, ?, ?)', [
|
|
261
|
+
files,
|
|
262
|
+
integrationId,
|
|
263
|
+
crowdinId,
|
|
264
|
+
type,
|
|
265
|
+
provider,
|
|
266
|
+
]);
|
|
267
|
+
}
|
|
268
|
+
exports.saveSyncSettings = saveSyncSettings;
|
|
269
|
+
function updateSyncSettings(files, integrationId, crowdinId, type, provider) {
|
|
270
|
+
return run('UPDATE sync_settings SET files = ? WHERE integration_id = ? AND crowdin_id = ? AND type = ? AND provider = ?', [files, integrationId, crowdinId, type, provider]);
|
|
271
|
+
}
|
|
272
|
+
exports.updateSyncSettings = updateSyncSettings;
|
|
273
|
+
function getSyncSettings(integrationId, crowdinId, type, provider) {
|
|
274
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
275
|
+
const row = yield get('SELECT id, files, integration_id as integrationId, crowdin_id as crowdinId, type FROM sync_settings WHERE integration_id = ? AND crowdin_id = ? AND type = ? AND provider = ?', [integrationId, crowdinId, type, provider]);
|
|
276
|
+
if (row) {
|
|
277
|
+
return row;
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
exports.getSyncSettings = getSyncSettings;
|
package/out/util/index.d.ts
CHANGED
|
@@ -14,3 +14,4 @@ export declare function applyDefaults(config: Config, integration: IntegrationLo
|
|
|
14
14
|
export declare function prepareCrowdinClient(config: Config, credentials: CrowdinCredentials): Promise<Crowdin>;
|
|
15
15
|
export declare function prepareIntegrationCredentials(config: Config, integration: IntegrationLogic, integrationCredentials: IntegrationCredentials): Promise<any>;
|
|
16
16
|
export declare function runJob(config: Config, integration: IntegrationLogic, job: CronJob): Promise<void>;
|
|
17
|
+
export declare function filesCron(config: Config, integration: IntegrationLogic, period: string): Promise<void>;
|
package/out/util/index.js
CHANGED
|
@@ -31,7 +31,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
31
31
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
32
|
};
|
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
-
exports.runJob = exports.prepareIntegrationCredentials = exports.prepareCrowdinClient = exports.applyDefaults = exports.getRootFolder = exports.getOauthRoute = exports.decryptData = exports.encryptData = exports.runAsyncWrapper = exports.CodeError = void 0;
|
|
34
|
+
exports.filesCron = exports.runJob = exports.prepareIntegrationCredentials = exports.prepareCrowdinClient = exports.applyDefaults = exports.getRootFolder = exports.getOauthRoute = exports.decryptData = exports.encryptData = exports.runAsyncWrapper = exports.CodeError = void 0;
|
|
35
35
|
const crowdin_api_client_1 = __importDefault(require("@crowdin/crowdin-api-client"));
|
|
36
36
|
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
37
37
|
const axios_1 = __importDefault(require("axios"));
|
|
@@ -156,6 +156,46 @@ function applyDefaults(config, integration) {
|
|
|
156
156
|
],
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
|
+
if (integration.withCronSync) {
|
|
160
|
+
const getUserSettings = integration.getConfiguration;
|
|
161
|
+
integration.getConfiguration = (projectId, crowdinClient, integrationCredentials) => __awaiter(this, void 0, void 0, function* () {
|
|
162
|
+
let fields = [];
|
|
163
|
+
if (getUserSettings) {
|
|
164
|
+
fields = yield getUserSettings(projectId, crowdinClient, integrationCredentials);
|
|
165
|
+
}
|
|
166
|
+
return [
|
|
167
|
+
{
|
|
168
|
+
key: 'schedule',
|
|
169
|
+
label: 'Sync schedule',
|
|
170
|
+
helpText: 'Set the frequency for pushing sources and translations',
|
|
171
|
+
type: 'select',
|
|
172
|
+
options: [
|
|
173
|
+
{
|
|
174
|
+
value: '1',
|
|
175
|
+
label: '1 hour',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
value: '3',
|
|
179
|
+
label: '3 hours',
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
value: '6',
|
|
183
|
+
label: '6 hours',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
value: '12',
|
|
187
|
+
label: '12 hours',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
value: '24',
|
|
191
|
+
label: '24 hours',
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
...fields,
|
|
196
|
+
];
|
|
197
|
+
});
|
|
198
|
+
}
|
|
159
199
|
}
|
|
160
200
|
exports.applyDefaults = applyDefaults;
|
|
161
201
|
function prepareCrowdinClient(config, credentials) {
|
|
@@ -244,3 +284,31 @@ function runJob(config, integration, job) {
|
|
|
244
284
|
});
|
|
245
285
|
}
|
|
246
286
|
exports.runJob = runJob;
|
|
287
|
+
function filesCron(config, integration, period) {
|
|
288
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
289
|
+
const syncSettingsList = yield (0, storage_1.getAllSyncSettingsByType)('schedule');
|
|
290
|
+
yield Promise.all(syncSettingsList.map((syncSettings) => __awaiter(this, void 0, void 0, function* () {
|
|
291
|
+
const files = JSON.parse(syncSettings.files);
|
|
292
|
+
const crowdinCredentials = yield (0, storage_1.getCrowdinCredentials)(syncSettings.crowdinId);
|
|
293
|
+
const integrationCredentials = yield (0, storage_1.getIntegrationCredentials)(syncSettings.integrationId);
|
|
294
|
+
if (crowdinCredentials && integrationCredentials) {
|
|
295
|
+
const intConfig = integrationCredentials.config
|
|
296
|
+
? JSON.parse(integrationCredentials.config)
|
|
297
|
+
: { schedule: 24 };
|
|
298
|
+
if (period === intConfig.schedule) {
|
|
299
|
+
const projectId = crowdinAppFunctions.getProjectId(integrationCredentials.id);
|
|
300
|
+
const crowdinClient = yield prepareCrowdinClient(config, crowdinCredentials);
|
|
301
|
+
const apiCredentials = yield prepareIntegrationCredentials(config, integration, integrationCredentials);
|
|
302
|
+
const rootFolder = yield getRootFolder(config, integration, crowdinClient, projectId);
|
|
303
|
+
if (syncSettings.provider === 'crowdin') {
|
|
304
|
+
yield integration.updateIntegration(projectId, crowdinClient, apiCredentials, files, rootFolder, intConfig);
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
yield integration.updateCrowdin(projectId, crowdinClient, apiCredentials, files, rootFolder, intConfig);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
})));
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
exports.filesCron = filesCron;
|
|
@@ -61,6 +61,8 @@
|
|
|
61
61
|
<crowdin-toasts></crowdin-toasts>
|
|
62
62
|
</body>
|
|
63
63
|
<script type="text/javascript">
|
|
64
|
+
const loginButton = document.querySelector('crowdin-button');
|
|
65
|
+
|
|
64
66
|
function oauthLogin() {
|
|
65
67
|
const url = '{{{ oauthUrl }}}';
|
|
66
68
|
const oauthWindow = window.open(url, '{{ name }}', 'location=0,status=0,width=800,height=400');
|
|
@@ -86,6 +88,8 @@
|
|
|
86
88
|
{{/ifeq}}
|
|
87
89
|
{{/each}}
|
|
88
90
|
};
|
|
91
|
+
loginButton.setAttribute('disabled', true);
|
|
92
|
+
loginButton.setAttribute('is-loading', true);
|
|
89
93
|
checkOrigin()
|
|
90
94
|
.then(queryParams =>
|
|
91
95
|
fetch(`api/login${queryParams}`, {
|
|
@@ -96,7 +100,11 @@
|
|
|
96
100
|
)
|
|
97
101
|
.then(checkResponse)
|
|
98
102
|
.then(reloadLocation)
|
|
99
|
-
.catch(e => catchRejection(e, 'Credentials are not stored'))
|
|
103
|
+
.catch(e => catchRejection(e, 'Credentials are not stored'))
|
|
104
|
+
.finally(() => {
|
|
105
|
+
loginButton.setAttribute('disabled', false);
|
|
106
|
+
loginButton.setAttribute('is-loading', false);
|
|
107
|
+
});
|
|
100
108
|
}
|
|
101
109
|
</script>
|
|
102
110
|
|
|
@@ -13,7 +13,22 @@
|
|
|
13
13
|
{{/if}}
|
|
14
14
|
<crowdin-button icon-before="account_circle" onclick="integrationLogout()">Log out</crowdin-button>
|
|
15
15
|
</div>
|
|
16
|
-
<crowdin-simple-integration
|
|
16
|
+
<crowdin-simple-integration
|
|
17
|
+
{{#if withWebhookSync.crowdin}}
|
|
18
|
+
crowdin-sync="true"
|
|
19
|
+
{{/if}}
|
|
20
|
+
{{#if withWebhookSync.integration}}
|
|
21
|
+
integration-sync="true"
|
|
22
|
+
{{/if}}
|
|
23
|
+
{{#if withCronSync.crowdin}}
|
|
24
|
+
crowdin-schedule="true"
|
|
25
|
+
{{/if}}
|
|
26
|
+
{{#if withCronSync.integration}}
|
|
27
|
+
integration-schedule="true"
|
|
28
|
+
{{/if}}
|
|
29
|
+
integration-name="{{name}}"
|
|
30
|
+
integration-logo="logo.png"
|
|
31
|
+
>
|
|
17
32
|
</crowdin-simple-integration>
|
|
18
33
|
</div>
|
|
19
34
|
<crowdin-toasts></crowdin-toasts>
|
|
@@ -25,7 +40,7 @@
|
|
|
25
40
|
</crowdin-modal>
|
|
26
41
|
{{/if}}
|
|
27
42
|
{{#if configurationFields}}
|
|
28
|
-
<crowdin-modal id="settings-modal" modal-width="50" modal-title="Settings" close-button-title="Close">
|
|
43
|
+
<crowdin-modal id="settings-modal" body-overflow-unset modal-width="50" modal-title="Settings" close-button-title="Close">
|
|
29
44
|
<div id="modal-content">
|
|
30
45
|
{{#each configurationFields}}
|
|
31
46
|
{{#ifeq type "checkbox"}}
|
|
@@ -82,7 +97,6 @@
|
|
|
82
97
|
{{/if}}
|
|
83
98
|
</body>
|
|
84
99
|
<script type="text/javascript">
|
|
85
|
-
|
|
86
100
|
document.body.addEventListener('refreshFilesList', (e) => {
|
|
87
101
|
if (e.detail.refreshIntegration) {
|
|
88
102
|
getIntegrationData();
|
|
@@ -146,6 +160,9 @@
|
|
|
146
160
|
.then((res) => {
|
|
147
161
|
project = res;
|
|
148
162
|
appComponent.setCrowdinLanguagesData(project.targetLanguages)
|
|
163
|
+
{{#if withCronSync}}
|
|
164
|
+
getSyncSettings('crowdin');
|
|
165
|
+
{{/if}}
|
|
149
166
|
})
|
|
150
167
|
.catch(e => catchRejection(e, 'Can\'t fetch Crowdin data'))
|
|
151
168
|
.finally(() => (appComponent.setAttribute('is-crowdin-loading', false)));
|
|
@@ -173,10 +190,22 @@
|
|
|
173
190
|
});
|
|
174
191
|
appComponent.setIntegrationFilesData(tree);
|
|
175
192
|
})
|
|
193
|
+
{{#if withCronSync}}
|
|
194
|
+
.then(() => getSyncSettings('integration'))
|
|
195
|
+
{{/if}}
|
|
176
196
|
.catch(e => catchRejection(e, 'Can\'t fetch {{name}} templates'))
|
|
177
197
|
.finally(() => (appComponent.setAttribute('is-integration-loading', false)));
|
|
178
198
|
}
|
|
179
199
|
|
|
200
|
+
function getSyncSettings(provider) {
|
|
201
|
+
const filesComponent = appComponent.querySelector(`#${provider}-files`);
|
|
202
|
+
checkOrigin()
|
|
203
|
+
.then(restParams => fetch(`/api/sync-settings/${provider}` + restParams))
|
|
204
|
+
.then(checkResponse)
|
|
205
|
+
.then((res) => filesComponent.addScheduledFiles(res))
|
|
206
|
+
.catch(e => catchRejection(e, 'Can\'t fetch file progress'));
|
|
207
|
+
}
|
|
208
|
+
|
|
180
209
|
function getFileProgress(fileId) {
|
|
181
210
|
checkOrigin()
|
|
182
211
|
.then(restParams => fetch(`api/crowdin/file-progress/${fileId}` + restParams))
|
|
@@ -311,6 +340,69 @@
|
|
|
311
340
|
}
|
|
312
341
|
}
|
|
313
342
|
});
|
|
343
|
+
|
|
344
|
+
{{#if withCronSync}}
|
|
345
|
+
document.body.addEventListener('integrationScheduleSync', setIntegrationScheduleSync);
|
|
346
|
+
document.body.addEventListener('crowdinScheduleSync', setCrowdinScheduleSync);
|
|
347
|
+
document.body.addEventListener('crowdinDisableSync', disableCrowdinSync);
|
|
348
|
+
document.body.addEventListener('integrationDisableSync', disableIntegrationSync);
|
|
349
|
+
|
|
350
|
+
async function setIntegrationScheduleSync(e) {
|
|
351
|
+
if (e.detail.length === 0) {
|
|
352
|
+
showToast('Select templates which will be pushed to Crowdin');
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
appComponent.setAttribute('is-integration-loading', true);
|
|
356
|
+
const syncedFiles = await appComponent.getIntegrationScheduleSync();
|
|
357
|
+
|
|
358
|
+
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
async function setCrowdinScheduleSync(e) {
|
|
362
|
+
if (e.detail.length === 0) {
|
|
363
|
+
showToast('Select templates which will be pushed to Crowdin');
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
appComponent.setAttribute('is-crowdin-loading', true);
|
|
367
|
+
const syncedFiles = await appComponent.getCrowdinScheduleSync();
|
|
368
|
+
|
|
369
|
+
updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
async function disableIntegrationSync(e) {
|
|
373
|
+
if (e.detail.length === 0) {
|
|
374
|
+
showToast('Select templates which will be pushed to Crowdin');
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
appComponent.setAttribute('is-integration-loading', true);
|
|
378
|
+
const syncedFiles = await appComponent.getIntegrationScheduleSync();
|
|
379
|
+
|
|
380
|
+
updateSyncSettings(syncedFiles, 'schedule', 'integration');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async function disableCrowdinSync(e) {
|
|
384
|
+
if (e.detail.length === 0) {
|
|
385
|
+
showToast('Select templates which will be pushed to Crowdin');
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
appComponent.setAttribute('is-crowdin-loading', true);
|
|
389
|
+
const syncedFiles = await appComponent.getCrowdinScheduleSync();
|
|
390
|
+
|
|
391
|
+
updateSyncSettings(syncedFiles, 'schedule', 'crowdin');
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function updateSyncSettings(files, type, provider) {
|
|
395
|
+
checkOrigin()
|
|
396
|
+
.then(restParams => fetch('api/sync-settings' + restParams, {
|
|
397
|
+
method: 'POST',
|
|
398
|
+
headers: { 'Content-Type': 'application/json' },
|
|
399
|
+
body: JSON.stringify({ files, type, provider })
|
|
400
|
+
}))
|
|
401
|
+
.then(checkResponse)
|
|
402
|
+
.catch(e => catchRejection(e, 'Can\'t save schedule sync settings'))
|
|
403
|
+
.finally(() => (appComponent.setAttribute(`is-${provider}-loading`, false)));
|
|
404
|
+
}
|
|
405
|
+
{{/if}}
|
|
314
406
|
</script>
|
|
315
407
|
|
|
316
408
|
</html>
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
5
5
|
<title></title>
|
|
6
6
|
<link rel="stylesheet" href="assets/css/styles.css">
|
|
7
|
-
<script
|
|
7
|
+
<script type="module"
|
|
8
|
+
src="https://crowdin-web-components.s3.amazonaws.com/crowdin-web-components/crowdin-web-components.esm.js"></script>
|
|
9
|
+
<script nomodule=""
|
|
10
|
+
src="https://crowdin-web-components.s3.amazonaws.com/crowdin-web-components/crowdin-web-components.js"></script>
|
|
8
11
|
<script type="text/javascript" src="https://cdn.crowdin.com/apps/dist/iframe.js"></script>
|
|
9
12
|
<script type="text/javascript" src="assets/js/polyfills/promise.js"></script>
|
|
10
13
|
<script type="text/javascript" src="assets/js/polyfills/fetch.js"></script>
|
package/package.json
CHANGED