@crowdin/app-project-module 0.66.0 → 0.67.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/README.md +3 -17
- package/out/modules/ai-provider/handlers/chat-completions.js +75 -5
- package/out/modules/ai-provider/handlers/get-model-list.js +3 -2
- package/out/modules/ai-provider/types.d.ts +3 -0
- package/out/modules/install.js +10 -2
- package/out/modules/integration/index.js +1 -0
- package/out/static/css/crowdin-ui-colors.css +115 -0
- package/out/types.d.ts +8 -0
- package/out/util/handlebars.js +2 -2
- package/out/views/main.handlebars +15 -30
- package/out/views/partials/head.handlebars +1 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -2,26 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Module that will automatically add all necessary endpoints for Crowdin App.
|
|
4
4
|
|
|
5
|
-
:bookmark: See the [docs](/
|
|
5
|
+
:bookmark: See the [docs](https://crowdin.github.io/app-project-module/) for more information.
|
|
6
6
|
|
|
7
7
|
## Contributing
|
|
8
8
|
|
|
9
|
-
If you
|
|
9
|
+
If you would like to contribute please read the [Contributing](/CONTRIBUTING.md) guidelines.
|
|
10
10
|
|
|
11
11
|
## Seeking Assistance
|
|
12
12
|
|
|
13
|
-
If you find any problems or would like to suggest a feature, please feel free to file an issue on
|
|
14
|
-
|
|
15
|
-
If you've found an error in these samples, please [Contact Customer Success Service](https://crowdin.com/contacts).
|
|
16
|
-
|
|
17
|
-
## License
|
|
18
|
-
|
|
19
|
-
<pre>
|
|
20
|
-
The Crowdin App Project module is licensed under the MIT License.
|
|
21
|
-
See the LICENSE.md file distributed with this work for additional
|
|
22
|
-
information regarding copyright ownership.
|
|
23
|
-
|
|
24
|
-
Except as contained in the LICENSE file, the name(s) of the above copyright
|
|
25
|
-
holders shall not be used in advertising or otherwise to promote the sale,
|
|
26
|
-
use or other dealings in this Software without prior written authorization.
|
|
27
|
-
</pre>
|
|
13
|
+
If you find any problems or would like to suggest a feature, please feel free to file an issue on GitHub at [Issues Page](https://github.com/crowdin/app-project-module/issues) or [Contact Customer Success Service](https://crowdin.com/contacts).
|
|
@@ -13,13 +13,43 @@ const util_1 = require("../../../util");
|
|
|
13
13
|
const logger_1 = require("../../../util/logger");
|
|
14
14
|
const files_1 = require("../../integration/util/files");
|
|
15
15
|
const util_2 = require("../util");
|
|
16
|
+
// more about roles in AI messages https://platform.openai.com/docs/api-reference/chat/create#chat-create-messages
|
|
17
|
+
// Crowdin documentation https://support.crowdin.com/developer/crowdin-apps-module-custom-ai/#expected-response-from-the-app
|
|
18
|
+
const ROLES = {
|
|
19
|
+
assistant: 'assistant',
|
|
20
|
+
};
|
|
21
|
+
const DEFAULT_ROLE = ROLES.assistant;
|
|
22
|
+
const getErrorStatus = (e) => {
|
|
23
|
+
if (typeof e === 'object' && 'status' in e && typeof e.status === 'number') {
|
|
24
|
+
return e.status;
|
|
25
|
+
}
|
|
26
|
+
return 500;
|
|
27
|
+
};
|
|
28
|
+
const getErrorCode = (e) => {
|
|
29
|
+
if (typeof e === 'object' && 'code' in e) {
|
|
30
|
+
return e.code;
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
};
|
|
16
34
|
function handle(aiProvider) {
|
|
17
35
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
let isStream = false;
|
|
18
37
|
try {
|
|
19
38
|
let choices;
|
|
20
39
|
let message;
|
|
21
40
|
let data;
|
|
22
|
-
const
|
|
41
|
+
const chunks = [];
|
|
42
|
+
const { crowdinApiClient: client, crowdinContext: context, body: { messages, model, action, stream, responseFormat: { type: responseFormatType } = { type: undefined }, }, } = req;
|
|
43
|
+
isStream = !!stream;
|
|
44
|
+
const startStream = () => {
|
|
45
|
+
if (!res.headersSent) {
|
|
46
|
+
res.writeHead(200, {
|
|
47
|
+
Connection: 'keep-alive',
|
|
48
|
+
'Cache-Control': 'no-cache',
|
|
49
|
+
'Content-Type': 'text/event-stream',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
};
|
|
23
53
|
const result = yield aiProvider.chatCompletions({
|
|
24
54
|
messages,
|
|
25
55
|
model,
|
|
@@ -28,7 +58,32 @@ function handle(aiProvider) {
|
|
|
28
58
|
client,
|
|
29
59
|
context,
|
|
30
60
|
req,
|
|
61
|
+
isStream,
|
|
62
|
+
sendEvent: ({ content, role }) => __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
if (!isStream) {
|
|
64
|
+
chunks.push({ content, role });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
startStream();
|
|
68
|
+
const message = {
|
|
69
|
+
choices: [
|
|
70
|
+
{
|
|
71
|
+
delta: {
|
|
72
|
+
role: role || DEFAULT_ROLE,
|
|
73
|
+
content,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
res.write(`data: ${JSON.stringify(message)}\n\n`);
|
|
79
|
+
}),
|
|
31
80
|
});
|
|
81
|
+
if (isStream) {
|
|
82
|
+
startStream();
|
|
83
|
+
res.write('[DONE]');
|
|
84
|
+
res.end();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
32
87
|
if ((0, files_1.isExtendedResultType)(result)) {
|
|
33
88
|
data = result.data;
|
|
34
89
|
message = result.message;
|
|
@@ -36,10 +91,18 @@ function handle(aiProvider) {
|
|
|
36
91
|
else {
|
|
37
92
|
data = result;
|
|
38
93
|
}
|
|
94
|
+
if (chunks.length) {
|
|
95
|
+
data = [
|
|
96
|
+
{
|
|
97
|
+
role: chunks[0].role || DEFAULT_ROLE,
|
|
98
|
+
content: chunks.map((chunk) => chunk.content).join(''),
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
}
|
|
39
102
|
if (data && data.length > 0) {
|
|
40
103
|
choices = data.map((message) => ({
|
|
41
104
|
message: {
|
|
42
|
-
role: message.role ||
|
|
105
|
+
role: message.role || DEFAULT_ROLE,
|
|
43
106
|
content: message.content,
|
|
44
107
|
},
|
|
45
108
|
}));
|
|
@@ -50,10 +113,17 @@ function handle(aiProvider) {
|
|
|
50
113
|
if (req.logError) {
|
|
51
114
|
req.logError(e);
|
|
52
115
|
}
|
|
53
|
-
if (
|
|
54
|
-
res.status(429);
|
|
116
|
+
if (!res.headersSent) {
|
|
117
|
+
res.status((0, util_2.isRateLimitError)(e) ? 429 : getErrorStatus(e));
|
|
118
|
+
}
|
|
119
|
+
if (isStream && res.headersSent) {
|
|
120
|
+
res.write(`data: ${JSON.stringify({ error: { message: (0, logger_1.getErrorMessage)(e), code: getErrorCode(e) } })}\n\n`);
|
|
121
|
+
res.write('[DONE]');
|
|
122
|
+
res.end();
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
res.send({ error: { message: (0, logger_1.getErrorMessage)(e) } });
|
|
55
126
|
}
|
|
56
|
-
res.send({ error: { message: (0, logger_1.getErrorMessage)(e) } });
|
|
57
127
|
}
|
|
58
128
|
}));
|
|
59
129
|
}
|
|
@@ -22,12 +22,13 @@ function handle(aiProvider) {
|
|
|
22
22
|
context: req.crowdinContext,
|
|
23
23
|
});
|
|
24
24
|
const data = modelList.map((model) => {
|
|
25
|
-
var _a, _b, _c;
|
|
25
|
+
var _a, _b, _c, _d;
|
|
26
26
|
return ({
|
|
27
27
|
id: model.id,
|
|
28
28
|
supportsJsonMode: (_a = model.supportsJsonMode) !== null && _a !== void 0 ? _a : false,
|
|
29
29
|
supportsFunctionCalling: (_b = model.supportsFunctionCalling) !== null && _b !== void 0 ? _b : false,
|
|
30
|
-
|
|
30
|
+
supportsStreaming: (_c = model.supportsStreaming) !== null && _c !== void 0 ? _c : false,
|
|
31
|
+
contextWindowLimit: (_d = model.contextWindowLimit) !== null && _d !== void 0 ? _d : exports.CONTEXT_WINDOW_LIMIT,
|
|
31
32
|
});
|
|
32
33
|
});
|
|
33
34
|
res.send({ data });
|
|
@@ -25,6 +25,8 @@ export interface AiProviderModule extends Environments {
|
|
|
25
25
|
client: Crowdin;
|
|
26
26
|
context: CrowdinContextInfo;
|
|
27
27
|
req: CrowdinClientRequest;
|
|
28
|
+
isStream: boolean;
|
|
29
|
+
sendEvent: (chunk: Message) => Promise<void>;
|
|
28
30
|
}) => Promise<Message[] | ExtendedResult<Message[]>>;
|
|
29
31
|
/**
|
|
30
32
|
* provides a list of available model
|
|
@@ -38,6 +40,7 @@ export interface SupportedModels {
|
|
|
38
40
|
id: string;
|
|
39
41
|
supportsJsonMode?: boolean;
|
|
40
42
|
supportsFunctionCalling?: boolean;
|
|
43
|
+
supportsStreaming?: boolean;
|
|
41
44
|
contextWindowLimit?: number;
|
|
42
45
|
}
|
|
43
46
|
export interface Message {
|
package/out/modules/install.js
CHANGED
|
@@ -14,16 +14,19 @@ const types_1 = require("../types");
|
|
|
14
14
|
const storage_1 = require("../storage");
|
|
15
15
|
const util_1 = require("../util");
|
|
16
16
|
const logger_1 = require("../util/logger");
|
|
17
|
+
const connection_1 = require("../util/connection");
|
|
17
18
|
function handle(config) {
|
|
18
19
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
19
20
|
const event = req.body;
|
|
20
21
|
(0, logger_1.log)(`Received install request ${JSON.stringify(event, null, 2)}`);
|
|
21
22
|
const token = yield fetchToken(config, event);
|
|
23
|
+
const userId = event.userId;
|
|
24
|
+
const organization = (event.domain || event.organizationId).toString();
|
|
22
25
|
const credentials = {
|
|
23
|
-
id:
|
|
26
|
+
id: organization,
|
|
24
27
|
appSecret: event.appSecret,
|
|
25
28
|
domain: event.domain,
|
|
26
|
-
userId
|
|
29
|
+
userId,
|
|
27
30
|
agentId: event.agentId,
|
|
28
31
|
organizationId: event.organizationId,
|
|
29
32
|
baseUrl: event.baseUrl,
|
|
@@ -41,6 +44,11 @@ function handle(config) {
|
|
|
41
44
|
yield (0, storage_1.getStorage)().saveCrowdinCredentials(credentials);
|
|
42
45
|
(0, logger_1.log)('A new App has been installed');
|
|
43
46
|
}
|
|
47
|
+
if (config.onInstall) {
|
|
48
|
+
const { client } = yield (0, connection_1.prepareCrowdinClient)({ config, credentials, autoRenew: true });
|
|
49
|
+
(0, logger_1.log)('Invoking onInstall hook');
|
|
50
|
+
yield config.onInstall({ organization, userId, client });
|
|
51
|
+
}
|
|
44
52
|
res.status(204).end();
|
|
45
53
|
}));
|
|
46
54
|
}
|
|
@@ -106,6 +106,7 @@ function register({ config, app }) {
|
|
|
106
106
|
cron.schedule('0 */3 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '3' }).catch(console.error));
|
|
107
107
|
cron.schedule('0 */6 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '6' }).catch(console.error));
|
|
108
108
|
cron.schedule('0 */12 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '12' }).catch(console.error));
|
|
109
|
+
cron.schedule('0 0 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '24' }).catch(console.error));
|
|
109
110
|
}
|
|
110
111
|
// remove user errors
|
|
111
112
|
cron.schedule('0 0 * * *', () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* text color */
|
|
2
|
+
*[class*="crdn-text"] {
|
|
3
|
+
color: var(--crdn-color, var(--crowdin-body-color));
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.crdn-text\:primary {
|
|
7
|
+
--crdn-color: var(--crowdin-primary);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.crdn-text\:title {
|
|
11
|
+
--crdn-color: var(--crowdin-title-color);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.crdn-text\:body {
|
|
15
|
+
--crdn-color: var(--crowdin-body-color);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.crdn-text\:muted {
|
|
19
|
+
--crdn-color: var(--crowdin-text-muted);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.crdn-text\:disabled {
|
|
23
|
+
--crdn-color: var(--crowdin-text-disabled);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.crdn-text\:info {
|
|
27
|
+
--crdn-color: var(--crowdin-info)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.crdn-text\:success {
|
|
31
|
+
--crdn-color: var(--crowdin-success)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.crdn-text\:warning {
|
|
35
|
+
--crdn-color: var(--crowdin-warning)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.crdn-text\:danger {
|
|
39
|
+
--crdn-color: var(--crowdin-danger)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* backgrounds */
|
|
43
|
+
|
|
44
|
+
*[class*="crdn-bg"] {
|
|
45
|
+
background-color: var(--crdn-bg, var(--crowdin-body-bg));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.crdn-bg\:lvl-0 {
|
|
49
|
+
--crdn-bg: var(--crowdin-level-0-bg);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.crdn-bg\:lvl-1 {
|
|
53
|
+
--crdn-bg: var(--crowdin-level-1-bg);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.crdn-bg\:lvl-2 {
|
|
57
|
+
--crdn-bg: var(--crowdin-level-2-bg);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.crdn-bg\:lvl-2\:05 {
|
|
61
|
+
--crdn-bg: var(--crowdin-level-2-bg-05);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.crdn-bg\:lvl-3 {
|
|
65
|
+
--crdn-bg: var(--crowdin-level-3-bg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.crdn-bg\:primary {
|
|
69
|
+
--crdn-bg: var(--crowdin-primary);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.crdn-bg\:success {
|
|
73
|
+
--crdn-bg: var(--crowdin-success-bg)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.crdn-bg\:success {
|
|
77
|
+
--crdn-bg: var(--crowdin-success-bg)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
.crdn-bg\:warning {
|
|
82
|
+
--crdn-bg: var(--crowdin-warning-bg)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.crdn-bg\:danger {
|
|
86
|
+
--crdn-bg: var(--crowdin-danger-bg)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* borders */
|
|
90
|
+
|
|
91
|
+
*[class*="crdn-border"] {
|
|
92
|
+
border-width: 1px;
|
|
93
|
+
border-style: solid;
|
|
94
|
+
border-color: var(--crdn-border, var(--crowdin-border-color));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.crdn-border\:primary {
|
|
98
|
+
--crdn-border: var(--crowdin-primary);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.crdn-border\:danger {
|
|
102
|
+
--crdn-border: var(--crowdin-danger);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.crdn-border\:info {
|
|
106
|
+
--crdn-border: var(--crowdin-danger);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.crdn-border\:success {
|
|
110
|
+
--crdn-border: var(--crowdin-success);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.crdn-border\:warning {
|
|
114
|
+
--crdn-border: var(--crowdin-warning);
|
|
115
|
+
}
|
package/out/types.d.ts
CHANGED
|
@@ -140,6 +140,14 @@ export interface ClientConfig extends ImagePath {
|
|
|
140
140
|
* modal module
|
|
141
141
|
*/
|
|
142
142
|
modal?: ModuleContent & UiModule & Environments;
|
|
143
|
+
/**
|
|
144
|
+
* Install hook
|
|
145
|
+
*/
|
|
146
|
+
onInstall?: ({ organization, userId, client, }: {
|
|
147
|
+
organization: string;
|
|
148
|
+
userId: number;
|
|
149
|
+
client: Crowdin;
|
|
150
|
+
}) => Promise<void>;
|
|
143
151
|
/**
|
|
144
152
|
* Uninstall hook for cleanup logic
|
|
145
153
|
*/
|
package/out/util/handlebars.js
CHANGED
|
@@ -25,10 +25,10 @@ exports.engine = (0, express_handlebars_1.default)({
|
|
|
25
25
|
if (a !== undefined && a !== null && b !== undefined && b !== null) {
|
|
26
26
|
let bArray;
|
|
27
27
|
if (Array.isArray(b)) {
|
|
28
|
-
bArray = b;
|
|
28
|
+
bArray = b.map((item) => item.toString());
|
|
29
29
|
}
|
|
30
30
|
else {
|
|
31
|
-
bArray = b.split(' ');
|
|
31
|
+
bArray = b.toString().split(' ');
|
|
32
32
|
}
|
|
33
33
|
if (bArray.includes(a === null || a === void 0 ? void 0 : a.toString())) {
|
|
34
34
|
return options.fn(this);
|
|
@@ -44,18 +44,6 @@
|
|
|
44
44
|
{{/if}}
|
|
45
45
|
<crowdin-button icon-before="account_circle" onclick="integrationLogout()">Log out</crowdin-button>
|
|
46
46
|
</div>
|
|
47
|
-
{{#if uploadTranslations}}
|
|
48
|
-
<crowdin-alert id="translation-info" no-icon="true" style="display: none;">
|
|
49
|
-
<div class="box-center">
|
|
50
|
-
<p class="info-text">
|
|
51
|
-
We recommend importing existing translations into your Crowdin project for newly uploaded source content.
|
|
52
|
-
Please note that translations imported for non-key-value formats may require additional review.
|
|
53
|
-
Read more about <crowdin-a href="https://support.crowdin.com/uploading-translations/" target="_blank">Uploading Translations</crowdin-a>.
|
|
54
|
-
</p>
|
|
55
|
-
</div>
|
|
56
|
-
<crowdin-button onclick="closeAlert(this)" class="dismiss-alert" icon>close</crowdin-button>
|
|
57
|
-
</crowdin-alert>
|
|
58
|
-
{{/if}}
|
|
59
47
|
</div>
|
|
60
48
|
<crowdin-simple-integration
|
|
61
49
|
async-progress
|
|
@@ -83,7 +71,7 @@
|
|
|
83
71
|
integration-name="{{name}}"
|
|
84
72
|
integration-logo="logo.png"
|
|
85
73
|
{{#if uploadTranslations}}
|
|
86
|
-
integration-button-menu-items='[{"label":"
|
|
74
|
+
integration-button-menu-items='[{"label":"Sync translations", "title":"Sync translations to Crowdin", "action":"uploadTranslations"}]'
|
|
87
75
|
{{/if}}
|
|
88
76
|
{{#if filtering.crowdinLanguages}}
|
|
89
77
|
crowdin-filter
|
|
@@ -126,7 +114,7 @@
|
|
|
126
114
|
<crowdin-modal
|
|
127
115
|
id="settings-modal"
|
|
128
116
|
body-overflow-unset="{{#checkLength configurationFields 3}}false{{else}}true{{/checkLength}}"
|
|
129
|
-
modal-width="
|
|
117
|
+
modal-width="65"
|
|
130
118
|
modal-title="Settings"
|
|
131
119
|
close-button-title="Close"
|
|
132
120
|
>
|
|
@@ -179,6 +167,7 @@
|
|
|
179
167
|
{{#if dependencySettings}}
|
|
180
168
|
data-dependency="{{dependencySettings}}"
|
|
181
169
|
{{/if}}
|
|
170
|
+
is-position-fixed
|
|
182
171
|
>
|
|
183
172
|
{{#each options}}
|
|
184
173
|
<option
|
|
@@ -467,18 +456,19 @@
|
|
|
467
456
|
appComponent.setIntegrationFilesData(tree);
|
|
468
457
|
} else if (tree.length) {
|
|
469
458
|
appComponent.pushIntegrationFilesData(tree).then(() => {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
459
|
+
if (parentId) {
|
|
460
|
+
appIntegrationFiles.getSelected().then(selection => {
|
|
461
|
+
const selectedIds = selection?.filter((node) => node).map(({id}) => id.toString());
|
|
462
|
+
if (!selectedIds?.length) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const filteredNodes = tree.filter((node) => selectedIds.includes(node.parent_id.toString()));
|
|
466
|
+
filteredNodes.forEach((node) => {
|
|
467
|
+
selectedIds.push(node.id);
|
|
468
|
+
});
|
|
469
|
+
appIntegrationFiles.setSelected(selectedIds);
|
|
479
470
|
});
|
|
480
|
-
|
|
481
|
-
});
|
|
471
|
+
}
|
|
482
472
|
});
|
|
483
473
|
}
|
|
484
474
|
{{#if integrationPagination}}
|
|
@@ -1118,11 +1108,6 @@
|
|
|
1118
1108
|
localStorage.setItem(`revised_${name}`, 1);
|
|
1119
1109
|
}
|
|
1120
1110
|
|
|
1121
|
-
{{#if uploadTranslations}}
|
|
1122
|
-
const translationInfo = document.getElementById('translation-info');
|
|
1123
|
-
checkAlert(translationInfo);
|
|
1124
|
-
{{/if}}
|
|
1125
|
-
|
|
1126
1111
|
{{#if notice}}
|
|
1127
1112
|
const notice = document.getElementById('notice');
|
|
1128
1113
|
checkAlert(notice, 'notice');
|
|
@@ -4,6 +4,7 @@
|
|
|
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
|
+
<link rel="stylesheet" href="/assets/css/crowdin-ui-colors.css">
|
|
7
8
|
<script type="module"
|
|
8
9
|
src="https://crowdin-web-components.s3.amazonaws.com/crowdin-web-components/crowdin-web-components.esm.js"></script>
|
|
9
10
|
<script nomodule=""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crowdin/app-project-module",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.67.0",
|
|
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",
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
"@aws-sdk/client-s3": "^3.606.0",
|
|
22
22
|
"@aws-sdk/s3-request-presigner": "^3.598.0",
|
|
23
23
|
"@crowdin/crowdin-apps-functions": "0.8.1",
|
|
24
|
-
"@crowdin/logs-formatter": "^2.1.
|
|
24
|
+
"@crowdin/logs-formatter": "^2.1.6",
|
|
25
25
|
"@godaddy/terminus": "^4.12.1",
|
|
26
26
|
"amqplib": "^0.10.4",
|
|
27
27
|
"crypto-js": "^4.2.0",
|
|
28
|
-
"express": "4.
|
|
28
|
+
"express": "^4.21.0",
|
|
29
29
|
"express-handlebars": "^5.3.5",
|
|
30
30
|
"lodash.get": "^4.4.2",
|
|
31
31
|
"lodash.uniqby": "^4.7.0",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"@types/express": "4.17.21",
|
|
59
59
|
"@types/express-handlebars": "^5.3.1",
|
|
60
60
|
"@types/jest": "^29.5.12",
|
|
61
|
-
"@types/lodash.uniqby": "^4.7.9",
|
|
62
61
|
"@types/lodash.get": "^4.4.9",
|
|
62
|
+
"@types/lodash.uniqby": "^4.7.9",
|
|
63
63
|
"@types/node": "^16.18.101",
|
|
64
64
|
"@types/node-cron": "^3.0.11",
|
|
65
65
|
"@types/pg": "^8.11.6",
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"@types/uuid": "^9.0.7",
|
|
68
68
|
"@typescript-eslint/eslint-plugin": "^2.3.1",
|
|
69
69
|
"@typescript-eslint/parser": "^2.3.1",
|
|
70
|
+
"auto-changelog": "^2.5.0",
|
|
70
71
|
"eslint": "^6.4.0",
|
|
71
72
|
"eslint-config-prettier": "^6.3.0",
|
|
72
73
|
"eslint-plugin-prettier": "^3.1.1",
|