@crowdin/app-project-module 0.9.0 → 0.10.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 CHANGED
@@ -11,6 +11,13 @@ Module expose two main methods:
11
11
 
12
12
  In both options you will need to provide Crowdin App configuration file. Please refer to jsdoc for more details.
13
13
 
14
+ `addCrowdinEndpoints` will return an object with several methods to help you add your own custom logic [see example](#resources).
15
+
16
+ - `saveMetadata` to save metadata (may be associated with an organization, project, etc)
17
+ - `getMetadata` to get metadata
18
+ - `deleteMetadata` to delete metadata (usually useful in `onUninstall` hook)
19
+ - `establishCrowdinConnection` method that accept jwt token that you may forward from module UI and it will return back Crowdin client instance and the context.
20
+
14
21
  ## Status
15
22
 
16
23
  [![npm](https://img.shields.io/npm/v/@crowdin/app-project-module?logo=npm&cacheSeconds=1800)](https://www.npmjs.com/package/@crowdin/app-project-module)
@@ -32,6 +39,7 @@ In both options you will need to provide Crowdin App configuration file. Please
32
39
  - [Custom File Format](#custom-file-format)
33
40
  - [Custom MT](#custom-mt)
34
41
  - [Resources](#resources)
42
+ - [Other modules](#other-modules)
35
43
  - [Contributing](#contributing)
36
44
  - [Seeking Assistance](#seeking-assistance)
37
45
  - [License](#license)
@@ -526,11 +534,7 @@ app.post('/metadata', async (req, res) => {
526
534
  const { context } = await crowdinApp.establishCrowdinConnection(req.query.jwt);
527
535
  const organization = context.jwtPayload.domain || context.jwtPayload.context.organization_id;
528
536
  const metadata = await crowdinApp.getMetadata(organization);
529
- if (metadata) {
530
- await crowdinApp.updateMetadata(organization, req.body);
531
- } else {
532
- await crowdinApp.saveMetadata(organization, req.body);
533
- }
537
+ await crowdinApp.saveMetadata(organization, req.body);
534
538
  res.status(204).end();
535
539
  });
536
540
 
@@ -544,6 +548,38 @@ app.get('/metadata', async (req, res) => {
544
548
  app.listen(3000, () => console.log('Crowdin app started'));
545
549
  ```
546
550
 
551
+ ## Other modules
552
+
553
+ Framework also supports following modules:
554
+
555
+ - [editor-panels module](https://support.crowdin.com/crowdin-apps-modules/#editor-panels-module)
556
+ - [project menu module](https://support.crowdin.com/crowdin-apps-modules/#project-menu-module)
557
+ - [tools module](https://support.crowdin.com/crowdin-apps-modules/#tools-module)
558
+ - [reports module](https://support.crowdin.com/crowdin-apps-modules/#reports-module)
559
+
560
+ Example of Reports Module:
561
+
562
+ ```javascript
563
+ const crowdinModule = require('@crowdin/app-project-module');
564
+
565
+ const configuration = {
566
+ baseUrl: 'https://123.ngrok.io',
567
+ clientId: 'clientId',
568
+ clientSecret: 'clientSecret',
569
+ name: 'Sample App',
570
+ identifier: 'sample-app',
571
+ description: 'Sample App description',
572
+ dbFolder: __dirname,
573
+ imagePath: __dirname + '/' + 'logo.png',
574
+ reports: { //can be editorPanels, projectMenu, tools
575
+ fileName: 'reports.html', //optional, only needed if file is not index.html
576
+ uiPath: __dirname + '/' + 'public' // folder where UI of the module is located (js, html, css files)
577
+ },
578
+ };
579
+
580
+ crowdinModule.createApp(configuration);
581
+ ```
582
+
547
583
  ## Contributing
548
584
 
549
585
  If you want to contribute please read the [Contributing](/CONTRIBUTING.md) guidelines.
@@ -16,6 +16,10 @@ function handle(config, integration) {
16
16
  if (integration.checkConnection) {
17
17
  yield integration.checkConnection(req.body.credentials);
18
18
  }
19
+ const existing = yield (0, storage_1.getIntegrationCredentials)(req.crowdinContext.clientId);
20
+ if (!!existing) {
21
+ yield (0, storage_1.deleteIntegrationCredentials)(req.crowdinContext.clientId);
22
+ }
19
23
  yield (0, storage_1.saveIntegrationCredentials)(req.crowdinContext.clientId, (0, util_1.encryptData)(config.clientSecret, JSON.stringify(req.body.credentials)), req.crowdinContext.crowdinId);
20
24
  res.status(204).end();
21
25
  }));
@@ -50,6 +50,48 @@ function handle(config) {
50
50
  },
51
51
  ];
52
52
  }
53
+ if (config.editorPanels) {
54
+ modules['editor-panels'] = [
55
+ {
56
+ key: config.identifier + '-editor-panels',
57
+ name: config.name,
58
+ position: 'right',
59
+ url: '/editor-panels/' + (config.editorPanels.fileName || 'index.html'),
60
+ modes: config.editorPanels.modes,
61
+ },
62
+ ];
63
+ }
64
+ if (config.projectMenu) {
65
+ modules['project-menu'] = [
66
+ {
67
+ key: config.identifier + '-project-menu',
68
+ name: config.name,
69
+ url: '/project-menu/' + (config.projectMenu.fileName || 'index.html'),
70
+ },
71
+ ];
72
+ }
73
+ if (config.tools) {
74
+ modules['tools'] = [
75
+ {
76
+ key: config.identifier + '-tools',
77
+ name: config.name,
78
+ description: config.description,
79
+ logo: '/logo.png',
80
+ icon: '/logo.png',
81
+ url: '/tools/' + (config.tools.fileName || 'index.html'),
82
+ },
83
+ ];
84
+ }
85
+ if (config.reports) {
86
+ modules['reports'] = [
87
+ {
88
+ key: config.identifier + '-reports',
89
+ name: config.name,
90
+ description: config.description,
91
+ url: '/reports/' + (config.reports.fileName || 'index.html'),
92
+ },
93
+ ];
94
+ }
53
95
  return (_req, res) => {
54
96
  const manifest = {
55
97
  identifier: config.identifier,
package/out/index.js CHANGED
@@ -18,6 +18,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
18
18
  __setModuleDefault(result, mod);
19
19
  return result;
20
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
+ };
21
30
  var __importDefault = (this && this.__importDefault) || function (mod) {
22
31
  return (mod && mod.__esModule) ? mod : { "default": mod };
23
32
  };
@@ -103,10 +112,29 @@ function addCrowdinEndpoints(app, config) {
103
112
  if (config.resources) {
104
113
  app.use('/resources', express_1.default.static(config.resources.uiPath));
105
114
  }
115
+ if (config.editorPanels) {
116
+ app.use('/editor-panels', express_1.default.static(config.editorPanels.uiPath));
117
+ }
118
+ if (config.projectMenu) {
119
+ app.use('/project-menu', express_1.default.static(config.projectMenu.uiPath));
120
+ }
121
+ if (config.tools) {
122
+ app.use('/tools', express_1.default.static(config.tools.uiPath));
123
+ }
124
+ if (config.reports) {
125
+ app.use('/reports', express_1.default.static(config.reports.uiPath));
126
+ }
106
127
  return {
107
128
  getMetadata: storage.getMetadata,
108
- saveMetadata: storage.saveMetadata,
109
- updateMetadata: storage.updateMetadata,
129
+ saveMetadata: (id, metadata) => __awaiter(this, void 0, void 0, function* () {
130
+ const existing = yield storage.getMetadata(id);
131
+ if (existing) {
132
+ yield storage.updateMetadata(id, metadata);
133
+ }
134
+ else {
135
+ yield storage.saveMetadata(id, metadata);
136
+ }
137
+ }),
110
138
  deleteMetadata: storage.deleteMetadata,
111
139
  establishCrowdinConnection: jwtToken => (0, crowdin_client_1.prepareCrowdinRequest)(jwtToken, config),
112
140
  };
@@ -53,7 +53,23 @@ export interface Config {
53
53
  /**
54
54
  * resources module
55
55
  */
56
- resources?: Resources;
56
+ resources?: UiModule;
57
+ /**
58
+ * editor-panels module
59
+ */
60
+ editorPanels?: EditorPanels;
61
+ /**
62
+ * project menu module
63
+ */
64
+ projectMenu?: UiModule;
65
+ /**
66
+ * tools module
67
+ */
68
+ tools?: UiModule;
69
+ /**
70
+ * reports module
71
+ */
72
+ reports?: UiModule;
57
73
  /**
58
74
  * Uninstall hook for cleanup logic
59
75
  */
@@ -234,7 +250,7 @@ export interface FormField {
234
250
  helpText?: string;
235
251
  helpTextHtml?: string;
236
252
  label: string;
237
- type?: 'text' | 'password';
253
+ type?: 'text' | 'password' | 'checkbox';
238
254
  }
239
255
  export declare type TreeItem = File | Folder;
240
256
  export interface File {
@@ -364,7 +380,7 @@ export interface CustomMTLogic {
364
380
  export interface CustomMTRequest {
365
381
  strings: string[];
366
382
  }
367
- export interface Resources {
383
+ export interface UiModule {
368
384
  /**
369
385
  * path to ui folder (e.g. {@example join(__dirname, 'public')})
370
386
  */
@@ -374,9 +390,20 @@ export interface Resources {
374
390
  */
375
391
  fileName?: string;
376
392
  }
393
+ export interface EditorPanels extends UiModule {
394
+ /**
395
+ * The Editor's mode list where the module will be available.
396
+ */
397
+ modes: EditorPanelsMode[];
398
+ }
399
+ export declare enum EditorPanelsMode {
400
+ ASSETS = "assets",
401
+ REVIEW = "review",
402
+ TRANSLATE = "TRANSLATE",
403
+ PROOFREAD = "proofread"
404
+ }
377
405
  export interface CrowdinAppUtilities {
378
406
  saveMetadata: (id: string, metadata: any) => Promise<void>;
379
- updateMetadata: (id: string, metadata: any) => Promise<void>;
380
407
  getMetadata: (id: string) => Promise<any | undefined>;
381
408
  deleteMetadata: (id: string) => Promise<void>;
382
409
  establishCrowdinConnection: (jwtToken: string) => Promise<{
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ProcessFileJobType = exports.AccountType = void 0;
3
+ exports.EditorPanelsMode = exports.ProcessFileJobType = exports.AccountType = void 0;
4
4
  var AccountType;
5
5
  (function (AccountType) {
6
6
  AccountType["NORMAL"] = "normal";
@@ -11,3 +11,10 @@ var ProcessFileJobType;
11
11
  ProcessFileJobType["PARSE_FILE"] = "parse-file";
12
12
  ProcessFileJobType["BUILD_FILE"] = "build-file";
13
13
  })(ProcessFileJobType = exports.ProcessFileJobType || (exports.ProcessFileJobType = {}));
14
+ var EditorPanelsMode;
15
+ (function (EditorPanelsMode) {
16
+ EditorPanelsMode["ASSETS"] = "assets";
17
+ EditorPanelsMode["REVIEW"] = "review";
18
+ EditorPanelsMode["TRANSLATE"] = "TRANSLATE";
19
+ EditorPanelsMode["PROOFREAD"] = "proofread";
20
+ })(EditorPanelsMode = exports.EditorPanelsMode || (exports.EditorPanelsMode = {}));
@@ -12,20 +12,36 @@
12
12
  {{else}}
13
13
  <div class="inputs">
14
14
  {{#each loginFields}}
15
- <crowdin-input
16
- id="{{key}}"
17
- label="{{label}}"
18
- {{#if helpText}}
19
- help-text="{{helpText}}"
20
- {{/if}}
21
- {{#if helpTextHtml}}
22
- help-text-html="{{helpTextHtml}}"
23
- {{/if}}
24
- {{#if type}}
25
- type="{{type}}"
26
- {{/if}}
27
- value="">
28
- </crowdin-input>
15
+ {{#ifeq type "checkbox"}}
16
+ <crowdin-checkbox
17
+ id="{{key}}"
18
+ label="{{label}}"
19
+ value="false"
20
+ use-switch
21
+ {{#if helpText}}
22
+ help-text="{{helpText}}"
23
+ {{/if}}
24
+ {{#if helpTextHtml}}
25
+ help-text-html="{{helpTextHtml}}"
26
+ {{/if}}
27
+ >
28
+ </crowdin-checkbox>
29
+ {{else}}
30
+ <crowdin-input
31
+ id="{{key}}"
32
+ label="{{label}}"
33
+ {{#if helpText}}
34
+ help-text="{{helpText}}"
35
+ {{/if}}
36
+ {{#if helpTextHtml}}
37
+ help-text-html="{{helpTextHtml}}"
38
+ {{/if}}
39
+ {{#if type}}
40
+ type="{{type}}"
41
+ {{/if}}
42
+ value="">
43
+ </crowdin-input>
44
+ {{/ifeq}}
29
45
  {{/each}}
30
46
  </div>
31
47
  {{/if}}
@@ -63,7 +79,11 @@
63
79
  function integrationLogin(oauthCredentials) {
64
80
  const credentials = oauthCredentials || {
65
81
  {{#each loginFields}}
66
- '{{key}}': document.querySelector('#{{key}}').getAttribute('value'),
82
+ {{#ifeq type "checkbox"}}
83
+ '{{key}}': !!document.querySelector('#{{key}}').checked,
84
+ {{else}}
85
+ '{{key}}': document.querySelector('#{{key}}').getAttribute('value'),
86
+ {{/ifeq}}
67
87
  {{/each}}
68
88
  };
69
89
  checkOrigin()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.9.0",
3
+ "version": "0.10.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",