inviton-powerduck 0.0.155 → 0.0.157

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.
@@ -265,9 +265,6 @@ export class AppHttpProvider {
265
265
  if (keyVal != null && keyVal.indexOf && TemporalUtils.isSerializedDate(keyVal)) {
266
266
  try {
267
267
  obj[key] = TemporalUtils.fromString(keyVal);
268
- if (isNaN(obj[key].getTime())) {
269
- obj[key] = keyVal;
270
- }
271
268
  } catch (e) {
272
269
  obj[key] = keyVal;
273
270
  }
@@ -1,537 +1,537 @@
1
1
  import type { DropdownButtonItemArgs } from '../dropdown-button/dropdown-button-item';
2
2
  import type { FormItemWrapperArgs, MarginType } from '../form/form-item-wrapper';
3
+ import { Temporal } from '@js-temporal/polyfill';
3
4
  import { Prop, toNative } from 'vue-facing-decorator';
4
5
  import PowerduckState from '../../app/powerduck-state';
5
6
  import TsxComponent, { Component } from '../../app/vuetsx';
7
+ import { utcEpochMilliseconds } from '../../common/extensions/temporal-extensions';
6
8
  import DateUtils from '../../common/utils/date-utils';
7
9
  import { isNullOrEmpty } from '../../common/utils/is-null-or-empty';
10
+ import TemporalUtils from '../../common/utils/temporal-utils';
8
11
  import { PortalUtils } from '../../common/utils/utils';
9
12
  import FormItemWrapper from '../form/form-item-wrapper';
10
13
  import DateInputHelper from './ts/dateInputHelper';
11
14
  import './plugins/daterangepicker/jquery.daterangepicker';
12
15
  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';
16
16
 
17
17
  export interface DaterangePickerArgsCustomCellRenderArgs {
18
- attributesHtml: string;
19
- attributes: { [index: string]: string };
20
- day: DaterangePickerArgsCustomCellRenderDay;
18
+ attributesHtml: string;
19
+ attributes: { [index: string]: string };
20
+ day: DaterangePickerArgsCustomCellRenderDay;
21
21
  }
22
22
 
23
23
  export interface DaterangePickerArgsCustomCellRenderDay {
24
- date: Date;
25
- day: number;
26
- extraClass: string;
27
- time: number;
28
- tooltip: string;
29
- type: 'toMonth' | 'nextMonth' | 'lastMonth';
30
- valid: boolean;
24
+ date: Temporal.PlainDateTime;
25
+ day: number;
26
+ extraClass: string;
27
+ time: number;
28
+ tooltip: string;
29
+ type: 'toMonth' | 'nextMonth' | 'lastMonth';
30
+ valid: boolean;
31
31
  }
32
32
 
33
33
  interface DaterangePickerArgs extends FormItemWrapperArgs {
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;
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;
58
58
  }
59
59
 
60
60
  export interface DaterangeChangedArgs {
61
- startTime: Temporal.PlainDateTime;
62
- endTime: Temporal.PlainDateTime;
61
+ startTime: Temporal.PlainDateTime;
62
+ endTime: Temporal.PlainDateTime;
63
63
  }
64
64
 
65
65
  const DATE_FORMAT_FOR_RANGE_PICKER = (() => {
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');
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');
79
79
  })();
80
80
 
81
81
  const DATE_FORMAT_FOR_RANGE_PICKER_WITH_TIME = `${DATE_FORMAT_FOR_RANGE_PICKER.split('. ').join('.')} HH:mm`;
82
82
 
83
83
  @Component
84
84
  class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> implements DaterangePickerArgs {
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
- }
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
+ }
535
535
  }
536
536
 
537
537
  const DaterangePicker = toNative(DaterangePickerComponent);
@@ -1274,7 +1274,7 @@ import { utcEpochMilliseconds } from '../../../../common/extensions/temporal-ext
1274
1274
  return r;
1275
1275
  }
1276
1276
 
1277
- function dayClicked(day) {
1277
+ function dayClicked(day: JQuery) {
1278
1278
  if (day.hasClass('invalid')) { return; }
1279
1279
 
1280
1280
  const time = Number(day.attr('time'));
@@ -1671,7 +1671,7 @@ import { utcEpochMilliseconds } from '../../../../common/extensions/temporal-ext
1671
1671
  }
1672
1672
  }
1673
1673
 
1674
- function showSelectedInfo(forceValid?, silent?) {
1674
+ function showSelectedInfo(forceValid?: boolean, silent?: boolean) {
1675
1675
  box.find('.start-day').html('...');
1676
1676
  box.find('.end-day').html('...');
1677
1677
  box.find('.selected-days').hide();
@@ -1795,7 +1795,7 @@ import { utcEpochMilliseconds } from '../../../../common/extensions/temporal-ext
1795
1795
  autoclose();
1796
1796
  }
1797
1797
 
1798
- function setSingleDate(date1) {
1798
+ function setSingleDate(date1: Temporal.PlainDateTime) {
1799
1799
  let valid = true;
1800
1800
  if (opt.startDate && compare_day(date1, opt.startDate) < 0) { valid = false; }
1801
1801
 
@@ -1806,8 +1806,7 @@ import { utcEpochMilliseconds } from '../../../../common/extensions/temporal-ext
1806
1806
  return;
1807
1807
  }
1808
1808
 
1809
- opt.start = date1.getTime();
1810
-
1809
+ opt.start = date1;
1811
1810
  if (opt.time.enabled) {
1812
1811
  renderTime('time1', date1);
1813
1812
  }
@@ -1907,6 +1906,10 @@ import { utcEpochMilliseconds } from '../../../../common/extensions/temporal-ext
1907
1906
  }
1908
1907
 
1909
1908
  function getDateString(d: Temporal.PlainDateTime) {
1909
+ if (d == null) {
1910
+ return '';
1911
+ }
1912
+
1910
1913
  return DateUtils.formatDate(d, opt.format);
1911
1914
  }
1912
1915
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "inviton-powerduck",
3
3
  "type": "module",
4
- "version": "0.0.155",
4
+ "version": "0.0.157",
5
5
  "files": [
6
6
  "app/",
7
7
  "common/",