inviton-powerduck 0.0.153 → 0.0.155
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/app/powerduck-initializer.ts +3 -3
- package/common/api-http.ts +20 -14
- package/common/css/ladda-themeless-zoomin.min.css +89 -89
- package/common/enum-translation/day-translator.ts +3 -2
- package/common/excel/excel-reader.ts +2 -9
- package/common/extensions/array-extensions.ts +116 -0
- package/common/extensions/string-extensions.ts +92 -0
- package/common/extensions/temporal-extensions.ts +115 -0
- package/common/scroll-utils.ts +2 -1
- package/common/temporal-helpers.ts +551 -0
- package/common/throttled-api-caller.ts +149 -0
- package/common/timezone-helper.ts +39 -29
- package/common/utils/cookie.ts +11 -8
- package/common/utils/date-localization-utils.ts +25 -19
- package/common/utils/date-utils.ts +37 -47
- package/common/utils/form-utils.ts +3 -1
- package/common/utils/language-utils.ts +21 -27
- package/common/utils/temporal-utils.ts +43 -0
- package/common/utils/upload-image-helper.ts +1 -1
- package/common/utils/utils.ts +14 -14
- package/common/validation.ts +17 -5
- package/components/chart-js/line-chart-flot.tsx +9 -9
- package/components/chart-js/thirdparty/flot/jquery.flot.categories.min.js +93 -93
- package/components/chart-js/thirdparty/flot/jquery.flot.crosshair.min.js +83 -83
- package/components/chart-js/thirdparty/flot/jquery.flot.navigate.min.js +270 -270
- package/components/chart-js/thirdparty/flot/jquery.flot.pie.min.js +507 -507
- package/components/chart-js/thirdparty/flot/jquery.flot.resize.js +7 -9
- package/components/chart-js/thirdparty/flot/jquery.flot.resize.min.js +9 -11
- package/components/chart-js/thirdparty/flot/jquery.flot.stack.min.js +104 -104
- package/components/chart-js/ts/line-chart-contracts.ts +2 -2
- package/components/container-with-breakpoints/ts/breakpoint-handler.ts +2 -2
- package/components/counter/testall.tsx +89 -75
- package/components/datatable/datatable.tsx +2379 -2375
- package/components/datatable/export-excel-modal.tsx +12 -14
- package/components/datatable/ts/reorder.ts +4 -2
- package/components/dropdown/index.tsx +48 -22
- package/components/dropdown/mobile/legacy_fdd.ts +10 -11
- package/components/dropzone/gallery-dropzone.tsx +394 -382
- package/components/fullcalendar/fullcalendar-draggable-event.tsx +8 -7
- package/components/fullcalendar/timegrid-calendar.tsx +60 -67
- package/components/image-crop/image-cropping-modal.tsx +9 -8
- package/components/image-crop/upload-and-crop.tsx +162 -162
- package/components/image-crop/vendor/jquery.Jcrop.min.css +344 -344
- package/components/import/import-mapper.tsx +2 -2
- package/components/input/daterange-picker.tsx +502 -521
- package/components/input/datetime-picker.tsx +45 -50
- package/components/input/plugins/daterangepicker/daterangepicker.min.css +400 -400
- package/components/input/plugins/daterangepicker/jquery.daterangepicker.min.js +346 -339
- package/components/input/plugins/daterangepicker/jquery.daterangepicker.ts +580 -402
- package/components/input/radio-button-group.tsx +2 -2
- package/components/input/ts/dateInputHelper.ts +1 -0
- package/components/input/wysiwig.tsx +12 -7
- package/components/svg/skilift-svg.tsx +6 -6
- package/package.json +2 -1
- package/common/date-wrapper.ts +0 -422
- package/common/utils/array-extend.ts +0 -215
- package/common/utils/array-remove.ts +0 -10
- package/common/utils/array-sort.ts +0 -56
- package/common/utils/capitalize-string.ts +0 -11
- package/common/utils/format-string.ts +0 -14
- package/common/utils/latinize-string.ts +0 -7
|
@@ -6,6 +6,7 @@ import moment from 'moment';
|
|
|
6
6
|
import select2 from 'select2';
|
|
7
7
|
import { isNullOrEmpty } from '../common/utils/is-null-or-empty';
|
|
8
8
|
import { LanguageUtils } from '../common/utils/language-utils';
|
|
9
|
+
import TemporalUtils from '../common/utils/temporal-utils';
|
|
9
10
|
import PowerduckState from './powerduck-state';
|
|
10
11
|
|
|
11
12
|
export interface PoweduckInitFrameworkArgs {
|
|
@@ -25,8 +26,8 @@ export default class PowerduckInitializer {
|
|
|
25
26
|
window.addEventListener('vite:preloadError', (event) => {
|
|
26
27
|
const key = `${PowerduckState.getAppPrefix()}errLastReload`;
|
|
27
28
|
const lastTry = Number(localStorage.getItem(key) || '0');
|
|
28
|
-
if (
|
|
29
|
-
localStorage.setItem(key,
|
|
29
|
+
if (TemporalUtils.dateNowMs() - lastTry > 3000) {
|
|
30
|
+
localStorage.setItem(key, TemporalUtils.dateNowMs().toString());
|
|
30
31
|
|
|
31
32
|
if ((window as any).__routerNextTo != null && !isNullOrEmpty((window as any).__routerNextTo.path)) {
|
|
32
33
|
location.href = (window as any).__routerNextTo.path;
|
|
@@ -39,7 +40,6 @@ export default class PowerduckInitializer {
|
|
|
39
40
|
|
|
40
41
|
if (args != null) {
|
|
41
42
|
if (args.supportedLanguages?.length as number > 0) {
|
|
42
|
-
// @ts-ignore
|
|
43
43
|
LanguageUtils.supportedLanguages = args.supportedLanguages as Language[];
|
|
44
44
|
}
|
|
45
45
|
}
|
package/common/api-http.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import PowerduckState from './../app/powerduck-state';
|
|
2
2
|
import { AjaxProviderXhr } from './ajax-xhr';
|
|
3
|
-
import
|
|
3
|
+
import TemporalUtils from './utils/temporal-utils';
|
|
4
4
|
import { PortalUtils } from './utils/utils';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -262,9 +262,9 @@ export class AppHttpProvider {
|
|
|
262
262
|
} else if (keyVal != null && typeof keyVal === 'object') {
|
|
263
263
|
recIterate(keyVal);
|
|
264
264
|
} else {
|
|
265
|
-
if (keyVal != null && keyVal.indexOf &&
|
|
265
|
+
if (keyVal != null && keyVal.indexOf && TemporalUtils.isSerializedDate(keyVal)) {
|
|
266
266
|
try {
|
|
267
|
-
obj[key] =
|
|
267
|
+
obj[key] = TemporalUtils.fromString(keyVal);
|
|
268
268
|
if (isNaN(obj[key].getTime())) {
|
|
269
269
|
obj[key] = keyVal;
|
|
270
270
|
}
|
|
@@ -281,10 +281,8 @@ export class AppHttpProvider {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
private static performAjaxCall<T>(args: AjaxDefinition<T>, url: string): Promise<T> {
|
|
284
|
-
const mySelf = this;
|
|
285
|
-
|
|
286
284
|
return new (window as any).Promise((resolve, reject) => {
|
|
287
|
-
|
|
285
|
+
const tryGetJSON = (resp: any): any => {
|
|
288
286
|
try {
|
|
289
287
|
return JSON.parse(resp);
|
|
290
288
|
} catch (e) {
|
|
@@ -294,12 +292,12 @@ export class AppHttpProvider {
|
|
|
294
292
|
return null;
|
|
295
293
|
}
|
|
296
294
|
}
|
|
297
|
-
}
|
|
295
|
+
};
|
|
298
296
|
|
|
299
297
|
const method = (args.type || 'GET').toUpperCase();
|
|
300
298
|
let data = <any>(args.data || {});
|
|
301
|
-
const ajaxDefaults =
|
|
302
|
-
|
|
299
|
+
const ajaxDefaults = this.ajaxDefaults;
|
|
300
|
+
let blockUiEnabled = false;
|
|
303
301
|
const query: string[] = [];
|
|
304
302
|
|
|
305
303
|
if ((method == 'GET' || method == 'DELETE') && data != null) {
|
|
@@ -321,9 +319,17 @@ export class AppHttpProvider {
|
|
|
321
319
|
}
|
|
322
320
|
|
|
323
321
|
if (args.blockUi != null) {
|
|
324
|
-
|
|
322
|
+
if (typeof args.blockUi.enabled === 'string') {
|
|
323
|
+
blockUiEnabled = args.blockUi.enabled === 'true';
|
|
324
|
+
} else {
|
|
325
|
+
blockUiEnabled = args.blockUi.enabled;
|
|
326
|
+
}
|
|
325
327
|
} else if (ajaxDefaults.blockUi != null) {
|
|
326
|
-
|
|
328
|
+
if (typeof ajaxDefaults.blockUi.enabled === 'string') {
|
|
329
|
+
blockUiEnabled = ajaxDefaults.blockUi.enabled === 'true';
|
|
330
|
+
} else {
|
|
331
|
+
blockUiEnabled = ajaxDefaults.blockUi.enabled;
|
|
332
|
+
}
|
|
327
333
|
}
|
|
328
334
|
|
|
329
335
|
let customAuth = false;
|
|
@@ -388,7 +394,7 @@ export class AppHttpProvider {
|
|
|
388
394
|
// Start request
|
|
389
395
|
let retryCount = 0;
|
|
390
396
|
const requestLoop = () => {
|
|
391
|
-
const start =
|
|
397
|
+
const start = TemporalUtils.dateNowMs();
|
|
392
398
|
AppHttpProvider.getRequestProvider()
|
|
393
399
|
.sendRequest({
|
|
394
400
|
data,
|
|
@@ -401,11 +407,11 @@ export class AppHttpProvider {
|
|
|
401
407
|
.then((resp) => {
|
|
402
408
|
if (blockUiEnabled) {
|
|
403
409
|
try {
|
|
404
|
-
|
|
410
|
+
this.unblockUi(args);
|
|
405
411
|
} catch (e) { }
|
|
406
412
|
}
|
|
407
413
|
|
|
408
|
-
const stop =
|
|
414
|
+
const stop = TemporalUtils.dateNowMs();
|
|
409
415
|
const jsonData = tryGetJSON(resp.responseText);
|
|
410
416
|
if (jsonData != null) {
|
|
411
417
|
AppHttpProvider.postProcessJsObject(jsonData, args.jsonAdapter);
|
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
/*! Ladda http://lab.hakim.se/ladda MIT licensed Copyright (C) 2016 Hakim El Hattab, http://hakim.se ....Lightweight adaptation for Inviton API needs*/
|
|
2
|
-
.ladda-button {
|
|
3
|
-
position: relative;
|
|
4
|
-
}
|
|
5
|
-
.ladda-button .ladda-spinner {
|
|
6
|
-
position: absolute;
|
|
7
|
-
z-index: 2;
|
|
8
|
-
display: inline-block;
|
|
9
|
-
width: 32px;
|
|
10
|
-
height: 32px;
|
|
11
|
-
top: 50%;
|
|
12
|
-
margin-top: 0;
|
|
13
|
-
opacity: 0;
|
|
14
|
-
pointer-events: none;
|
|
15
|
-
}
|
|
16
|
-
.ladda-button .ladda-label {
|
|
17
|
-
position: relative;
|
|
18
|
-
z-index: 3;
|
|
19
|
-
}
|
|
20
|
-
.ladda-button .ladda-progress {
|
|
21
|
-
position: absolute;
|
|
22
|
-
width: 0;
|
|
23
|
-
height: 100%;
|
|
24
|
-
left: 0;
|
|
25
|
-
top: 0;
|
|
26
|
-
background: rgba(0, 0, 0, 0.2);
|
|
27
|
-
visibility: hidden;
|
|
28
|
-
opacity: 0;
|
|
29
|
-
-webkit-transition: 0.1s linear all !important;
|
|
30
|
-
-moz-transition: 0.1s linear all !important;
|
|
31
|
-
-ms-transition: 0.1s linear all !important;
|
|
32
|
-
-o-transition: 0.1s linear all !important;
|
|
33
|
-
transition: 0.1s linear all !important;
|
|
34
|
-
}
|
|
35
|
-
.ladda-button[data-loading] .ladda-progress {
|
|
36
|
-
opacity: 1;
|
|
37
|
-
visibility: visible;
|
|
38
|
-
}
|
|
39
|
-
.ladda-button,
|
|
40
|
-
.ladda-button .ladda-label,
|
|
41
|
-
.ladda-button .ladda-spinner {
|
|
42
|
-
-webkit-transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
43
|
-
-moz-transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
44
|
-
-ms-transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
45
|
-
-o-transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
46
|
-
transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
47
|
-
}
|
|
48
|
-
.ladda-button[data-style="zoom-in"],
|
|
49
|
-
.ladda-button[data-style="zoom-in"] .ladda-label,
|
|
50
|
-
.ladda-button[data-style="zoom-in"] .ladda-spinner {
|
|
51
|
-
-webkit-transition: 0.3s ease all !important;
|
|
52
|
-
-moz-transition: 0.3s ease all !important;
|
|
53
|
-
-ms-transition: 0.3s ease all !important;
|
|
54
|
-
-o-transition: 0.3s ease all !important;
|
|
55
|
-
transition: 0.3s ease all !important;
|
|
56
|
-
}
|
|
57
|
-
.ladda-button[data-style="zoom-in"] {
|
|
58
|
-
overflow: hidden;
|
|
59
|
-
}
|
|
60
|
-
.ladda-button[data-style="zoom-in"] .ladda-spinner {
|
|
61
|
-
left: 50%;
|
|
62
|
-
margin-left: -16px;
|
|
63
|
-
-webkit-transform: scale(0.2);
|
|
64
|
-
-moz-transform: scale(0.2);
|
|
65
|
-
-ms-transform: scale(0.2);
|
|
66
|
-
-o-transform: scale(0.2);
|
|
67
|
-
transform: scale(0.2);
|
|
68
|
-
}
|
|
69
|
-
.ladda-button[data-style="zoom-in"] .ladda-label {
|
|
70
|
-
position: relative;
|
|
71
|
-
display: inline-block;
|
|
72
|
-
}
|
|
73
|
-
.ladda-button[data-style="zoom-in"][data-loading] .ladda-label {
|
|
74
|
-
opacity: 0;
|
|
75
|
-
-webkit-transform: scale(2.2);
|
|
76
|
-
-moz-transform: scale(2.2);
|
|
77
|
-
-ms-transform: scale(2.2);
|
|
78
|
-
-o-transform: scale(2.2);
|
|
79
|
-
transform: scale(2.2);
|
|
80
|
-
}
|
|
81
|
-
.ladda-button[data-style="zoom-in"][data-loading] .ladda-spinner {
|
|
82
|
-
opacity: 1;
|
|
83
|
-
margin-left: 0;
|
|
84
|
-
-webkit-transform: none;
|
|
85
|
-
-moz-transform: none;
|
|
86
|
-
-ms-transform: none;
|
|
87
|
-
-o-transform: none;
|
|
88
|
-
transform: none;
|
|
89
|
-
}
|
|
1
|
+
/*! Ladda http://lab.hakim.se/ladda MIT licensed Copyright (C) 2016 Hakim El Hattab, http://hakim.se ....Lightweight adaptation for Inviton API needs*/
|
|
2
|
+
.ladda-button {
|
|
3
|
+
position: relative;
|
|
4
|
+
}
|
|
5
|
+
.ladda-button .ladda-spinner {
|
|
6
|
+
position: absolute;
|
|
7
|
+
z-index: 2;
|
|
8
|
+
display: inline-block;
|
|
9
|
+
width: 32px;
|
|
10
|
+
height: 32px;
|
|
11
|
+
top: 50%;
|
|
12
|
+
margin-top: 0;
|
|
13
|
+
opacity: 0;
|
|
14
|
+
pointer-events: none;
|
|
15
|
+
}
|
|
16
|
+
.ladda-button .ladda-label {
|
|
17
|
+
position: relative;
|
|
18
|
+
z-index: 3;
|
|
19
|
+
}
|
|
20
|
+
.ladda-button .ladda-progress {
|
|
21
|
+
position: absolute;
|
|
22
|
+
width: 0;
|
|
23
|
+
height: 100%;
|
|
24
|
+
left: 0;
|
|
25
|
+
top: 0;
|
|
26
|
+
background: rgba(0, 0, 0, 0.2);
|
|
27
|
+
visibility: hidden;
|
|
28
|
+
opacity: 0;
|
|
29
|
+
-webkit-transition: 0.1s linear all !important;
|
|
30
|
+
-moz-transition: 0.1s linear all !important;
|
|
31
|
+
-ms-transition: 0.1s linear all !important;
|
|
32
|
+
-o-transition: 0.1s linear all !important;
|
|
33
|
+
transition: 0.1s linear all !important;
|
|
34
|
+
}
|
|
35
|
+
.ladda-button[data-loading] .ladda-progress {
|
|
36
|
+
opacity: 1;
|
|
37
|
+
visibility: visible;
|
|
38
|
+
}
|
|
39
|
+
.ladda-button,
|
|
40
|
+
.ladda-button .ladda-label,
|
|
41
|
+
.ladda-button .ladda-spinner {
|
|
42
|
+
-webkit-transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
43
|
+
-moz-transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
44
|
+
-ms-transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
45
|
+
-o-transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
46
|
+
transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) all !important;
|
|
47
|
+
}
|
|
48
|
+
.ladda-button[data-style="zoom-in"],
|
|
49
|
+
.ladda-button[data-style="zoom-in"] .ladda-label,
|
|
50
|
+
.ladda-button[data-style="zoom-in"] .ladda-spinner {
|
|
51
|
+
-webkit-transition: 0.3s ease all !important;
|
|
52
|
+
-moz-transition: 0.3s ease all !important;
|
|
53
|
+
-ms-transition: 0.3s ease all !important;
|
|
54
|
+
-o-transition: 0.3s ease all !important;
|
|
55
|
+
transition: 0.3s ease all !important;
|
|
56
|
+
}
|
|
57
|
+
.ladda-button[data-style="zoom-in"] {
|
|
58
|
+
overflow: hidden;
|
|
59
|
+
}
|
|
60
|
+
.ladda-button[data-style="zoom-in"] .ladda-spinner {
|
|
61
|
+
left: 50%;
|
|
62
|
+
margin-left: -16px;
|
|
63
|
+
-webkit-transform: scale(0.2);
|
|
64
|
+
-moz-transform: scale(0.2);
|
|
65
|
+
-ms-transform: scale(0.2);
|
|
66
|
+
-o-transform: scale(0.2);
|
|
67
|
+
transform: scale(0.2);
|
|
68
|
+
}
|
|
69
|
+
.ladda-button[data-style="zoom-in"] .ladda-label {
|
|
70
|
+
position: relative;
|
|
71
|
+
display: inline-block;
|
|
72
|
+
}
|
|
73
|
+
.ladda-button[data-style="zoom-in"][data-loading] .ladda-label {
|
|
74
|
+
opacity: 0;
|
|
75
|
+
-webkit-transform: scale(2.2);
|
|
76
|
+
-moz-transform: scale(2.2);
|
|
77
|
+
-ms-transform: scale(2.2);
|
|
78
|
+
-o-transform: scale(2.2);
|
|
79
|
+
transform: scale(2.2);
|
|
80
|
+
}
|
|
81
|
+
.ladda-button[data-style="zoom-in"][data-loading] .ladda-spinner {
|
|
82
|
+
opacity: 1;
|
|
83
|
+
margin-left: 0;
|
|
84
|
+
-webkit-transform: none;
|
|
85
|
+
-moz-transform: none;
|
|
86
|
+
-ms-transform: none;
|
|
87
|
+
-o-transform: none;
|
|
88
|
+
transform: none;
|
|
89
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Day } from './../enums/day';
|
|
2
2
|
import PowerduckState from './../../app/powerduck-state';
|
|
3
|
-
import { capitalize } from '
|
|
3
|
+
import { capitalize } from '../extensions/string-extensions';
|
|
4
4
|
|
|
5
5
|
export default class DayTranslator {
|
|
6
6
|
private static _dayMap: { [index: string]: string } = null as any;
|
|
@@ -18,12 +18,13 @@ export default class DayTranslator {
|
|
|
18
18
|
this._dayMap = {};
|
|
19
19
|
const locale = PowerduckState.getCurrentLanguage();
|
|
20
20
|
for (let i = 7; i < 15; i++) {
|
|
21
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
21
22
|
const dayDate = new Date(Date.UTC(
|
|
22
23
|
2015,
|
|
23
24
|
5,
|
|
24
25
|
i,
|
|
25
26
|
));
|
|
26
|
-
const dayName =
|
|
27
|
+
const dayName = dayDate.toLocaleDateString(locale, { weekday: 'long', timeZone: 'UTC' })[capitalize]();
|
|
27
28
|
const dayEnumName = dayDate.toLocaleDateString('en', { weekday: 'long', timeZone: 'UTC' }).toUpperCase();
|
|
28
29
|
this._dayMap[dayEnumName] = dayName;
|
|
29
30
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// var XLSX = require("xlsx");
|
|
2
2
|
// import XLSX from "xlsx";
|
|
3
3
|
import * as XLSX from 'xlsx/xlsx.mjs';
|
|
4
|
-
import
|
|
4
|
+
import TemporalUtils from '../utils/temporal-utils';
|
|
5
5
|
import { PortalUtils } from '../utils/utils';
|
|
6
6
|
|
|
7
7
|
export class ExcelReader {
|
|
@@ -52,14 +52,7 @@ export class ExcelReader {
|
|
|
52
52
|
let rowVal = sheetRow[i];
|
|
53
53
|
if (rowVal != null) {
|
|
54
54
|
if (rowVal != null && rowVal.getUTCFullYear) {
|
|
55
|
-
rowVal =
|
|
56
|
-
rowVal.getFullYear(),
|
|
57
|
-
rowVal.getMonth(),
|
|
58
|
-
rowVal.getDate(),
|
|
59
|
-
rowVal.getHours(),
|
|
60
|
-
rowVal.getMinutes(),
|
|
61
|
-
rowVal.getSeconds(),
|
|
62
|
-
);
|
|
55
|
+
rowVal = TemporalUtils.fromDate(rowVal);
|
|
63
56
|
} else if (PortalUtils.isString(rowVal)) {
|
|
64
57
|
rowVal = rowVal.trim();
|
|
65
58
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* eslint-disable func-style */
|
|
2
|
+
export const distinct = Symbol('distinct');
|
|
3
|
+
function distinctImpl<T>(this: Array<T>): Array<T> {
|
|
4
|
+
return [...new Set(this)];
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const groupBy = Symbol('groupBy');
|
|
8
|
+
function groupByImpl<T, K>(this: Array<T>, keySelector: (item: T) => K): Map<K, T[]> {
|
|
9
|
+
const groups = new Map<K, T[]>();
|
|
10
|
+
for (const item of this) {
|
|
11
|
+
const key = keySelector(item);
|
|
12
|
+
const group = groups.get(key);
|
|
13
|
+
if (group) {
|
|
14
|
+
group.push(item);
|
|
15
|
+
} else {
|
|
16
|
+
groups.set(key, [item]);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return groups;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const remove = Symbol('remove');
|
|
23
|
+
function removeImpl<T>(this: Array<T>, ...items: T[]) {
|
|
24
|
+
for (let i = 1, len = arguments.length; i < len; i++) {
|
|
25
|
+
// eslint-disable-next-line prefer-rest-params
|
|
26
|
+
const item = arguments[i];
|
|
27
|
+
const itemIndex = this.indexOf(item);
|
|
28
|
+
|
|
29
|
+
if (itemIndex > -1) {
|
|
30
|
+
this.splice(itemIndex, 1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const sortBy = Symbol('sortBy');
|
|
36
|
+
function sortByImpl<T>(this: T[], propName: string | ((item: T) => string | number)): Array<T> {
|
|
37
|
+
function dynamicSort(property) {
|
|
38
|
+
if (propName && {}.toString.call(propName) === '[object Function]') {
|
|
39
|
+
return function (a, b) {
|
|
40
|
+
let v1 = (<any>propName)(a);
|
|
41
|
+
let v2 = (<any>propName)(b);
|
|
42
|
+
|
|
43
|
+
if (v1.constructor && v1.call && v1.apply) {
|
|
44
|
+
v1 = v1();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (v2.constructor && v2.call && v2.apply) {
|
|
48
|
+
v2 = v2();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return v1 < v2 ? -1 : v1 > v2 ? 1 : 0;
|
|
52
|
+
};
|
|
53
|
+
} else {
|
|
54
|
+
let propArr: string[] = property;
|
|
55
|
+
if (typeof property === 'string' || property instanceof String) {
|
|
56
|
+
propArr = <any>[property];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return function (a, b) {
|
|
60
|
+
for (let i = 0, len = propArr.length; i < len; i++) {
|
|
61
|
+
let currProp = propArr[i];
|
|
62
|
+
let sortOrder = 1;
|
|
63
|
+
if (currProp[0] === '-') {
|
|
64
|
+
sortOrder = -1;
|
|
65
|
+
currProp = currProp.substr(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let aVal = a[currProp];
|
|
69
|
+
let bVal = b[currProp];
|
|
70
|
+
if (aVal.constructor && aVal.call && aVal.apply) {
|
|
71
|
+
aVal = aVal();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (bVal.constructor && bVal.call && bVal.apply) {
|
|
75
|
+
bVal = bVal();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const result = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
79
|
+
if (result != 0) {
|
|
80
|
+
return result * sortOrder;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return 0;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.sort(dynamicSort(propName));
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
declare global {
|
|
95
|
+
export interface Array<T> {
|
|
96
|
+
[distinct]: typeof distinctImpl;
|
|
97
|
+
[groupBy]: typeof groupByImpl;
|
|
98
|
+
/**
|
|
99
|
+
* Removes given items from the Array
|
|
100
|
+
*
|
|
101
|
+
* @param items Items that should be removed from the Array
|
|
102
|
+
*/
|
|
103
|
+
[remove]: typeof removeImpl;
|
|
104
|
+
/**
|
|
105
|
+
* Sorts array by given property
|
|
106
|
+
*
|
|
107
|
+
* @param propName Property name (or function returning the sort key), the array should be sorted by
|
|
108
|
+
*/
|
|
109
|
+
[sortBy]: typeof sortByImpl
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
(Array as any).prototype[distinct] = distinctImpl;
|
|
114
|
+
(Array as any).prototype[groupBy] = groupByImpl;
|
|
115
|
+
(Array as any).prototype[remove] = removeImpl;
|
|
116
|
+
(Array as any).prototype[sortBy] = sortByImpl;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export const format = Symbol('format');
|
|
2
|
+
function formatImpl(this: string, ...replaceArgs: Array<string | number>) {
|
|
3
|
+
var args = arguments;
|
|
4
|
+
return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (m, n) {
|
|
5
|
+
if (m == "{{") { return "{"; }
|
|
6
|
+
if (m == "}}") { return "}"; }
|
|
7
|
+
return args[n];
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const startsWith = Symbol('startsWith');
|
|
12
|
+
function startsWithImpl(this: string, str: string) {
|
|
13
|
+
return this.indexOf(str) == 0;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const endsWith = Symbol('endsWith');
|
|
17
|
+
function endsWithImpl(this: string, suffix: string) {
|
|
18
|
+
return this.indexOf(suffix, this.length - suffix.length) !== -1;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
export const capitalize = Symbol('capitalize');
|
|
23
|
+
function capitalizeImpl(this: string) {
|
|
24
|
+
{
|
|
25
|
+
if (this != null) {
|
|
26
|
+
if (this.length > 1) {
|
|
27
|
+
return this.charAt(0).toUpperCase() + this.slice(1);
|
|
28
|
+
} else {
|
|
29
|
+
return this.toUpperCase();
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const latinize = Symbol('latinize');
|
|
38
|
+
function latinizeImpl(this: string) {
|
|
39
|
+
{
|
|
40
|
+
try {
|
|
41
|
+
return (<any>this).normalize('NFD').replace(/[\u0300-\u036f]/g, "");
|
|
42
|
+
} catch (e) {
|
|
43
|
+
return this as any;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
declare global {
|
|
50
|
+
export interface String {
|
|
51
|
+
/**
|
|
52
|
+
* Replaces one or more format items in the string with the string specification of specified object
|
|
53
|
+
*
|
|
54
|
+
* @param replaceArgs Format objects
|
|
55
|
+
*/
|
|
56
|
+
[format]: typeof formatImpl;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Determines if current string starts with given string
|
|
60
|
+
*
|
|
61
|
+
* @param str String that should be checked
|
|
62
|
+
*/
|
|
63
|
+
[startsWith]: typeof startsWithImpl;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Determines if current string ends with given string
|
|
67
|
+
*
|
|
68
|
+
* @param str String that should be checked
|
|
69
|
+
*/
|
|
70
|
+
[endsWith]: typeof endsWithImpl;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Returns capitalized string (with leading letter ensured in capitals)
|
|
74
|
+
*
|
|
75
|
+
* @param str String that should be capitalized
|
|
76
|
+
*/
|
|
77
|
+
[capitalize]: typeof capitalizeImpl
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Returns latinized string (with local accents replaced with ASCII ones)
|
|
81
|
+
*
|
|
82
|
+
* @param str String that should be latinized
|
|
83
|
+
*/
|
|
84
|
+
[latinize]: typeof latinizeImpl
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
(String as any).prototype[format] = formatImpl;
|
|
89
|
+
(String as any).prototype[startsWith] = startsWithImpl;
|
|
90
|
+
(String as any).prototype[endsWith] = endsWithImpl;
|
|
91
|
+
(String as any).prototype[capitalize] = capitalizeImpl;
|
|
92
|
+
(String as any).prototype[latinize] = latinizeImpl;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* eslint-disable func-style */
|
|
2
|
+
import { Temporal } from '@js-temporal/polyfill';
|
|
3
|
+
import PowerduckState from '../../app/powerduck-state';
|
|
4
|
+
|
|
5
|
+
export const toDisplayString = Symbol('toDisplayString');
|
|
6
|
+
function toDisplayStringImpl(
|
|
7
|
+
this: Temporal.PlainDateTime,
|
|
8
|
+
options?: {
|
|
9
|
+
showTime?: boolean;
|
|
10
|
+
showSeconds?: boolean;
|
|
11
|
+
monthLong?: boolean;
|
|
12
|
+
dayLong?: boolean;
|
|
13
|
+
hideDay?: boolean;
|
|
14
|
+
hideMonth?: boolean;
|
|
15
|
+
hideYear?: boolean;
|
|
16
|
+
language?: string;
|
|
17
|
+
} | boolean,
|
|
18
|
+
showTime?: boolean,
|
|
19
|
+
showSeconds?: boolean,
|
|
20
|
+
monthLong?: boolean,
|
|
21
|
+
): string {
|
|
22
|
+
let opts: any = {};
|
|
23
|
+
if (typeof options === 'object') {
|
|
24
|
+
opts = options ?? {};
|
|
25
|
+
} else {
|
|
26
|
+
opts = {
|
|
27
|
+
showTime: options as any,
|
|
28
|
+
showSeconds: showTime as any,
|
|
29
|
+
monthLong: showSeconds,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const fmt: Intl.DateTimeFormatOptions = {
|
|
34
|
+
year: !opts.hideYear ? 'numeric' : undefined,
|
|
35
|
+
month: !opts.hideMonth ? (opts.monthLong ? 'long' : 'numeric') : undefined,
|
|
36
|
+
day: !opts.hideDay && !opts.dayLong ? 'numeric' : undefined,
|
|
37
|
+
weekday: opts.dayLong ? 'long' : undefined,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
if (showTime || opts.showTime) {
|
|
41
|
+
fmt.hour = 'numeric';
|
|
42
|
+
fmt.minute = '2-digit';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (showSeconds || opts.showSeconds) {
|
|
46
|
+
fmt.second = '2-digit';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const locale = opts.language || PowerduckState.getCurrentLanguage?.() || undefined;
|
|
51
|
+
return this.toLocaleString(locale, fmt);
|
|
52
|
+
} catch {
|
|
53
|
+
return this.toString();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const fromDate = Symbol('fromDate');
|
|
58
|
+
function fromDateImpl(this: typeof Temporal.PlainDateTime, date: Date): Temporal.PlainDateTime {
|
|
59
|
+
return Temporal.PlainDateTime.from({
|
|
60
|
+
year: date.getFullYear(),
|
|
61
|
+
month: date.getMonth() + 1, // JS Date months are 0-based
|
|
62
|
+
day: date.getDate(),
|
|
63
|
+
hour: date.getHours(),
|
|
64
|
+
minute: date.getMinutes(),
|
|
65
|
+
second: date.getSeconds(),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const utcEpochMilliseconds = Symbol('utcEpochMilliseconds');
|
|
70
|
+
function utcEpochMillisecondsImpl(this: Temporal.PlainDateTime): number {
|
|
71
|
+
return this.toZonedDateTime('UTC').epochMilliseconds;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const toJsDate = Symbol('toJsDate');
|
|
75
|
+
function toJsDateImpl(this: Temporal.PlainDateTime): Date {
|
|
76
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
77
|
+
return new Date(this.toString());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const toWire = Symbol('toWire');
|
|
81
|
+
function toWireImp(
|
|
82
|
+
this: Temporal.PlainDateTime,
|
|
83
|
+
includeTime?: boolean,
|
|
84
|
+
includeMs?: boolean,
|
|
85
|
+
): string {
|
|
86
|
+
if (includeTime) {
|
|
87
|
+
if (includeMs) {
|
|
88
|
+
return this.toString();
|
|
89
|
+
} else {
|
|
90
|
+
return this.toString().split('.')[0];
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
return this.toPlainDate().toString();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
declare module '@js-temporal/polyfill' {
|
|
98
|
+
// eslint-disable-next-line ts/no-namespace
|
|
99
|
+
namespace Temporal {
|
|
100
|
+
interface PlainDateConstructor {
|
|
101
|
+
[fromDate]: typeof fromDateImpl;
|
|
102
|
+
}
|
|
103
|
+
interface PlainDateTime {
|
|
104
|
+
[toJsDate]: typeof toJsDateImpl;
|
|
105
|
+
[toWire]: typeof toWireImp;
|
|
106
|
+
[toDisplayString]: typeof toDisplayStringImpl;
|
|
107
|
+
[utcEpochMilliseconds]: typeof utcEpochMillisecondsImpl;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
(Temporal.PlainDateTime.prototype as any)[toJsDate] = toJsDateImpl;
|
|
113
|
+
(Temporal.PlainDateTime.prototype as any)[toWire] = toWireImp;
|
|
114
|
+
(Temporal.PlainDateTime.prototype as any)[toDisplayString] = toDisplayStringImpl;
|
|
115
|
+
(Temporal.PlainDateTime.prototype as any)[utcEpochMilliseconds] = utcEpochMillisecondsImpl;
|
package/common/scroll-utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Vue } from 'vue-facing-decorator';
|
|
2
2
|
import PowerduckState from '../app/powerduck-state';
|
|
3
|
+
import TemporalUtils from './utils/temporal-utils';
|
|
3
4
|
|
|
4
5
|
export default class ScrollUtils {
|
|
5
6
|
static scrollToFirstPossibleError(context: JQuery) {
|
|
@@ -12,7 +13,7 @@ export default class ScrollUtils {
|
|
|
12
13
|
if (scrollContext.length > 0) {
|
|
13
14
|
// Prevents multiple scrolling in one run
|
|
14
15
|
const lastScroll = (PowerduckState as any)._lastValidationScroll || 0;
|
|
15
|
-
const now =
|
|
16
|
+
const now = TemporalUtils.dateNowMs();
|
|
16
17
|
if (now - lastScroll < 800) {
|
|
17
18
|
return;
|
|
18
19
|
} else {
|