@sme.up/ketchup 8.0.1 → 8.0.2
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/dist/cjs/{f-button-c0ede055.js → f-button-9524bbf7.js} +1 -1
- package/dist/cjs/{f-cell-1c17dbac.js → f-cell-bcb75ade.js} +10 -8
- package/dist/cjs/{f-chip-bace36bb.js → f-chip-2249b386.js} +2 -2
- package/dist/cjs/{f-image-22174590.js → f-image-47d74999.js} +1 -1
- package/dist/cjs/{f-paginator-utils-e21e1f06.js → f-paginator-utils-b0a9ae5f.js} +63 -62
- package/dist/cjs/{f-text-field-503f2bb0.js → f-text-field-579c0fc0.js} +1 -1
- package/dist/cjs/kup-accordion.cjs.entry.js +2 -2
- package/dist/cjs/kup-autocomplete_27.cjs.entry.js +32 -87
- package/dist/cjs/kup-box.cjs.entry.js +7 -7
- package/dist/cjs/kup-calendar.cjs.entry.js +4 -4
- package/dist/cjs/kup-cell.cjs.entry.js +5 -5
- package/dist/cjs/kup-dash-list.cjs.entry.js +1 -1
- package/dist/cjs/kup-dash_2.cjs.entry.js +1 -1
- package/dist/cjs/kup-dashboard.cjs.entry.js +4 -4
- package/dist/cjs/kup-drawer.cjs.entry.js +1 -1
- package/dist/cjs/kup-echart.cjs.entry.js +1 -1
- package/dist/cjs/kup-family-tree.cjs.entry.js +3 -3
- package/dist/cjs/kup-iframe.cjs.entry.js +1 -1
- package/dist/cjs/kup-image-list.cjs.entry.js +6 -6
- package/dist/cjs/kup-lazy.cjs.entry.js +1 -1
- package/dist/cjs/kup-magic-box.cjs.entry.js +2 -2
- package/dist/cjs/{kup-manager-b994cf71.js → kup-manager-85b2a756.js} +679 -531
- package/dist/cjs/kup-nav-bar.cjs.entry.js +1 -1
- package/dist/cjs/kup-numeric-picker.cjs.entry.js +2 -2
- package/dist/cjs/kup-photo-frame.cjs.entry.js +1 -1
- package/dist/cjs/kup-planner.cjs.entry.js +2 -2
- package/dist/cjs/kup-probe.cjs.entry.js +1 -1
- package/dist/cjs/kup-qlik.cjs.entry.js +1 -1
- package/dist/cjs/kup-snackbar.cjs.entry.js +3 -3
- package/dist/collection/assets/data-table.js +0 -44
- package/dist/collection/components/kup-card/built-in/kup-card-calendar.js +5 -61
- package/dist/collection/components/kup-card/built-in/kup-card-clock.js +1 -1
- package/dist/collection/components/kup-data-table/kup-data-table-helper.js +7 -8
- package/dist/collection/components/kup-data-table/kup-data-table-state.js +1 -1
- package/dist/collection/components/kup-data-table/kup-data-table.js +5 -4
- package/dist/collection/components/kup-gauge/kup-gauge.js +4 -4
- package/dist/collection/components/kup-text-field/kup-text-field.js +4 -5
- package/dist/collection/components/kup-time-picker/kup-time-picker.js +7 -7
- package/dist/collection/components/kup-tree/kup-tree.js +2 -2
- package/dist/collection/f-components/f-cell/f-cell.js +6 -5
- package/dist/collection/f-components/f-paginator/f-paginator-utils.js +3 -3
- package/dist/collection/managers/kup-data/kup-data.js +3 -1
- package/dist/collection/managers/kup-dates/kup-dates-declarations.js +21 -10
- package/dist/collection/managers/kup-dates/kup-dates.js +312 -1
- package/dist/collection/managers/kup-math/kup-math.js +180 -9
- package/dist/collection/utils/cell-utils.js +5 -6
- package/dist/collection/utils/filters/filters.js +11 -13
- package/dist/collection/utils/utils.js +18 -435
- package/dist/components/kup-autocomplete2.js +915 -810
- package/dist/components/kup-box2.js +1 -1
- package/dist/components/kup-calendar.js +1 -1
- package/dist/components/kup-cell.js +1 -1
- package/dist/components/kup-dashboard.js +1 -1
- package/dist/components/kup-echart2.js +1 -1
- package/dist/components/kup-family-tree.js +1 -1
- package/dist/components/kup-grid2.js +1 -1
- package/dist/components/kup-iframe.js +1 -1
- package/dist/components/kup-image-list.js +1 -1
- package/dist/components/kup-magic-box.js +1 -1
- package/dist/components/kup-numeric-picker.js +1 -1
- package/dist/components/kup-planner.js +1 -1
- package/dist/esm/{f-button-c377973d.js → f-button-024f0cfe.js} +1 -1
- package/dist/esm/{f-cell-e5a98bc8.js → f-cell-90240a8c.js} +10 -8
- package/dist/esm/{f-chip-c8a18c48.js → f-chip-2238ad43.js} +2 -2
- package/dist/esm/{f-image-5cbdf39d.js → f-image-f2e9bf79.js} +1 -1
- package/dist/esm/{f-paginator-utils-a1dab059.js → f-paginator-utils-8cb3c023.js} +63 -62
- package/dist/esm/{f-text-field-dafb7c8b.js → f-text-field-d231982c.js} +1 -1
- package/dist/esm/kup-accordion.entry.js +2 -2
- package/dist/esm/kup-autocomplete_27.entry.js +26 -81
- package/dist/esm/kup-box.entry.js +7 -7
- package/dist/esm/kup-calendar.entry.js +4 -4
- package/dist/esm/kup-cell.entry.js +5 -5
- package/dist/esm/kup-dash-list.entry.js +1 -1
- package/dist/esm/kup-dash_2.entry.js +1 -1
- package/dist/esm/kup-dashboard.entry.js +4 -4
- package/dist/esm/kup-drawer.entry.js +1 -1
- package/dist/esm/kup-echart.entry.js +1 -1
- package/dist/esm/kup-family-tree.entry.js +3 -3
- package/dist/esm/kup-iframe.entry.js +1 -1
- package/dist/esm/kup-image-list.entry.js +6 -6
- package/dist/esm/kup-lazy.entry.js +1 -1
- package/dist/esm/kup-magic-box.entry.js +2 -2
- package/dist/esm/{kup-manager-3594cde8.js → kup-manager-d1da769e.js} +679 -522
- package/dist/esm/kup-nav-bar.entry.js +1 -1
- package/dist/esm/kup-numeric-picker.entry.js +2 -2
- package/dist/esm/kup-photo-frame.entry.js +1 -1
- package/dist/esm/kup-planner.entry.js +2 -2
- package/dist/esm/kup-probe.entry.js +1 -1
- package/dist/esm/kup-qlik.entry.js +1 -1
- package/dist/esm/kup-snackbar.entry.js +3 -3
- package/dist/ketchup/ketchup.esm.js +1 -1
- package/dist/ketchup/{p-31abf4b6.entry.js → p-063d4c27.entry.js} +1 -1
- package/dist/ketchup/{p-9fc6a9a8.entry.js → p-0bcda0e2.entry.js} +1 -1
- package/dist/ketchup/{p-473d2bea.entry.js → p-0d7d59c7.entry.js} +1 -1
- package/dist/ketchup/{p-b718af72.entry.js → p-163b18b9.entry.js} +1 -1
- package/dist/ketchup/{p-37ada0f0.entry.js → p-1ad628fb.entry.js} +1 -1
- package/dist/ketchup/{p-5205286a.entry.js → p-33aff1ca.entry.js} +1 -1
- package/dist/ketchup/p-3432ebaf.entry.js +9 -0
- package/dist/ketchup/{p-80815edf.entry.js → p-35b29b22.entry.js} +1 -1
- package/dist/ketchup/{p-acaa171f.js → p-36dac88e.js} +3 -3
- package/dist/ketchup/{p-22e72f06.entry.js → p-37067ee6.entry.js} +1 -1
- package/dist/ketchup/p-39a55c47.js +1 -0
- package/dist/ketchup/{p-8b248655.js → p-3cf64473.js} +1 -1
- package/dist/ketchup/p-410c102a.js +1 -0
- package/dist/ketchup/{p-d76be079.entry.js → p-43b67de4.entry.js} +1 -1
- package/dist/ketchup/{p-ef0b4f19.entry.js → p-489d55ff.entry.js} +1 -1
- package/dist/ketchup/{p-2d32e3cd.js → p-5f3680f2.js} +1 -1
- package/dist/ketchup/{p-cf322853.entry.js → p-651d89c8.entry.js} +1 -1
- package/dist/ketchup/{p-4c56e199.entry.js → p-73c8d651.entry.js} +1 -1
- package/dist/ketchup/{p-d1164680.entry.js → p-83435e6c.entry.js} +1 -1
- package/dist/ketchup/{p-7f4f5f0f.entry.js → p-89743989.entry.js} +1 -1
- package/dist/ketchup/{p-6762d447.js → p-8b46e7ce.js} +1 -1
- package/dist/ketchup/p-a84f1d24.entry.js +1 -0
- package/dist/ketchup/{p-ed7e118e.entry.js → p-b2fd2dbf.entry.js} +1 -1
- package/dist/ketchup/{p-ce5b6ce7.entry.js → p-c42b80c1.entry.js} +1 -1
- package/dist/ketchup/p-d1b050d0.entry.js +27 -0
- package/dist/ketchup/{p-d4eb9a76.entry.js → p-d6ea709e.entry.js} +1 -1
- package/dist/ketchup/{p-7be5ef32.entry.js → p-e1f1e661.entry.js} +1 -1
- package/dist/ketchup/p-eda7f130.js +1 -0
- package/dist/ketchup/{p-afff7a6e.entry.js → p-f876125d.entry.js} +1 -1
- package/dist/types/components/kup-data-table/kup-data-table-state.d.ts +1 -1
- package/dist/types/managers/kup-dates/kup-dates-declarations.d.ts +19 -9
- package/dist/types/managers/kup-dates/kup-dates.d.ts +94 -1
- package/dist/types/managers/kup-math/kup-math.d.ts +68 -7
- package/dist/types/utils/utils.d.ts +13 -102
- package/package.json +1 -1
- package/dist/ketchup/p-017418e7.entry.js +0 -27
- package/dist/ketchup/p-38f16697.entry.js +0 -9
- package/dist/ketchup/p-4638fbff.js +0 -1
- package/dist/ketchup/p-61319cfa.js +0 -1
- package/dist/ketchup/p-6c726886.entry.js +0 -1
- package/dist/ketchup/p-bf4a881b.js +0 -1
|
@@ -8,7 +8,7 @@ import 'dayjs/locale/it';
|
|
|
8
8
|
import 'dayjs/locale/pl';
|
|
9
9
|
import 'dayjs/locale/ru';
|
|
10
10
|
import 'dayjs/locale/zh';
|
|
11
|
-
import { KupDatesLocales, KupDatesNormalize } from './kup-dates-declarations';
|
|
11
|
+
import { KupDateTimeFormatOptionsMonth, KupDatesFormats, KupDatesLocales, KupDatesNormalize, } from './kup-dates-declarations';
|
|
12
12
|
/**
|
|
13
13
|
* Handles operations and formatting of dates.
|
|
14
14
|
* @module KupDates
|
|
@@ -84,6 +84,59 @@ export class KupDates {
|
|
|
84
84
|
.filter((value) => typeof value === 'string');
|
|
85
85
|
return items;
|
|
86
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Gets date format by browser locale
|
|
89
|
+
* @returns {string} date format pattern, by browser locale
|
|
90
|
+
*/
|
|
91
|
+
getDateFormat() {
|
|
92
|
+
const formatObj = new Intl.DateTimeFormat(this.getLocale()).formatToParts(new Date());
|
|
93
|
+
let dateFormat = formatObj
|
|
94
|
+
.map((obj) => {
|
|
95
|
+
switch (obj.type) {
|
|
96
|
+
case 'day':
|
|
97
|
+
return 'DD';
|
|
98
|
+
case 'month':
|
|
99
|
+
return 'MM';
|
|
100
|
+
case 'year':
|
|
101
|
+
return 'YYYY';
|
|
102
|
+
default:
|
|
103
|
+
return obj.value;
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
.join('');
|
|
107
|
+
return dateFormat;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Gets time format by browser locale
|
|
111
|
+
* @param {boolean} manageSeconds flag to set seconds managing
|
|
112
|
+
* @returns {string} time format pattern, by browser locale
|
|
113
|
+
*/
|
|
114
|
+
getTimeFormat(manageSeconds) {
|
|
115
|
+
const options = {
|
|
116
|
+
hour: '2-digit',
|
|
117
|
+
minute: '2-digit',
|
|
118
|
+
hour12: false,
|
|
119
|
+
};
|
|
120
|
+
if (manageSeconds == true) {
|
|
121
|
+
options.second = '2-digit';
|
|
122
|
+
}
|
|
123
|
+
const formatObj = new Intl.DateTimeFormat(this.getLocale() + '-u-hc-h23', options).formatToParts(new Date());
|
|
124
|
+
let timeFormat = formatObj
|
|
125
|
+
.map((obj) => {
|
|
126
|
+
switch (obj.type) {
|
|
127
|
+
case 'hour':
|
|
128
|
+
return 'HH';
|
|
129
|
+
case 'minute':
|
|
130
|
+
return 'mm';
|
|
131
|
+
case 'second':
|
|
132
|
+
return 'ss';
|
|
133
|
+
default:
|
|
134
|
+
return obj.value;
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
.join('');
|
|
138
|
+
return timeFormat;
|
|
139
|
+
}
|
|
87
140
|
/**
|
|
88
141
|
* Formats the given date.
|
|
89
142
|
* @param {dayjs.ConfigType} input - Date to be formatted.
|
|
@@ -96,6 +149,23 @@ export class KupDates {
|
|
|
96
149
|
}
|
|
97
150
|
return dayjs(input).format(format);
|
|
98
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Gets the time formatted
|
|
154
|
+
* @param {Date} time time as Date object
|
|
155
|
+
* @param {boolean} manageSeconds flag to set seconds managing
|
|
156
|
+
* @return {string} time as string, formatted
|
|
157
|
+
**/
|
|
158
|
+
formatTime(time, manageSeconds) {
|
|
159
|
+
const options = {
|
|
160
|
+
hour: '2-digit',
|
|
161
|
+
minute: '2-digit',
|
|
162
|
+
hour12: false,
|
|
163
|
+
};
|
|
164
|
+
if (manageSeconds == true) {
|
|
165
|
+
options.second = '2-digit';
|
|
166
|
+
}
|
|
167
|
+
return time.toLocaleTimeString(this.getLocale() + '-u-hc-h23', options);
|
|
168
|
+
}
|
|
99
169
|
/**
|
|
100
170
|
* Validates the given date.
|
|
101
171
|
* @param {dayjs.ConfigType} date - Date to be validated.
|
|
@@ -111,6 +181,16 @@ export class KupDates {
|
|
|
111
181
|
return dayjs(date, undefined, strict).isValid();
|
|
112
182
|
}
|
|
113
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Validates the given date as string.
|
|
186
|
+
* @param {string} value time string, formatted by actual browser locale
|
|
187
|
+
* @param {boolean} manageSeconds if manage seconds
|
|
188
|
+
* @returns {boolean} true if time string in input is a valid time
|
|
189
|
+
*/
|
|
190
|
+
isValidFormattedStringTime(value, manageSeconds) {
|
|
191
|
+
let format = this.getTimeFormat(manageSeconds);
|
|
192
|
+
return this.isValid(value, format, true);
|
|
193
|
+
}
|
|
114
194
|
/**
|
|
115
195
|
* Converts the input in a Date object.
|
|
116
196
|
* @param {dayjs.ConfigType} input - Input date.
|
|
@@ -323,6 +403,237 @@ export class KupDates {
|
|
|
323
403
|
subtract(input, value, unit) {
|
|
324
404
|
return dayjs(input).subtract(value, unit);
|
|
325
405
|
}
|
|
406
|
+
/**
|
|
407
|
+
* Gets the month formatted
|
|
408
|
+
* @param {number} month month id
|
|
409
|
+
* @param {KupDateTimeFormatOptionsMonth} format format
|
|
410
|
+
* @returns {string} the month formatted, by browser locale
|
|
411
|
+
*/
|
|
412
|
+
getMonthAsString(month, format) {
|
|
413
|
+
if (month == null) {
|
|
414
|
+
return '';
|
|
415
|
+
}
|
|
416
|
+
const dateTmp = new Date();
|
|
417
|
+
dateTmp.setDate(1);
|
|
418
|
+
dateTmp.setMonth(month - 1);
|
|
419
|
+
const options = {
|
|
420
|
+
month: format,
|
|
421
|
+
};
|
|
422
|
+
const dateTimeFormat = new Intl.DateTimeFormat(this.getLocale(), options);
|
|
423
|
+
return dateTimeFormat.format(dateTmp);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Gets the year months formatted
|
|
427
|
+
* @param {KupDateTimeFormatOptionsMonth} format format
|
|
428
|
+
* @returns {string[]} the months formatted, by browser locale
|
|
429
|
+
*/
|
|
430
|
+
getMonthsAsString(format) {
|
|
431
|
+
if (format == null || format.trim() == '') {
|
|
432
|
+
format = KupDateTimeFormatOptionsMonth.LONG;
|
|
433
|
+
}
|
|
434
|
+
var months = [];
|
|
435
|
+
for (var i = 0; i < 12; i++) {
|
|
436
|
+
months[i] = this.getMonthAsString(i + 1, format);
|
|
437
|
+
}
|
|
438
|
+
return months;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Gets the day formatted
|
|
442
|
+
* @param {Date} date date
|
|
443
|
+
* @returns {string} the day formatted, by browser locale
|
|
444
|
+
*/
|
|
445
|
+
getDayAsString(date) {
|
|
446
|
+
if (date == null) {
|
|
447
|
+
return '';
|
|
448
|
+
}
|
|
449
|
+
const options = {
|
|
450
|
+
weekday: 'narrow',
|
|
451
|
+
/** weekday: 'narrow' 'short' 'long' */
|
|
452
|
+
};
|
|
453
|
+
const dateTimeFormat = new Intl.DateTimeFormat(this.getLocale(), options);
|
|
454
|
+
return dateTimeFormat.format(date);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* First day of current week
|
|
458
|
+
* @param {number} firstDayIndex first day of week index
|
|
459
|
+
* @returns {Date} the first day of current week
|
|
460
|
+
*/
|
|
461
|
+
firstDayThisWeek(firstDayIndex) {
|
|
462
|
+
var d = new Date();
|
|
463
|
+
const day = d.getDay();
|
|
464
|
+
// dayIndex0
|
|
465
|
+
d.setDate(d.getDate() - day);
|
|
466
|
+
// dayIndexX
|
|
467
|
+
d.setDate(d.getDate() + firstDayIndex);
|
|
468
|
+
return d;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Dates of current week
|
|
472
|
+
* @param {number} firstDayIndex first day of week index
|
|
473
|
+
* @returns { startDate: Date; endDate: Date } the dates of current week
|
|
474
|
+
*/
|
|
475
|
+
thisWeek(firstDayIndex) {
|
|
476
|
+
const firstDay = this.firstDayThisWeek(firstDayIndex);
|
|
477
|
+
return {
|
|
478
|
+
startDate: firstDay,
|
|
479
|
+
endDate: offsetDate(firstDay, 6),
|
|
480
|
+
};
|
|
481
|
+
function offsetDate(base, count) {
|
|
482
|
+
const date = new Date(base);
|
|
483
|
+
date.setDate(base.getDate() + count);
|
|
484
|
+
return date;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Gets the days of current week as string
|
|
489
|
+
* @param {number} firstDayIndex first day of week index
|
|
490
|
+
* @returns {string[]} the days of current week as string
|
|
491
|
+
*/
|
|
492
|
+
getDaysOfWeekAsString(firstDayIndex) {
|
|
493
|
+
var thisWeekDays = this.thisWeek(firstDayIndex);
|
|
494
|
+
var monday = thisWeekDays.startDate;
|
|
495
|
+
var days = [];
|
|
496
|
+
for (var i = 0; i < 7; i++) {
|
|
497
|
+
var date = new Date(monday.toISOString());
|
|
498
|
+
date.setDate(date.getDate() + i);
|
|
499
|
+
days[i] = this.getDayAsString(date);
|
|
500
|
+
}
|
|
501
|
+
return days;
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Gets the timestamp formatted
|
|
505
|
+
* @param {string} value date/time as string, formatted ISO
|
|
506
|
+
* @returns {string} date/time as string, formatted by actual browser locale
|
|
507
|
+
**/
|
|
508
|
+
timestampStringToFormattedString(value) {
|
|
509
|
+
const options = {
|
|
510
|
+
day: '2-digit',
|
|
511
|
+
month: '2-digit',
|
|
512
|
+
year: 'numeric',
|
|
513
|
+
hour: '2-digit',
|
|
514
|
+
minute: '2-digit',
|
|
515
|
+
second: '2-digit',
|
|
516
|
+
hour12: false,
|
|
517
|
+
};
|
|
518
|
+
let date = this.toDate(this.normalize(value, KupDatesNormalize.TIMESTAMP));
|
|
519
|
+
return date.toLocaleString(this.getLocale() + '-u-hc-h23', options);
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Gets ISO date/time from formatted string, as string
|
|
523
|
+
* @param {string} value date/time as string, formatted by actual browser locale
|
|
524
|
+
* @returns {string} date/time as string, formatted ISO
|
|
525
|
+
**/
|
|
526
|
+
formattedStringToTimestampString(value) {
|
|
527
|
+
return this.formattedStringToCustomDateTime(value, KupDatesFormats.ISO_DATE_TIME, true);
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Gets formatted dateTime as customed ISO (see KupDatesFormats)
|
|
531
|
+
* @param {string} value time as string, formatted by actual browser locale
|
|
532
|
+
* @param {string} outputFormat time format to return (see KupDatesFormats)
|
|
533
|
+
* @param {boolean} manageSeconds flag to set seconds managing
|
|
534
|
+
* @returns {string} time as string, formatted
|
|
535
|
+
**/
|
|
536
|
+
formattedStringToCustomDateTime(value, outputFormat, manageSeconds) {
|
|
537
|
+
let inputFormat = this.getTimeFormat(manageSeconds);
|
|
538
|
+
if (this.isValid(value, inputFormat)) {
|
|
539
|
+
return this.format(this.normalize(value, KupDatesNormalize.TIME), outputFormat);
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
return '';
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Gets the time formatted
|
|
547
|
+
* @param {string} value time as string, formatted ISO
|
|
548
|
+
* @param {boolean} manageSeconds flag to set seconds managing
|
|
549
|
+
* @param {string} customedFormat time format from smeupObject
|
|
550
|
+
* @returns {string} time as string, formatted by actual browser locale
|
|
551
|
+
**/
|
|
552
|
+
timeStringToFormattedString(value, manageSeconds, customedFormat) {
|
|
553
|
+
const options = {
|
|
554
|
+
hour: '2-digit',
|
|
555
|
+
minute: '2-digit',
|
|
556
|
+
hour12: false,
|
|
557
|
+
};
|
|
558
|
+
if (manageSeconds == true) {
|
|
559
|
+
options.second = '2-digit';
|
|
560
|
+
}
|
|
561
|
+
let date = this.toDate(this.normalize(value, KupDatesNormalize.TIME));
|
|
562
|
+
return formatByCustomedOutputTimeFormat(value, date, options, customedFormat, this);
|
|
563
|
+
function formatByCustomedOutputTimeFormat(valueStr, date, options, customedFormat, kupDates) {
|
|
564
|
+
if (customedFormat == null) {
|
|
565
|
+
return date.toLocaleTimeString(kupDates.getLocale() + '-u-hc-h23', options);
|
|
566
|
+
}
|
|
567
|
+
switch (customedFormat) {
|
|
568
|
+
case 'I13': {
|
|
569
|
+
//hh:mm
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
case 'I12': {
|
|
573
|
+
//hh:mm:ss
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
case 'I11': {
|
|
577
|
+
//???
|
|
578
|
+
//hh:dddd
|
|
579
|
+
//return moment(date).format('HH:DDDD');
|
|
580
|
+
return valueStr;
|
|
581
|
+
}
|
|
582
|
+
case 'I14': {
|
|
583
|
+
//???
|
|
584
|
+
//sssss
|
|
585
|
+
//return moment(date).format('SSSSS');
|
|
586
|
+
return valueStr;
|
|
587
|
+
}
|
|
588
|
+
case 'I1H': {
|
|
589
|
+
//???
|
|
590
|
+
//Ora,Cen/Min HH,xx
|
|
591
|
+
return valueStr;
|
|
592
|
+
}
|
|
593
|
+
case 'I1M': {
|
|
594
|
+
//???
|
|
595
|
+
//Min,Cen/Sec MMMM,xx
|
|
596
|
+
return valueStr;
|
|
597
|
+
}
|
|
598
|
+
case 'I21': {
|
|
599
|
+
//???
|
|
600
|
+
//Giorni,(4 decim)
|
|
601
|
+
return valueStr;
|
|
602
|
+
}
|
|
603
|
+
case 'I22': {
|
|
604
|
+
//???
|
|
605
|
+
//Ore,(4 decim)
|
|
606
|
+
return valueStr;
|
|
607
|
+
}
|
|
608
|
+
case 'I23': {
|
|
609
|
+
//???
|
|
610
|
+
//Minuti,(4 decim)
|
|
611
|
+
return valueStr;
|
|
612
|
+
}
|
|
613
|
+
case 'I24': {
|
|
614
|
+
//???
|
|
615
|
+
//Secondi
|
|
616
|
+
return valueStr;
|
|
617
|
+
}
|
|
618
|
+
case 'I2H': {
|
|
619
|
+
//???
|
|
620
|
+
//Ora,Cen/Min HHHH,xx
|
|
621
|
+
return valueStr;
|
|
622
|
+
}
|
|
623
|
+
case 'I2D': {
|
|
624
|
+
//???
|
|
625
|
+
//Ore Minuti Secondi HHMMS
|
|
626
|
+
return valueStr;
|
|
627
|
+
}
|
|
628
|
+
case 'I2M': {
|
|
629
|
+
//???
|
|
630
|
+
//Min,Cen/Sec MMMM,xx
|
|
631
|
+
return valueStr;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return date.toLocaleTimeString(kupDates.getLocale() + '-u-hc-h23', options);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
326
637
|
/**
|
|
327
638
|
* Registers a KupComponent in KupDates, in order to be properly handled whenever the locale changes.
|
|
328
639
|
* @param {any} component - The Ketchup component to be registered.
|
|
@@ -8,6 +8,7 @@ import 'numeral/locales/ru';
|
|
|
8
8
|
import { KupDebugCategory } from '../kup-debug/kup-debug-declarations';
|
|
9
9
|
import { KupMathLocales, } from './kup-math-declarations';
|
|
10
10
|
import { customFormula, normalDistributionFormula } from './kup-math-helper';
|
|
11
|
+
import { getRegExpFromString } from '../../utils/utils';
|
|
11
12
|
const dom = document.documentElement;
|
|
12
13
|
/**
|
|
13
14
|
* Handles mathematical operations and number formatting/conversion.
|
|
@@ -31,7 +32,7 @@ export class KupMath {
|
|
|
31
32
|
const maximumFractionDigits = 14;
|
|
32
33
|
if (value == null || value == '')
|
|
33
34
|
return value;
|
|
34
|
-
return Number(value).toLocaleString(
|
|
35
|
+
return Number(value).toLocaleString(this.locale, {
|
|
35
36
|
maximumFractionDigits: maximumFractionDigits,
|
|
36
37
|
});
|
|
37
38
|
},
|
|
@@ -120,14 +121,15 @@ export class KupMath {
|
|
|
120
121
|
return this.numeral(n).format(format);
|
|
121
122
|
}
|
|
122
123
|
/**
|
|
123
|
-
*
|
|
124
|
+
* Create the pattern string for format a number
|
|
124
125
|
* @param {boolean} thousandPoint - show thousandPoint
|
|
125
126
|
* @param {number} decimals - number of decimals
|
|
127
|
+
* @returns {string} - formatter pattern
|
|
126
128
|
*/
|
|
127
129
|
createFormatPattern(thousandPoint, decimals) {
|
|
128
130
|
var format = '0';
|
|
129
131
|
if (thousandPoint) {
|
|
130
|
-
format += ',
|
|
132
|
+
format += ',0';
|
|
131
133
|
}
|
|
132
134
|
if (decimals && decimals > 0) {
|
|
133
135
|
format += '.';
|
|
@@ -139,7 +141,7 @@ export class KupMath {
|
|
|
139
141
|
}
|
|
140
142
|
/**
|
|
141
143
|
* Returns the decimal separator of current browser
|
|
142
|
-
* @returns current decimal separator, by locale
|
|
144
|
+
* @returns {string} current decimal separator, by locale
|
|
143
145
|
*/
|
|
144
146
|
decimalSeparator() {
|
|
145
147
|
const numberWithGroupAndDecimalSeparator = 1000.1;
|
|
@@ -149,7 +151,7 @@ export class KupMath {
|
|
|
149
151
|
}
|
|
150
152
|
/**
|
|
151
153
|
* Returns the group separator of current browser
|
|
152
|
-
* @returns current group separator, by locale
|
|
154
|
+
* @returns {string} current group separator, by locale
|
|
153
155
|
*/
|
|
154
156
|
groupSeparator() {
|
|
155
157
|
const numberWithGroupAndDecimalSeparator = 1000.1;
|
|
@@ -159,11 +161,12 @@ export class KupMath {
|
|
|
159
161
|
}
|
|
160
162
|
/**
|
|
161
163
|
* Checks if an input string matches options, for desired formatted decimal number (integer digits, decimal digits)
|
|
162
|
-
* @param value the input value to check
|
|
163
|
-
* @param options options for customize the check
|
|
164
|
-
* @returns an object from applying the regular expression for check
|
|
164
|
+
* @param {string} value the input value to check
|
|
165
|
+
* @param {NumericFieldFormatOptions} options options for customize the check
|
|
166
|
+
* @returns {RegExpMatchArray} an object from applying the regular expression for check
|
|
165
167
|
*/
|
|
166
168
|
matchNumericValueWithOptions(value, options) {
|
|
169
|
+
value = value.replace(getRegExpFromString(this.groupSeparator(), 'g'), '');
|
|
167
170
|
// see https://github.com/24eme/jquery-input-number-format.git
|
|
168
171
|
let found = undefined;
|
|
169
172
|
let integerPartSuffix = '+';
|
|
@@ -204,9 +207,22 @@ export class KupMath {
|
|
|
204
207
|
* Returns a number from a non-specified input type between string, number, or String.
|
|
205
208
|
* @param {string | String | number} input - Input value to numberify.
|
|
206
209
|
* @param {boolean} inputIsLocalized - Numberifies assuming the input string is in the current KupMath locale's format.
|
|
210
|
+
* @param {string} type - type of number for calculate suffix
|
|
207
211
|
* @returns {number} Resulting number or NaN (when not a number).
|
|
208
212
|
*/
|
|
209
|
-
numberify(input, inputIsLocalized) {
|
|
213
|
+
numberify(input, inputIsLocalized, type) {
|
|
214
|
+
if (typeof input != 'number') {
|
|
215
|
+
if (type) {
|
|
216
|
+
let suffix = this.getNumericValueSuffix(type);
|
|
217
|
+
if (suffix != '') {
|
|
218
|
+
input = input.replace(getRegExpFromString(suffix, 'g'), '');
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const groupSeparator = inputIsLocalized
|
|
222
|
+
? this.groupSeparator()
|
|
223
|
+
: ',';
|
|
224
|
+
input = input.replace(getRegExpFromString(groupSeparator, 'g'), '');
|
|
225
|
+
}
|
|
210
226
|
let n = NaN;
|
|
211
227
|
if (inputIsLocalized) {
|
|
212
228
|
n = this.numeral(input).value();
|
|
@@ -222,6 +238,161 @@ export class KupMath {
|
|
|
222
238
|
}
|
|
223
239
|
return n;
|
|
224
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Returns a number from a non-specified input type between string, number, or String.
|
|
243
|
+
* If value in is null, undefined or blank, returns 0
|
|
244
|
+
* @param {string} input number as string, formatted by locale US, decimal separator . (like java decimal numbers)
|
|
245
|
+
* @param {boolean} inputIsLocalized - Numberifies assuming the input string is in the current KupMath locale's format.
|
|
246
|
+
* @param {string} type - type of number for calculate suffix
|
|
247
|
+
* @returns {number} Resulting number
|
|
248
|
+
**/
|
|
249
|
+
numberifySafe(input, inputIsLocalized, type) {
|
|
250
|
+
if (!input || input == null || input.trim() == '') {
|
|
251
|
+
input = '0';
|
|
252
|
+
}
|
|
253
|
+
return this.numberify(input, inputIsLocalized, type);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Checks if input is a valid number
|
|
257
|
+
* @param {any} value input value to check
|
|
258
|
+
* @returns {boolean} if input value is valid number
|
|
259
|
+
*/
|
|
260
|
+
isNumber(value) {
|
|
261
|
+
//return typeof value === 'number';
|
|
262
|
+
return !isNaN(value);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Checks if string in input is a valid formatted number
|
|
266
|
+
* @param {string} value number as string, formatted by actual browser locale
|
|
267
|
+
* @param {string} type - type of number for calculate suffix
|
|
268
|
+
* @returns {boolean} true if number string in input is a valid number
|
|
269
|
+
*/
|
|
270
|
+
isStringNumber(value, type) {
|
|
271
|
+
if (value == null || value.trim() == '') {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
let tmpStr = this.formattedStringToNumberString(value, type);
|
|
275
|
+
if (this.isNumber(tmpStr)) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Gets number as string, formatted by locale US, decimal separator . (like java decimal numbers)
|
|
282
|
+
* @param {string} input number as string, formatted by actual browser locale (maybe)
|
|
283
|
+
* @param {string} type - type of number for calculate suffix
|
|
284
|
+
* @param {string} decSeparator - decimal serparator of input string
|
|
285
|
+
* @returns {string} number as string, formatted by locale US, decimal separator . (like java decimal numbers), without group separator
|
|
286
|
+
**/
|
|
287
|
+
formattedStringToNumberString(input, type, decSeparator) {
|
|
288
|
+
return numberStringToNumberString(input, type, decSeparator !== null && decSeparator !== void 0 ? decSeparator : this.decimalSeparator(), this);
|
|
289
|
+
function numberStringToNumberString(input, type, decFmt, kupMath) {
|
|
290
|
+
if (!input || input == null || input.trim() == '') {
|
|
291
|
+
return '';
|
|
292
|
+
}
|
|
293
|
+
let unf = kupMath.numberifySafe(input, decFmt != '.', type);
|
|
294
|
+
if (unf == null || isNaN(unf)) {
|
|
295
|
+
return input;
|
|
296
|
+
}
|
|
297
|
+
return numberToString(unf, -1, 'en-US', kupMath);
|
|
298
|
+
}
|
|
299
|
+
function numberToString(input, decimals, locale, kupMath) {
|
|
300
|
+
if (input == null) {
|
|
301
|
+
input = 0;
|
|
302
|
+
}
|
|
303
|
+
if (decimals == null || decimals == -1) {
|
|
304
|
+
decimals = kupMath.countDecimals(input);
|
|
305
|
+
}
|
|
306
|
+
let n = Number(input);
|
|
307
|
+
let f = decimals > -1
|
|
308
|
+
? {
|
|
309
|
+
minimumFractionDigits: decimals,
|
|
310
|
+
maximumFractionDigits: decimals,
|
|
311
|
+
useGrouping: false,
|
|
312
|
+
}
|
|
313
|
+
: { useGrouping: false };
|
|
314
|
+
return n.toLocaleString(locale, f);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Gets the number of decimals for current number
|
|
319
|
+
* @param {number} value numer input
|
|
320
|
+
* @returns {number} the number of decimals
|
|
321
|
+
*/
|
|
322
|
+
countDecimals(value) {
|
|
323
|
+
var _a;
|
|
324
|
+
if (Math.floor(value) === value)
|
|
325
|
+
return 0;
|
|
326
|
+
let stringValue = value.toString().split('.')[1];
|
|
327
|
+
if (stringValue) {
|
|
328
|
+
return (_a = stringValue.length) !== null && _a !== void 0 ? _a : 0;
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
return 0;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Gets the suffix for number, by type
|
|
336
|
+
* @param {string} type - type of number for calculate suffix
|
|
337
|
+
* @returns {string} suffix for number, by type
|
|
338
|
+
**/
|
|
339
|
+
getNumericValueSuffix(type) {
|
|
340
|
+
type = type.toUpperCase();
|
|
341
|
+
let nstr = '';
|
|
342
|
+
if (type == 'P') {
|
|
343
|
+
nstr = ' %';
|
|
344
|
+
}
|
|
345
|
+
else if (type == 'VE') {
|
|
346
|
+
nstr = ' €';
|
|
347
|
+
}
|
|
348
|
+
else if (type == 'VL') {
|
|
349
|
+
nstr = ' £';
|
|
350
|
+
}
|
|
351
|
+
else if (type == 'VV') {
|
|
352
|
+
nstr = ' $';
|
|
353
|
+
}
|
|
354
|
+
return nstr;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Gets the number as string, formatted by actual browser locale, with suffix by type
|
|
358
|
+
* @param {number} input number
|
|
359
|
+
* @param {number} decimals number of significant decimal digits for output
|
|
360
|
+
* @param {string} type - type of number for calculate suffix
|
|
361
|
+
* @returns {string} number as string, formatted by actual browser locale, with suffix by type
|
|
362
|
+
**/
|
|
363
|
+
numberToFormattedString(input, decimals, type) {
|
|
364
|
+
if (input == null || isNaN(input)) {
|
|
365
|
+
return '';
|
|
366
|
+
}
|
|
367
|
+
if (decimals == null || decimals == -1) {
|
|
368
|
+
decimals = this.countDecimals(input);
|
|
369
|
+
}
|
|
370
|
+
let nstr = this.format(input, this.createFormatPattern(true, decimals));
|
|
371
|
+
nstr = nstr + this.getNumericValueSuffix(type);
|
|
372
|
+
return nstr;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Gets the number as string, formatted by actual browser locale, with suffix by type
|
|
376
|
+
* @param {string} input number as string, formatted by locale US, decimal separator . (like java decimal numbers)
|
|
377
|
+
* @param {number} decimals number of significant decimal digits for output
|
|
378
|
+
* @param {string} type - type of number for calculate suffix
|
|
379
|
+
* @param {string} decSeparator decimal separator for outpu string
|
|
380
|
+
* @returns {string} number as string, formatted by actual browser locale (or using decimal separator param), with suffix by type
|
|
381
|
+
**/
|
|
382
|
+
numberStringToFormattedString(input, decimals, type, decSeparator) {
|
|
383
|
+
let value = this.numberToFormattedString(this.numberifySafe(input), decimals, type);
|
|
384
|
+
if (!decSeparator) {
|
|
385
|
+
return value;
|
|
386
|
+
}
|
|
387
|
+
const browserDecSeparator = this.decimalSeparator();
|
|
388
|
+
if (browserDecSeparator == decSeparator) {
|
|
389
|
+
return value;
|
|
390
|
+
}
|
|
391
|
+
const browserGroupSeparator = this.groupSeparator();
|
|
392
|
+
value = value.replace(getRegExpFromString(browserGroupSeparator, 'g'), '');
|
|
393
|
+
value = value.replace(getRegExpFromString(browserDecSeparator, 'g'), decSeparator);
|
|
394
|
+
return value;
|
|
395
|
+
}
|
|
225
396
|
/**
|
|
226
397
|
* Registers a KupComponent in KupMath, in order to be properly handled whenever the locale changes.
|
|
227
398
|
* @param {any} component - The Ketchup component to be registered.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { stringToNumber, unformattedStringToFormattedStringNumber, unformattedStringToFormattedStringTime, unformattedStringToFormattedStringTimestamp, } from './utils';
|
|
2
1
|
import { KupDatesFormats } from '../managers/kup-dates/kup-dates-declarations';
|
|
3
2
|
const dom = document.documentElement;
|
|
4
3
|
// -------------
|
|
@@ -43,17 +42,17 @@ export function getValueForDisplay(value, obj, decimals) {
|
|
|
43
42
|
return value;
|
|
44
43
|
}
|
|
45
44
|
if (dom.ketchup.objects.isNumber(obj)) {
|
|
46
|
-
return
|
|
45
|
+
return dom.ketchup.math.numberStringToFormattedString(value, decimals ? decimals : -1, obj ? obj.p : '');
|
|
47
46
|
}
|
|
48
47
|
if (dom.ketchup.objects.isDate(obj) &&
|
|
49
48
|
dom.ketchup.dates.isValid(value, KupDatesFormats.ISO_DATE)) {
|
|
50
49
|
return dom.ketchup.dates.format(value);
|
|
51
50
|
}
|
|
52
51
|
if (dom.ketchup.objects.isTime(obj)) {
|
|
53
|
-
return
|
|
52
|
+
return dom.ketchup.dates.timeStringToFormattedString(value, dom.ketchup.objects.isTimeWithSeconds(obj), obj.t + obj.p);
|
|
54
53
|
}
|
|
55
54
|
if (dom.ketchup.objects.isTimestamp(obj)) {
|
|
56
|
-
return
|
|
55
|
+
return dom.ketchup.dates.timestampStringToFormattedString(value);
|
|
57
56
|
}
|
|
58
57
|
return value;
|
|
59
58
|
}
|
|
@@ -98,8 +97,8 @@ export function compareValues(obj1, value1, obj2, value2, sortMode) {
|
|
|
98
97
|
let v1 = s1;
|
|
99
98
|
let v2 = s2;
|
|
100
99
|
if (dom.ketchup.objects.isNumber(obj1)) {
|
|
101
|
-
v1 =
|
|
102
|
-
v2 =
|
|
100
|
+
v1 = dom.ketchup.math.numberifySafe(s1);
|
|
101
|
+
v2 = dom.ketchup.math.numberifySafe(s2);
|
|
103
102
|
}
|
|
104
103
|
else if (dom.ketchup.objects.isDate(obj1)) {
|
|
105
104
|
v1 = dom.ketchup.dates.toDate(dom.ketchup.dates.format(s1, KupDatesFormats.ISO_DATE));
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { KupTagNames } from '../../types/GenericTypes';
|
|
2
2
|
import { KupDatesFormats, KupDatesNormalize, } from '../../managers/kup-dates/kup-dates-declarations';
|
|
3
|
-
import { formattedStringToCustomUnformattedStringTime, formattedStringToDefaultUnformattedStringTimestamp, formattedStringToUnformattedStringNumber, isValidFormattedStringNumber, isValidFormattedStringTime, stringToNumber, unformattedStringNumberToNumber, isNumber as isNumberThisString, } from '../utils';
|
|
4
3
|
import { FilterInterval, FILTER_ANALIZER, } from './filters-declarations';
|
|
5
4
|
const dom = document.documentElement;
|
|
6
5
|
/**
|
|
@@ -52,8 +51,8 @@ export class Filters {
|
|
|
52
51
|
: KupDatesFormats.ISO_TIME_WITHOUT_SECONDS)) {
|
|
53
52
|
return newValue;
|
|
54
53
|
}
|
|
55
|
-
if (isValidFormattedStringTime(value, manageSeconds)) {
|
|
56
|
-
return
|
|
54
|
+
if (dom.ketchup.dates.isValidFormattedStringTime(value, manageSeconds)) {
|
|
55
|
+
return dom.ketchup.dates.formattedStringToCustomDateTime(value, manageSeconds
|
|
57
56
|
? KupDatesFormats.ISO_TIME
|
|
58
57
|
: KupDatesFormats.ISO_TIME_WITHOUT_SECONDS, manageSeconds);
|
|
59
58
|
}
|
|
@@ -62,13 +61,13 @@ export class Filters {
|
|
|
62
61
|
if (dom.ketchup.dates.isValid(value, KupDatesFormats.ISO_DATE_TIME)) {
|
|
63
62
|
return newValue;
|
|
64
63
|
}
|
|
65
|
-
if (isValidFormattedStringTime(value, true)) {
|
|
66
|
-
return
|
|
64
|
+
if (dom.ketchup.dates.isValidFormattedStringTime(value, true)) {
|
|
65
|
+
return dom.ketchup.dates.formattedStringToTimestampString(value);
|
|
67
66
|
}
|
|
68
67
|
}
|
|
69
68
|
else if (dom.ketchup.objects.isNumber(smeupObj)) {
|
|
70
|
-
if (
|
|
71
|
-
return
|
|
69
|
+
if (dom.ketchup.math.isStringNumber(value, smeupObj ? smeupObj.p : '')) {
|
|
70
|
+
return dom.ketchup.math.formattedStringToNumberString(value, smeupObj ? smeupObj.p : '');
|
|
72
71
|
}
|
|
73
72
|
}
|
|
74
73
|
return newValue;
|
|
@@ -190,12 +189,11 @@ export class Filters {
|
|
|
190
189
|
}
|
|
191
190
|
let checkByRegularExpression = true;
|
|
192
191
|
if (dom.ketchup.objects.isNumber(obj)) {
|
|
193
|
-
|
|
194
|
-
let valueNumber = stringToNumber(value);
|
|
192
|
+
let valueNumber = dom.ketchup.math.numberifySafe(value, obj ? obj.p : '');
|
|
195
193
|
if (from != '') {
|
|
196
|
-
if (
|
|
194
|
+
if (dom.ketchup.math.isNumber(from)) {
|
|
197
195
|
checkByRegularExpression = false;
|
|
198
|
-
let fromNumber =
|
|
196
|
+
let fromNumber = dom.ketchup.math.numberifySafe(from);
|
|
199
197
|
if (valueNumber < fromNumber) {
|
|
200
198
|
return false;
|
|
201
199
|
}
|
|
@@ -205,9 +203,9 @@ export class Filters {
|
|
|
205
203
|
}
|
|
206
204
|
}
|
|
207
205
|
if (to != '') {
|
|
208
|
-
if (
|
|
206
|
+
if (dom.ketchup.math.isNumber(to)) {
|
|
209
207
|
checkByRegularExpression = false;
|
|
210
|
-
let toNumber =
|
|
208
|
+
let toNumber = dom.ketchup.math.numberifySafe(to);
|
|
211
209
|
if (valueNumber > toNumber) {
|
|
212
210
|
return false;
|
|
213
211
|
}
|