@crowdin/app-project-module 0.14.1 → 0.15.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.
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
22
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
23
+ return new (P || (P = Promise))(function (resolve, reject) {
24
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
25
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
26
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
27
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
28
+ });
29
+ };
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.applyDefaults = exports.getOauthRoute = exports.getRootFolder = void 0;
32
+ const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
33
+ function getRootFolder(config, integration, client, projectId) {
34
+ return __awaiter(this, void 0, void 0, function* () {
35
+ if (!integration.withRootFolder) {
36
+ return;
37
+ }
38
+ const folder = integration.appFolderName || config.name;
39
+ const directories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId)).data.map(d => d.data);
40
+ const { folder: rootFolder } = yield crowdinAppFunctions.getOrCreateFolder(directories, client, projectId, folder);
41
+ return rootFolder;
42
+ });
43
+ }
44
+ exports.getRootFolder = getRootFolder;
45
+ function getOauthRoute(integration) {
46
+ var _a;
47
+ return ((_a = integration.oauthLogin) === null || _a === void 0 ? void 0 : _a.redirectUriRoute) || '/oauth/code';
48
+ }
49
+ exports.getOauthRoute = getOauthRoute;
50
+ function applyDefaults(config, integration) {
51
+ if (!integration.getCrowdinFiles) {
52
+ integration.getCrowdinFiles = (projectId, client, rootFolder) => __awaiter(this, void 0, void 0, function* () {
53
+ let allDirectories;
54
+ if (rootFolder) {
55
+ allDirectories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId, {
56
+ directoryId: rootFolder.id,
57
+ recursion: 'true',
58
+ })).data.map(d => d.data);
59
+ }
60
+ else {
61
+ allDirectories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId)).data.map(d => d.data);
62
+ }
63
+ const directoryIds = allDirectories.map(d => d.id);
64
+ let files = (yield client.sourceFilesApi.withFetchAll().listProjectFiles(projectId)).data.map(d => d.data);
65
+ files = files.filter(f => (rootFolder && f.directoryId === rootFolder.id) ||
66
+ directoryIds.includes(f.directoryId) ||
67
+ (!rootFolder && !f.directoryId));
68
+ const res = [];
69
+ allDirectories.forEach(e => {
70
+ const parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
71
+ res.push({
72
+ id: e.id.toString(),
73
+ parentId: parentId ? parentId.toString() : undefined,
74
+ name: e.name,
75
+ });
76
+ });
77
+ files.forEach(e => {
78
+ const parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
79
+ res.push({
80
+ id: e.id.toString(),
81
+ parentId: parentId ? parentId.toString() : undefined,
82
+ name: e.title || e.name,
83
+ type: e.type,
84
+ });
85
+ });
86
+ return res;
87
+ });
88
+ }
89
+ if (!integration.loginForm) {
90
+ integration.loginForm = {
91
+ fields: [
92
+ {
93
+ helpText: 'You need to create standard api key',
94
+ key: 'apikey',
95
+ label: `${config.name} API Key`,
96
+ },
97
+ ],
98
+ };
99
+ }
100
+ if (integration.withCronSync) {
101
+ const getUserSettings = integration.getConfiguration;
102
+ integration.getConfiguration = (projectId, crowdinClient, integrationCredentials) => __awaiter(this, void 0, void 0, function* () {
103
+ let fields = [];
104
+ if (getUserSettings) {
105
+ fields = yield getUserSettings(projectId, crowdinClient, integrationCredentials);
106
+ }
107
+ return [
108
+ {
109
+ key: 'schedule',
110
+ label: 'Sync schedule',
111
+ helpText: 'Set the frequency for pushing sources and translations',
112
+ type: 'select',
113
+ options: [
114
+ {
115
+ value: '0',
116
+ label: 'Disabled',
117
+ },
118
+ {
119
+ value: '1',
120
+ label: '1 hour',
121
+ },
122
+ {
123
+ value: '3',
124
+ label: '3 hours',
125
+ },
126
+ {
127
+ value: '6',
128
+ label: '6 hours',
129
+ },
130
+ {
131
+ value: '12',
132
+ label: '12 hours',
133
+ },
134
+ {
135
+ value: '24',
136
+ label: '24 hours',
137
+ },
138
+ ],
139
+ },
140
+ ...fields,
141
+ ];
142
+ });
143
+ }
144
+ if (!integration.checkConnection) {
145
+ integration.checkConnection = (apiCredentials) => __awaiter(this, void 0, void 0, function* () {
146
+ yield integration.getIntegrationFiles(apiCredentials);
147
+ });
148
+ }
149
+ }
150
+ exports.applyDefaults = applyDefaults;
@@ -1,6 +1,5 @@
1
- import Crowdin, { SourceFilesModel } from '@crowdin/crowdin-api-client';
2
1
  import { Request, Response } from 'express';
3
- import { Config, CronJob, CrowdinCredentials, IntegrationCredentials, IntegrationLogic, Logger } from '../models';
2
+ import { Logger } from '../models';
4
3
  export declare class CodeError extends Error {
5
4
  code: number | undefined;
6
5
  constructor(message: string, code?: number);
@@ -10,10 +9,3 @@ export declare function getMessage(err: any): any;
10
9
  export declare function runAsyncWrapper(callback: Function, onError?: (e: any) => void): (req: Request, res: Response, next: Function) => void;
11
10
  export declare function encryptData(secret: string, data: string): string;
12
11
  export declare function decryptData(secret: string, data: string): string;
13
- export declare function getOauthRoute(integration: IntegrationLogic): string;
14
- export declare function getRootFolder(config: Config, integration: IntegrationLogic, client: Crowdin, projectId: number): Promise<SourceFilesModel.Directory | undefined>;
15
- export declare function applyDefaults(config: Config, integration: IntegrationLogic): void;
16
- export declare function prepareCrowdinClient(config: Config, credentials: CrowdinCredentials): Promise<Crowdin>;
17
- export declare function prepareIntegrationCredentials(config: Config, integration: IntegrationLogic, integrationCredentials: IntegrationCredentials): Promise<any>;
18
- export declare function runJob(config: Config, integration: IntegrationLogic, job: CronJob): Promise<void>;
19
- export declare function filesCron(config: Config, integration: IntegrationLogic, period: string): Promise<void>;
package/out/util/index.js CHANGED
@@ -27,16 +27,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
27
27
  step((generator = generator.apply(thisArg, _arguments || [])).next());
28
28
  });
29
29
  };
30
- var __importDefault = (this && this.__importDefault) || function (mod) {
31
- return (mod && mod.__esModule) ? mod : { "default": mod };
32
- };
33
30
  Object.defineProperty(exports, "__esModule", { value: true });
34
- exports.filesCron = exports.runJob = exports.prepareIntegrationCredentials = exports.prepareCrowdinClient = exports.applyDefaults = exports.getRootFolder = exports.getOauthRoute = exports.decryptData = exports.encryptData = exports.runAsyncWrapper = exports.getMessage = exports.log = exports.CodeError = void 0;
35
- const crowdin_api_client_1 = __importDefault(require("@crowdin/crowdin-api-client"));
36
- const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
37
- const axios_1 = __importDefault(require("axios"));
31
+ exports.decryptData = exports.encryptData = exports.runAsyncWrapper = exports.getMessage = exports.log = exports.CodeError = void 0;
38
32
  const crypto = __importStar(require("crypto-js"));
39
- const models_1 = require("../models");
40
33
  const storage_1 = require("../storage");
41
34
  class CodeError extends Error {
42
35
  constructor(message, code) {
@@ -110,250 +103,3 @@ function decryptData(secret, data) {
110
103
  return crypto.AES.decrypt(data, secret).toString(crypto.enc.Utf8);
111
104
  }
112
105
  exports.decryptData = decryptData;
113
- function getOauthRoute(integration) {
114
- var _a;
115
- return ((_a = integration.oauthLogin) === null || _a === void 0 ? void 0 : _a.redirectUriRoute) || '/oauth/code';
116
- }
117
- exports.getOauthRoute = getOauthRoute;
118
- function getRootFolder(config, integration, client, projectId) {
119
- return __awaiter(this, void 0, void 0, function* () {
120
- if (!integration.withRootFolder) {
121
- return;
122
- }
123
- const folder = integration.appFolderName || config.name;
124
- const directories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId)).data.map(d => d.data);
125
- const { folder: rootFolder } = yield crowdinAppFunctions.getOrCreateFolder(directories, client, projectId, folder);
126
- return rootFolder;
127
- });
128
- }
129
- exports.getRootFolder = getRootFolder;
130
- function applyDefaults(config, integration) {
131
- if (!integration.getCrowdinFiles) {
132
- integration.getCrowdinFiles = (projectId, client, rootFolder) => __awaiter(this, void 0, void 0, function* () {
133
- let allDirectories;
134
- if (rootFolder) {
135
- allDirectories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId, {
136
- directoryId: rootFolder.id,
137
- recursion: 'true',
138
- })).data.map(d => d.data);
139
- }
140
- else {
141
- allDirectories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId)).data.map(d => d.data);
142
- }
143
- const directoryIds = allDirectories.map(d => d.id);
144
- let files = (yield client.sourceFilesApi.withFetchAll().listProjectFiles(projectId)).data.map(d => d.data);
145
- files = files.filter(f => (rootFolder && f.directoryId === rootFolder.id) ||
146
- directoryIds.includes(f.directoryId) ||
147
- (!rootFolder && !f.directoryId));
148
- const res = [];
149
- allDirectories.forEach(e => {
150
- const parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
151
- res.push({
152
- id: e.id.toString(),
153
- parentId: parentId ? parentId.toString() : undefined,
154
- name: e.name,
155
- });
156
- });
157
- files.forEach(e => {
158
- const parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
159
- res.push({
160
- id: e.id.toString(),
161
- parentId: parentId ? parentId.toString() : undefined,
162
- name: e.title || e.name,
163
- type: e.type,
164
- });
165
- });
166
- return res;
167
- });
168
- }
169
- if (!integration.loginForm) {
170
- integration.loginForm = {
171
- fields: [
172
- {
173
- helpText: 'You need to create standard api key',
174
- key: 'apikey',
175
- label: `${config.name} API Key`,
176
- },
177
- ],
178
- };
179
- }
180
- if (integration.withCronSync) {
181
- const getUserSettings = integration.getConfiguration;
182
- integration.getConfiguration = (projectId, crowdinClient, integrationCredentials) => __awaiter(this, void 0, void 0, function* () {
183
- let fields = [];
184
- if (getUserSettings) {
185
- fields = yield getUserSettings(projectId, crowdinClient, integrationCredentials);
186
- }
187
- return [
188
- {
189
- key: 'schedule',
190
- label: 'Sync schedule',
191
- helpText: 'Set the frequency for pushing sources and translations',
192
- type: 'select',
193
- options: [
194
- {
195
- value: '0',
196
- label: 'Disabled',
197
- },
198
- {
199
- value: '1',
200
- label: '1 hour',
201
- },
202
- {
203
- value: '3',
204
- label: '3 hours',
205
- },
206
- {
207
- value: '6',
208
- label: '6 hours',
209
- },
210
- {
211
- value: '12',
212
- label: '12 hours',
213
- },
214
- {
215
- value: '24',
216
- label: '24 hours',
217
- },
218
- ],
219
- },
220
- ...fields,
221
- ];
222
- });
223
- }
224
- if (!integration.checkConnection) {
225
- integration.checkConnection = (apiCredentials) => __awaiter(this, void 0, void 0, function* () {
226
- yield integration.getIntegrationFiles(apiCredentials);
227
- });
228
- }
229
- }
230
- exports.applyDefaults = applyDefaults;
231
- function prepareCrowdinClient(config, credentials) {
232
- return __awaiter(this, void 0, void 0, function* () {
233
- const isExpired = +credentials.expire < +new Date().getTime() / 1000;
234
- if (!isExpired) {
235
- const crowdinToken = decryptData(config.clientSecret, credentials.accessToken);
236
- return new crowdin_api_client_1.default({
237
- token: crowdinToken,
238
- organization: credentials.type === models_1.AccountType.ENTERPRISE ? credentials.id : undefined,
239
- });
240
- }
241
- else {
242
- log('Crowdin credentials have expired. Requesting a new credentials', config.logger);
243
- const newCredentials = yield crowdinAppFunctions.refreshOAuthToken(config.clientId, config.clientSecret, decryptData(config.clientSecret, credentials.refreshToken));
244
- log('Saving updated crowdin credentials in the database', config.logger);
245
- yield (0, storage_1.updateCrowdinCredentials)({
246
- id: credentials.id,
247
- refreshToken: encryptData(config.clientSecret, newCredentials.refreshToken),
248
- accessToken: encryptData(config.clientSecret, newCredentials.accessToken),
249
- expire: (new Date().getTime() / 1000 + newCredentials.expiresIn).toString(),
250
- type: credentials.type,
251
- });
252
- return new crowdin_api_client_1.default({
253
- token: newCredentials.accessToken,
254
- organization: credentials.type === models_1.AccountType.ENTERPRISE ? credentials.id : undefined,
255
- });
256
- }
257
- });
258
- }
259
- exports.prepareCrowdinClient = prepareCrowdinClient;
260
- function prepareIntegrationCredentials(config, integration, integrationCredentials) {
261
- var _a, _b, _c, _d, _e, _f, _g, _h;
262
- return __awaiter(this, void 0, void 0, function* () {
263
- const credentials = JSON.parse(decryptData(config.clientSecret, integrationCredentials.credentials));
264
- if ((_a = integration.oauthLogin) === null || _a === void 0 ? void 0 : _a.refresh) {
265
- log('Checking if integration credentials need to be refreshed', config.logger);
266
- const oauthLogin = integration.oauthLogin;
267
- const { expireIn } = credentials;
268
- //2 min as an extra buffer
269
- const isExpired = expireIn + 120 < Date.now() / 1000;
270
- if (isExpired) {
271
- log('Integration credentials have expired. Requesting a new credentials', config.logger);
272
- let newCredentials;
273
- if (oauthLogin.performRefreshTokenRequest) {
274
- newCredentials = yield oauthLogin.performRefreshTokenRequest(credentials);
275
- }
276
- else {
277
- const url = oauthLogin.refreshTokenUrl || oauthLogin.accessTokenUrl;
278
- const request = {};
279
- request[((_b = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _b === void 0 ? void 0 : _b.clientId) || 'client_id'] = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.clientId;
280
- request[((_c = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _c === void 0 ? void 0 : _c.clientSecret) || 'client_secret'] = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.clientSecret;
281
- request[((_d = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _d === void 0 ? void 0 : _d.refreshToken) || 'refresh_token'] = credentials.refreshToken;
282
- if (oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.extraRefreshTokenParameters) {
283
- Object.entries(oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.extraRefreshTokenParameters).forEach(([key, value]) => (request[key] = value));
284
- }
285
- newCredentials = (yield axios_1.default.post(url || '', request, {
286
- headers: { Accept: 'application/json' },
287
- })).data;
288
- }
289
- credentials.accessToken = newCredentials[((_e = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _e === void 0 ? void 0 : _e.accessToken) || 'access_token'];
290
- credentials.expireIn =
291
- Number(newCredentials[((_f = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _f === void 0 ? void 0 : _f.expiresIn) || 'expires_in']) + Date.now() / 1000;
292
- if (newCredentials[((_g = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _g === void 0 ? void 0 : _g.refreshToken) || 'refresh_token']) {
293
- credentials.refreshToken = newCredentials[((_h = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _h === void 0 ? void 0 : _h.refreshToken) || 'refresh_token'];
294
- }
295
- log('Saving updated integration credentials in the database', config.logger);
296
- yield (0, storage_1.updateIntegrationCredentials)(integrationCredentials.id, encryptData(config.clientSecret, JSON.stringify(credentials)));
297
- }
298
- }
299
- return credentials;
300
- });
301
- }
302
- exports.prepareIntegrationCredentials = prepareIntegrationCredentials;
303
- function runJob(config, integration, job) {
304
- return __awaiter(this, void 0, void 0, function* () {
305
- log(`Starting cron job with expression [${job.expression}]`, config.logger);
306
- const crowdinCredentialsList = yield (0, storage_1.getAllCrowdinCredentials)();
307
- yield Promise.all(crowdinCredentialsList.map((crowdinCredentials) => __awaiter(this, void 0, void 0, function* () {
308
- const crowdinClient = yield prepareCrowdinClient(config, crowdinCredentials);
309
- const integrationCredentialsList = yield (0, storage_1.getAllIntegrationCredentials)(crowdinCredentials.id);
310
- yield Promise.all(integrationCredentialsList.map((integrationCredentials) => __awaiter(this, void 0, void 0, function* () {
311
- const projectId = crowdinAppFunctions.getProjectId(integrationCredentials.id);
312
- const apiCredentials = yield prepareIntegrationCredentials(config, integration, integrationCredentials);
313
- const rootFolder = yield getRootFolder(config, integration, crowdinClient, projectId);
314
- const intConfig = integrationCredentials.config
315
- ? JSON.parse(integrationCredentials.config)
316
- : undefined;
317
- log(`Executing task for cron job with expression [${job.expression}] for project ${projectId}`, config.logger);
318
- yield job.task(projectId, crowdinClient, apiCredentials, rootFolder, intConfig);
319
- log(`Task for cron job with expression [${job.expression}] for project ${projectId} completed`, config.logger);
320
- })));
321
- })));
322
- log(`Cron job with expression [${job.expression}] completed`, config.logger);
323
- });
324
- }
325
- exports.runJob = runJob;
326
- function filesCron(config, integration, period) {
327
- return __awaiter(this, void 0, void 0, function* () {
328
- log(`Starting files cron job with period [${period}]`, config.logger);
329
- const syncSettingsList = yield (0, storage_1.getAllSyncSettingsByType)('schedule');
330
- yield Promise.all(syncSettingsList.map((syncSettings) => __awaiter(this, void 0, void 0, function* () {
331
- const files = JSON.parse(syncSettings.files);
332
- const crowdinCredentials = yield (0, storage_1.getCrowdinCredentials)(syncSettings.crowdinId);
333
- const integrationCredentials = yield (0, storage_1.getIntegrationCredentials)(syncSettings.integrationId);
334
- if (crowdinCredentials && integrationCredentials) {
335
- const intConfig = integrationCredentials.config
336
- ? JSON.parse(integrationCredentials.config)
337
- : { schedule: '0' };
338
- if (period === intConfig.schedule) {
339
- const projectId = crowdinAppFunctions.getProjectId(integrationCredentials.id);
340
- const crowdinClient = yield prepareCrowdinClient(config, crowdinCredentials);
341
- const apiCredentials = yield prepareIntegrationCredentials(config, integration, integrationCredentials);
342
- const rootFolder = yield getRootFolder(config, integration, crowdinClient, projectId);
343
- if (syncSettings.provider === 'crowdin') {
344
- log(`Executing updateIntegration task for files cron job with period [${period}] for project ${projectId} and request ${JSON.stringify(files, null, 2)}`, config.logger);
345
- yield integration.updateIntegration(projectId, crowdinClient, apiCredentials, files, rootFolder, intConfig);
346
- log(`updateIntegration task for files cron job with period [${period}] for project ${projectId} completed`, config.logger);
347
- }
348
- else {
349
- log(`Executing updateCrowdin task for files cron job with period [${period}] for project ${projectId} and request ${JSON.stringify(files, null, 2)}`, config.logger);
350
- yield integration.updateCrowdin(projectId, crowdinClient, apiCredentials, files, rootFolder, intConfig);
351
- log(`updateCrowdin task for files cron job with period [${period}] for project ${projectId} completed`, config.logger);
352
- }
353
- }
354
- }
355
- })));
356
- log(`Files cron job with period [${period}] completed`, config.logger);
357
- });
358
- }
359
- exports.filesCron = filesCron;
@@ -32,6 +32,16 @@
32
32
  </crowdin-simple-integration>
33
33
  </div>
34
34
  <crowdin-toasts></crowdin-toasts>
35
+ <crowdin-modal id="subscription-modal" modal-width="50" close-button="false">
36
+ <div>
37
+ <crowdin-alert type="warning">Subscribe to continue using the {{name}} app.</crowdin-alert>
38
+ </div>
39
+ <div slot="footer">
40
+ <crowdin-button primary onclick="window.open(subscriptionLink,'_blank')">Subscribe</crowdin-button>
41
+ <crowdin-button outlined onclick="window.open('https://crowdin.com/contacts','_blank')">Contact us</crowdin-button>
42
+ <crowdin-button class="ml-10" secondary onclick="integrationLogout()">Log out</crowdin-button>
43
+ </div>
44
+ </crowdin-modal>
35
45
  {{#if infoModal}}
36
46
  <crowdin-modal id="info-modal" modal-width="50" modal-title="{{infoModal.title}}" close-button-title="Close">
37
47
  <div>
@@ -119,6 +129,7 @@
119
129
  document.body.addEventListener('uploadFilesToIntegration', uploadFilesToIntegration);
120
130
 
121
131
  const appComponent = document.querySelector('crowdin-simple-integration');
132
+ const subscriptionModal = document.getElementById('subscription-modal');
122
133
 
123
134
  const folderType = '0';
124
135
  const fileType = '1';
@@ -1,15 +1,20 @@
1
1
  <head>
2
- <meta charset="UTF-8">
3
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
4
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
5
- <title></title>
6
- <link rel="stylesheet" href="assets/css/styles.css">
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>
11
- <script type="text/javascript" src="https://cdn.crowdin.com/apps/dist/iframe.js"></script>
12
- <script type="text/javascript" src="assets/js/polyfills/promise.js"></script>
13
- <script type="text/javascript" src="assets/js/polyfills/fetch.js"></script>
14
- <script type="text/javascript" src="assets/js/main.js"></script>
2
+ <meta charset="UTF-8">
3
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
4
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
5
+ <title></title>
6
+ <link rel="stylesheet" href="assets/css/styles.css">
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>
11
+ <script type="text/javascript" src="https://cdn.crowdin.com/apps/dist/iframe.js"></script>
12
+ <script type="text/javascript" src="assets/js/polyfills/promise.js"></script>
13
+ <script type="text/javascript" src="assets/js/polyfills/fetch.js"></script>
14
+ <script type="text/javascript" src="assets/js/main.js"></script>
15
+ <style>
16
+ .ml-10 {
17
+ margin-left: 10px;
18
+ }
19
+ </style>
15
20
  </head>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
8
+ <title></title>
9
+ <script type="module"
10
+ src="https://crowdin-web-components.s3.amazonaws.com/crowdin-web-components/crowdin-web-components.esm.js"></script>
11
+ <script nomodule=""
12
+ src="https://crowdin-web-components.s3.amazonaws.com/crowdin-web-components/crowdin-web-components.js"></script>
13
+ <script type="text/javascript" src="https://cdn.crowdin.com/apps/dist/iframe.js"></script>
14
+ </head>
15
+
16
+ <body>
17
+ <div class="i_w center">
18
+ <crowdin-alert type="warning">Subscribe to continue using the {{name}} app.</crowdin-alert>
19
+ <br/>
20
+ <crowdin-button primary onclick="window.open('{{subscribeLink}}','_blank')">Subscribe</crowdin-button>
21
+ <crowdin-button outlined onclick="window.open('https://crowdin.com/contacts','_blank')">Contact us
22
+ </crowdin-button>
23
+ </div>
24
+ </body>
25
+
26
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.14.1",
3
+ "version": "0.15.1",
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",
@@ -12,7 +12,7 @@
12
12
  "test": "echo \"test not implemented\""
13
13
  },
14
14
  "dependencies": {
15
- "@crowdin/crowdin-apps-functions": "0.1.0",
15
+ "@crowdin/crowdin-apps-functions": "0.1.2",
16
16
  "crypto-js": "^4.0.0",
17
17
  "express": "4.17.1",
18
18
  "express-handlebars": "^5.3.4",