@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 +41 -5
- package/out/handlers/integration-login.js +4 -0
- package/out/handlers/manifest.js +42 -0
- package/out/index.js +30 -2
- package/out/models/index.d.ts +31 -4
- package/out/models/index.js +8 -1
- package/out/views/login.handlebars +35 -15
- package/package.json +1 -1
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
|
[](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
|
-
|
|
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
|
}));
|
package/out/handlers/manifest.js
CHANGED
|
@@ -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:
|
|
109
|
-
|
|
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
|
};
|
package/out/models/index.d.ts
CHANGED
|
@@ -53,7 +53,23 @@ export interface Config {
|
|
|
53
53
|
/**
|
|
54
54
|
* resources module
|
|
55
55
|
*/
|
|
56
|
-
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
|
|
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<{
|
package/out/models/index.js
CHANGED
|
@@ -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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
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