@crowdin/app-project-module 0.53.0 → 0.54.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/handlers/crowdin-webhook.js +5 -1
- package/out/modules/integration/handlers/integration-data.js +1 -0
- package/out/modules/integration/handlers/integration-login.js +9 -2
- package/out/modules/integration/types.d.ts +26 -1
- package/out/modules/integration/util/cron.js +27 -8
- package/out/modules/integration/util/defaults.js +42 -36
- package/out/modules/integration/util/types.d.ts +2 -2
- package/out/static/js/form.js +10 -10
- package/out/util/connection.js +19 -14
- package/out/util/handlebars.js +11 -2
- package/out/views/login.handlebars +118 -72
- package/out/views/main.handlebars +20 -2
- package/package.json +11 -11
|
@@ -37,7 +37,11 @@ function filterSyncFiles(args) {
|
|
|
37
37
|
if (!projectData) {
|
|
38
38
|
projectData = yield crowdinClient.projectsGroupsApi.getProject(projectId);
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
const projectLanguages = projectData.data.targetLanguageIds;
|
|
41
|
+
if (projectData.data.inContext) {
|
|
42
|
+
projectLanguages.push(projectData.data.inContextPseudoLanguageId);
|
|
43
|
+
}
|
|
44
|
+
addFileToResponse(fileId, projectLanguages);
|
|
41
45
|
continue;
|
|
42
46
|
}
|
|
43
47
|
// sync file that was selected for sync schedule
|
|
@@ -38,6 +38,7 @@ function handle(integration) {
|
|
|
38
38
|
crowdinId: req.crowdinContext.crowdinId,
|
|
39
39
|
clientId: req.crowdinContext.clientId,
|
|
40
40
|
});
|
|
41
|
+
res.send({ data: [], message: (e === null || e === void 0 ? void 0 : e.message) || e });
|
|
41
42
|
throw e;
|
|
42
43
|
}
|
|
43
44
|
req.logInfo(`Integration data response ${JSON.stringify(files, null, 2)}`);
|
|
@@ -14,11 +14,18 @@ const util_1 = require("../../../util");
|
|
|
14
14
|
const logger_1 = require("../../../util/logger");
|
|
15
15
|
function handle(config, integration) {
|
|
16
16
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
var _a;
|
|
17
18
|
req.logInfo('Received integration login request');
|
|
19
|
+
let credentials = req.body.credentials;
|
|
20
|
+
if ((_a = integration.loginForm) === null || _a === void 0 ? void 0 : _a.performGetTokenRequest) {
|
|
21
|
+
req.logInfo('Performing custom get bearer token request');
|
|
22
|
+
const tokenCredentials = yield integration.loginForm.performGetTokenRequest(credentials);
|
|
23
|
+
credentials = Object.assign(Object.assign({}, credentials), { expireIn: Number(tokenCredentials.expires_in) + Date.now() / 1000, accessToken: tokenCredentials.access_token, refreshToken: tokenCredentials.refresh_token });
|
|
24
|
+
}
|
|
18
25
|
if (integration.checkConnection) {
|
|
19
26
|
try {
|
|
20
27
|
req.logInfo('Checking the integration credentials');
|
|
21
|
-
yield integration.checkConnection(
|
|
28
|
+
yield integration.checkConnection(credentials);
|
|
22
29
|
}
|
|
23
30
|
catch (e) {
|
|
24
31
|
yield (0, logger_1.handleUserError)({
|
|
@@ -35,7 +42,7 @@ function handle(config, integration) {
|
|
|
35
42
|
req.logInfo('Deleting old credentials');
|
|
36
43
|
yield (0, storage_1.getStorage)().deleteIntegrationCredentials(req.crowdinContext.clientId);
|
|
37
44
|
}
|
|
38
|
-
yield (0, storage_1.getStorage)().saveIntegrationCredentials(req.crowdinContext.clientId, (0, util_1.encryptData)(config, JSON.stringify(
|
|
45
|
+
yield (0, storage_1.getStorage)().saveIntegrationCredentials(req.crowdinContext.clientId, (0, util_1.encryptData)(config, JSON.stringify(credentials)), req.crowdinContext.crowdinId);
|
|
39
46
|
res.status(204).end();
|
|
40
47
|
}));
|
|
41
48
|
}
|
|
@@ -145,6 +145,18 @@ export interface IntegrationLogic {
|
|
|
145
145
|
}
|
|
146
146
|
export interface LoginForm {
|
|
147
147
|
fields: FormEntity[];
|
|
148
|
+
/**
|
|
149
|
+
* Override to implement request for retrieving access token (and refresh token if 'refresh' is enabled)
|
|
150
|
+
*/
|
|
151
|
+
performGetTokenRequest?: (fieldsCredentials: any) => Promise<LoginFormTokenResponse>;
|
|
152
|
+
/**
|
|
153
|
+
* Override to implement request for refreshing token (only if 'refresh' is enabled)
|
|
154
|
+
*/
|
|
155
|
+
performRefreshTokenRequest?: (currentCredentials: any) => Promise<LoginFormTokenResponse>;
|
|
156
|
+
/**
|
|
157
|
+
* default 'false' which means that the access token has no expiration date
|
|
158
|
+
*/
|
|
159
|
+
refresh?: boolean;
|
|
148
160
|
}
|
|
149
161
|
export interface OAuthLogin {
|
|
150
162
|
/**
|
|
@@ -287,7 +299,7 @@ export interface FormField {
|
|
|
287
299
|
helpText?: string;
|
|
288
300
|
helpTextHtml?: string;
|
|
289
301
|
label: string;
|
|
290
|
-
type?: 'text' | 'password' | 'checkbox' | 'select' | 'textarea' | 'file';
|
|
302
|
+
type?: 'text' | 'password' | 'checkbox' | 'select' | 'textarea' | 'file' | 'notice';
|
|
291
303
|
defaultValue?: any;
|
|
292
304
|
/**
|
|
293
305
|
* only for select
|
|
@@ -312,6 +324,14 @@ export interface FormField {
|
|
|
312
324
|
* field dependency settings
|
|
313
325
|
*/
|
|
314
326
|
dependencySettings?: string;
|
|
327
|
+
/**
|
|
328
|
+
* only for notice type
|
|
329
|
+
*/
|
|
330
|
+
noticeType?: string;
|
|
331
|
+
/**
|
|
332
|
+
* only for notice type
|
|
333
|
+
*/
|
|
334
|
+
noIcon?: boolean;
|
|
315
335
|
}
|
|
316
336
|
type NoticeType = 'info' | 'warning' | 'danger' | 'success' | 'error' | 'dataLostWarning';
|
|
317
337
|
export interface IntegrationCredentials {
|
|
@@ -432,4 +452,9 @@ export interface AppSettings {
|
|
|
432
452
|
'new-integration-files'?: boolean;
|
|
433
453
|
[key: string]: any;
|
|
434
454
|
}
|
|
455
|
+
interface LoginFormTokenResponse {
|
|
456
|
+
access_token: string;
|
|
457
|
+
expires_in: number;
|
|
458
|
+
refresh_token: string;
|
|
459
|
+
}
|
|
435
460
|
export {};
|
|
@@ -131,6 +131,10 @@ function filesCron({ config, integration, period, }) {
|
|
|
131
131
|
(0, logger_1.log)(`Subscription expired. Skipping job [${period}] for organization ${crowdinCredentials.id}`);
|
|
132
132
|
continue;
|
|
133
133
|
}
|
|
134
|
+
const projectData = (yield crowdinClient.projectsGroupsApi.getProject(projectId))
|
|
135
|
+
.data;
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
137
|
+
context.jwtPayload.context.project_identifier = projectData.identifier;
|
|
134
138
|
const rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, crowdinClient, projectId);
|
|
135
139
|
const apiCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
136
140
|
if (!integration.webhooks &&
|
|
@@ -139,13 +143,13 @@ function filesCron({ config, integration, period, }) {
|
|
|
139
143
|
newFiles = yield getAllNewFiles({
|
|
140
144
|
config,
|
|
141
145
|
integration,
|
|
146
|
+
projectData,
|
|
147
|
+
syncSettings,
|
|
142
148
|
crowdinApiClient: crowdinClient,
|
|
143
149
|
crowdinId: crowdinCredentials.id,
|
|
144
150
|
integrationCredentials: apiCredentials,
|
|
145
151
|
integrationId: integrationCredentials.id,
|
|
146
|
-
projectId,
|
|
147
152
|
integrationSettings: intConfig,
|
|
148
|
-
syncSettings,
|
|
149
153
|
});
|
|
150
154
|
}
|
|
151
155
|
if (integration.webhooks) {
|
|
@@ -192,6 +196,9 @@ function filesCron({ config, integration, period, }) {
|
|
|
192
196
|
}
|
|
193
197
|
}
|
|
194
198
|
const apiCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
199
|
+
if (!(intConfig === null || intConfig === void 0 ? void 0 : intConfig.inContext)) {
|
|
200
|
+
removeInContextLanguage(filesToProcess, projectData);
|
|
201
|
+
}
|
|
195
202
|
try {
|
|
196
203
|
yield (0, job_1.runAsJob)({
|
|
197
204
|
integrationId: syncSettings.integrationId,
|
|
@@ -215,7 +222,7 @@ function filesCron({ config, integration, period, }) {
|
|
|
215
222
|
}
|
|
216
223
|
catch (e) {
|
|
217
224
|
(0, logger_1.logError)(e, context);
|
|
218
|
-
|
|
225
|
+
continue;
|
|
219
226
|
}
|
|
220
227
|
if (Object.keys(newFiles).length) {
|
|
221
228
|
yield (0, storage_1.getStorage)().updateSyncSettings(JSON.stringify(Object.assign(Object.assign({}, files), newFiles)), syncSettings.integrationId, syncSettings.crowdinId, 'schedule', syncSettings.provider);
|
|
@@ -256,7 +263,7 @@ function filesCron({ config, integration, period, }) {
|
|
|
256
263
|
}
|
|
257
264
|
catch (e) {
|
|
258
265
|
(0, logger_1.logError)(e, context);
|
|
259
|
-
|
|
266
|
+
continue;
|
|
260
267
|
}
|
|
261
268
|
if (Object.keys(newFiles).length) {
|
|
262
269
|
const newSyncSettingsFields = allIntFiles.map((file) => (Object.assign(Object.assign({}, file), { schedule: true, sync: false })));
|
|
@@ -276,12 +283,12 @@ function getFileDiff(currentFiles, savedFiles) {
|
|
|
276
283
|
}
|
|
277
284
|
function getAllNewFiles(args) {
|
|
278
285
|
return __awaiter(this, void 0, void 0, function* () {
|
|
279
|
-
const { config, integration, crowdinApiClient, crowdinId, integrationCredentials, integrationId,
|
|
286
|
+
const { config, integration, crowdinApiClient, crowdinId, integrationCredentials, integrationId, projectData, integrationSettings, syncSettings, } = args;
|
|
280
287
|
let currentFileSnapshot = [];
|
|
281
288
|
const fileSnapshotData = yield (0, storage_1.getStorage)().getFilesSnapshot(integrationId, crowdinId, syncSettings.provider);
|
|
282
289
|
const snapshotFiles = (fileSnapshotData === null || fileSnapshotData === void 0 ? void 0 : fileSnapshotData.files) ? JSON.parse(fileSnapshotData.files) : [];
|
|
283
290
|
if (syncSettings.provider === types_1.Provider.CROWDIN) {
|
|
284
|
-
currentFileSnapshot = yield (0, snapshot_1.getCrowdinSnapshot)(config, integration, crowdinApiClient,
|
|
291
|
+
currentFileSnapshot = yield (0, snapshot_1.getCrowdinSnapshot)(config, integration, crowdinApiClient, projectData.id, integrationSettings);
|
|
285
292
|
}
|
|
286
293
|
else {
|
|
287
294
|
currentFileSnapshot = yield (0, snapshot_1.getIntegrationSnapshot)(integration, integrationCredentials, integrationSettings);
|
|
@@ -298,8 +305,10 @@ function getAllNewFiles(args) {
|
|
|
298
305
|
}
|
|
299
306
|
else {
|
|
300
307
|
const files = {};
|
|
301
|
-
const
|
|
302
|
-
|
|
308
|
+
const targetLanguages = projectData.targetLanguageIds;
|
|
309
|
+
if (projectData.inContext) {
|
|
310
|
+
targetLanguages.push(projectData.inContextPseudoLanguageId);
|
|
311
|
+
}
|
|
303
312
|
if (integrationSettings[`new-${syncSettings.provider}-files`]) {
|
|
304
313
|
for (const file of onlyFiles) {
|
|
305
314
|
files[file.id] = targetLanguages;
|
|
@@ -429,3 +438,13 @@ function removeFinishedJobs() {
|
|
|
429
438
|
});
|
|
430
439
|
}
|
|
431
440
|
exports.removeFinishedJobs = removeFinishedJobs;
|
|
441
|
+
function removeInContextLanguage(filesToProcess, projectData) {
|
|
442
|
+
(0, logger_1.log)('Removing in-context language from files to process');
|
|
443
|
+
if (!projectData.inContext) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
for (const fileId in filesToProcess) {
|
|
447
|
+
filesToProcess[fileId] = filesToProcess[fileId].filter((language) => language !== projectData.inContextPseudoLanguageId);
|
|
448
|
+
}
|
|
449
|
+
(0, logger_1.log)('In-context language(' + projectData.inContextPseudoLanguageId + ') removed from files to process');
|
|
450
|
+
}
|
|
@@ -138,15 +138,24 @@ function applyIntegrationModuleDefaults(config, integration) {
|
|
|
138
138
|
],
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
141
|
+
const getUserSettings = integration.getConfiguration;
|
|
142
|
+
integration.getConfiguration = (projectId, crowdinClient, integrationCredentials) => __awaiter(this, void 0, void 0, function* () {
|
|
143
|
+
var _c, _d;
|
|
144
|
+
let fields = [];
|
|
145
|
+
const project = (yield crowdinClient.projectsGroupsApi.getProject(projectId));
|
|
146
|
+
if (getUserSettings) {
|
|
147
|
+
fields = yield getUserSettings(projectId, crowdinClient, integrationCredentials);
|
|
148
|
+
}
|
|
149
|
+
const defaultSettings = [];
|
|
150
|
+
if (project.data.inContext) {
|
|
151
|
+
defaultSettings.push({
|
|
152
|
+
key: 'inContext',
|
|
153
|
+
label: 'Show In-Context Pseudo Language',
|
|
154
|
+
type: 'checkbox',
|
|
155
|
+
defaultValue: 'false',
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (integration.withCronSync || integration.webhooks) {
|
|
150
159
|
defaultSettings.push({
|
|
151
160
|
key: 'schedule',
|
|
152
161
|
label: 'Auto sync',
|
|
@@ -211,33 +220,30 @@ function applyIntegrationModuleDefaults(config, integration) {
|
|
|
211
220
|
type: 'checkbox',
|
|
212
221
|
});
|
|
213
222
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
];
|
|
239
|
-
});
|
|
240
|
-
}
|
|
223
|
+
defaultSettings.push({
|
|
224
|
+
key: 'condition',
|
|
225
|
+
label: 'Files export settings',
|
|
226
|
+
type: 'select',
|
|
227
|
+
defaultValue: '0',
|
|
228
|
+
dependencySettings: JSON.stringify([{ '#schedule-settings': { type: '!equal', value: ['0'] } }]),
|
|
229
|
+
options: [
|
|
230
|
+
{
|
|
231
|
+
value: '0',
|
|
232
|
+
label: 'Export all',
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
value: '1',
|
|
236
|
+
label: 'Export translated only',
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
value: '2',
|
|
240
|
+
label: 'Export approved only',
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return [...defaultSettings, ...fields];
|
|
246
|
+
});
|
|
241
247
|
if (!integration.checkConnection) {
|
|
242
248
|
integration.checkConnection = (apiCredentials) => __awaiter(this, void 0, void 0, function* () {
|
|
243
249
|
yield integration.getIntegrationFiles(apiCredentials);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Crowdin from '@crowdin/crowdin-api-client';
|
|
1
|
+
import Crowdin, { ProjectsGroupsModel } from '@crowdin/crowdin-api-client';
|
|
2
2
|
import { Config } from '../../../types';
|
|
3
3
|
import { IntegrationLogic, IntegrationSyncSettings } from '../types';
|
|
4
4
|
export declare enum JobType {
|
|
@@ -59,7 +59,7 @@ export interface GetAllNewFilesArgs {
|
|
|
59
59
|
crowdinId: string;
|
|
60
60
|
integrationCredentials: any;
|
|
61
61
|
integrationId: string;
|
|
62
|
-
|
|
62
|
+
projectData: ProjectsGroupsModel.ProjectSettings;
|
|
63
63
|
integrationSettings: any;
|
|
64
64
|
syncSettings: IntegrationSyncSettings;
|
|
65
65
|
}
|