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.
Files changed (61) hide show
  1. package/app/powerduck-initializer.ts +3 -3
  2. package/common/api-http.ts +20 -14
  3. package/common/css/ladda-themeless-zoomin.min.css +89 -89
  4. package/common/enum-translation/day-translator.ts +3 -2
  5. package/common/excel/excel-reader.ts +2 -9
  6. package/common/extensions/array-extensions.ts +116 -0
  7. package/common/extensions/string-extensions.ts +92 -0
  8. package/common/extensions/temporal-extensions.ts +115 -0
  9. package/common/scroll-utils.ts +2 -1
  10. package/common/temporal-helpers.ts +551 -0
  11. package/common/throttled-api-caller.ts +149 -0
  12. package/common/timezone-helper.ts +39 -29
  13. package/common/utils/cookie.ts +11 -8
  14. package/common/utils/date-localization-utils.ts +25 -19
  15. package/common/utils/date-utils.ts +37 -47
  16. package/common/utils/form-utils.ts +3 -1
  17. package/common/utils/language-utils.ts +21 -27
  18. package/common/utils/temporal-utils.ts +43 -0
  19. package/common/utils/upload-image-helper.ts +1 -1
  20. package/common/utils/utils.ts +14 -14
  21. package/common/validation.ts +17 -5
  22. package/components/chart-js/line-chart-flot.tsx +9 -9
  23. package/components/chart-js/thirdparty/flot/jquery.flot.categories.min.js +93 -93
  24. package/components/chart-js/thirdparty/flot/jquery.flot.crosshair.min.js +83 -83
  25. package/components/chart-js/thirdparty/flot/jquery.flot.navigate.min.js +270 -270
  26. package/components/chart-js/thirdparty/flot/jquery.flot.pie.min.js +507 -507
  27. package/components/chart-js/thirdparty/flot/jquery.flot.resize.js +7 -9
  28. package/components/chart-js/thirdparty/flot/jquery.flot.resize.min.js +9 -11
  29. package/components/chart-js/thirdparty/flot/jquery.flot.stack.min.js +104 -104
  30. package/components/chart-js/ts/line-chart-contracts.ts +2 -2
  31. package/components/container-with-breakpoints/ts/breakpoint-handler.ts +2 -2
  32. package/components/counter/testall.tsx +89 -75
  33. package/components/datatable/datatable.tsx +2379 -2375
  34. package/components/datatable/export-excel-modal.tsx +12 -14
  35. package/components/datatable/ts/reorder.ts +4 -2
  36. package/components/dropdown/index.tsx +48 -22
  37. package/components/dropdown/mobile/legacy_fdd.ts +10 -11
  38. package/components/dropzone/gallery-dropzone.tsx +394 -382
  39. package/components/fullcalendar/fullcalendar-draggable-event.tsx +8 -7
  40. package/components/fullcalendar/timegrid-calendar.tsx +60 -67
  41. package/components/image-crop/image-cropping-modal.tsx +9 -8
  42. package/components/image-crop/upload-and-crop.tsx +162 -162
  43. package/components/image-crop/vendor/jquery.Jcrop.min.css +344 -344
  44. package/components/import/import-mapper.tsx +2 -2
  45. package/components/input/daterange-picker.tsx +502 -521
  46. package/components/input/datetime-picker.tsx +45 -50
  47. package/components/input/plugins/daterangepicker/daterangepicker.min.css +400 -400
  48. package/components/input/plugins/daterangepicker/jquery.daterangepicker.min.js +346 -339
  49. package/components/input/plugins/daterangepicker/jquery.daterangepicker.ts +580 -402
  50. package/components/input/radio-button-group.tsx +2 -2
  51. package/components/input/ts/dateInputHelper.ts +1 -0
  52. package/components/input/wysiwig.tsx +12 -7
  53. package/components/svg/skilift-svg.tsx +6 -6
  54. package/package.json +2 -1
  55. package/common/date-wrapper.ts +0 -422
  56. package/common/utils/array-extend.ts +0 -215
  57. package/common/utils/array-remove.ts +0 -10
  58. package/common/utils/array-sort.ts +0 -56
  59. package/common/utils/capitalize-string.ts +0 -11
  60. package/common/utils/format-string.ts +0 -14
  61. package/common/utils/latinize-string.ts +0 -7
@@ -3,7 +3,6 @@ import type { FormItemWrapperArgs, MarginType } from '../form/form-item-wrapper'
3
3
  import { Prop, toNative } from 'vue-facing-decorator';
4
4
  import PowerduckState from '../../app/powerduck-state';
5
5
  import TsxComponent, { Component } from '../../app/vuetsx';
6
- import { DateWrapper } from '../../common/date-wrapper';
7
6
  import DateUtils from '../../common/utils/date-utils';
8
7
  import { isNullOrEmpty } from '../../common/utils/is-null-or-empty';
9
8
  import { PortalUtils } from '../../common/utils/utils';
@@ -11,546 +10,528 @@ import FormItemWrapper from '../form/form-item-wrapper';
11
10
  import DateInputHelper from './ts/dateInputHelper';
12
11
  import './plugins/daterangepicker/jquery.daterangepicker';
13
12
  import './css/daterange-picker.css';
13
+ import { Temporal } from '@js-temporal/polyfill';
14
+ import TemporalUtils from '../../common/utils/temporal-utils';
15
+ import { utcEpochMilliseconds } from '../../common/extensions/temporal-extensions';
14
16
 
15
17
  export interface DaterangePickerArgsCustomCellRenderArgs {
16
- attributesHtml: string;
17
- attributes: { [index: string]: string };
18
- day: DaterangePickerArgsCustomCellRenderDay;
18
+ attributesHtml: string;
19
+ attributes: { [index: string]: string };
20
+ day: DaterangePickerArgsCustomCellRenderDay;
19
21
  }
20
22
 
21
23
  export interface DaterangePickerArgsCustomCellRenderDay {
22
- date: Date;
23
- day: number;
24
- extraClass: string;
25
- time: number;
26
- tooltip: string;
27
- type: 'toMonth' | 'nextMonth' | 'lastMonth';
28
- valid: boolean;
24
+ date: Date;
25
+ day: number;
26
+ extraClass: string;
27
+ time: number;
28
+ tooltip: string;
29
+ type: 'toMonth' | 'nextMonth' | 'lastMonth';
30
+ valid: boolean;
29
31
  }
30
32
 
31
33
  interface DaterangePickerArgs extends FormItemWrapperArgs {
32
- value?: DaterangeChangedArgs;
33
- placeholder?: string;
34
- format?: string;
35
- enableTime?: boolean;
36
- autoClose?: boolean;
37
- separator?: string;
38
- inputReadOnly?: boolean;
39
- minDate?: DateWrapper;
40
- alwaysOpen?: boolean;
41
- singleDate?: boolean;
42
- maxDate?: DateWrapper;
43
- prevIcon?: string;
44
- nextIcon?: string;
45
- hideYearInMonthName?: boolean;
46
- singleMonth?: boolean;
47
- calendarPlacement?: 'body' | 'inline' | 'input-container-leftalign' | 'input-container-rightalign';
48
- ensureMonthContinuity?: boolean;
49
- customInputText?: () => string;
50
- customTooltip?: (dayCount: number) => string;
51
- maxDays?: number;
52
- maxDaysTooltip?: (maxDays: number) => string;
53
- getCellHtml?: (args: DaterangePickerArgsCustomCellRenderArgs) => string;
54
- changed?: (newValue: DaterangeChangedArgs) => void;
55
- showCustomClearButton?: boolean;
34
+ value?: DaterangeChangedArgs;
35
+ placeholder?: string;
36
+ format?: string;
37
+ enableTime?: boolean;
38
+ autoClose?: boolean;
39
+ separator?: string;
40
+ inputReadOnly?: boolean;
41
+ minDate?: Temporal.PlainDateTime;
42
+ alwaysOpen?: boolean;
43
+ singleDate?: boolean;
44
+ maxDate?: Temporal.PlainDateTime;
45
+ prevIcon?: string;
46
+ nextIcon?: string;
47
+ hideYearInMonthName?: boolean;
48
+ singleMonth?: boolean;
49
+ calendarPlacement?: 'body' | 'inline' | 'input-container-leftalign' | 'input-container-rightalign';
50
+ ensureMonthContinuity?: boolean;
51
+ customInputText?: () => string;
52
+ customTooltip?: (dayCount: number) => string;
53
+ maxDays?: number;
54
+ maxDaysTooltip?: (maxDays: number) => string;
55
+ getCellHtml?: (args: DaterangePickerArgsCustomCellRenderArgs) => string;
56
+ changed?: (newValue: DaterangeChangedArgs) => void;
57
+ showCustomClearButton?: boolean;
56
58
  }
57
59
 
58
60
  export interface DaterangeChangedArgs {
59
- startTime: DateWrapper;
60
- endTime: DateWrapper;
61
+ startTime: Temporal.PlainDateTime;
62
+ endTime: Temporal.PlainDateTime;
61
63
  }
62
64
 
63
65
  const DATE_FORMAT_FOR_RANGE_PICKER = (() => {
64
- const dummyDate = new Date(Date.UTC(
65
- 2022,
66
- 11,
67
- 20,
68
- ));
69
- const formatted = dummyDate.toLocaleDateString(PowerduckState.getCurrentLanguage(), {
70
- day: '2-digit',
71
- month: '2-digit',
72
- year: 'numeric',
73
- timeZone: 'UTC',
74
- });
75
-
76
- return formatted.replace('20', 'dd').replace('12', 'MM').replace('2022', 'yyyy');
66
+ const dummyDate = new Date(Date.UTC(
67
+ 2022,
68
+ 11,
69
+ 20,
70
+ ));
71
+ const formatted = dummyDate.toLocaleDateString(PowerduckState.getCurrentLanguage(), {
72
+ day: '2-digit',
73
+ month: '2-digit',
74
+ year: 'numeric',
75
+ timeZone: 'UTC',
76
+ });
77
+
78
+ return formatted.replace('20', 'dd').replace('12', 'MM').replace('2022', 'yyyy');
77
79
  })();
78
80
 
79
81
  const DATE_FORMAT_FOR_RANGE_PICKER_WITH_TIME = `${DATE_FORMAT_FOR_RANGE_PICKER.split('. ').join('.')} HH:mm`;
80
82
 
81
83
  @Component
82
84
  class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> implements DaterangePickerArgs {
83
- @Prop() label!: string;
84
- @Prop() labelButtons!: DropdownButtonItemArgs[];
85
- @Prop() cssClass!: string;
86
- @Prop() subtitle!: string;
87
- @Prop() value!: DaterangeChangedArgs;
88
- @Prop() placeholder!: string;
89
- @Prop() mandatory!: boolean;
90
- @Prop() customInputText?: () => string;
91
- @Prop() inputReadOnly?: boolean;
92
- @Prop() alwaysOpen!: boolean;
93
- @Prop() singleDate!: boolean;
94
- @Prop() wrap!: boolean;
95
- @Prop() hint: string;
96
- @Prop() appendIcon: string;
97
- @Prop() prependIcon: string;
98
- @Prop() getCellHtml?: (args: DaterangePickerArgsCustomCellRenderArgs) => string;
99
- @Prop() appendClicked: () => void;
100
- @Prop() prependClicked: () => void;
101
- @Prop() prependIconClicked: () => void;
102
- @Prop() appendIconClicked: () => void;
103
- @Prop() marginType?: MarginType;
104
- @Prop() calendarPlacement?: 'body' | 'inline' | 'input-container-leftalign' | 'input-container-rightalign';
105
- @Prop() changed: (newValue: DaterangeChangedArgs) => void;
106
- @Prop() format?: string;
107
- @Prop() showClearValueButton!: boolean;
108
- @Prop() autoClose?: boolean;
109
- @Prop() enableTime?: boolean;
110
- @Prop() separator?: string;
111
- @Prop() singleMonth?: boolean;
112
- @Prop() minDate?: DateWrapper;
113
- @Prop() maxDate?: DateWrapper;
114
- @Prop() prevIcon?: string;
115
- @Prop() nextIcon?: string;
116
- @Prop() hideYearInMonthName?: boolean;
117
- @Prop() disabled!: boolean;
118
- @Prop() readOnly?: boolean;
119
- @Prop() customTooltip?: (dayCount: number) => string;
120
- @Prop() maxDays?: number;
121
- @Prop() maxDaysTooltip?: (maxDays: number) => string;
122
- @Prop() ensureMonthContinuity?: boolean;
123
-
124
- _startDate: DateWrapper;
125
- _endDate: DateWrapper;
126
- _changed: boolean;
127
- _lastText: string;
128
- _opened: boolean = false;
129
-
130
- raiseChangedEvent() {
131
- if (this._changed && this.changed != null) {
132
- this._lastText = this.getCurrentInputValue();
133
- if (isNullOrEmpty(this._lastText)) {
134
- this.changed(null);
135
- return;
136
- }
137
-
138
- this.changed({
139
- startTime: this._startDate,
140
- endTime: this._endDate,
141
- });
142
- }
143
- }
144
-
145
- beforeMount() {
146
- this.handleModelValueChange();
147
- }
148
-
149
- beforeUnmount() {
150
- try {
151
- this.getInputElement().data('dateRangePicker').destroy();
152
- } catch (error) { }
153
- }
154
-
155
- mounted() {
156
- const self = this;
157
- const $elem = this.getInputElement();
158
- const now = new DateWrapper();
159
-
160
- ($elem as any).dateRangePicker({
161
- singleMonth: this.singleMonth == true,
162
- alwaysOpen: this.alwaysOpen == true,
163
- singleDate: this.singleDate == true,
164
- startOfWeek: DateInputHelper.getStartOfWeek() == 0 ? 'sunday' : 'monday',
165
- separator: self.getSeparator(),
166
- hideYearInMonthName: this.hideYearInMonthName == true,
167
- format: self.getFormat(),
168
- language: self.getLanguage(),
169
- autoClose: self.autoClose,
170
- ensureMonthContinuity: self.ensureMonthContinuity,
171
- maxDays: this.maxDays,
172
- getCellHtml: this.getCellHtml,
173
- maxDaysTooltip: this.maxDaysTooltip,
174
- calendarPlacement: this.calendarPlacement,
175
- container: (this.calendarPlacement == null || this.calendarPlacement == 'body') ? 'body' : $elem.parent(),
176
- displayMode: () => {
177
- if (PortalUtils.treatAsMobileDevice() && this.alwaysOpen != true) {
178
- return 'modal';
179
- }
180
-
181
- return 'below-input';
182
- },
183
- leftOffset: () => {
184
- if (this.prependIcon == null) {
185
- return 0;
186
- } else {
187
- return $elem.closest('.input-group').find('.input-group-text.prepend-icon')[0].clientWidth;
188
- }
189
- },
190
- time: {
191
- enabled: self.enableTime,
192
- },
193
- hoveringTooltip: this.customTooltip == null ? null : days => self.customTooltip(days),
194
- startDate: self.minDate,
195
- endDate: self.maxDate,
196
- customArrowPrevSymbol: self.getPrevSymbol(),
197
- customArrowNextSymbol: self.getNextSymbol(),
198
- setValue(
199
- this: any,
200
- dateRange,
201
- dateStart,
202
- dateEnd,
203
- ) {
204
- if (!$(this).attr('readonly') && !$(this).is(':disabled') && dateRange != $(this).val()) {
205
- $(this).val(dateRange);
206
- }
207
-
208
- self.syncInputWithValues.call(self, dateRange);
209
- },
210
- defaultTime: new DateWrapper(
211
- now.getFullYear(),
212
- now.getMonth(),
213
- now.getDate(),
214
- ),
215
- defaultEndTime: new DateWrapper(
216
- now.getFullYear(),
217
- now.getMonth(),
218
- now.getDate(),
219
- 23,
220
- 59,
221
- 59,
222
- ),
223
- start: this.value?.startTime?.getTime(),
224
- end: this.value?.endTime?.getTime(),
225
- }).bind('datepicker-open', () => {
226
- self._changed = false;
227
- self._opened = true;
228
- }).bind('datepicker-change', (event, obj) => {
229
- self._startDate = obj.date1;
230
- self._endDate = obj.date2 || obj.date1;
231
- self._changed = true;
232
-
233
- if (this.alwaysOpen) {
234
- self.raiseChangedEvent();
235
- }
236
- }).bind('datepicker-closed', () => {
237
- const val = $elem.val() as string;
238
- if (isNullOrEmpty(val)) {
239
- if (self._startDate != null) {
240
- self._startDate = null;
241
- self._changed = true;
242
- }
243
-
244
- if (self._endDate != null) {
245
- self._endDate = null;
246
- self._changed = true;
247
- }
248
- }
249
-
250
- self._opened = false;
251
- self.raiseChangedEvent();
252
- });
253
- }
254
-
255
- beforeUpdate() {
256
- this.handleModelValueChange();
257
- }
258
-
259
- handleModelValueChange() {
260
- if (this.value?.endTime && this.value?.startTime) {
261
- if (this.enableTime) {
262
- const sd = this.value.startTime;
263
- const startDate = new DateWrapper(
264
- sd.getFullYear(),
265
- sd.getMonth(),
266
- sd.getDate(),
267
- sd.getHours(),
268
- sd.getMinutes(),
269
- sd.getSeconds(),
270
- );
271
-
272
- const ed = this.value.endTime;
273
- const endDate = new DateWrapper(
274
- ed.getFullYear(),
275
- ed.getMonth(),
276
- ed.getDate(),
277
- ed.getHours(),
278
- ed.getMinutes(),
279
- ed.getSeconds(),
280
- );
281
-
282
- this.syncInputDefaultValue(startDate.toISOString(), endDate.toISOString());
283
- } else {
284
- this.syncInputDefaultValue(this.value.startTime.innerDate.toISOString(), this.value.endTime.innerDate.toISOString());
285
- }
286
-
287
- this.$nextTick(() => {
288
- this.writeCustomText();
289
- });
290
- }
291
- }
292
-
293
- handleModalOpenClick(e: any): void {
294
- setTimeout(() => {
295
- this.$nextTick(() => {
296
- this.getInputElement().data('dateRangePicker').ensurePickerOpen();
297
- });
298
- }, 0);
299
- }
300
-
301
- isOpened(): boolean {
302
- return this._opened;
303
- }
304
-
305
- open(ms?: number): void {
306
- const $elem = this.getInputElement();
307
-
308
- setTimeout(() => {
309
- this.$nextTick(() => {
310
- $elem.data('dateRangePicker').open(ms);
311
- });
312
- }, 0);
313
- }
314
-
315
- close(ms?: number): void {
316
- const $elem = this.getInputElement();
317
-
318
- setTimeout(() => {
319
- this.$nextTick(() => {
320
- $elem.data('dateRangePicker').close(ms);
321
- });
322
- }, 0);
323
- }
324
-
325
- toggle(ms?: number): void {
326
- const isOpened = this._opened;
327
-
328
- if (isOpened) {
329
- this.close(ms);
330
- } else {
331
- this.open(ms);
332
- }
333
- }
334
-
335
- getPrevSymbol(): string {
336
- if (this.prevIcon != null) {
337
- return `<i class="${this.prevIcon}"></i>`;
338
- }
339
- }
340
-
341
- getNextSymbol(): string {
342
- if (this.nextIcon != null) {
343
- return `<i class="${this.nextIcon}"></i>`;
344
- }
345
- }
346
-
347
- getIsSingleDate(): boolean {
348
- return this.singleDate == true;
349
- }
350
-
351
- getInputElement(): JQuery {
352
- return $(this.$refs.innerInput as any);
353
- }
354
-
355
- getRangeText(e: DaterangeChangedArgs) {
356
- return this._lastText;
357
-
358
- if (e == null) {
359
- return null;
360
- }
361
- }
362
-
363
- getLanguage(): string {
364
- let lang = DateInputHelper.getLocale();
365
- if (lang == 'cs') {
366
- lang = 'cz';
367
- }
368
-
369
- return lang;
370
- }
371
-
372
- getFormat(): string {
373
- if (this.format) {
374
- return this.format;
375
- }
376
-
377
- if (this.enableTime != true) {
378
- return DATE_FORMAT_FOR_RANGE_PICKER;
379
- } else {
380
- return DATE_FORMAT_FOR_RANGE_PICKER_WITH_TIME;
381
- }
382
- }
383
-
384
- getSeparator(): string {
385
- return this.separator ?? ' ~ ';
386
- }
387
-
388
- getDateFromString(dateStr: string): DateWrapper {
389
- if (isNullOrEmpty(dateStr?.trim())) {
390
- return null;
391
- }
392
-
393
- try {
394
- const retVal = DateUtils.getDateWrapperFromFormat(dateStr, this.getFormat());
395
- if (retVal != null) {
396
- return retVal;
397
- }
398
- } catch (e1) { }
399
-
400
- try {
401
- return DateWrapper.fromWire(dateStr.trim());
402
- } catch (e2) {
403
- try {
404
- return new DateWrapper(dateStr.trim() as any);
405
- } catch (e3) {
406
- return DateWrapper.getCurrent();
407
- }
408
- }
409
- }
410
-
411
- syncInputDefaultValue (dateStart?: string, dateEnd?: string) {
412
- const startDate = this.getDateFromString(dateStart);
413
- if (startDate?.getTime() != this._startDate?.getTime()) {
414
- this._startDate = startDate;
415
- }
416
-
417
- const endDate = this.getDateFromString(dateEnd);
418
- if (endDate != this._endDate) {
419
- this._endDate = endDate;
420
-
421
- if (this._endDate == null) {
422
- this._endDate = this._startDate;
423
- }
424
- }
425
-
426
- const getInputValue = (): string => {
427
- const formattedStartDate = DateUtils.formatDate(startDate, this.getFormat());
428
- if (this.singleDate) {
429
- return formattedStartDate;
430
- }
431
-
432
- return formattedStartDate + this.getSeparator() + DateUtils.formatDate(endDate, this.getFormat());
433
- }
434
-
435
- const inputValue = getInputValue();
436
- this._lastText = inputValue;
437
- this.writeCustomText();
438
- }
439
-
440
- syncInputWithValues(
441
- dateRange?: string,
442
- dateStart?: string,
443
- dateEnd?: string,
444
- ) {
445
- if (isNullOrEmpty(dateStart) || isNullOrEmpty(dateEnd)) {
446
- const __default_string: string = dateRange || this.getInputElement().val() as string;
447
- const defaults = __default_string ? __default_string.split(this.getSeparator()) : [];
448
-
449
- if (defaults && ((defaults.length == 1 && this.getIsSingleDate()) || defaults.length >= 2)) {
450
- let ___format = this.getFormat();
451
- if (___format.match(/Do/)) {
452
- ___format = ___format.replace(/Do/, 'D');
453
- defaults[0] = defaults[0].replace(/(\d+)(th|nd|st)/, '$1');
454
- if (defaults.length >= 2) {
455
- defaults[1] = defaults[1].replace(/(\d+)(th|nd|st)/, '$1');
456
- }
457
- }
458
-
459
- dateStart = defaults[0];
460
- dateEnd = defaults[1];
461
- }
462
- }
463
-
464
- const startDate = this.getDateFromString(dateStart);
465
- if (startDate != this._startDate) {
466
- this._startDate = startDate;
467
- this._changed = true;
468
- }
469
-
470
- const endDate = this.getDateFromString(dateEnd);
471
- if (endDate != this._endDate) {
472
- this._endDate = endDate;
473
- this._changed = true;
474
- }
475
-
476
- this.writeCustomText();
477
- }
478
-
479
- writeCustomText(): void {
480
- if (this.customInputText != null) {
481
- this.getInputElement().parent().attr('data-customtext', (this.customInputText() || ''));
482
- }
483
- }
484
-
485
- getCssClass(): string {
486
- return `daterange-picker-input${this.customInputText != null ? ' daterange-picker-input-customtext' : ''}${PortalUtils.treatAsMobileDevice() ? ' pd-daterange-picker-modal-mode' : ''} ${this.cssClass ?? ''}${this.prependIcon != null ? ' input-group-prepend-icon' : ''}${this.appendIcon != null ? ' input-group-append-icon' : ''}`;
487
- }
488
-
489
- getCurrentInputValue(): string {
490
- return $(this.$el).find('input').val() as any; // TODO: Implement
491
- }
492
-
493
- inputValueChanged(): void {
494
- this.$nextTick(() => {
495
- setTimeout(() => {
496
- const currentVal = this.getCurrentInputValue();
497
- if (currentVal != this._lastText) {
498
- if (isNullOrEmpty(currentVal)) {
499
- this._lastText = currentVal;
500
- this.changed(null);
501
- }
502
- }
503
- }, 10);
504
- });
505
- }
506
-
507
- shouldAddModalClick() {
508
- if (!PortalUtils.treatAsMobileDevice()) {
509
- return false;
510
- }
511
-
512
- if (this.calendarPlacement == 'input-container-leftalign' || this.calendarPlacement == 'input-container-rightalign') {
513
- return false;
514
- }
515
-
516
- return true;
517
- }
518
-
519
- clearValue() {
520
- this._startDate = null;
521
- this._endDate = null;
522
- this._lastText = null;
523
- this._changed = true;
524
- this.getInputElement().val('');
525
- this.inputValueChanged();
526
- }
527
-
528
- render(h) {
529
- return (
530
- <FormItemWrapper label={this.label} cssClass={this.getCssClass()} mandatory={this.mandatory} wrap={this.wrap} appendIcon={this.appendIcon} prependIcon={this.prependIcon} hint={this.hint} marginType={this.marginType} appendClicked={this.appendClicked} prependClicked={this.prependClicked} prependIconClicked={this.prependIconClicked} appendIconClicked={this.appendIconClicked} validationState={this.validationState} labelButtons={this.labelButtons} subtitle={this.subtitle}>
531
- {this.shouldAddModalClick()
532
- && <div class="pd-daterange-picker-modalclick" onClick={(e) => { this.handleModalOpenClick(e); }}></div>}
533
-
534
- <div style="position: relative; display: flex; align-items: center; flex-grow:1">
535
- {' '}
536
- {/* Added a wrapper for input and clear button */}
537
- <input
538
- type="text"
539
- ref="innerInput"
540
- disabled={this.disabled as any != true ? null : 'disabled'}
541
- readonly={this.readOnly as any != true ? null : 'readonly'}
542
- value={this.getRangeText(this.value)}
543
- class={PowerduckState.getFormControlCssClass()}
544
- placeholder={this.placeholder}
545
- onChange={() => { this.inputValueChanged(); }}
546
- />
547
- {this.showClearValueButton && this._startDate && (
548
- <span class="pd-daterange-picker-clear-button" onClick={() => this.clearValue()}>×</span>
549
- )}
550
- </div>
551
- </FormItemWrapper>
552
- );
553
- }
85
+ @Prop() label!: string;
86
+ @Prop() labelButtons!: DropdownButtonItemArgs[];
87
+ @Prop() cssClass!: string;
88
+ @Prop() subtitle!: string;
89
+ @Prop() value!: DaterangeChangedArgs;
90
+ @Prop() placeholder!: string;
91
+ @Prop() mandatory!: boolean;
92
+ @Prop() customInputText?: () => string;
93
+ @Prop() inputReadOnly?: boolean;
94
+ @Prop() alwaysOpen!: boolean;
95
+ @Prop() singleDate!: boolean;
96
+ @Prop() wrap!: boolean;
97
+ @Prop() hint: string;
98
+ @Prop() appendIcon: string;
99
+ @Prop() prependIcon: string;
100
+ @Prop() getCellHtml?: (args: DaterangePickerArgsCustomCellRenderArgs) => string;
101
+ @Prop() appendClicked: () => void;
102
+ @Prop() prependClicked: () => void;
103
+ @Prop() prependIconClicked: () => void;
104
+ @Prop() appendIconClicked: () => void;
105
+ @Prop() marginType?: MarginType;
106
+ @Prop() calendarPlacement?: 'body' | 'inline' | 'input-container-leftalign' | 'input-container-rightalign';
107
+ @Prop() changed: (newValue: DaterangeChangedArgs) => void;
108
+ @Prop() format?: string;
109
+ @Prop() showClearValueButton!: boolean;
110
+ @Prop() autoClose?: boolean;
111
+ @Prop() enableTime?: boolean;
112
+ @Prop() separator?: string;
113
+ @Prop() singleMonth?: boolean;
114
+ @Prop() minDate?: Temporal.PlainDateTime;
115
+ @Prop() maxDate?: Temporal.PlainDateTime;
116
+ @Prop() prevIcon?: string;
117
+ @Prop() nextIcon?: string;
118
+ @Prop() hideYearInMonthName?: boolean;
119
+ @Prop() disabled!: boolean;
120
+ @Prop() readOnly?: boolean;
121
+ @Prop() customTooltip?: (dayCount: number) => string;
122
+ @Prop() maxDays?: number;
123
+ @Prop() maxDaysTooltip?: (maxDays: number) => string;
124
+ @Prop() ensureMonthContinuity?: boolean;
125
+
126
+ _startDate: Temporal.PlainDateTime;
127
+ _endDate: Temporal.PlainDateTime;
128
+ _changed: boolean;
129
+ _lastText: string;
130
+ _opened: boolean = false;
131
+
132
+ raiseChangedEvent() {
133
+ if (this._changed && this.changed != null) {
134
+ this._lastText = this.getCurrentInputValue();
135
+ if (isNullOrEmpty(this._lastText)) {
136
+ this.changed(null);
137
+ return;
138
+ }
139
+
140
+ this.changed({
141
+ startTime: this._startDate,
142
+ endTime: this._endDate,
143
+ });
144
+ }
145
+ }
146
+
147
+ beforeMount() {
148
+ this.handleModelValueChange();
149
+ }
150
+
151
+ beforeUnmount() {
152
+ try {
153
+ this.getInputElement().data('dateRangePicker').destroy();
154
+ } catch (error) { }
155
+ }
156
+
157
+ mounted() {
158
+ const self = this;
159
+ const $elem = this.getInputElement();
160
+ const now = Temporal.Now.plainDateTimeISO();
161
+
162
+ ($elem as any).dateRangePicker({
163
+ singleMonth: this.singleMonth == true,
164
+ alwaysOpen: this.alwaysOpen == true,
165
+ singleDate: this.singleDate == true,
166
+ startOfWeek: DateInputHelper.getStartOfWeek() == 0 ? 'sunday' : 'monday',
167
+ separator: self.getSeparator(),
168
+ hideYearInMonthName: this.hideYearInMonthName == true,
169
+ format: self.getFormat(),
170
+ language: self.getLanguage(),
171
+ autoClose: self.autoClose,
172
+ ensureMonthContinuity: self.ensureMonthContinuity,
173
+ maxDays: this.maxDays,
174
+ getCellHtml: this.getCellHtml,
175
+ maxDaysTooltip: this.maxDaysTooltip,
176
+ calendarPlacement: this.calendarPlacement,
177
+ container: (this.calendarPlacement == null || this.calendarPlacement == 'body') ? 'body' : $elem.parent(),
178
+ displayMode: () => {
179
+ if (PortalUtils.treatAsMobileDevice() && this.alwaysOpen != true) {
180
+ return 'modal';
181
+ }
182
+
183
+ return 'below-input';
184
+ },
185
+ leftOffset: () => {
186
+ if (this.prependIcon == null) {
187
+ return 0;
188
+ } else {
189
+ return $elem.closest('.input-group').find('.input-group-text.prepend-icon')[0].clientWidth;
190
+ }
191
+ },
192
+ time: {
193
+ enabled: self.enableTime,
194
+ },
195
+ hoveringTooltip: this.customTooltip == null ? null : days => self.customTooltip(days),
196
+ startDate: self.minDate,
197
+ endDate: self.maxDate,
198
+ customArrowPrevSymbol: self.getPrevSymbol(),
199
+ customArrowNextSymbol: self.getNextSymbol(),
200
+ setValue(
201
+ this: any,
202
+ dateRange,
203
+ dateStart,
204
+ dateEnd,
205
+ ) {
206
+ if (!$(this).attr('readonly') && !$(this).is(':disabled') && dateRange != $(this).val()) {
207
+ $(this).val(dateRange);
208
+ }
209
+
210
+ self.syncInputWithValues.call(self, dateRange);
211
+ },
212
+ defaultTime: Temporal.PlainDateTime.from({
213
+ year: now.year,
214
+ month: now.month,
215
+ day: now.day,
216
+ }),
217
+ defaultEndTime:Temporal.PlainDateTime.from({
218
+ year: now.year,
219
+ month: now.month,
220
+ day: now.day,
221
+ hour: 23,
222
+ minute: 59,
223
+ second: 59
224
+ }),
225
+ start: this.value?.startTime,
226
+ end: this.value?.endTime,
227
+ }).bind('datepicker-open', () => {
228
+ self._changed = false;
229
+ self._opened = true;
230
+ }).bind('datepicker-change', (event, obj) => {
231
+ self._startDate = obj.date1;
232
+ self._endDate = obj.date2 || obj.date1;
233
+ self._changed = true;
234
+
235
+ if (this.alwaysOpen) {
236
+ self.raiseChangedEvent();
237
+ }
238
+ }).bind('datepicker-closed', () => {
239
+ const val = $elem.val() as string;
240
+ if (isNullOrEmpty(val)) {
241
+ if (self._startDate != null) {
242
+ self._startDate = null;
243
+ self._changed = true;
244
+ }
245
+
246
+ if (self._endDate != null) {
247
+ self._endDate = null;
248
+ self._changed = true;
249
+ }
250
+ }
251
+
252
+ self._opened = false;
253
+ self.raiseChangedEvent();
254
+ });
255
+ }
256
+
257
+ beforeUpdate() {
258
+ this.handleModelValueChange();
259
+ }
260
+
261
+ handleModelValueChange() {
262
+ if (this.value?.endTime && this.value?.startTime) {
263
+ if (this.enableTime) {
264
+ const startDate = this.value.startTime;
265
+ const endDate = this.value.endTime;
266
+
267
+ this.syncInputDefaultValue(startDate.toString(), endDate.toString());
268
+ } else {
269
+ this.syncInputDefaultValue(this.value.startTime.toString(), this.value.endTime.toString());
270
+ }
271
+
272
+ this.$nextTick(() => {
273
+ this.writeCustomText();
274
+ });
275
+ }
276
+ }
277
+
278
+ handleModalOpenClick(e: any): void {
279
+ setTimeout(() => {
280
+ this.$nextTick(() => {
281
+ this.getInputElement().data('dateRangePicker').ensurePickerOpen();
282
+ });
283
+ }, 0);
284
+ }
285
+
286
+ isOpened(): boolean {
287
+ return this._opened;
288
+ }
289
+
290
+ open(ms?: number): void {
291
+ const $elem = this.getInputElement();
292
+
293
+ setTimeout(() => {
294
+ this.$nextTick(() => {
295
+ $elem.data('dateRangePicker').open(ms);
296
+ });
297
+ }, 0);
298
+ }
299
+
300
+ close(ms?: number): void {
301
+ const $elem = this.getInputElement();
302
+
303
+ setTimeout(() => {
304
+ this.$nextTick(() => {
305
+ $elem.data('dateRangePicker').close(ms);
306
+ });
307
+ }, 0);
308
+ }
309
+
310
+ toggle(ms?: number): void {
311
+ const isOpened = this._opened;
312
+
313
+ if (isOpened) {
314
+ this.close(ms);
315
+ } else {
316
+ this.open(ms);
317
+ }
318
+ }
319
+
320
+ getPrevSymbol(): string {
321
+ if (this.prevIcon != null) {
322
+ return `<i class="${this.prevIcon}"></i>`;
323
+ }
324
+ }
325
+
326
+ getNextSymbol(): string {
327
+ if (this.nextIcon != null) {
328
+ return `<i class="${this.nextIcon}"></i>`;
329
+ }
330
+ }
331
+
332
+ getIsSingleDate(): boolean {
333
+ return this.singleDate == true;
334
+ }
335
+
336
+ getInputElement(): JQuery {
337
+ return $(this.$refs.innerInput as any);
338
+ }
339
+
340
+ getRangeText(e: DaterangeChangedArgs) {
341
+ return this._lastText;
342
+
343
+ if (e == null) {
344
+ return null;
345
+ }
346
+ }
347
+
348
+ getLanguage(): string {
349
+ let lang = DateInputHelper.getLocale();
350
+ if (lang == 'cs') {
351
+ lang = 'cz';
352
+ }
353
+
354
+ return lang;
355
+ }
356
+
357
+ getFormat(): string {
358
+ if (this.format) {
359
+ return this.format;
360
+ }
361
+
362
+ if (this.enableTime != true) {
363
+ return DATE_FORMAT_FOR_RANGE_PICKER;
364
+ } else {
365
+ return DATE_FORMAT_FOR_RANGE_PICKER_WITH_TIME;
366
+ }
367
+ }
368
+
369
+ getSeparator(): string {
370
+ return this.separator ?? ' ~ ';
371
+ }
372
+
373
+ getDateFromString(dateStr: string): Temporal.PlainDateTime {
374
+ if (isNullOrEmpty(dateStr?.trim())) {
375
+ return null;
376
+ }
377
+
378
+ try {
379
+ const retVal = DateUtils.getTemporalFromFormat(dateStr, this.getFormat());
380
+ if (retVal != null) {
381
+ return retVal;
382
+ }
383
+ } catch (e1) { }
384
+
385
+ try {
386
+ return TemporalUtils.fromString(dateStr.trim());
387
+ } catch (e2) {
388
+ return Temporal.Now.plainDateTimeISO();
389
+ }
390
+ }
391
+
392
+ syncInputDefaultValue(dateStart?: string, dateEnd?: string) {
393
+ const startDate = this.getDateFromString(dateStart);
394
+ if (startDate?.[utcEpochMilliseconds]() != this._startDate?.[utcEpochMilliseconds]()) {
395
+ this._startDate = startDate;
396
+ }
397
+
398
+ const endDate = this.getDateFromString(dateEnd);
399
+ if (endDate != this._endDate) {
400
+ this._endDate = endDate;
401
+
402
+ if (this._endDate == null) {
403
+ this._endDate = this._startDate;
404
+ }
405
+ }
406
+
407
+ const getInputValue = (): string => {
408
+ const formattedStartDate = DateUtils.formatDate(startDate, this.getFormat());
409
+ if (this.singleDate) {
410
+ return formattedStartDate;
411
+ }
412
+
413
+ return formattedStartDate + this.getSeparator() + DateUtils.formatDate(endDate, this.getFormat());
414
+ }
415
+
416
+ const inputValue = getInputValue();
417
+ this._lastText = inputValue;
418
+ this.writeCustomText();
419
+ }
420
+
421
+ syncInputWithValues(
422
+ dateRange?: string,
423
+ dateStart?: string,
424
+ dateEnd?: string,
425
+ ) {
426
+ if (isNullOrEmpty(dateStart) || isNullOrEmpty(dateEnd)) {
427
+ const __default_string: string = dateRange || this.getInputElement().val() as string;
428
+ const defaults = __default_string ? __default_string.split(this.getSeparator()) : [];
429
+
430
+ if (defaults && ((defaults.length == 1 && this.getIsSingleDate()) || defaults.length >= 2)) {
431
+ let ___format = this.getFormat();
432
+ if (___format.match(/Do/)) {
433
+ ___format = ___format.replace(/Do/, 'D');
434
+ defaults[0] = defaults[0].replace(/(\d+)(th|nd|st)/, '$1');
435
+ if (defaults.length >= 2) {
436
+ defaults[1] = defaults[1].replace(/(\d+)(th|nd|st)/, '$1');
437
+ }
438
+ }
439
+
440
+ dateStart = defaults[0];
441
+ dateEnd = defaults[1];
442
+ }
443
+ }
444
+
445
+ const startDate = this.getDateFromString(dateStart);
446
+ if (startDate != this._startDate) {
447
+ this._startDate = startDate;
448
+ this._changed = true;
449
+ }
450
+
451
+ const endDate = this.getDateFromString(dateEnd);
452
+ if (endDate != this._endDate) {
453
+ this._endDate = endDate;
454
+ this._changed = true;
455
+ }
456
+
457
+ this.writeCustomText();
458
+ }
459
+
460
+ writeCustomText(): void {
461
+ if (this.customInputText != null) {
462
+ this.getInputElement().parent().attr('data-customtext', (this.customInputText() || ''));
463
+ }
464
+ }
465
+
466
+ getCssClass(): string {
467
+ return `daterange-picker-input${this.customInputText != null ? ' daterange-picker-input-customtext' : ''}${PortalUtils.treatAsMobileDevice() ? ' pd-daterange-picker-modal-mode' : ''} ${this.cssClass ?? ''}${this.prependIcon != null ? ' input-group-prepend-icon' : ''}${this.appendIcon != null ? ' input-group-append-icon' : ''}`;
468
+ }
469
+
470
+ getCurrentInputValue(): string {
471
+ return $(this.$el).find('input').val() as any; // TODO: Implement
472
+ }
473
+
474
+ inputValueChanged(): void {
475
+ this.$nextTick(() => {
476
+ setTimeout(() => {
477
+ const currentVal = this.getCurrentInputValue();
478
+ if (currentVal != this._lastText) {
479
+ if (isNullOrEmpty(currentVal)) {
480
+ this._lastText = currentVal;
481
+ this.changed(null);
482
+ }
483
+ }
484
+ }, 10);
485
+ });
486
+ }
487
+
488
+ shouldAddModalClick() {
489
+ if (!PortalUtils.treatAsMobileDevice()) {
490
+ return false;
491
+ }
492
+
493
+ if (this.calendarPlacement == 'input-container-leftalign' || this.calendarPlacement == 'input-container-rightalign') {
494
+ return false;
495
+ }
496
+
497
+ return true;
498
+ }
499
+
500
+ clearValue() {
501
+ this._startDate = null;
502
+ this._endDate = null;
503
+ this._lastText = null;
504
+ this._changed = true;
505
+ this.getInputElement().val('');
506
+ this.inputValueChanged();
507
+ }
508
+
509
+ render(h) {
510
+ return (
511
+ <FormItemWrapper label={this.label} cssClass={this.getCssClass()} mandatory={this.mandatory} wrap={this.wrap} appendIcon={this.appendIcon} prependIcon={this.prependIcon} hint={this.hint} marginType={this.marginType} appendClicked={this.appendClicked} prependClicked={this.prependClicked} prependIconClicked={this.prependIconClicked} appendIconClicked={this.appendIconClicked} validationState={this.validationState} labelButtons={this.labelButtons} subtitle={this.subtitle}>
512
+ {this.shouldAddModalClick()
513
+ && <div class="pd-daterange-picker-modalclick" onClick={(e) => { this.handleModalOpenClick(e); }}></div>}
514
+
515
+ <div style="position: relative; display: flex; align-items: center; flex-grow:1">
516
+ {' '}
517
+ {/* Added a wrapper for input and clear button */}
518
+ <input
519
+ type="text"
520
+ ref="innerInput"
521
+ disabled={this.disabled as any != true ? null : 'disabled'}
522
+ readonly={this.readOnly as any != true ? null : 'readonly'}
523
+ value={this.getRangeText(this.value)}
524
+ class={PowerduckState.getFormControlCssClass()}
525
+ placeholder={this.placeholder}
526
+ onChange={() => { this.inputValueChanged(); }}
527
+ />
528
+ {this.showClearValueButton && this._startDate && (
529
+ <span class="pd-daterange-picker-clear-button" onClick={() => this.clearValue()}>×</span>
530
+ )}
531
+ </div>
532
+ </FormItemWrapper>
533
+ );
534
+ }
554
535
  }
555
536
 
556
537
  const DaterangePicker = toNative(DaterangePickerComponent);