@crowdin/app-project-module 0.26.6 → 0.28.0-10
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/CONTRIBUTING.md +19 -1
- package/README.md +1 -855
- package/out/handlers/crowdin-file-progress.d.ts +2 -2
- package/out/handlers/crowdin-file-progress.js +9 -4
- package/out/handlers/crowdin-update.js +4 -3
- package/out/handlers/crowdin-webhook.d.ts +4 -0
- package/out/handlers/crowdin-webhook.js +43 -0
- package/out/handlers/form-data-display.d.ts +3 -0
- package/out/handlers/form-data-display.js +46 -0
- package/out/handlers/form-data-save.d.ts +3 -0
- package/out/handlers/form-data-save.js +56 -0
- package/out/handlers/integration-logout.js +4 -0
- package/out/handlers/integration-webhook.d.ts +4 -0
- package/out/handlers/integration-webhook.js +39 -0
- package/out/handlers/main.js +7 -1
- package/out/handlers/settings-save.d.ts +2 -2
- package/out/handlers/settings-save.js +8 -3
- package/out/handlers/uninstall.js +4 -0
- package/out/index.js +50 -10
- package/out/middlewares/render-ui-module.d.ts +4 -0
- package/out/middlewares/render-ui-module.js +33 -0
- package/out/models/index.d.ts +79 -7
- package/out/models/index.js +13 -1
- package/out/static/css/styles.css +96 -0
- package/out/static/js/dependent.js +307 -0
- package/out/static/js/form.js +115 -0
- package/out/static/js/main.js +11 -1
- package/out/util/cron.js +9 -10
- package/out/util/defaults.js +55 -12
- package/out/util/index.js +5 -1
- package/out/util/webhooks.d.ts +29 -0
- package/out/util/webhooks.js +308 -0
- package/out/views/form.handlebars +29 -0
- package/out/views/login.handlebars +84 -16
- package/out/views/main.handlebars +171 -88
- package/out/views/partials/head.handlebars +5 -4
- package/package.json +37 -23
package/out/models/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Crowdin, { LanguagesModel, SourceFilesModel, SourceStringsModel } from '@crowdin/crowdin-api-client';
|
|
1
|
+
import Crowdin, { LanguagesModel, SourceFilesModel, SourceStringsModel, TranslationStatusModel } from '@crowdin/crowdin-api-client';
|
|
2
2
|
import { JwtPayload, VerifyOptions } from '@crowdin/crowdin-apps-functions';
|
|
3
3
|
import { Request } from 'express';
|
|
4
4
|
import { MySQLStorageConfig } from '../storage/mysql';
|
|
@@ -187,7 +187,7 @@ export interface IntegrationLogic {
|
|
|
187
187
|
/**
|
|
188
188
|
* function to update crowdin files (e.g. pull integration data to crowdin source files)
|
|
189
189
|
*/
|
|
190
|
-
updateCrowdin: (projectId: number, client: Crowdin, apiCredentials: any, request: IntegrationFile[], appRootFolder?: SourceFilesModel.Directory, config?: any) => Promise<void | ExtendedResult<void>>;
|
|
190
|
+
updateCrowdin: (projectId: number, client: Crowdin, apiCredentials: any, request: IntegrationFile[], appRootFolder?: SourceFilesModel.Directory, config?: any, uploadTranslations?: boolean) => Promise<void | ExtendedResult<void>>;
|
|
191
191
|
/**
|
|
192
192
|
* function to update integration content (e.g. load crowdin translations and push them to integration service)
|
|
193
193
|
*/
|
|
@@ -235,8 +235,22 @@ export interface IntegrationLogic {
|
|
|
235
235
|
* Enable integration next page event
|
|
236
236
|
*/
|
|
237
237
|
integrationPagination?: boolean;
|
|
238
|
+
/**
|
|
239
|
+
* Enable the option to upload translations to crowdin that are already present in the integration.
|
|
240
|
+
*/
|
|
241
|
+
uploadTranslations?: boolean;
|
|
242
|
+
/**
|
|
243
|
+
* function to get crowdin file translation progress
|
|
244
|
+
*/
|
|
245
|
+
getFileProgress?: (projectId: number, client: Crowdin, fileId: number) => Promise<{
|
|
246
|
+
[key: number]: TranslationStatusModel.LanguageProgress[];
|
|
247
|
+
}>;
|
|
248
|
+
/**
|
|
249
|
+
* Register Crowdin webhook to get notified when translations are ready
|
|
250
|
+
*/
|
|
251
|
+
webhooks?: Webhooks;
|
|
238
252
|
}
|
|
239
|
-
export
|
|
253
|
+
export type FormEntity = FormField | FormDelimeter;
|
|
240
254
|
export interface FormDelimeter {
|
|
241
255
|
label: string;
|
|
242
256
|
}
|
|
@@ -358,7 +372,7 @@ export interface FormField {
|
|
|
358
372
|
helpText?: string;
|
|
359
373
|
helpTextHtml?: string;
|
|
360
374
|
label: string;
|
|
361
|
-
type?: 'text' | 'password' | 'checkbox' | 'select';
|
|
375
|
+
type?: 'text' | 'password' | 'checkbox' | 'select' | 'textarea' | 'file';
|
|
362
376
|
defaultValue?: any;
|
|
363
377
|
/**
|
|
364
378
|
* only for select
|
|
@@ -375,19 +389,27 @@ export interface FormField {
|
|
|
375
389
|
label: string;
|
|
376
390
|
value: string;
|
|
377
391
|
}[];
|
|
392
|
+
/**
|
|
393
|
+
* only for type file
|
|
394
|
+
*/
|
|
395
|
+
accept?: string;
|
|
396
|
+
/**
|
|
397
|
+
* field dependency settings
|
|
398
|
+
*/
|
|
399
|
+
dependencySettings?: string;
|
|
378
400
|
}
|
|
379
401
|
export interface ExtendedResult<T> {
|
|
380
402
|
data?: T;
|
|
381
403
|
message?: string;
|
|
382
404
|
stopPagination?: boolean;
|
|
383
405
|
}
|
|
384
|
-
export
|
|
406
|
+
export type TreeItem = File | Folder;
|
|
385
407
|
/**
|
|
386
408
|
* 0 - folder
|
|
387
409
|
* 1 - file
|
|
388
410
|
* 2 - branch
|
|
389
411
|
*/
|
|
390
|
-
|
|
412
|
+
type IntegrationTreeElementType = '0' | '1' | '2';
|
|
391
413
|
export interface File {
|
|
392
414
|
id: string;
|
|
393
415
|
name: string;
|
|
@@ -574,10 +596,29 @@ export interface CustomMTRequest {
|
|
|
574
596
|
strings: string[];
|
|
575
597
|
}
|
|
576
598
|
export interface UiModule {
|
|
599
|
+
/**
|
|
600
|
+
* Form schema for react-jsonschema-doc to be used as front-end
|
|
601
|
+
* https://rjsf-team.github.io/react-jsonschema-form/docs
|
|
602
|
+
*/
|
|
603
|
+
formSchema?: object;
|
|
604
|
+
/**
|
|
605
|
+
* URL to custom endpoint that can be used instead of default one to save form data.
|
|
606
|
+
* Endpoint should accept POST requests.
|
|
607
|
+
*/
|
|
608
|
+
formPostDataUrl?: string;
|
|
609
|
+
/**
|
|
610
|
+
* URL to custom endpoint that can be used instead of default one to retrieve form data.
|
|
611
|
+
* Endpoint should accept GET requests.
|
|
612
|
+
*/
|
|
613
|
+
formGetDataUrl?: string;
|
|
614
|
+
/**
|
|
615
|
+
* Additional attributes for react-jsonschema-doc
|
|
616
|
+
*/
|
|
617
|
+
formUiSchema?: object;
|
|
577
618
|
/**
|
|
578
619
|
* path to ui folder (e.g. {@example join(__dirname, 'public')})
|
|
579
620
|
*/
|
|
580
|
-
uiPath
|
|
621
|
+
uiPath?: string;
|
|
581
622
|
/**
|
|
582
623
|
* page name (default index.html)
|
|
583
624
|
*/
|
|
@@ -637,4 +678,35 @@ export interface Pricing {
|
|
|
637
678
|
cachingSeconds?: number;
|
|
638
679
|
infoDisplayDaysThreshold?: number;
|
|
639
680
|
}
|
|
681
|
+
export interface Webhooks {
|
|
682
|
+
crowdinWebhookUrl?: string;
|
|
683
|
+
integrationWebhookUrl?: string;
|
|
684
|
+
urlParam?: string;
|
|
685
|
+
crowdinWebhooks?: (client: Crowdin, projectId: number, available: boolean, config?: any) => Promise<void>;
|
|
686
|
+
integrationWebhooks?: (apiCredentials: any, urlParam: string, available: boolean, config?: any, syncSettings?: any) => Promise<void>;
|
|
687
|
+
crowdinWebhookInterceptor?: (projectId: number, client: Crowdin, appRootFolder?: SourceFilesModel.Directory, config?: any, syncSettings?: any, webhookRequest?: any) => Promise<UpdateIntegrationRequest>;
|
|
688
|
+
integrationWebhookInterceptor?: (projectId: number, client: Crowdin, apiCredentials: any, appRootFolder?: SourceFilesModel.Directory, config?: any, syncSettings?: any, webhookRequest?: any) => Promise<IntegrationFile[]>;
|
|
689
|
+
queueUrl: string;
|
|
690
|
+
}
|
|
691
|
+
export declare enum SyncCondition {
|
|
692
|
+
ALL = 0,
|
|
693
|
+
TRANSLATED = 1,
|
|
694
|
+
APPROVED = 2
|
|
695
|
+
}
|
|
696
|
+
export declare enum SyncType {
|
|
697
|
+
NONE = 0,
|
|
698
|
+
SCHEDULE = 1,
|
|
699
|
+
WEBHOOKS = 2
|
|
700
|
+
}
|
|
701
|
+
export type Payload = {
|
|
702
|
+
event: string;
|
|
703
|
+
projectId: string;
|
|
704
|
+
language: string;
|
|
705
|
+
fileId: string;
|
|
706
|
+
};
|
|
707
|
+
export type WebhookUrlParams = {
|
|
708
|
+
projectId: number;
|
|
709
|
+
crowdinId: string;
|
|
710
|
+
clientId: string;
|
|
711
|
+
};
|
|
640
712
|
export {};
|
package/out/models/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EditorPanelsMode = exports.ProcessFileJobType = exports.SubscriptionInfoType = exports.AccountType = exports.Scope = exports.AuthenticationType = void 0;
|
|
3
|
+
exports.SyncType = exports.SyncCondition = exports.EditorPanelsMode = exports.ProcessFileJobType = exports.SubscriptionInfoType = exports.AccountType = exports.Scope = exports.AuthenticationType = void 0;
|
|
4
4
|
var AuthenticationType;
|
|
5
5
|
(function (AuthenticationType) {
|
|
6
6
|
AuthenticationType["CODE"] = "authorization_code";
|
|
@@ -47,3 +47,15 @@ var EditorPanelsMode;
|
|
|
47
47
|
EditorPanelsMode["TRANSLATE"] = "TRANSLATE";
|
|
48
48
|
EditorPanelsMode["PROOFREAD"] = "proofread";
|
|
49
49
|
})(EditorPanelsMode = exports.EditorPanelsMode || (exports.EditorPanelsMode = {}));
|
|
50
|
+
var SyncCondition;
|
|
51
|
+
(function (SyncCondition) {
|
|
52
|
+
SyncCondition[SyncCondition["ALL"] = 0] = "ALL";
|
|
53
|
+
SyncCondition[SyncCondition["TRANSLATED"] = 1] = "TRANSLATED";
|
|
54
|
+
SyncCondition[SyncCondition["APPROVED"] = 2] = "APPROVED";
|
|
55
|
+
})(SyncCondition = exports.SyncCondition || (exports.SyncCondition = {}));
|
|
56
|
+
var SyncType;
|
|
57
|
+
(function (SyncType) {
|
|
58
|
+
SyncType[SyncType["NONE"] = 0] = "NONE";
|
|
59
|
+
SyncType[SyncType["SCHEDULE"] = 1] = "SCHEDULE";
|
|
60
|
+
SyncType[SyncType["WEBHOOKS"] = 2] = "WEBHOOKS";
|
|
61
|
+
})(SyncType = exports.SyncType || (exports.SyncType = {}));
|
|
@@ -55,4 +55,100 @@
|
|
|
55
55
|
|
|
56
56
|
.m-0 {
|
|
57
57
|
margin: 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.info-text {
|
|
61
|
+
max-width: 800px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#translation-info {
|
|
65
|
+
margin: 12px 0 12px 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.dismiss-alert {
|
|
69
|
+
position: absolute;
|
|
70
|
+
top: 0;
|
|
71
|
+
right: 0;
|
|
72
|
+
}
|
|
73
|
+
.file-field {
|
|
74
|
+
font-family: Roboto,‘Segoe UI’,-apple-system,BlinkMacSystemFont,‘Helvetica Neue’,Arial,sans-serif;
|
|
75
|
+
-moz-osx-font-smoothing: grayscale;
|
|
76
|
+
-webkit-font-smoothing: antialiased;
|
|
77
|
+
font-size: .875rem;
|
|
78
|
+
font-weight: 400;
|
|
79
|
+
line-height: 1.5;
|
|
80
|
+
-ms-text-size-adjust: 100%;
|
|
81
|
+
text-rendering: optimizeLegibility;
|
|
82
|
+
color: rgba(38,50,56,.87);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.file-field .help-text {
|
|
86
|
+
font-size: .75rem;
|
|
87
|
+
color: rgba(38,50,56,.54);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.file-field .upload {
|
|
91
|
+
margin-top: 8px;
|
|
92
|
+
display: flex;
|
|
93
|
+
align-items: center;
|
|
94
|
+
justify-content: space-between;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.file-field .uploaded-file {
|
|
98
|
+
font-style: italic;
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.loader {
|
|
104
|
+
background: rgba(255, 255, 255, 0.3);
|
|
105
|
+
position: absolute;
|
|
106
|
+
top: 0;
|
|
107
|
+
left: 0;
|
|
108
|
+
width: 100%;
|
|
109
|
+
height: 100%;
|
|
110
|
+
z-index: 4;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.loader crowdin-progress-indicator {
|
|
114
|
+
position: absolute;
|
|
115
|
+
top: calc(50% - 20px);
|
|
116
|
+
left: calc(50% - 20px);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.hidden {
|
|
120
|
+
width:0 !important;
|
|
121
|
+
height: 0 !important;
|
|
122
|
+
opacity: 0 !important;
|
|
123
|
+
z-index: -1 !important;
|
|
124
|
+
display: block !important;
|
|
125
|
+
overflow: hidden !important;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
[data-dependency]:not(.dependency-show):not(input) {
|
|
129
|
+
display : none;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
#form-loading {
|
|
134
|
+
position: absolute;
|
|
135
|
+
top: 0;
|
|
136
|
+
bottom: 0;
|
|
137
|
+
left: 0;
|
|
138
|
+
right: 0;
|
|
139
|
+
display: flex;
|
|
140
|
+
justify-content: center;
|
|
141
|
+
align-items: center;
|
|
142
|
+
background: rgb(251 251 251 / 70%);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
#form .MuiButtonBase-root[type="submit"] {
|
|
146
|
+
background: #fff;
|
|
147
|
+
color: #263238;
|
|
148
|
+
box-shadow: none;
|
|
149
|
+
border: 1px solid rgba(38,50,56,.24);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#form .MuiButtonBase-root[type="submit"]:hover {
|
|
153
|
+
background: rgba(236, 239, 241, .54);
|
|
58
154
|
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
2
|
+
const fields = document.querySelectorAll('[data-dependency]');
|
|
3
|
+
|
|
4
|
+
if (fields.length > 0) {
|
|
5
|
+
fields.forEach((field) => {
|
|
6
|
+
const conditionString = field.dataset['dependency'].replace(/'/g, '"');
|
|
7
|
+
const conditions = JSON.parse(conditionString);
|
|
8
|
+
action(field, conditions);
|
|
9
|
+
|
|
10
|
+
const success = check(conditions);
|
|
11
|
+
showHide(field, success);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function action(field, conditions) {
|
|
17
|
+
conditions.forEach((rules) => {
|
|
18
|
+
for (const [selector, rule] of Object.entries(rules)) {
|
|
19
|
+
['input', 'change'].forEach((event) => {
|
|
20
|
+
const element = document.querySelector(selector);
|
|
21
|
+
if (element) {
|
|
22
|
+
element.addEventListener(event, () => {
|
|
23
|
+
const success = check(conditions);
|
|
24
|
+
showHide(field, success);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function showHide(element, success) {
|
|
33
|
+
if (success) {
|
|
34
|
+
element.classList.remove('dependency-show');
|
|
35
|
+
element.classList.add('dependency-show');
|
|
36
|
+
return true;
|
|
37
|
+
} else {
|
|
38
|
+
element.classList.remove('dependency-show');
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function check(conditions) {
|
|
44
|
+
return conditions.every((conditionObj) => {
|
|
45
|
+
const selectors = Object.keys(conditionObj);
|
|
46
|
+
return selectors.every((selector) => {
|
|
47
|
+
const condition = conditionObj[selector];
|
|
48
|
+
return decision(selector, condition);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function decision(selector, condition) {
|
|
54
|
+
const type = condition['type'];
|
|
55
|
+
const currentValue = getValue(selector);
|
|
56
|
+
|
|
57
|
+
let checkValue = typeof condition['value'] === 'undefined' ? false : condition['value'];
|
|
58
|
+
|
|
59
|
+
let minValue = typeof condition['min'] === 'undefined' ? false : parseInt(condition['min']);
|
|
60
|
+
let maxValue = typeof condition['max'] === 'undefined' ? false : parseInt(condition['max']);
|
|
61
|
+
|
|
62
|
+
const allowEmpty = typeof condition['empty'] === 'undefined' ? false : condition['empty'];
|
|
63
|
+
const isEmpty = !allowEmpty && currentValue.length < 1;
|
|
64
|
+
|
|
65
|
+
const likeSelector = typeof condition['like'] === 'undefined' ? false : condition['like'];
|
|
66
|
+
const likeSelectorValue = getValue(likeSelector);
|
|
67
|
+
|
|
68
|
+
const regExpPattern = typeof condition['pattern'] === 'undefined' ? false : condition['pattern'];
|
|
69
|
+
const regExpModifier = typeof condition['modifier'] === 'undefined' ? 'gi' : condition['modifier'];
|
|
70
|
+
const sign = typeof condition['sign'] === 'undefined' ? false : condition['sign'];
|
|
71
|
+
const strict = typeof condition['strict'] === 'undefined' ? false : condition['strict'];
|
|
72
|
+
|
|
73
|
+
const emptyTypes = ['empty', 'blank'];
|
|
74
|
+
const notEmptyTypes = ['!empty', 'notEmpty', 'not-empty', 'notempty'];
|
|
75
|
+
|
|
76
|
+
const equalTypes = ['equal', '=', '==', '==='];
|
|
77
|
+
const notEqualTypes = ['!equal', '!=', '!==', '!===', 'notEqual', 'not-equal', 'notequal'];
|
|
78
|
+
|
|
79
|
+
const regularExpressionTypes = ['regexp', 'exp', 'expression', 'match'];
|
|
80
|
+
|
|
81
|
+
// if empty return true
|
|
82
|
+
if (emptyTypes.includes(type)) {
|
|
83
|
+
return currentValue.length < 1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// if not empty return true
|
|
87
|
+
if (notEmptyTypes.includes(type)) {
|
|
88
|
+
return currentValue.length > 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// if equal return true
|
|
92
|
+
if (equalTypes.includes(type)) {
|
|
93
|
+
if (isEmpty) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Match two selector value/s
|
|
98
|
+
if (likeSelector) {
|
|
99
|
+
if (strict) {
|
|
100
|
+
return likeSelectorValue.every((value) => {
|
|
101
|
+
return currentValue.includes(value);
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
return likeSelectorValue.some((value) => {
|
|
105
|
+
return currentValue.includes(value);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Match pre-defined value/s
|
|
111
|
+
if (strict) {
|
|
112
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
113
|
+
return checkValue.every((value) => {
|
|
114
|
+
return currentValue.includes(value);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
119
|
+
return currentValue.includes(checkValue);
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
123
|
+
return checkValue.some((value) => {
|
|
124
|
+
return currentValue.includes(value);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
129
|
+
return currentValue.includes(checkValue);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// if not equal return true
|
|
135
|
+
if (notEqualTypes.includes(type)) {
|
|
136
|
+
if (isEmpty) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Match two selector value/s
|
|
141
|
+
if (likeSelector) {
|
|
142
|
+
if (strict) {
|
|
143
|
+
return likeSelectorValue.every((value) => {
|
|
144
|
+
return !currentValue.includes(value);
|
|
145
|
+
});
|
|
146
|
+
} else {
|
|
147
|
+
return likeSelectorValue.some((value) => {
|
|
148
|
+
return !currentValue.includes(value);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Match pre-defined value/s
|
|
154
|
+
if (strict) {
|
|
155
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
156
|
+
return checkValue.every((value) => {
|
|
157
|
+
return !currentValue.includes(value);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
162
|
+
return !currentValue.includes(checkValue);
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
166
|
+
return checkValue.some((value) => {
|
|
167
|
+
return !currentValue.includes(value);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
172
|
+
return !currentValue.includes(checkValue);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// if regexp match
|
|
178
|
+
if (regularExpressionTypes.includes(type) && regExpPattern) {
|
|
179
|
+
if (isEmpty) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const exp = new RegExp(regExpPattern, regExpModifier);
|
|
184
|
+
return currentValue.every((value) => {
|
|
185
|
+
return exp.test(value);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// if length
|
|
190
|
+
if ('length' === type) {
|
|
191
|
+
if (isEmpty) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
196
|
+
minValue = parseInt(checkValue[0]);
|
|
197
|
+
maxValue = typeof checkValue[1] === 'undefined' ? false : parseInt(checkValue[1]);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (checkValue && !Array.isArray(checkValue)) {
|
|
201
|
+
minValue = parseInt(checkValue);
|
|
202
|
+
maxValue = false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return currentValue.every((value) => {
|
|
206
|
+
if (!maxValue) {
|
|
207
|
+
return value.length >= minValue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (!minValue) {
|
|
211
|
+
return value.length <= maxValue;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return value.length >= minValue && value.length <= maxValue;
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// if range
|
|
219
|
+
if ('range' === type) {
|
|
220
|
+
if (isEmpty) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (checkValue && Array.isArray(checkValue)) {
|
|
225
|
+
minValue = parseInt(checkValue[0]);
|
|
226
|
+
maxValue = typeof checkValue[1] === 'undefined' ? false : parseInt(checkValue[1]);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return currentValue.every((value) => {
|
|
230
|
+
if (!maxValue) {
|
|
231
|
+
return parseInt(value) > minValue;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (!minValue) {
|
|
235
|
+
return parseInt(value) < maxValue;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return parseInt(value) > minValue && parseInt(value) < maxValue;
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// if compare
|
|
243
|
+
if ('compare' === type && sign && checkValue) {
|
|
244
|
+
if (isEmpty) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
checkValue = parseInt(checkValue);
|
|
249
|
+
|
|
250
|
+
switch (sign) {
|
|
251
|
+
case '<':
|
|
252
|
+
return currentValue.every((value) => {
|
|
253
|
+
return parseInt(value) < checkValue;
|
|
254
|
+
});
|
|
255
|
+
break;
|
|
256
|
+
|
|
257
|
+
case '<=':
|
|
258
|
+
return currentValue.every((value) => {
|
|
259
|
+
return parseInt(value) <= checkValue;
|
|
260
|
+
});
|
|
261
|
+
break;
|
|
262
|
+
|
|
263
|
+
case '>':
|
|
264
|
+
return currentValue.every((value) => {
|
|
265
|
+
return parseInt(value) > checkValue;
|
|
266
|
+
});
|
|
267
|
+
break;
|
|
268
|
+
|
|
269
|
+
case '>=':
|
|
270
|
+
return currentValue.every((value) => {
|
|
271
|
+
return parseInt(value) >= checkValue;
|
|
272
|
+
});
|
|
273
|
+
break;
|
|
274
|
+
|
|
275
|
+
case '=':
|
|
276
|
+
case '==':
|
|
277
|
+
return currentValue.every((value) => {
|
|
278
|
+
return parseInt(value) === checkValue;
|
|
279
|
+
});
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function getValue(selector) {
|
|
286
|
+
const values = [];
|
|
287
|
+
if (selector && document.querySelector(selector)) {
|
|
288
|
+
const inputType = document.querySelector(selector).tagName.toLowerCase();``
|
|
289
|
+
|
|
290
|
+
let currentSelector = selector;
|
|
291
|
+
|
|
292
|
+
if ('crowdin-select' === inputType) {
|
|
293
|
+
currentSelector = `${selector} option:checked`;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if ('crowdin-checkbox' === inputType) {
|
|
297
|
+
currentSelector = `${selector}:not(input)`;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
document.querySelectorAll(`${currentSelector}`).forEach((element) => {
|
|
301
|
+
const value = element.value || element.checked;
|
|
302
|
+
values.push(value);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return values.filter((value) => value !== '');
|
|
307
|
+
}
|