@acorex/components 21.0.0-next.19 → 21.0.0-next.20
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/fesm2022/acorex-components-dialog.mjs +11 -2
- package/fesm2022/acorex-components-dialog.mjs.map +1 -1
- package/fesm2022/acorex-components-loading-dialog.mjs +11 -2
- package/fesm2022/acorex-components-loading-dialog.mjs.map +1 -1
- package/fesm2022/acorex-components-rrule.mjs +2 -2
- package/fesm2022/acorex-components-rrule.mjs.map +1 -1
- package/fesm2022/acorex-components-scheduler-picker.mjs +2339 -0
- package/fesm2022/acorex-components-scheduler-picker.mjs.map +1 -0
- package/fesm2022/acorex-components-uploader.mjs +13 -611
- package/fesm2022/acorex-components-uploader.mjs.map +1 -1
- package/package.json +11 -7
- package/scheduler-picker/README.md +15 -0
- package/scheduler-picker/index.d.ts +1360 -0
- package/uploader/index.d.ts +4 -331
|
@@ -0,0 +1,2339 @@
|
|
|
1
|
+
import { MXValueComponent, AXComponent, AXFocusableComponent, AXValuableComponent } from '@acorex/cdk/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { input, output, ViewEncapsulation, ChangeDetectionStrategy, Component, signal, effect, computed, InjectionToken, inject, Injectable, forwardRef } from '@angular/core';
|
|
4
|
+
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
5
|
+
import { AXSwitchComponent } from '@acorex/components/switch';
|
|
6
|
+
import { AXTranslatorPipe, AXTranslationService } from '@acorex/core/translation';
|
|
7
|
+
import { AsyncPipe, DatePipe } from '@angular/common';
|
|
8
|
+
import { AXNumberBoxComponent } from '@acorex/components/number-box';
|
|
9
|
+
import { AXSelectBoxComponent } from '@acorex/components/select-box';
|
|
10
|
+
import * as i1 from '@acorex/components/selection-list';
|
|
11
|
+
import { AXSelectionListModule } from '@acorex/components/selection-list';
|
|
12
|
+
import { AXDateTimeBoxComponent } from '@acorex/components/datetime-box';
|
|
13
|
+
import * as i2 from '@acorex/components/badge';
|
|
14
|
+
import { AXBadgeModule } from '@acorex/components/badge';
|
|
15
|
+
import { AXButtonComponent } from '@acorex/components/button';
|
|
16
|
+
import * as i3 from '@acorex/components/chips';
|
|
17
|
+
import { AXChipsModule } from '@acorex/components/chips';
|
|
18
|
+
import * as i1$1 from '@acorex/components/decorators';
|
|
19
|
+
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Interval selector component
|
|
23
|
+
* Allows user to select "Every X [units]"
|
|
24
|
+
*/
|
|
25
|
+
class AXSchedulerPickerIntervalSelectorComponent {
|
|
26
|
+
constructor() {
|
|
27
|
+
/**
|
|
28
|
+
* Current interval value
|
|
29
|
+
*/
|
|
30
|
+
this.interval = input.required(...(ngDevMode ? [{ debugName: "interval" }] : []));
|
|
31
|
+
/**
|
|
32
|
+
* Configuration
|
|
33
|
+
*/
|
|
34
|
+
this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
35
|
+
/**
|
|
36
|
+
* Emits when interval changes
|
|
37
|
+
*/
|
|
38
|
+
this.intervalChange = output();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Handle interval value change
|
|
42
|
+
*/
|
|
43
|
+
onIntervalChange(value) {
|
|
44
|
+
if (value && value > 0) {
|
|
45
|
+
this.intervalChange.emit(value);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get unit translation key based on mode
|
|
50
|
+
*/
|
|
51
|
+
getUnitKey() {
|
|
52
|
+
const mode = this.config().mode;
|
|
53
|
+
const pluralKey = this.interval() === 1 ? 'singular' : 'plural';
|
|
54
|
+
switch (mode) {
|
|
55
|
+
case 'hourly':
|
|
56
|
+
return `@acorex:schedulerPicker.units.hour.${pluralKey}`;
|
|
57
|
+
case 'daily':
|
|
58
|
+
return `@acorex:schedulerPicker.units.day.${pluralKey}`;
|
|
59
|
+
case 'weekly':
|
|
60
|
+
return `@acorex:schedulerPicker.units.week.${pluralKey}`;
|
|
61
|
+
case 'monthly':
|
|
62
|
+
return `@acorex:schedulerPicker.units.month.${pluralKey}`;
|
|
63
|
+
case 'yearly':
|
|
64
|
+
return `@acorex:schedulerPicker.units.year.${pluralKey}`;
|
|
65
|
+
default:
|
|
66
|
+
return '@acorex:schedulerPicker.units.day.plural';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerIntervalSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
70
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.9", type: AXSchedulerPickerIntervalSelectorComponent, isStandalone: true, selector: "ax-scheduler-picker-interval-selector", inputs: { interval: { classPropertyName: "interval", publicName: "interval", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { intervalChange: "intervalChange" }, ngImport: i0, template: "<div class=\"ax-scheduler-picker-interval-selector\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.repeatEvery' | translate | async }}\n </label>\n <div class=\"ax-scheduler-picker-interval-input-group\">\n <ax-number-box\n [value]=\"interval()\"\n [minValue]=\"config().minInterval || 1\"\n [maxValue]=\"config().maxInterval || 999\"\n [disabled]=\"false\"\n (valueChange)=\"onIntervalChange($event)\"\n />\n <span class=\"ax-scheduler-picker-interval-unit\">\n {{ getUnitKey() | translate | async }}\n </span>\n </div>\n</div>\n", styles: [".ax-scheduler-picker-interval-selector{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}.ax-scheduler-picker-interval-input-group{display:flex;align-items:center;gap:.375rem}.ax-scheduler-picker-interval-input-group ax-number-box{width:80px}.ax-scheduler-picker-interval-input-group .ax-scheduler-picker-interval-unit{color:var(--ax-comp-scheduler-picker-label-color);font-size:.875rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: AXNumberBoxComponent, selector: "ax-number-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "minValue", "maxValue", "showSpinButtons", "thousandsSeparator", "decimals", "changeOnScroll", "step"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "thousandsSeparatorChange"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
71
|
+
}
|
|
72
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerIntervalSelectorComponent, decorators: [{
|
|
73
|
+
type: Component,
|
|
74
|
+
args: [{ selector: 'ax-scheduler-picker-interval-selector', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [FormsModule, AXNumberBoxComponent, AXTranslatorPipe, AsyncPipe], template: "<div class=\"ax-scheduler-picker-interval-selector\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.repeatEvery' | translate | async }}\n </label>\n <div class=\"ax-scheduler-picker-interval-input-group\">\n <ax-number-box\n [value]=\"interval()\"\n [minValue]=\"config().minInterval || 1\"\n [maxValue]=\"config().maxInterval || 999\"\n [disabled]=\"false\"\n (valueChange)=\"onIntervalChange($event)\"\n />\n <span class=\"ax-scheduler-picker-interval-unit\">\n {{ getUnitKey() | translate | async }}\n </span>\n </div>\n</div>\n", styles: [".ax-scheduler-picker-interval-selector{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}.ax-scheduler-picker-interval-input-group{display:flex;align-items:center;gap:.375rem}.ax-scheduler-picker-interval-input-group ax-number-box{width:80px}.ax-scheduler-picker-interval-input-group .ax-scheduler-picker-interval-unit{color:var(--ax-comp-scheduler-picker-label-color);font-size:.875rem}\n"] }]
|
|
75
|
+
}], propDecorators: { interval: [{ type: i0.Input, args: [{ isSignal: true, alias: "interval", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], intervalChange: [{ type: i0.Output, args: ["intervalChange"] }] } });
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Constants for scheduler picker module
|
|
79
|
+
*/
|
|
80
|
+
/**
|
|
81
|
+
* Days of the week (0-6: Sunday-Saturday)
|
|
82
|
+
*/
|
|
83
|
+
const AX_SCHEDULER_PICKER_DAYS_OF_WEEK = Object.freeze([
|
|
84
|
+
{ id: 0, text: 'Sunday', key: 'sunday', rruleKey: 'SU' },
|
|
85
|
+
{ id: 1, text: 'Monday', key: 'monday', rruleKey: 'MO' },
|
|
86
|
+
{ id: 2, text: 'Tuesday', key: 'tuesday', rruleKey: 'TU' },
|
|
87
|
+
{ id: 3, text: 'Wednesday', key: 'wednesday', rruleKey: 'WE' },
|
|
88
|
+
{ id: 4, text: 'Thursday', key: 'thursday', rruleKey: 'TH' },
|
|
89
|
+
{ id: 5, text: 'Friday', key: 'friday', rruleKey: 'FR' },
|
|
90
|
+
{ id: 6, text: 'Saturday', key: 'saturday', rruleKey: 'SA' },
|
|
91
|
+
]);
|
|
92
|
+
/**
|
|
93
|
+
* Months of the year (0-11: January-December)
|
|
94
|
+
*/
|
|
95
|
+
const AX_SCHEDULER_PICKER_MONTHS = Object.freeze([
|
|
96
|
+
{ id: 0, text: 'January', key: 'january' },
|
|
97
|
+
{ id: 1, text: 'February', key: 'february' },
|
|
98
|
+
{ id: 2, text: 'March', key: 'march' },
|
|
99
|
+
{ id: 3, text: 'April', key: 'april' },
|
|
100
|
+
{ id: 4, text: 'May', key: 'may' },
|
|
101
|
+
{ id: 5, text: 'June', key: 'june' },
|
|
102
|
+
{ id: 6, text: 'July', key: 'july' },
|
|
103
|
+
{ id: 7, text: 'August', key: 'august' },
|
|
104
|
+
{ id: 8, text: 'September', key: 'september' },
|
|
105
|
+
{ id: 9, text: 'October', key: 'october' },
|
|
106
|
+
{ id: 10, text: 'November', key: 'november' },
|
|
107
|
+
{ id: 11, text: 'December', key: 'december' },
|
|
108
|
+
]);
|
|
109
|
+
/**
|
|
110
|
+
* Occurrence positions (1st, 2nd, 3rd, 4th, Last)
|
|
111
|
+
*/
|
|
112
|
+
const AX_SCHEDULER_PICKER_OCCURRENCE_POSITIONS = Object.freeze([
|
|
113
|
+
{ value: 1, text: 'First', key: 'first' },
|
|
114
|
+
{ value: 2, text: 'Second', key: 'second' },
|
|
115
|
+
{ value: 3, text: 'Third', key: 'third' },
|
|
116
|
+
{ value: 4, text: 'Fourth', key: 'fourth' },
|
|
117
|
+
{ value: -1, text: 'Last', key: 'last' },
|
|
118
|
+
]);
|
|
119
|
+
/**
|
|
120
|
+
* RRule day keys mapping (for RRule library)
|
|
121
|
+
*/
|
|
122
|
+
const AX_SCHEDULER_PICKER_RRULE_DAY_KEYS = Object.freeze(AX_SCHEDULER_PICKER_DAYS_OF_WEEK.map((d) => d.rruleKey));
|
|
123
|
+
/**
|
|
124
|
+
* Translation keys for days of week
|
|
125
|
+
*/
|
|
126
|
+
const AX_SCHEDULER_PICKER_DAY_TRANSLATION_KEYS = Object.freeze(AX_SCHEDULER_PICKER_DAYS_OF_WEEK.map((d) => d.key));
|
|
127
|
+
/**
|
|
128
|
+
* Translation keys for months
|
|
129
|
+
*/
|
|
130
|
+
const AX_SCHEDULER_PICKER_MONTH_TRANSLATION_KEYS = Object.freeze(AX_SCHEDULER_PICKER_MONTHS.map((m) => m.key));
|
|
131
|
+
/**
|
|
132
|
+
* Default first day of week (0 = Sunday)
|
|
133
|
+
*/
|
|
134
|
+
const AX_SCHEDULER_PICKER_DEFAULT_FIRST_DAY_OF_WEEK = 0;
|
|
135
|
+
/**
|
|
136
|
+
* Default time format
|
|
137
|
+
*/
|
|
138
|
+
const AX_SCHEDULER_PICKER_DEFAULT_TIME_FORMAT = '24h';
|
|
139
|
+
/**
|
|
140
|
+
* Default time precision
|
|
141
|
+
*/
|
|
142
|
+
const AX_SCHEDULER_PICKER_DEFAULT_TIME_PRECISION = 'minutes';
|
|
143
|
+
/**
|
|
144
|
+
* Default locale
|
|
145
|
+
*/
|
|
146
|
+
const AX_SCHEDULER_PICKER_DEFAULT_LOCALE = 'en-US';
|
|
147
|
+
/**
|
|
148
|
+
* Weekday range for daily mode (Monday-Friday)
|
|
149
|
+
*/
|
|
150
|
+
const AX_SCHEDULER_PICKER_WEEKDAY_START = 1; // Monday
|
|
151
|
+
const AX_SCHEDULER_PICKER_WEEKDAY_END = 5; // Friday
|
|
152
|
+
/**
|
|
153
|
+
* Default occurrences count for end condition
|
|
154
|
+
*/
|
|
155
|
+
const AX_SCHEDULER_PICKER_DEFAULT_OCCURRENCES = 10;
|
|
156
|
+
|
|
157
|
+
class AXSchedulerPickerDailyPanelComponent {
|
|
158
|
+
constructor() {
|
|
159
|
+
this.pattern = input.required(...(ngDevMode ? [{ debugName: "pattern" }] : []));
|
|
160
|
+
this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
161
|
+
this.patternChange = output();
|
|
162
|
+
this.weekdayOnly = signal(false, ...(ngDevMode ? [{ debugName: "weekdayOnly" }] : []));
|
|
163
|
+
// Initialize weekdayOnly from pattern
|
|
164
|
+
effect(() => {
|
|
165
|
+
const pattern = this.pattern();
|
|
166
|
+
if (pattern?.recurrence?.byDay) {
|
|
167
|
+
// Check if byDay is [1,2,3,4,5] (weekdays only)
|
|
168
|
+
const isWeekdaysOnly = pattern.recurrence.byDay.length === 5 &&
|
|
169
|
+
pattern.recurrence.byDay.every((d) => d >= AX_SCHEDULER_PICKER_WEEKDAY_START && d <= AX_SCHEDULER_PICKER_WEEKDAY_END);
|
|
170
|
+
this.weekdayOnly.set(isWeekdaysOnly);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
onIntervalChange(interval) {
|
|
175
|
+
this.patternChange.emit({ interval });
|
|
176
|
+
}
|
|
177
|
+
onWeekdayOnlyChange(value) {
|
|
178
|
+
this.weekdayOnly.set(value);
|
|
179
|
+
// Emit recurrence with weekday filter (Mon-Fri)
|
|
180
|
+
this.patternChange.emit({
|
|
181
|
+
recurrence: {
|
|
182
|
+
...this.pattern()?.recurrence,
|
|
183
|
+
byDay: value ? [AX_SCHEDULER_PICKER_WEEKDAY_START, 2, 3, 4, AX_SCHEDULER_PICKER_WEEKDAY_END] : undefined,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerDailyPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
188
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerDailyPanelComponent, isStandalone: true, selector: "ax-scheduler-picker-daily-panel", inputs: { pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { patternChange: "patternChange" }, ngImport: i0, template: "<div class=\"ax-scheduler-picker-daily-panel\">\n <!-- Interval selector -->\n @if (config().options?.showInterval) {\n <ax-scheduler-picker-interval-selector\n [interval]=\"pattern()?.interval || 1\"\n [config]=\"config()\"\n (intervalChange)=\"onIntervalChange($event)\"\n />\n }\n\n <!-- Weekdays only switch -->\n @if (config().options?.showWeekdaysOnly) {\n <div class=\"ax-scheduler-picker-weekdays-only\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.weekdaysOnly' | translate | async }}\n </label>\n <ax-switch [value]=\"weekdayOnly()\" (valueChange)=\"onWeekdayOnlyChange($event)\" />\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-daily-panel{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-weekday-option{display:flex;align-items:center;justify-content:space-between;padding:.25rem 0}.ax-scheduler-picker-time-selection{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: AXSwitchComponent, selector: "ax-switch", inputs: ["disabled", "readonly", "color", "tabIndex", "value", "name", "isLoading"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged", "readonlyChange", "disabledChange"] }, { kind: "component", type: AXSchedulerPickerIntervalSelectorComponent, selector: "ax-scheduler-picker-interval-selector", inputs: ["interval", "config"], outputs: ["intervalChange"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
189
|
+
}
|
|
190
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerDailyPanelComponent, decorators: [{
|
|
191
|
+
type: Component,
|
|
192
|
+
args: [{ selector: 'ax-scheduler-picker-daily-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
193
|
+
FormsModule,
|
|
194
|
+
AXSwitchComponent,
|
|
195
|
+
AXTranslatorPipe,
|
|
196
|
+
AsyncPipe,
|
|
197
|
+
AXSchedulerPickerIntervalSelectorComponent,
|
|
198
|
+
], template: "<div class=\"ax-scheduler-picker-daily-panel\">\n <!-- Interval selector -->\n @if (config().options?.showInterval) {\n <ax-scheduler-picker-interval-selector\n [interval]=\"pattern()?.interval || 1\"\n [config]=\"config()\"\n (intervalChange)=\"onIntervalChange($event)\"\n />\n }\n\n <!-- Weekdays only switch -->\n @if (config().options?.showWeekdaysOnly) {\n <div class=\"ax-scheduler-picker-weekdays-only\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.weekdaysOnly' | translate | async }}\n </label>\n <ax-switch [value]=\"weekdayOnly()\" (valueChange)=\"onWeekdayOnlyChange($event)\" />\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-daily-panel{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-weekday-option{display:flex;align-items:center;justify-content:space-between;padding:.25rem 0}.ax-scheduler-picker-time-selection{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}\n"] }]
|
|
199
|
+
}], ctorParameters: () => [], propDecorators: { pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], patternChange: [{ type: i0.Output, args: ["patternChange"] }] } });
|
|
200
|
+
|
|
201
|
+
class AXSchedulerPickerHourlyPanelComponent {
|
|
202
|
+
constructor() {
|
|
203
|
+
this.pattern = input.required(...(ngDevMode ? [{ debugName: "pattern" }] : []));
|
|
204
|
+
this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
205
|
+
this.patternChange = output();
|
|
206
|
+
}
|
|
207
|
+
onIntervalChange(interval) {
|
|
208
|
+
this.patternChange.emit({ interval });
|
|
209
|
+
}
|
|
210
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerHourlyPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
211
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerHourlyPanelComponent, isStandalone: true, selector: "ax-scheduler-picker-hourly-panel", inputs: { pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { patternChange: "patternChange" }, ngImport: i0, template: `
|
|
212
|
+
<div class="ax-scheduler-picker-hourly-panel">
|
|
213
|
+
@if (config().options?.showInterval) {
|
|
214
|
+
<ax-scheduler-picker-interval-selector
|
|
215
|
+
[interval]="pattern()?.interval || 1"
|
|
216
|
+
[config]="config()"
|
|
217
|
+
(intervalChange)="onIntervalChange($event)"
|
|
218
|
+
/>
|
|
219
|
+
}
|
|
220
|
+
</div>
|
|
221
|
+
`, isInline: true, styles: [".ax-scheduler-picker-hourly-panel{display:flex;flex-direction:column;gap:.75rem}\n"], dependencies: [{ kind: "component", type: AXSchedulerPickerIntervalSelectorComponent, selector: "ax-scheduler-picker-interval-selector", inputs: ["interval", "config"], outputs: ["intervalChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
222
|
+
}
|
|
223
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerHourlyPanelComponent, decorators: [{
|
|
224
|
+
type: Component,
|
|
225
|
+
args: [{ selector: 'ax-scheduler-picker-hourly-panel', template: `
|
|
226
|
+
<div class="ax-scheduler-picker-hourly-panel">
|
|
227
|
+
@if (config().options?.showInterval) {
|
|
228
|
+
<ax-scheduler-picker-interval-selector
|
|
229
|
+
[interval]="pattern()?.interval || 1"
|
|
230
|
+
[config]="config()"
|
|
231
|
+
(intervalChange)="onIntervalChange($event)"
|
|
232
|
+
/>
|
|
233
|
+
}
|
|
234
|
+
</div>
|
|
235
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [AXSchedulerPickerIntervalSelectorComponent], styles: [".ax-scheduler-picker-hourly-panel{display:flex;flex-direction:column;gap:.75rem}\n"] }]
|
|
236
|
+
}], propDecorators: { pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], patternChange: [{ type: i0.Output, args: ["patternChange"] }] } });
|
|
237
|
+
|
|
238
|
+
class AXSchedulerPickerDaySelectorComponent {
|
|
239
|
+
constructor() {
|
|
240
|
+
/**
|
|
241
|
+
* Selected day numbers (1-31)
|
|
242
|
+
*/
|
|
243
|
+
this.days = input(...(ngDevMode ? [undefined, { debugName: "days" }] : []));
|
|
244
|
+
/**
|
|
245
|
+
* Emits when day selection changes
|
|
246
|
+
*/
|
|
247
|
+
this.daysChange = output();
|
|
248
|
+
this.dayItems = Array.from({ length: 31 }, (_, i) => ({
|
|
249
|
+
id: i + 1,
|
|
250
|
+
text: String(i + 1),
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Handle day selection change
|
|
255
|
+
*/
|
|
256
|
+
onDaysChange(event) {
|
|
257
|
+
const selectedDays = Array.isArray(event.value) ? event.value : [event.value];
|
|
258
|
+
this.daysChange.emit(selectedDays.sort((a, b) => a - b));
|
|
259
|
+
}
|
|
260
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerDaySelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
261
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.9", type: AXSchedulerPickerDaySelectorComponent, isStandalone: true, selector: "ax-scheduler-picker-day-selector", inputs: { days: { classPropertyName: "days", publicName: "days", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { daysChange: "daysChange" }, ngImport: i0, template: `
|
|
262
|
+
<div class="ax-scheduler-picker-day-selector">
|
|
263
|
+
<label class="ax-scheduler-picker-label">
|
|
264
|
+
{{ '@acorex:schedulerPicker.labels.selectDays' | translate | async }}
|
|
265
|
+
</label>
|
|
266
|
+
<ax-select-box
|
|
267
|
+
[dataSource]="dayItems"
|
|
268
|
+
textField="text"
|
|
269
|
+
valueField="id"
|
|
270
|
+
[multiple]="true"
|
|
271
|
+
[value]="days()"
|
|
272
|
+
(onValueChanged)="onDaysChange($event)"
|
|
273
|
+
/>
|
|
274
|
+
</div>
|
|
275
|
+
`, isInline: true, styles: [".ax-scheduler-picker-day-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}ax-select-box{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
276
|
+
}
|
|
277
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerDaySelectorComponent, decorators: [{
|
|
278
|
+
type: Component,
|
|
279
|
+
args: [{ selector: 'ax-scheduler-picker-day-selector', template: `
|
|
280
|
+
<div class="ax-scheduler-picker-day-selector">
|
|
281
|
+
<label class="ax-scheduler-picker-label">
|
|
282
|
+
{{ '@acorex:schedulerPicker.labels.selectDays' | translate | async }}
|
|
283
|
+
</label>
|
|
284
|
+
<ax-select-box
|
|
285
|
+
[dataSource]="dayItems"
|
|
286
|
+
textField="text"
|
|
287
|
+
valueField="id"
|
|
288
|
+
[multiple]="true"
|
|
289
|
+
[value]="days()"
|
|
290
|
+
(onValueChanged)="onDaysChange($event)"
|
|
291
|
+
/>
|
|
292
|
+
</div>
|
|
293
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [FormsModule, AXSelectBoxComponent, AXTranslatorPipe, AsyncPipe], styles: [".ax-scheduler-picker-day-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}ax-select-box{width:100%}\n"] }]
|
|
294
|
+
}], propDecorators: { days: [{ type: i0.Input, args: [{ isSignal: true, alias: "days", required: false }] }], daysChange: [{ type: i0.Output, args: ["daysChange"] }] } });
|
|
295
|
+
|
|
296
|
+
class AXSchedulerPickerOccurrenceSelectorComponent {
|
|
297
|
+
constructor() {
|
|
298
|
+
/**
|
|
299
|
+
* Current occurrence selection (position + day)
|
|
300
|
+
*/
|
|
301
|
+
this.occurrence = input(...(ngDevMode ? [undefined, { debugName: "occurrence" }] : []));
|
|
302
|
+
/**
|
|
303
|
+
* Emits when occurrence selection changes
|
|
304
|
+
*/
|
|
305
|
+
this.occurrenceChange = output();
|
|
306
|
+
this.selectedPosition = signal(1, ...(ngDevMode ? [{ debugName: "selectedPosition" }] : []));
|
|
307
|
+
this.selectedDay = signal(1, ...(ngDevMode ? [{ debugName: "selectedDay" }] : []));
|
|
308
|
+
this.positions = AX_SCHEDULER_PICKER_OCCURRENCE_POSITIONS.map((pos) => ({
|
|
309
|
+
...pos,
|
|
310
|
+
text: `@acorex:schedulerPicker.positions.${pos.key}`,
|
|
311
|
+
}));
|
|
312
|
+
this.days = AX_SCHEDULER_PICKER_DAYS_OF_WEEK.map((d) => ({
|
|
313
|
+
value: d.id,
|
|
314
|
+
text: `@acorex:schedulerPicker.days.${d.key}`,
|
|
315
|
+
}));
|
|
316
|
+
// Sync input with internal state
|
|
317
|
+
effect(() => {
|
|
318
|
+
const occ = this.occurrence();
|
|
319
|
+
if (occ) {
|
|
320
|
+
this.selectedPosition.set(occ.position);
|
|
321
|
+
this.selectedDay.set(occ.day);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Handle position selection change
|
|
327
|
+
*/
|
|
328
|
+
onPositionChangeEvent(event) {
|
|
329
|
+
this.selectedPosition.set(event.value);
|
|
330
|
+
this.emitChange();
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Handle day selection change
|
|
334
|
+
*/
|
|
335
|
+
onDayChangeEvent(event) {
|
|
336
|
+
const day = event.value;
|
|
337
|
+
this.selectedDay.set(day);
|
|
338
|
+
this.emitChange();
|
|
339
|
+
}
|
|
340
|
+
emitChange() {
|
|
341
|
+
this.occurrenceChange.emit({
|
|
342
|
+
position: this.selectedPosition(),
|
|
343
|
+
day: this.selectedDay(),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerOccurrenceSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
347
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.9", type: AXSchedulerPickerOccurrenceSelectorComponent, isStandalone: true, selector: "ax-scheduler-picker-occurrence-selector", inputs: { occurrence: { classPropertyName: "occurrence", publicName: "occurrence", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { occurrenceChange: "occurrenceChange" }, ngImport: i0, template: `
|
|
348
|
+
<div class="ax-scheduler-picker-occurrence-selector">
|
|
349
|
+
<label class="ax-scheduler-picker-label">
|
|
350
|
+
{{ '@acorex:schedulerPicker.labels.occurrence' | translate | async }}
|
|
351
|
+
</label>
|
|
352
|
+
|
|
353
|
+
<div class="ax-scheduler-picker-row">
|
|
354
|
+
<ax-select-box
|
|
355
|
+
[value]="selectedPosition()"
|
|
356
|
+
[dataSource]="positions"
|
|
357
|
+
textField="text"
|
|
358
|
+
valueField="value"
|
|
359
|
+
(onValueChanged)="onPositionChangeEvent($event)"
|
|
360
|
+
/>
|
|
361
|
+
<ax-select-box
|
|
362
|
+
[value]="selectedDay()"
|
|
363
|
+
[dataSource]="days"
|
|
364
|
+
textField="text"
|
|
365
|
+
valueField="value"
|
|
366
|
+
(onValueChanged)="onDayChangeEvent($event)"
|
|
367
|
+
/>
|
|
368
|
+
</div>
|
|
369
|
+
</div>
|
|
370
|
+
`, isInline: true, styles: [".ax-scheduler-picker-occurrence-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-row{display:flex;gap:.5rem}.ax-scheduler-picker-row>*{flex:1}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
371
|
+
}
|
|
372
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerOccurrenceSelectorComponent, decorators: [{
|
|
373
|
+
type: Component,
|
|
374
|
+
args: [{ selector: 'ax-scheduler-picker-occurrence-selector', template: `
|
|
375
|
+
<div class="ax-scheduler-picker-occurrence-selector">
|
|
376
|
+
<label class="ax-scheduler-picker-label">
|
|
377
|
+
{{ '@acorex:schedulerPicker.labels.occurrence' | translate | async }}
|
|
378
|
+
</label>
|
|
379
|
+
|
|
380
|
+
<div class="ax-scheduler-picker-row">
|
|
381
|
+
<ax-select-box
|
|
382
|
+
[value]="selectedPosition()"
|
|
383
|
+
[dataSource]="positions"
|
|
384
|
+
textField="text"
|
|
385
|
+
valueField="value"
|
|
386
|
+
(onValueChanged)="onPositionChangeEvent($event)"
|
|
387
|
+
/>
|
|
388
|
+
<ax-select-box
|
|
389
|
+
[value]="selectedDay()"
|
|
390
|
+
[dataSource]="days"
|
|
391
|
+
textField="text"
|
|
392
|
+
valueField="value"
|
|
393
|
+
(onValueChanged)="onDayChangeEvent($event)"
|
|
394
|
+
/>
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [FormsModule, AXSelectBoxComponent, AXTranslatorPipe, AsyncPipe], styles: [".ax-scheduler-picker-occurrence-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-row{display:flex;gap:.5rem}.ax-scheduler-picker-row>*{flex:1}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}\n"] }]
|
|
398
|
+
}], ctorParameters: () => [], propDecorators: { occurrence: [{ type: i0.Input, args: [{ isSignal: true, alias: "occurrence", required: false }] }], occurrenceChange: [{ type: i0.Output, args: ["occurrenceChange"] }] } });
|
|
399
|
+
|
|
400
|
+
class AXSchedulerPickerMonthlyPanelComponent {
|
|
401
|
+
constructor() {
|
|
402
|
+
this.pattern = input.required(...(ngDevMode ? [{ debugName: "pattern" }] : []));
|
|
403
|
+
this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
404
|
+
this.patternChange = output();
|
|
405
|
+
this.selectedDays = signal([], ...(ngDevMode ? [{ debugName: "selectedDays" }] : []));
|
|
406
|
+
this.occurrence = signal(null, ...(ngDevMode ? [{ debugName: "occurrence" }] : []));
|
|
407
|
+
// Initialize state from pattern
|
|
408
|
+
effect(() => {
|
|
409
|
+
const pattern = this.pattern();
|
|
410
|
+
if (pattern?.recurrence) {
|
|
411
|
+
if (pattern.recurrence.byDay) {
|
|
412
|
+
this.selectedDays.set(pattern.recurrence.byDay);
|
|
413
|
+
}
|
|
414
|
+
if (pattern.recurrence.byOccurrence && pattern.recurrence.byOccurrence.length > 0) {
|
|
415
|
+
const occ = pattern.recurrence.byOccurrence[0];
|
|
416
|
+
this.occurrence.set({ position: occ.position, day: occ.dayOfWeek });
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
onIntervalChange(interval) {
|
|
422
|
+
this.patternChange.emit({ interval });
|
|
423
|
+
}
|
|
424
|
+
onDaysChange(days) {
|
|
425
|
+
this.selectedDays.set(days);
|
|
426
|
+
this.patternChange.emit({
|
|
427
|
+
recurrence: {
|
|
428
|
+
...this.pattern()?.recurrence,
|
|
429
|
+
byDay: days,
|
|
430
|
+
byOccurrence: undefined, // Clear occurrence when using specific days
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
onOccurrenceChange(occurrence) {
|
|
435
|
+
this.occurrence.set(occurrence);
|
|
436
|
+
this.patternChange.emit({
|
|
437
|
+
recurrence: {
|
|
438
|
+
...this.pattern()?.recurrence,
|
|
439
|
+
byOccurrence: [{ position: occurrence.position, dayOfWeek: occurrence.day }],
|
|
440
|
+
byDay: undefined, // Clear days when using occurrence
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerMonthlyPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
445
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerMonthlyPanelComponent, isStandalone: true, selector: "ax-scheduler-picker-monthly-panel", inputs: { pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { patternChange: "patternChange" }, ngImport: i0, template: "<div class=\"ax-scheduler-picker-monthly-panel\">\n <!-- Interval selector -->\n @if (config().options?.showInterval) {\n <ax-scheduler-picker-interval-selector\n [interval]=\"pattern()?.interval || 1\"\n [config]=\"config()\"\n (intervalChange)=\"onIntervalChange($event)\"\n />\n }\n\n <!-- Specific Days Mode: Calendar day picker -->\n @if (config().options?.recurrenceMode === 'specificDays') {\n <ax-scheduler-picker-day-selector\n [days]=\"selectedDays()\"\n (daysChange)=\"onDaysChange($event)\"\n />\n }\n\n <!-- Occurrence Mode: Position + Weekday selectors -->\n @if (config().options?.recurrenceMode === 'occurrence') {\n <ax-scheduler-picker-occurrence-selector\n [occurrence]=\"occurrence()\"\n (occurrenceChange)=\"onOccurrenceChange($event)\"\n />\n }\n</div>\n", styles: [".ax-scheduler-picker-monthly-panel{display:flex;flex-direction:column;gap:.5rem}\n"], dependencies: [{ kind: "component", type: AXSchedulerPickerIntervalSelectorComponent, selector: "ax-scheduler-picker-interval-selector", inputs: ["interval", "config"], outputs: ["intervalChange"] }, { kind: "component", type: AXSchedulerPickerDaySelectorComponent, selector: "ax-scheduler-picker-day-selector", inputs: ["days"], outputs: ["daysChange"] }, { kind: "component", type: AXSchedulerPickerOccurrenceSelectorComponent, selector: "ax-scheduler-picker-occurrence-selector", inputs: ["occurrence"], outputs: ["occurrenceChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
446
|
+
}
|
|
447
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerMonthlyPanelComponent, decorators: [{
|
|
448
|
+
type: Component,
|
|
449
|
+
args: [{ selector: 'ax-scheduler-picker-monthly-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
450
|
+
AXSchedulerPickerIntervalSelectorComponent,
|
|
451
|
+
AXSchedulerPickerDaySelectorComponent,
|
|
452
|
+
AXSchedulerPickerOccurrenceSelectorComponent,
|
|
453
|
+
], template: "<div class=\"ax-scheduler-picker-monthly-panel\">\n <!-- Interval selector -->\n @if (config().options?.showInterval) {\n <ax-scheduler-picker-interval-selector\n [interval]=\"pattern()?.interval || 1\"\n [config]=\"config()\"\n (intervalChange)=\"onIntervalChange($event)\"\n />\n }\n\n <!-- Specific Days Mode: Calendar day picker -->\n @if (config().options?.recurrenceMode === 'specificDays') {\n <ax-scheduler-picker-day-selector\n [days]=\"selectedDays()\"\n (daysChange)=\"onDaysChange($event)\"\n />\n }\n\n <!-- Occurrence Mode: Position + Weekday selectors -->\n @if (config().options?.recurrenceMode === 'occurrence') {\n <ax-scheduler-picker-occurrence-selector\n [occurrence]=\"occurrence()\"\n (occurrenceChange)=\"onOccurrenceChange($event)\"\n />\n }\n</div>\n", styles: [".ax-scheduler-picker-monthly-panel{display:flex;flex-direction:column;gap:.5rem}\n"] }]
|
|
454
|
+
}], ctorParameters: () => [], propDecorators: { pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], patternChange: [{ type: i0.Output, args: ["patternChange"] }] } });
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Helper function to reorder days based on first day of week
|
|
458
|
+
*/
|
|
459
|
+
function reorderDaysByFirstDay(firstDayOfWeek = AX_SCHEDULER_PICKER_DEFAULT_FIRST_DAY_OF_WEEK) {
|
|
460
|
+
return [...AX_SCHEDULER_PICKER_DAYS_OF_WEEK.slice(firstDayOfWeek), ...AX_SCHEDULER_PICKER_DAYS_OF_WEEK.slice(0, firstDayOfWeek)];
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Get RRule day key by day index
|
|
464
|
+
*/
|
|
465
|
+
function getRRuleDayKey(dayIndex) {
|
|
466
|
+
return AX_SCHEDULER_PICKER_RRULE_DAY_KEYS[dayIndex] || 'MO';
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Get day translation key by index
|
|
470
|
+
*/
|
|
471
|
+
function getDayTranslationKey(dayIndex) {
|
|
472
|
+
return AX_SCHEDULER_PICKER_DAY_TRANSLATION_KEYS[dayIndex] || 'monday';
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Get month translation key by index
|
|
476
|
+
*/
|
|
477
|
+
function getMonthTranslationKey(monthIndex) {
|
|
478
|
+
return AX_SCHEDULER_PICKER_MONTH_TRANSLATION_KEYS[monthIndex] || 'january';
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Normalize date to midnight for consistent comparison
|
|
482
|
+
*/
|
|
483
|
+
function normalizeDate(date) {
|
|
484
|
+
const normalized = new Date(date);
|
|
485
|
+
normalized.setHours(0, 0, 0, 0);
|
|
486
|
+
return normalized;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Check if two dates are the same day (ignoring time)
|
|
490
|
+
*/
|
|
491
|
+
function isSameDate(date1, date2) {
|
|
492
|
+
return normalizeDate(date1).getTime() === normalizeDate(date2).getTime();
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Check if date exists in array (day comparison only)
|
|
496
|
+
*/
|
|
497
|
+
function dateExistsInArray(date, dates) {
|
|
498
|
+
const normalized = normalizeDate(date);
|
|
499
|
+
return dates.some((d) => normalizeDate(d).getTime() === normalized.getTime());
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Weekly recurrence panel
|
|
504
|
+
*/
|
|
505
|
+
class AXSchedulerPickerWeeklyPanelComponent {
|
|
506
|
+
constructor() {
|
|
507
|
+
this.pattern = input.required(...(ngDevMode ? [{ debugName: "pattern" }] : []));
|
|
508
|
+
this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
509
|
+
this.patternChange = output();
|
|
510
|
+
this.selectedDays = signal([], ...(ngDevMode ? [{ debugName: "selectedDays" }] : []));
|
|
511
|
+
this.dayItems = computed(() => {
|
|
512
|
+
const firstDay = this.config().firstDayOfWeek || 0;
|
|
513
|
+
const days = reorderDaysByFirstDay(firstDay);
|
|
514
|
+
return days.map((day) => ({
|
|
515
|
+
...day,
|
|
516
|
+
text: `@acorex:schedulerPicker.days.${day.key}`,
|
|
517
|
+
}));
|
|
518
|
+
}, ...(ngDevMode ? [{ debugName: "dayItems" }] : []));
|
|
519
|
+
// Initialize selectedDays from pattern
|
|
520
|
+
effect(() => {
|
|
521
|
+
const pattern = this.pattern();
|
|
522
|
+
if (pattern?.recurrence?.byDay) {
|
|
523
|
+
this.selectedDays.set(pattern.recurrence.byDay);
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
onIntervalChange(interval) {
|
|
528
|
+
this.patternChange.emit({ interval });
|
|
529
|
+
}
|
|
530
|
+
onDaysChange(event) {
|
|
531
|
+
const days = event.value;
|
|
532
|
+
this.selectedDays.set(days);
|
|
533
|
+
this.patternChange.emit({
|
|
534
|
+
recurrence: {
|
|
535
|
+
...this.pattern()?.recurrence,
|
|
536
|
+
byDay: days,
|
|
537
|
+
},
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerWeeklyPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
541
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerWeeklyPanelComponent, isStandalone: true, selector: "ax-scheduler-picker-weekly-panel", inputs: { pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { patternChange: "patternChange" }, ngImport: i0, template: "<div class=\"ax-scheduler-picker-weekly-panel\">\n <!-- Interval selector -->\n @if (config().options?.showInterval) {\n <ax-scheduler-picker-interval-selector\n [interval]=\"pattern()?.interval || 1\"\n [config]=\"config()\"\n (intervalChange)=\"onIntervalChange($event)\"\n />\n }\n\n <!-- Day selection -->\n @if (config().options?.showWeekdaySelection) {\n <div class=\"ax-scheduler-picker-day-selection\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.onDays' | translate | async }}\n </label>\n <ax-selection-list\n [items]=\"dayItems()\"\n [multiple]=\"true\"\n [showControl]=\"true\"\n [look]=\"'solid'\"\n [direction]=\"'horizontal'\"\n [value]=\"selectedDays()\"\n (onValueChanged)=\"onDaysChange($event)\"\n />\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-weekly-panel{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-day-selection,.ax-scheduler-picker-time-selection{display:flex;flex-direction:column;gap:.375rem}ax-selection-list{width:100%}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: AXSelectionListModule }, { kind: "component", type: i1.AXSelectionListComponent, selector: "ax-selection-list", inputs: ["id", "name", "disabled", "readonly", "tabIndex", "size", "value", "valueField", "textField", "disabledField", "readonlyField", "multiple", "direction", "customTemplate", "showControl", "items", "look"], outputs: ["onValueChanged", "onBlur", "onFocus"] }, { kind: "component", type: AXSchedulerPickerIntervalSelectorComponent, selector: "ax-scheduler-picker-interval-selector", inputs: ["interval", "config"], outputs: ["intervalChange"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
542
|
+
}
|
|
543
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerWeeklyPanelComponent, decorators: [{
|
|
544
|
+
type: Component,
|
|
545
|
+
args: [{ selector: 'ax-scheduler-picker-weekly-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
546
|
+
FormsModule,
|
|
547
|
+
AXSelectionListModule,
|
|
548
|
+
AXTranslatorPipe,
|
|
549
|
+
AsyncPipe,
|
|
550
|
+
AXSchedulerPickerIntervalSelectorComponent,
|
|
551
|
+
], template: "<div class=\"ax-scheduler-picker-weekly-panel\">\n <!-- Interval selector -->\n @if (config().options?.showInterval) {\n <ax-scheduler-picker-interval-selector\n [interval]=\"pattern()?.interval || 1\"\n [config]=\"config()\"\n (intervalChange)=\"onIntervalChange($event)\"\n />\n }\n\n <!-- Day selection -->\n @if (config().options?.showWeekdaySelection) {\n <div class=\"ax-scheduler-picker-day-selection\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.onDays' | translate | async }}\n </label>\n <ax-selection-list\n [items]=\"dayItems()\"\n [multiple]=\"true\"\n [showControl]=\"true\"\n [look]=\"'solid'\"\n [direction]=\"'horizontal'\"\n [value]=\"selectedDays()\"\n (onValueChanged)=\"onDaysChange($event)\"\n />\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-weekly-panel{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-day-selection,.ax-scheduler-picker-time-selection{display:flex;flex-direction:column;gap:.375rem}ax-selection-list{width:100%}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}\n"] }]
|
|
552
|
+
}], ctorParameters: () => [], propDecorators: { pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], patternChange: [{ type: i0.Output, args: ["patternChange"] }] } });
|
|
553
|
+
|
|
554
|
+
class AXSchedulerPickerMonthSelectorComponent {
|
|
555
|
+
constructor() {
|
|
556
|
+
/**
|
|
557
|
+
* Selected month indices (0-11)
|
|
558
|
+
*/
|
|
559
|
+
this.months = input(...(ngDevMode ? [undefined, { debugName: "months" }] : []));
|
|
560
|
+
/**
|
|
561
|
+
* Emits when month selection changes
|
|
562
|
+
*/
|
|
563
|
+
this.monthsChange = output();
|
|
564
|
+
this.monthItems = AX_SCHEDULER_PICKER_MONTHS.map((month) => ({
|
|
565
|
+
...month,
|
|
566
|
+
text: `@acorex:schedulerPicker.months.${month.key}`,
|
|
567
|
+
}));
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Handle month selection change
|
|
571
|
+
*/
|
|
572
|
+
onMonthsChange(event) {
|
|
573
|
+
const selectedMonths = Array.isArray(event.value) ? event.value : [event.value];
|
|
574
|
+
this.monthsChange.emit(selectedMonths.sort((a, b) => a - b));
|
|
575
|
+
}
|
|
576
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerMonthSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
577
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.9", type: AXSchedulerPickerMonthSelectorComponent, isStandalone: true, selector: "ax-scheduler-picker-month-selector", inputs: { months: { classPropertyName: "months", publicName: "months", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { monthsChange: "monthsChange" }, ngImport: i0, template: `
|
|
578
|
+
<div class="ax-scheduler-picker-month-selector">
|
|
579
|
+
<label class="ax-scheduler-picker-label">
|
|
580
|
+
{{ '@acorex:schedulerPicker.labels.selectMonths' | translate | async }}
|
|
581
|
+
</label>
|
|
582
|
+
<ax-select-box
|
|
583
|
+
[dataSource]="monthItems"
|
|
584
|
+
textField="text"
|
|
585
|
+
valueField="id"
|
|
586
|
+
[multiple]="true"
|
|
587
|
+
[value]="months()"
|
|
588
|
+
(onValueChanged)="onMonthsChange($event)"
|
|
589
|
+
/>
|
|
590
|
+
</div>
|
|
591
|
+
`, isInline: true, styles: [".ax-scheduler-picker-month-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}ax-select-box{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
592
|
+
}
|
|
593
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerMonthSelectorComponent, decorators: [{
|
|
594
|
+
type: Component,
|
|
595
|
+
args: [{ selector: 'ax-scheduler-picker-month-selector', template: `
|
|
596
|
+
<div class="ax-scheduler-picker-month-selector">
|
|
597
|
+
<label class="ax-scheduler-picker-label">
|
|
598
|
+
{{ '@acorex:schedulerPicker.labels.selectMonths' | translate | async }}
|
|
599
|
+
</label>
|
|
600
|
+
<ax-select-box
|
|
601
|
+
[dataSource]="monthItems"
|
|
602
|
+
textField="text"
|
|
603
|
+
valueField="id"
|
|
604
|
+
[multiple]="true"
|
|
605
|
+
[value]="months()"
|
|
606
|
+
(onValueChanged)="onMonthsChange($event)"
|
|
607
|
+
/>
|
|
608
|
+
</div>
|
|
609
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [FormsModule, AXSelectBoxComponent, AXTranslatorPipe, AsyncPipe], styles: [".ax-scheduler-picker-month-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}ax-select-box{width:100%}\n"] }]
|
|
610
|
+
}], propDecorators: { months: [{ type: i0.Input, args: [{ isSignal: true, alias: "months", required: false }] }], monthsChange: [{ type: i0.Output, args: ["monthsChange"] }] } });
|
|
611
|
+
|
|
612
|
+
class AXSchedulerPickerYearlyPanelComponent {
|
|
613
|
+
constructor() {
|
|
614
|
+
this.pattern = input.required(...(ngDevMode ? [{ debugName: "pattern" }] : []));
|
|
615
|
+
this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
616
|
+
this.patternChange = output();
|
|
617
|
+
this.selectedMonths = signal([], ...(ngDevMode ? [{ debugName: "selectedMonths" }] : []));
|
|
618
|
+
this.selectedDays = signal([], ...(ngDevMode ? [{ debugName: "selectedDays" }] : []));
|
|
619
|
+
this.occurrence = signal(null, ...(ngDevMode ? [{ debugName: "occurrence" }] : []));
|
|
620
|
+
// Initialize state from pattern
|
|
621
|
+
effect(() => {
|
|
622
|
+
const pattern = this.pattern();
|
|
623
|
+
if (pattern?.recurrence) {
|
|
624
|
+
if (pattern.recurrence.byMonth) {
|
|
625
|
+
this.selectedMonths.set(pattern.recurrence.byMonth);
|
|
626
|
+
}
|
|
627
|
+
if (pattern.recurrence.byDay) {
|
|
628
|
+
this.selectedDays.set(pattern.recurrence.byDay);
|
|
629
|
+
}
|
|
630
|
+
if (pattern.recurrence.byOccurrence && pattern.recurrence.byOccurrence.length > 0) {
|
|
631
|
+
const occ = pattern.recurrence.byOccurrence[0];
|
|
632
|
+
this.occurrence.set({ position: occ.position, day: occ.dayOfWeek });
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
onIntervalChange(interval) {
|
|
638
|
+
this.patternChange.emit({ interval });
|
|
639
|
+
}
|
|
640
|
+
onMonthsChange(months) {
|
|
641
|
+
this.selectedMonths.set(months);
|
|
642
|
+
this.patternChange.emit({
|
|
643
|
+
recurrence: {
|
|
644
|
+
...this.pattern()?.recurrence,
|
|
645
|
+
byMonth: months,
|
|
646
|
+
},
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
onDaysChange(days) {
|
|
650
|
+
this.selectedDays.set(days);
|
|
651
|
+
this.patternChange.emit({
|
|
652
|
+
recurrence: {
|
|
653
|
+
...this.pattern()?.recurrence,
|
|
654
|
+
byDay: days,
|
|
655
|
+
byOccurrence: undefined, // Clear occurrence when using specific date
|
|
656
|
+
},
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
onOccurrenceChange(occurrence) {
|
|
660
|
+
this.occurrence.set(occurrence);
|
|
661
|
+
this.patternChange.emit({
|
|
662
|
+
recurrence: {
|
|
663
|
+
...this.pattern()?.recurrence,
|
|
664
|
+
byOccurrence: [{ position: occurrence.position, dayOfWeek: occurrence.day }],
|
|
665
|
+
byDay: undefined, // Clear days when using occurrence
|
|
666
|
+
},
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerYearlyPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
670
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerYearlyPanelComponent, isStandalone: true, selector: "ax-scheduler-picker-yearly-panel", inputs: { pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { patternChange: "patternChange" }, ngImport: i0, template: "<div class=\"ax-scheduler-picker-yearly-panel\">\n <!-- Interval selector -->\n @if (config().options?.showInterval) {\n <ax-scheduler-picker-interval-selector\n [interval]=\"pattern()?.interval || 1\"\n [config]=\"config()\"\n (intervalChange)=\"onIntervalChange($event)\"\n />\n }\n\n <!-- Month selector (independent of recurrence mode) -->\n @if (config().options?.showMonthSelection !== false) {\n <ax-scheduler-picker-month-selector\n [months]=\"selectedMonths()\"\n (monthsChange)=\"onMonthsChange($event)\"\n />\n }\n\n <!-- Specific Date Mode: Day picker -->\n @if (config().options?.recurrenceMode === 'specificDate') {\n <ax-scheduler-picker-day-selector\n [days]=\"selectedDays()\"\n (daysChange)=\"onDaysChange($event)\"\n />\n }\n\n <!-- Occurrence Mode: Month + Position + Weekday selectors -->\n @if (config().options?.recurrenceMode === 'occurrence') {\n @if (config().options?.showMonthSelection !== false) {\n <ax-scheduler-picker-month-selector\n [months]=\"selectedMonths()\"\n (monthsChange)=\"onMonthsChange($event)\"\n />\n }\n <ax-scheduler-picker-occurrence-selector\n [occurrence]=\"occurrence()\"\n (occurrenceChange)=\"onOccurrenceChange($event)\"\n />\n }\n</div>\n", styles: [".ax-scheduler-picker-yearly-panel{display:flex;flex-direction:column;gap:.5rem}\n"], dependencies: [{ kind: "component", type: AXSchedulerPickerIntervalSelectorComponent, selector: "ax-scheduler-picker-interval-selector", inputs: ["interval", "config"], outputs: ["intervalChange"] }, { kind: "component", type: AXSchedulerPickerMonthSelectorComponent, selector: "ax-scheduler-picker-month-selector", inputs: ["months"], outputs: ["monthsChange"] }, { kind: "component", type: AXSchedulerPickerDaySelectorComponent, selector: "ax-scheduler-picker-day-selector", inputs: ["days"], outputs: ["daysChange"] }, { kind: "component", type: AXSchedulerPickerOccurrenceSelectorComponent, selector: "ax-scheduler-picker-occurrence-selector", inputs: ["occurrence"], outputs: ["occurrenceChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
671
|
+
}
|
|
672
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerYearlyPanelComponent, decorators: [{
|
|
673
|
+
type: Component,
|
|
674
|
+
args: [{ selector: 'ax-scheduler-picker-yearly-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
675
|
+
AXSchedulerPickerIntervalSelectorComponent,
|
|
676
|
+
AXSchedulerPickerMonthSelectorComponent,
|
|
677
|
+
AXSchedulerPickerDaySelectorComponent,
|
|
678
|
+
AXSchedulerPickerOccurrenceSelectorComponent,
|
|
679
|
+
], template: "<div class=\"ax-scheduler-picker-yearly-panel\">\n <!-- Interval selector -->\n @if (config().options?.showInterval) {\n <ax-scheduler-picker-interval-selector\n [interval]=\"pattern()?.interval || 1\"\n [config]=\"config()\"\n (intervalChange)=\"onIntervalChange($event)\"\n />\n }\n\n <!-- Month selector (independent of recurrence mode) -->\n @if (config().options?.showMonthSelection !== false) {\n <ax-scheduler-picker-month-selector\n [months]=\"selectedMonths()\"\n (monthsChange)=\"onMonthsChange($event)\"\n />\n }\n\n <!-- Specific Date Mode: Day picker -->\n @if (config().options?.recurrenceMode === 'specificDate') {\n <ax-scheduler-picker-day-selector\n [days]=\"selectedDays()\"\n (daysChange)=\"onDaysChange($event)\"\n />\n }\n\n <!-- Occurrence Mode: Month + Position + Weekday selectors -->\n @if (config().options?.recurrenceMode === 'occurrence') {\n @if (config().options?.showMonthSelection !== false) {\n <ax-scheduler-picker-month-selector\n [months]=\"selectedMonths()\"\n (monthsChange)=\"onMonthsChange($event)\"\n />\n }\n <ax-scheduler-picker-occurrence-selector\n [occurrence]=\"occurrence()\"\n (occurrenceChange)=\"onOccurrenceChange($event)\"\n />\n }\n</div>\n", styles: [".ax-scheduler-picker-yearly-panel{display:flex;flex-direction:column;gap:.5rem}\n"] }]
|
|
680
|
+
}], ctorParameters: () => [], propDecorators: { pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], patternChange: [{ type: i0.Output, args: ["patternChange"] }] } });
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Hourly mode default configuration
|
|
684
|
+
*/
|
|
685
|
+
const AXSchedulerPickerHourlyDefaultConfig = {
|
|
686
|
+
mode: 'hourly',
|
|
687
|
+
showEndConditions: true,
|
|
688
|
+
showExclusions: false,
|
|
689
|
+
showInclusions: false,
|
|
690
|
+
defaultInterval: 1,
|
|
691
|
+
minInterval: 1,
|
|
692
|
+
maxInterval: 23,
|
|
693
|
+
firstDayOfWeek: 0,
|
|
694
|
+
options: {
|
|
695
|
+
showInterval: true,
|
|
696
|
+
},
|
|
697
|
+
};
|
|
698
|
+
/**
|
|
699
|
+
* Daily mode default configuration
|
|
700
|
+
*/
|
|
701
|
+
const AXSchedulerPickerDailyDefaultConfig = {
|
|
702
|
+
mode: 'daily',
|
|
703
|
+
showEndConditions: true,
|
|
704
|
+
showExclusions: false,
|
|
705
|
+
showInclusions: false,
|
|
706
|
+
defaultInterval: 1,
|
|
707
|
+
minInterval: 1,
|
|
708
|
+
maxInterval: 365,
|
|
709
|
+
firstDayOfWeek: 0,
|
|
710
|
+
options: {
|
|
711
|
+
showInterval: true,
|
|
712
|
+
showWeekdaysOnly: true,
|
|
713
|
+
},
|
|
714
|
+
};
|
|
715
|
+
/**
|
|
716
|
+
* Weekly mode default configuration
|
|
717
|
+
*/
|
|
718
|
+
const AXSchedulerPickerWeeklyDefaultConfig = {
|
|
719
|
+
mode: 'weekly',
|
|
720
|
+
showEndConditions: true,
|
|
721
|
+
showExclusions: false,
|
|
722
|
+
showInclusions: false,
|
|
723
|
+
defaultInterval: 1,
|
|
724
|
+
minInterval: 1,
|
|
725
|
+
maxInterval: 52,
|
|
726
|
+
firstDayOfWeek: 0,
|
|
727
|
+
options: {
|
|
728
|
+
showInterval: true,
|
|
729
|
+
showWeekdaySelection: true,
|
|
730
|
+
},
|
|
731
|
+
};
|
|
732
|
+
/**
|
|
733
|
+
* Monthly mode default configuration
|
|
734
|
+
*/
|
|
735
|
+
const AXSchedulerPickerMonthlyDefaultConfig = {
|
|
736
|
+
mode: 'monthly',
|
|
737
|
+
showEndConditions: true,
|
|
738
|
+
showExclusions: false,
|
|
739
|
+
showInclusions: false,
|
|
740
|
+
defaultInterval: 1,
|
|
741
|
+
minInterval: 1,
|
|
742
|
+
maxInterval: 12,
|
|
743
|
+
firstDayOfWeek: 0,
|
|
744
|
+
options: {
|
|
745
|
+
showInterval: true,
|
|
746
|
+
recurrenceMode: 'specificDays',
|
|
747
|
+
},
|
|
748
|
+
};
|
|
749
|
+
/**
|
|
750
|
+
* Yearly mode default configuration
|
|
751
|
+
*/
|
|
752
|
+
const AXSchedulerPickerYearlyDefaultConfig = {
|
|
753
|
+
mode: 'yearly',
|
|
754
|
+
showEndConditions: true,
|
|
755
|
+
showExclusions: false,
|
|
756
|
+
showInclusions: false,
|
|
757
|
+
defaultInterval: 1,
|
|
758
|
+
minInterval: 1,
|
|
759
|
+
maxInterval: 10,
|
|
760
|
+
firstDayOfWeek: 0,
|
|
761
|
+
options: {
|
|
762
|
+
showInterval: true,
|
|
763
|
+
recurrenceMode: 'specificDate',
|
|
764
|
+
},
|
|
765
|
+
};
|
|
766
|
+
/**
|
|
767
|
+
* Injection tokens for each mode configuration
|
|
768
|
+
*/
|
|
769
|
+
const AX_SCHEDULER_PICKER_HOURLY_CONFIG = new InjectionToken('AX_SCHEDULER_PICKER_HOURLY_CONFIG', {
|
|
770
|
+
providedIn: 'root',
|
|
771
|
+
factory: () => AXSchedulerPickerHourlyDefaultConfig,
|
|
772
|
+
});
|
|
773
|
+
const AX_SCHEDULER_PICKER_DAILY_CONFIG = new InjectionToken('AX_SCHEDULER_PICKER_DAILY_CONFIG', {
|
|
774
|
+
providedIn: 'root',
|
|
775
|
+
factory: () => AXSchedulerPickerDailyDefaultConfig,
|
|
776
|
+
});
|
|
777
|
+
const AX_SCHEDULER_PICKER_WEEKLY_CONFIG = new InjectionToken('AX_SCHEDULER_PICKER_WEEKLY_CONFIG', {
|
|
778
|
+
providedIn: 'root',
|
|
779
|
+
factory: () => AXSchedulerPickerWeeklyDefaultConfig,
|
|
780
|
+
});
|
|
781
|
+
const AX_SCHEDULER_PICKER_MONTHLY_CONFIG = new InjectionToken('AX_SCHEDULER_PICKER_MONTHLY_CONFIG', {
|
|
782
|
+
providedIn: 'root',
|
|
783
|
+
factory: () => AXSchedulerPickerMonthlyDefaultConfig,
|
|
784
|
+
});
|
|
785
|
+
const AX_SCHEDULER_PICKER_YEARLY_CONFIG = new InjectionToken('AX_SCHEDULER_PICKER_YEARLY_CONFIG', {
|
|
786
|
+
providedIn: 'root',
|
|
787
|
+
factory: () => AXSchedulerPickerYearlyDefaultConfig,
|
|
788
|
+
});
|
|
789
|
+
/**
|
|
790
|
+
* Helper function to get default config by mode
|
|
791
|
+
*/
|
|
792
|
+
function getDefaultSchedulerPickerConfig(mode) {
|
|
793
|
+
switch (mode) {
|
|
794
|
+
case 'hourly':
|
|
795
|
+
return AXSchedulerPickerHourlyDefaultConfig;
|
|
796
|
+
case 'daily':
|
|
797
|
+
return AXSchedulerPickerDailyDefaultConfig;
|
|
798
|
+
case 'weekly':
|
|
799
|
+
return AXSchedulerPickerWeeklyDefaultConfig;
|
|
800
|
+
case 'monthly':
|
|
801
|
+
return AXSchedulerPickerMonthlyDefaultConfig;
|
|
802
|
+
case 'yearly':
|
|
803
|
+
return AXSchedulerPickerYearlyDefaultConfig;
|
|
804
|
+
default:
|
|
805
|
+
throw new Error(`Unknown mode: ${mode}`);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* Service for scheduler picker utilities
|
|
811
|
+
* Handles conversions, calculations, and validation
|
|
812
|
+
*/
|
|
813
|
+
class AXSchedulerPickerService {
|
|
814
|
+
constructor() {
|
|
815
|
+
this.translationService = inject(AXTranslationService);
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Calculate next N occurrences from pattern
|
|
819
|
+
* Uses lazy-loaded rrule library for complex calculations
|
|
820
|
+
*/
|
|
821
|
+
async calculateOccurrences(pattern, count, startFrom) {
|
|
822
|
+
const { RRule } = await import('rrule');
|
|
823
|
+
const rruleObj = this.toRRuleObject(pattern, RRule);
|
|
824
|
+
if (!rruleObj) {
|
|
825
|
+
return [];
|
|
826
|
+
}
|
|
827
|
+
const start = startFrom || new Date();
|
|
828
|
+
return rruleObj.after(start, true) ? rruleObj.all((date, i) => i < count) : [];
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Convert pattern to cron expression
|
|
832
|
+
* Uses lazy-loaded cron-parser library
|
|
833
|
+
*/
|
|
834
|
+
async toCronExpression(pattern) {
|
|
835
|
+
// Lazy load cron-parser if needed for validation
|
|
836
|
+
const { parseExpression } = await import('cron-parser');
|
|
837
|
+
// Build cron expression based on pattern
|
|
838
|
+
const parts = ['*', '*', '*', '*', '*'];
|
|
839
|
+
switch (pattern.mode) {
|
|
840
|
+
case 'hourly':
|
|
841
|
+
if (pattern.recurrence.byMinute) {
|
|
842
|
+
parts[0] = pattern.recurrence.byMinute.join(',');
|
|
843
|
+
}
|
|
844
|
+
if (pattern.recurrence.byHour) {
|
|
845
|
+
parts[1] = pattern.recurrence.byHour.join(',');
|
|
846
|
+
}
|
|
847
|
+
else {
|
|
848
|
+
parts[1] = `*/${pattern.interval}`;
|
|
849
|
+
}
|
|
850
|
+
break;
|
|
851
|
+
case 'daily':
|
|
852
|
+
parts[2] = `*/${pattern.interval}`;
|
|
853
|
+
break;
|
|
854
|
+
case 'weekly':
|
|
855
|
+
if (pattern.recurrence.byDay) {
|
|
856
|
+
parts[4] = pattern.recurrence.byDay.join(',');
|
|
857
|
+
}
|
|
858
|
+
break;
|
|
859
|
+
case 'monthly':
|
|
860
|
+
if (pattern.recurrence.byDay) {
|
|
861
|
+
parts[2] = pattern.recurrence.byDay.join(',');
|
|
862
|
+
}
|
|
863
|
+
break;
|
|
864
|
+
case 'yearly':
|
|
865
|
+
if (pattern.recurrence.byDay) {
|
|
866
|
+
parts[2] = pattern.recurrence.byDay.join(',');
|
|
867
|
+
}
|
|
868
|
+
if (pattern.recurrence.byMonth) {
|
|
869
|
+
parts[3] = pattern.recurrence.byMonth.join(',');
|
|
870
|
+
}
|
|
871
|
+
break;
|
|
872
|
+
}
|
|
873
|
+
const cronExpr = parts.join(' ');
|
|
874
|
+
// Validate the cron expression
|
|
875
|
+
try {
|
|
876
|
+
parseExpression(cronExpr);
|
|
877
|
+
return cronExpr;
|
|
878
|
+
}
|
|
879
|
+
catch {
|
|
880
|
+
// Return default cron if generation fails
|
|
881
|
+
return '* * * * *';
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Convert cron expression to pattern
|
|
886
|
+
* Parses standard cron format: minute hour day month weekday
|
|
887
|
+
*/
|
|
888
|
+
async fromCronExpression(cron) {
|
|
889
|
+
try {
|
|
890
|
+
const { parseExpression } = await import('cron-parser');
|
|
891
|
+
const parsed = parseExpression(cron);
|
|
892
|
+
const fields = parsed.fields;
|
|
893
|
+
// Analyze cron fields to determine mode
|
|
894
|
+
const minutePattern = this.analyzeCronField(fields.minute);
|
|
895
|
+
const hourPattern = this.analyzeCronField(fields.hour);
|
|
896
|
+
const dayPattern = this.analyzeCronField(fields.dayOfMonth);
|
|
897
|
+
const monthPattern = this.analyzeCronField(fields.month);
|
|
898
|
+
const weekdayPattern = this.analyzeCronField(fields.dayOfWeek);
|
|
899
|
+
// Determine mode based on which fields have intervals/values
|
|
900
|
+
let mode = 'daily';
|
|
901
|
+
let interval = 1;
|
|
902
|
+
const recurrence = {};
|
|
903
|
+
// Hourly mode: */N in hour field or specific hours
|
|
904
|
+
if (hourPattern.isInterval && !dayPattern.hasValues && !monthPattern.hasValues) {
|
|
905
|
+
mode = 'hourly';
|
|
906
|
+
interval = hourPattern.interval || 1;
|
|
907
|
+
if (minutePattern.hasValues) {
|
|
908
|
+
recurrence.byMinute = minutePattern.values;
|
|
909
|
+
}
|
|
910
|
+
if (hourPattern.hasValues) {
|
|
911
|
+
recurrence.byHour = hourPattern.values;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
// Yearly mode: specific months or */N in month field
|
|
915
|
+
else if (monthPattern.hasValues || monthPattern.isInterval) {
|
|
916
|
+
mode = 'yearly';
|
|
917
|
+
interval = monthPattern.interval || 1;
|
|
918
|
+
if (monthPattern.hasValues) {
|
|
919
|
+
recurrence.byMonth = monthPattern.values;
|
|
920
|
+
}
|
|
921
|
+
if (dayPattern.hasValues) {
|
|
922
|
+
recurrence.byDay = dayPattern.values;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
// Monthly mode: */N in day field or specific days
|
|
926
|
+
else if (dayPattern.isInterval || (dayPattern.hasValues && !weekdayPattern.hasValues)) {
|
|
927
|
+
mode = 'monthly';
|
|
928
|
+
interval = dayPattern.interval || 1;
|
|
929
|
+
if (dayPattern.hasValues) {
|
|
930
|
+
recurrence.byDay = dayPattern.values;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
// Weekly mode: specific weekdays
|
|
934
|
+
else if (weekdayPattern.hasValues) {
|
|
935
|
+
mode = 'weekly';
|
|
936
|
+
interval = 1;
|
|
937
|
+
recurrence.byDay = weekdayPattern.values;
|
|
938
|
+
}
|
|
939
|
+
// Daily mode: default fallback
|
|
940
|
+
else {
|
|
941
|
+
mode = 'daily';
|
|
942
|
+
interval = 1;
|
|
943
|
+
}
|
|
944
|
+
return {
|
|
945
|
+
mode,
|
|
946
|
+
interval,
|
|
947
|
+
startCondition: { type: 'now', startDate: new Date() },
|
|
948
|
+
recurrence,
|
|
949
|
+
endCondition: { type: 'never' },
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
catch (error) {
|
|
953
|
+
console.error('[SchedulerPicker] Failed to parse cron expression:', error);
|
|
954
|
+
return null;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Analyze a cron field to extract interval and values
|
|
959
|
+
*/
|
|
960
|
+
analyzeCronField(field) {
|
|
961
|
+
if (!field || field.length === 0) {
|
|
962
|
+
return { hasValues: false, values: [], isInterval: false, interval: null };
|
|
963
|
+
}
|
|
964
|
+
// Check if it's an interval pattern (e.g., */2 produces [0,2,4,6...])
|
|
965
|
+
const isInterval = field.length > 1 && field.length < 60;
|
|
966
|
+
let interval = null;
|
|
967
|
+
if (isInterval && field.length >= 2) {
|
|
968
|
+
// Calculate interval from difference between consecutive values
|
|
969
|
+
interval = field[1] - field[0];
|
|
970
|
+
// Verify it's consistent
|
|
971
|
+
const isConsistent = field.every((val, idx) => idx === 0 || val - field[idx - 1] === interval);
|
|
972
|
+
if (!isConsistent) {
|
|
973
|
+
interval = null;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
return {
|
|
977
|
+
hasValues: field.length > 0 && field.length < 60, // Exclude wildcard (all values)
|
|
978
|
+
values: field,
|
|
979
|
+
isInterval: interval !== null,
|
|
980
|
+
interval,
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Convert pattern to RRule string (iCalendar format)
|
|
985
|
+
*/
|
|
986
|
+
async toRRule(pattern) {
|
|
987
|
+
const { RRule } = await import('rrule');
|
|
988
|
+
const rruleObj = this.toRRuleObject(pattern, RRule);
|
|
989
|
+
return rruleObj ? rruleObj.toString() : '';
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Convert RRule string to pattern
|
|
993
|
+
*/
|
|
994
|
+
async fromRRule(rruleStr) {
|
|
995
|
+
try {
|
|
996
|
+
const { RRule, rrulestr } = await import('rrule');
|
|
997
|
+
const rrule = rrulestr(rruleStr);
|
|
998
|
+
// Convert RRule options back to our pattern
|
|
999
|
+
const options = rrule.origOptions;
|
|
1000
|
+
let mode = 'daily';
|
|
1001
|
+
if (options.freq === RRule.HOURLY)
|
|
1002
|
+
mode = 'hourly';
|
|
1003
|
+
else if (options.freq === RRule.DAILY)
|
|
1004
|
+
mode = 'daily';
|
|
1005
|
+
else if (options.freq === RRule.WEEKLY)
|
|
1006
|
+
mode = 'weekly';
|
|
1007
|
+
else if (options.freq === RRule.MONTHLY)
|
|
1008
|
+
mode = 'monthly';
|
|
1009
|
+
else if (options.freq === RRule.YEARLY)
|
|
1010
|
+
mode = 'yearly';
|
|
1011
|
+
return {
|
|
1012
|
+
mode,
|
|
1013
|
+
interval: options.interval || 1,
|
|
1014
|
+
startCondition: { type: 'now', startDate: new Date() },
|
|
1015
|
+
recurrence: {
|
|
1016
|
+
byDay: options.byweekday,
|
|
1017
|
+
byMonth: options.bymonth,
|
|
1018
|
+
byHour: options.byhour,
|
|
1019
|
+
byMinute: options.byminute,
|
|
1020
|
+
},
|
|
1021
|
+
endCondition: {
|
|
1022
|
+
type: options.count ? 'afterOccurrences' : options.until ? 'byDate' : 'never',
|
|
1023
|
+
occurrences: options.count,
|
|
1024
|
+
endDate: options.until,
|
|
1025
|
+
},
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
catch {
|
|
1029
|
+
return null;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
/**
|
|
1033
|
+
* Generate human-readable description
|
|
1034
|
+
* Uses lazy-loaded cronstrue library for i18n
|
|
1035
|
+
*/
|
|
1036
|
+
async toNaturalLanguage(pattern, locale) {
|
|
1037
|
+
const lang = locale || 'en-US';
|
|
1038
|
+
// Build natural language string based on pattern
|
|
1039
|
+
const parts = [];
|
|
1040
|
+
// Interval part
|
|
1041
|
+
const intervalKey = `@acorex:schedulerPicker.naturalLanguage.every${pattern.mode.charAt(0).toUpperCase() + pattern.mode.slice(1)}`;
|
|
1042
|
+
const intervalText = await this.translationService.translateAsync(intervalKey, {
|
|
1043
|
+
params: { count: pattern.interval },
|
|
1044
|
+
});
|
|
1045
|
+
parts.push(intervalText);
|
|
1046
|
+
// Recurrence part
|
|
1047
|
+
if (pattern.mode === 'weekly' && pattern.recurrence.byDay) {
|
|
1048
|
+
const days = await this.getDayNames(pattern.recurrence.byDay);
|
|
1049
|
+
parts.push(await this.translationService.translateAsync('@acorex:schedulerPicker.naturalLanguage.onDays', {
|
|
1050
|
+
params: { days: days.join(', ') },
|
|
1051
|
+
}));
|
|
1052
|
+
}
|
|
1053
|
+
if (pattern.mode === 'monthly') {
|
|
1054
|
+
if (pattern.recurrence.byOccurrence && pattern.recurrence.byOccurrence.length > 0) {
|
|
1055
|
+
// e.g., "on the 2nd Monday"
|
|
1056
|
+
const occ = pattern.recurrence.byOccurrence[0];
|
|
1057
|
+
const positionText = await this.getOccurrencePositionText(occ.position);
|
|
1058
|
+
const dayName = await this.translationService.translateAsync(`@acorex:schedulerPicker.days.${getDayTranslationKey(occ.dayOfWeek)}`);
|
|
1059
|
+
const onThe = await this.translationService.translateAsync('@acorex:schedulerPicker.naturalLanguage.onThe');
|
|
1060
|
+
parts.push(`${onThe} ${positionText} ${dayName}`);
|
|
1061
|
+
}
|
|
1062
|
+
else if (pattern.recurrence.byDay && pattern.recurrence.byDay.length > 0) {
|
|
1063
|
+
// e.g., "on day 15" or "on days 1, 15, 30"
|
|
1064
|
+
const dayList = pattern.recurrence.byDay.join(', ');
|
|
1065
|
+
const onDayKey = pattern.recurrence.byDay.length > 1 ? '@acorex:schedulerPicker.naturalLanguage.onDaysPlural' : '@acorex:schedulerPicker.naturalLanguage.onDay';
|
|
1066
|
+
const onDay = await this.translationService.translateAsync(onDayKey);
|
|
1067
|
+
parts.push(`${onDay} ${dayList}`);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
if (pattern.mode === 'yearly') {
|
|
1071
|
+
const yearlyParts = [];
|
|
1072
|
+
// Month part
|
|
1073
|
+
if (pattern.recurrence.byMonth && pattern.recurrence.byMonth.length > 0) {
|
|
1074
|
+
const months = await this.getMonthNames(pattern.recurrence.byMonth);
|
|
1075
|
+
const inWord = await this.translationService.translateAsync('@acorex:schedulerPicker.naturalLanguage.in');
|
|
1076
|
+
yearlyParts.push(`${inWord} ${months.join(', ')}`);
|
|
1077
|
+
}
|
|
1078
|
+
// Day/Occurrence part
|
|
1079
|
+
if (pattern.recurrence.byOccurrence && pattern.recurrence.byOccurrence.length > 0) {
|
|
1080
|
+
// e.g., "on the 2nd Monday"
|
|
1081
|
+
const occ = pattern.recurrence.byOccurrence[0];
|
|
1082
|
+
const positionText = await this.getOccurrencePositionText(occ.position);
|
|
1083
|
+
const dayName = await this.translationService.translateAsync(`@acorex:schedulerPicker.days.${getDayTranslationKey(occ.dayOfWeek)}`);
|
|
1084
|
+
const onThe = await this.translationService.translateAsync('@acorex:schedulerPicker.naturalLanguage.onThe');
|
|
1085
|
+
yearlyParts.push(`${onThe} ${positionText} ${dayName}`);
|
|
1086
|
+
}
|
|
1087
|
+
else if (pattern.recurrence.byDay && pattern.recurrence.byDay.length > 0) {
|
|
1088
|
+
// e.g., "on day 15" or "on days 1, 15, 30"
|
|
1089
|
+
const dayList = pattern.recurrence.byDay.join(', ');
|
|
1090
|
+
const onDayKey = pattern.recurrence.byDay.length > 1 ? '@acorex:schedulerPicker.naturalLanguage.onDaysPlural' : '@acorex:schedulerPicker.naturalLanguage.onDay';
|
|
1091
|
+
const onDay = await this.translationService.translateAsync(onDayKey);
|
|
1092
|
+
yearlyParts.push(`${onDay} ${dayList}`);
|
|
1093
|
+
}
|
|
1094
|
+
if (yearlyParts.length > 0) {
|
|
1095
|
+
parts.push(yearlyParts.join(' '));
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
// Start condition part
|
|
1099
|
+
if (pattern.startCondition.type === 'byDate' && pattern.startCondition.startDate) {
|
|
1100
|
+
parts.push(await this.translationService.translateAsync('@acorex:schedulerPicker.naturalLanguage.startingFrom', {
|
|
1101
|
+
params: { date: pattern.startCondition.startDate.toLocaleDateString(lang) },
|
|
1102
|
+
}));
|
|
1103
|
+
}
|
|
1104
|
+
// End condition part
|
|
1105
|
+
if (pattern.endCondition.type === 'afterOccurrences') {
|
|
1106
|
+
parts.push(await this.translationService.translateAsync('@acorex:schedulerPicker.naturalLanguage.forOccurrences', {
|
|
1107
|
+
params: { count: pattern.endCondition.occurrences },
|
|
1108
|
+
}));
|
|
1109
|
+
}
|
|
1110
|
+
else if (pattern.endCondition.type === 'byDate' && pattern.endCondition.endDate) {
|
|
1111
|
+
parts.push(await this.translationService.translateAsync('@acorex:schedulerPicker.naturalLanguage.until', {
|
|
1112
|
+
params: { date: pattern.endCondition.endDate.toLocaleDateString(lang) },
|
|
1113
|
+
}));
|
|
1114
|
+
}
|
|
1115
|
+
return parts.join(' ');
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Validate pattern against config and rules
|
|
1119
|
+
*/
|
|
1120
|
+
async validatePattern(pattern, settings) {
|
|
1121
|
+
const errors = [];
|
|
1122
|
+
// Required fields
|
|
1123
|
+
if (!pattern.mode) {
|
|
1124
|
+
errors.push({
|
|
1125
|
+
field: 'mode',
|
|
1126
|
+
code: 'required',
|
|
1127
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.modeRequired'),
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
if (!pattern.interval || pattern.interval < 1) {
|
|
1131
|
+
errors.push({
|
|
1132
|
+
field: 'interval',
|
|
1133
|
+
code: 'required',
|
|
1134
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.intervalRequired'),
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
// Interval constraints
|
|
1138
|
+
if (settings.minInterval && pattern.interval < settings.minInterval) {
|
|
1139
|
+
errors.push({
|
|
1140
|
+
field: 'interval',
|
|
1141
|
+
code: 'outOfRange',
|
|
1142
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.intervalTooSmall', {
|
|
1143
|
+
params: { min: settings.minInterval },
|
|
1144
|
+
}),
|
|
1145
|
+
params: { min: settings.minInterval },
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
if (settings.maxInterval && pattern.interval > settings.maxInterval) {
|
|
1149
|
+
errors.push({
|
|
1150
|
+
field: 'interval',
|
|
1151
|
+
code: 'outOfRange',
|
|
1152
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.intervalTooLarge', {
|
|
1153
|
+
params: { max: settings.maxInterval },
|
|
1154
|
+
}),
|
|
1155
|
+
params: { max: settings.maxInterval },
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
// Mode-specific recurrence validation
|
|
1159
|
+
if (pattern.mode === 'monthly') {
|
|
1160
|
+
const hasByDay = pattern.recurrence.byDay && pattern.recurrence.byDay.length > 0;
|
|
1161
|
+
const hasByOccurrence = pattern.recurrence.byOccurrence && pattern.recurrence.byOccurrence.length > 0;
|
|
1162
|
+
// Conflict: Cannot have both day of month and occurrence pattern
|
|
1163
|
+
if (hasByDay && hasByOccurrence) {
|
|
1164
|
+
errors.push({
|
|
1165
|
+
field: 'recurrence',
|
|
1166
|
+
code: 'conflict',
|
|
1167
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.cannotCombineDayAndOccurrence'),
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
// Yearly mode: Validate occurrence conflicts
|
|
1172
|
+
if (pattern.mode === 'yearly') {
|
|
1173
|
+
const hasByDay = pattern.recurrence.byDay && pattern.recurrence.byDay.length > 0;
|
|
1174
|
+
const hasByOccurrence = pattern.recurrence.byOccurrence && pattern.recurrence.byOccurrence.length > 0;
|
|
1175
|
+
if (hasByDay && hasByOccurrence) {
|
|
1176
|
+
errors.push({
|
|
1177
|
+
field: 'recurrence',
|
|
1178
|
+
code: 'conflict',
|
|
1179
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.cannotCombineDayAndOccurrence'),
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
// Validate exclusions and inclusions size for performance
|
|
1184
|
+
const maxDateArraySize = 1000; // Prevent excessive memory usage
|
|
1185
|
+
if (pattern.exclusions && pattern.exclusions.length > maxDateArraySize) {
|
|
1186
|
+
errors.push({
|
|
1187
|
+
field: 'exclusions',
|
|
1188
|
+
code: 'outOfRange',
|
|
1189
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.tooManyExclusions', {
|
|
1190
|
+
params: { max: maxDateArraySize },
|
|
1191
|
+
}),
|
|
1192
|
+
params: { max: maxDateArraySize },
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
if (pattern.inclusions && pattern.inclusions.length > maxDateArraySize) {
|
|
1196
|
+
errors.push({
|
|
1197
|
+
field: 'inclusions',
|
|
1198
|
+
code: 'outOfRange',
|
|
1199
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.tooManyInclusions', {
|
|
1200
|
+
params: { max: maxDateArraySize },
|
|
1201
|
+
}),
|
|
1202
|
+
params: { max: maxDateArraySize },
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
// End date validation
|
|
1206
|
+
if (pattern.endCondition.type === 'byDate' && pattern.endCondition.endDate) {
|
|
1207
|
+
if (pattern.endCondition.endDate < new Date()) {
|
|
1208
|
+
errors.push({
|
|
1209
|
+
field: 'endCondition.endDate',
|
|
1210
|
+
code: 'pastDate',
|
|
1211
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.endDateInPast'),
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
if (settings.maxDate && pattern.endCondition.endDate > settings.maxDate) {
|
|
1215
|
+
errors.push({
|
|
1216
|
+
field: 'endCondition.endDate',
|
|
1217
|
+
code: 'outOfRange',
|
|
1218
|
+
message: await this.translationService.translateAsync('@acorex:schedulerPicker.validation.endDateTooFar', {
|
|
1219
|
+
params: { maxDate: settings.maxDate.toLocaleDateString() },
|
|
1220
|
+
}),
|
|
1221
|
+
params: { maxDate: settings.maxDate },
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
// Custom validators
|
|
1226
|
+
if (settings.customValidators) {
|
|
1227
|
+
for (const validator of settings.customValidators) {
|
|
1228
|
+
const error = validator(pattern, settings);
|
|
1229
|
+
if (error) {
|
|
1230
|
+
errors.push(error);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
return errors;
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Check if a specific date matches the pattern
|
|
1238
|
+
*/
|
|
1239
|
+
async isDateMatch(pattern, date) {
|
|
1240
|
+
const { RRule } = await import('rrule');
|
|
1241
|
+
const rruleObj = this.toRRuleObject(pattern, RRule);
|
|
1242
|
+
if (!rruleObj) {
|
|
1243
|
+
return false;
|
|
1244
|
+
}
|
|
1245
|
+
// Check if date is in the generated occurrences
|
|
1246
|
+
const occurrences = rruleObj.between(new Date(date.getTime() - 1000), new Date(date.getTime() + 1000), true);
|
|
1247
|
+
return occurrences.length > 0;
|
|
1248
|
+
}
|
|
1249
|
+
/**
|
|
1250
|
+
* Get next occurrence from a specific date
|
|
1251
|
+
*/
|
|
1252
|
+
async getNextOccurrence(pattern, from) {
|
|
1253
|
+
const { RRule } = await import('rrule');
|
|
1254
|
+
const rruleObj = this.toRRuleObject(pattern, RRule);
|
|
1255
|
+
if (!rruleObj) {
|
|
1256
|
+
return null;
|
|
1257
|
+
}
|
|
1258
|
+
return rruleObj.after(from, false) || null;
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Convert pattern to RRule object
|
|
1262
|
+
* Helper method for RRule operations
|
|
1263
|
+
*/
|
|
1264
|
+
toRRuleObject(pattern, RRule) {
|
|
1265
|
+
const options = {
|
|
1266
|
+
interval: pattern.interval,
|
|
1267
|
+
};
|
|
1268
|
+
// Set frequency
|
|
1269
|
+
switch (pattern.mode) {
|
|
1270
|
+
case 'hourly':
|
|
1271
|
+
options.freq = RRule.HOURLY;
|
|
1272
|
+
break;
|
|
1273
|
+
case 'daily':
|
|
1274
|
+
options.freq = RRule.DAILY;
|
|
1275
|
+
break;
|
|
1276
|
+
case 'weekly':
|
|
1277
|
+
options.freq = RRule.WEEKLY;
|
|
1278
|
+
break;
|
|
1279
|
+
case 'monthly':
|
|
1280
|
+
options.freq = RRule.MONTHLY;
|
|
1281
|
+
break;
|
|
1282
|
+
case 'yearly':
|
|
1283
|
+
options.freq = RRule.YEARLY;
|
|
1284
|
+
break;
|
|
1285
|
+
}
|
|
1286
|
+
// Set recurrence rules
|
|
1287
|
+
if (pattern.recurrence.byDay) {
|
|
1288
|
+
if (pattern.mode === 'weekly') {
|
|
1289
|
+
options.byweekday = pattern.recurrence.byDay;
|
|
1290
|
+
}
|
|
1291
|
+
else if (pattern.mode === 'monthly' || pattern.mode === 'yearly') {
|
|
1292
|
+
options.bymonthday = pattern.recurrence.byDay;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
if (pattern.recurrence.byMonth) {
|
|
1296
|
+
options.bymonth = pattern.recurrence.byMonth;
|
|
1297
|
+
}
|
|
1298
|
+
if (pattern.recurrence.byHour) {
|
|
1299
|
+
options.byhour = pattern.recurrence.byHour;
|
|
1300
|
+
}
|
|
1301
|
+
if (pattern.recurrence.byMinute) {
|
|
1302
|
+
options.byminute = pattern.recurrence.byMinute;
|
|
1303
|
+
}
|
|
1304
|
+
// Set occurrence rules
|
|
1305
|
+
if (pattern.recurrence.byOccurrence) {
|
|
1306
|
+
// RRule format for "first Monday" etc.
|
|
1307
|
+
options.byweekday = pattern.recurrence.byOccurrence.map((occ) => {
|
|
1308
|
+
return RRule[this.getDayName(occ.dayOfWeek)].nth(occ.position);
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
// Set end condition
|
|
1312
|
+
switch (pattern.endCondition.type) {
|
|
1313
|
+
case 'afterOccurrences':
|
|
1314
|
+
options.count = pattern.endCondition.occurrences;
|
|
1315
|
+
break;
|
|
1316
|
+
case 'byDate':
|
|
1317
|
+
options.until = pattern.endCondition.endDate;
|
|
1318
|
+
break;
|
|
1319
|
+
}
|
|
1320
|
+
try {
|
|
1321
|
+
return new RRule(options);
|
|
1322
|
+
}
|
|
1323
|
+
catch {
|
|
1324
|
+
return null;
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Get day name constant for RRule
|
|
1329
|
+
*/
|
|
1330
|
+
getDayName(dayIndex) {
|
|
1331
|
+
return getRRuleDayKey(dayIndex);
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Get localized day names
|
|
1335
|
+
*/
|
|
1336
|
+
async getDayNames(dayIndices) {
|
|
1337
|
+
return Promise.all(dayIndices.map((index) => this.translationService.translateAsync(`@acorex:schedulerPicker.days.${getDayTranslationKey(index)}`)));
|
|
1338
|
+
}
|
|
1339
|
+
/**
|
|
1340
|
+
* Get localized month names
|
|
1341
|
+
*/
|
|
1342
|
+
async getMonthNames(monthIndices) {
|
|
1343
|
+
const monthKeys = [
|
|
1344
|
+
'january',
|
|
1345
|
+
'february',
|
|
1346
|
+
'march',
|
|
1347
|
+
'april',
|
|
1348
|
+
'may',
|
|
1349
|
+
'june',
|
|
1350
|
+
'july',
|
|
1351
|
+
'august',
|
|
1352
|
+
'september',
|
|
1353
|
+
'october',
|
|
1354
|
+
'november',
|
|
1355
|
+
'december',
|
|
1356
|
+
];
|
|
1357
|
+
return Promise.all(monthIndices.map((index) => this.translationService.translateAsync(`@acorex:schedulerPicker.months.${monthKeys[index]}`)));
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Get text for occurrence position
|
|
1361
|
+
*/
|
|
1362
|
+
async getOccurrencePositionText(position) {
|
|
1363
|
+
const ordinalKeys = {
|
|
1364
|
+
1: '1st',
|
|
1365
|
+
2: '2nd',
|
|
1366
|
+
3: '3rd',
|
|
1367
|
+
4: '4th',
|
|
1368
|
+
'-1': 'last',
|
|
1369
|
+
};
|
|
1370
|
+
const key = ordinalKeys[position] || '1st';
|
|
1371
|
+
return this.translationService.translateAsync(`@acorex:schedulerPicker.ordinals.${key}`);
|
|
1372
|
+
}
|
|
1373
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1374
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerService, providedIn: 'root' }); }
|
|
1375
|
+
}
|
|
1376
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerService, decorators: [{
|
|
1377
|
+
type: Injectable,
|
|
1378
|
+
args: [{
|
|
1379
|
+
providedIn: 'root',
|
|
1380
|
+
}]
|
|
1381
|
+
}] });
|
|
1382
|
+
|
|
1383
|
+
class AXSchedulerPickerStartConditionSelectorComponent {
|
|
1384
|
+
constructor() {
|
|
1385
|
+
this.startCondition = input(...(ngDevMode ? [undefined, { debugName: "startCondition" }] : []));
|
|
1386
|
+
this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
1387
|
+
this.startConditionChange = output();
|
|
1388
|
+
this.selectedType = signal('now', ...(ngDevMode ? [{ debugName: "selectedType" }] : []));
|
|
1389
|
+
this.startDate = signal(null, ...(ngDevMode ? [{ debugName: "startDate" }] : []));
|
|
1390
|
+
this.startTypeItems = [
|
|
1391
|
+
{ id: 'now', text: '@acorex:schedulerPicker.startCondition.now' },
|
|
1392
|
+
{ id: 'byDate', text: '@acorex:schedulerPicker.startCondition.byDate' },
|
|
1393
|
+
];
|
|
1394
|
+
// Initialize from input
|
|
1395
|
+
effect(() => {
|
|
1396
|
+
const condition = this.startCondition();
|
|
1397
|
+
if (condition) {
|
|
1398
|
+
this.selectedType.set(condition.type);
|
|
1399
|
+
this.startDate.set(condition.startDate);
|
|
1400
|
+
}
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
onTypeChange(event) {
|
|
1404
|
+
this.selectedType.set(event.value);
|
|
1405
|
+
this.emitChange();
|
|
1406
|
+
}
|
|
1407
|
+
onDateChange(value) {
|
|
1408
|
+
this.startDate.set(value);
|
|
1409
|
+
this.emitChange();
|
|
1410
|
+
}
|
|
1411
|
+
emitChange() {
|
|
1412
|
+
const type = this.selectedType();
|
|
1413
|
+
const condition = {
|
|
1414
|
+
type,
|
|
1415
|
+
startDate: type === 'byDate' ? this.startDate() || new Date() : new Date(),
|
|
1416
|
+
};
|
|
1417
|
+
this.startConditionChange.emit(condition);
|
|
1418
|
+
}
|
|
1419
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerStartConditionSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1420
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerStartConditionSelectorComponent, isStandalone: true, selector: "ax-scheduler-picker-start-condition-selector", inputs: { startCondition: { classPropertyName: "startCondition", publicName: "startCondition", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { startConditionChange: "startConditionChange" }, ngImport: i0, template: "<div class=\"ax-scheduler-picker-start-condition-selector\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.startCondition' | translate | async }}\n </label>\n\n <ax-selection-list\n [items]=\"startTypeItems\"\n [multiple]=\"false\"\n [showControl]=\"true\"\n [look]=\"'solid'\"\n [direction]=\"'horizontal'\"\n [value]=\"selectedType()\"\n (onValueChanged)=\"onTypeChange($event)\"\n />\n\n @if (selectedType() === 'byDate') {\n <div class=\"ax-scheduler-picker-input-group\">\n <label class=\"ax-scheduler-picker-sublabel\">\n {{ '@acorex:schedulerPicker.labels.startDate' | translate | async }}\n </label>\n <ax-datetime-box [value]=\"startDate()\" [picker]=\"'datetime'\" (valueChange)=\"onDateChange($event)\" />\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-start-condition-selector{display:flex;flex-direction:column;gap:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: AXSelectionListModule }, { kind: "component", type: i1.AXSelectionListComponent, selector: "ax-selection-list", inputs: ["id", "name", "disabled", "readonly", "tabIndex", "size", "value", "valueField", "textField", "disabledField", "readonlyField", "multiple", "direction", "customTemplate", "showControl", "items", "look"], outputs: ["onValueChanged", "onBlur", "onFocus"] }, { kind: "component", type: AXDateTimeBoxComponent, selector: "ax-datetime-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "depth", "id", "type", "look", "holidayDates", "allowTyping", "picker", "calendar", "weekend", "weekdays", "format"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "onOpened", "onClosed", "readonlyChange", "disabledChange", "formatChange"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
1421
|
+
}
|
|
1422
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerStartConditionSelectorComponent, decorators: [{
|
|
1423
|
+
type: Component,
|
|
1424
|
+
args: [{ selector: 'ax-scheduler-picker-start-condition-selector', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [FormsModule, AXSelectionListModule, AXDateTimeBoxComponent, AXTranslatorPipe, AsyncPipe], template: "<div class=\"ax-scheduler-picker-start-condition-selector\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.startCondition' | translate | async }}\n </label>\n\n <ax-selection-list\n [items]=\"startTypeItems\"\n [multiple]=\"false\"\n [showControl]=\"true\"\n [look]=\"'solid'\"\n [direction]=\"'horizontal'\"\n [value]=\"selectedType()\"\n (onValueChanged)=\"onTypeChange($event)\"\n />\n\n @if (selectedType() === 'byDate') {\n <div class=\"ax-scheduler-picker-input-group\">\n <label class=\"ax-scheduler-picker-sublabel\">\n {{ '@acorex:schedulerPicker.labels.startDate' | translate | async }}\n </label>\n <ax-datetime-box [value]=\"startDate()\" [picker]=\"'datetime'\" (valueChange)=\"onDateChange($event)\" />\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-start-condition-selector{display:flex;flex-direction:column;gap:.5rem}\n"] }]
|
|
1425
|
+
}], ctorParameters: () => [], propDecorators: { startCondition: [{ type: i0.Input, args: [{ isSignal: true, alias: "startCondition", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], startConditionChange: [{ type: i0.Output, args: ["startConditionChange"] }] } });
|
|
1426
|
+
|
|
1427
|
+
class AXSchedulerPickerEndConditionSelectorComponent {
|
|
1428
|
+
constructor() {
|
|
1429
|
+
this.endCondition = input(...(ngDevMode ? [undefined, { debugName: "endCondition" }] : []));
|
|
1430
|
+
this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
1431
|
+
this.endConditionChange = output();
|
|
1432
|
+
this.selectedType = signal('never', ...(ngDevMode ? [{ debugName: "selectedType" }] : []));
|
|
1433
|
+
this.occurrences = signal(AX_SCHEDULER_PICKER_DEFAULT_OCCURRENCES, ...(ngDevMode ? [{ debugName: "occurrences" }] : []));
|
|
1434
|
+
this.endDate = signal(null, ...(ngDevMode ? [{ debugName: "endDate" }] : []));
|
|
1435
|
+
this.endTypeItems = [
|
|
1436
|
+
{ id: 'never', text: '@acorex:schedulerPicker.endCondition.never' },
|
|
1437
|
+
{ id: 'afterOccurrences', text: '@acorex:schedulerPicker.endCondition.afterOccurrences' },
|
|
1438
|
+
{ id: 'byDate', text: '@acorex:schedulerPicker.endCondition.byDate' },
|
|
1439
|
+
];
|
|
1440
|
+
// Sync input with internal state
|
|
1441
|
+
effect(() => {
|
|
1442
|
+
const condition = this.endCondition();
|
|
1443
|
+
if (condition) {
|
|
1444
|
+
this.selectedType.set(condition.type);
|
|
1445
|
+
if (condition.type === 'afterOccurrences' && condition.occurrences) {
|
|
1446
|
+
this.occurrences.set(condition.occurrences);
|
|
1447
|
+
}
|
|
1448
|
+
if (condition.type === 'byDate' && condition.endDate) {
|
|
1449
|
+
this.endDate.set(condition.endDate);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
onTypeChange(event) {
|
|
1455
|
+
this.selectedType.set(event.value);
|
|
1456
|
+
this.emitChange();
|
|
1457
|
+
}
|
|
1458
|
+
onOccurrencesChange(value) {
|
|
1459
|
+
this.occurrences.set(value);
|
|
1460
|
+
this.emitChange();
|
|
1461
|
+
}
|
|
1462
|
+
onDateChange(value) {
|
|
1463
|
+
this.endDate.set(value);
|
|
1464
|
+
this.emitChange();
|
|
1465
|
+
}
|
|
1466
|
+
emitChange() {
|
|
1467
|
+
const type = this.selectedType();
|
|
1468
|
+
let condition;
|
|
1469
|
+
switch (type) {
|
|
1470
|
+
case 'afterOccurrences':
|
|
1471
|
+
condition = { type: 'afterOccurrences', occurrences: this.occurrences() };
|
|
1472
|
+
break;
|
|
1473
|
+
case 'byDate':
|
|
1474
|
+
condition = { type: 'byDate', endDate: this.endDate() || new Date() };
|
|
1475
|
+
break;
|
|
1476
|
+
default:
|
|
1477
|
+
condition = { type: 'never' };
|
|
1478
|
+
}
|
|
1479
|
+
this.endConditionChange.emit(condition);
|
|
1480
|
+
}
|
|
1481
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerEndConditionSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1482
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerEndConditionSelectorComponent, isStandalone: true, selector: "ax-scheduler-picker-end-condition-selector", inputs: { endCondition: { classPropertyName: "endCondition", publicName: "endCondition", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { endConditionChange: "endConditionChange" }, ngImport: i0, template: "<div class=\"ax-scheduler-picker-end-condition-selector\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.endCondition' | translate | async }}\n </label>\n\n <ax-selection-list\n [items]=\"endTypeItems\"\n [multiple]=\"false\"\n [showControl]=\"true\"\n [look]=\"'solid'\"\n [direction]=\"'horizontal'\"\n [value]=\"selectedType()\"\n (onValueChanged)=\"onTypeChange($event)\"\n />\n\n @if (selectedType() === 'afterOccurrences') {\n <div class=\"ax-scheduler-picker-input-group\">\n <label class=\"ax-scheduler-picker-sublabel\">\n {{ '@acorex:schedulerPicker.labels.numberOfOccurrences' | translate | async }}\n </label>\n <ax-number-box [value]=\"occurrences()\" (valueChange)=\"onOccurrencesChange($event)\" />\n </div>\n }\n\n @if (selectedType() === 'byDate') {\n <div class=\"ax-scheduler-picker-input-group\">\n <label class=\"ax-scheduler-picker-sublabel\">\n {{ '@acorex:schedulerPicker.labels.endDate' | translate | async }}\n </label>\n <ax-datetime-box [value]=\"endDate()\" mode=\"date\" (valueChange)=\"onDateChange($event)\" />\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-end-condition-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-input-group{display:flex;flex-direction:column;gap:.375rem;padding-left:.5rem}.ax-scheduler-picker-label,.ax-scheduler-picker-sublabel{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}ax-selection-list{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: AXSelectionListModule }, { kind: "component", type: i1.AXSelectionListComponent, selector: "ax-selection-list", inputs: ["id", "name", "disabled", "readonly", "tabIndex", "size", "value", "valueField", "textField", "disabledField", "readonlyField", "multiple", "direction", "customTemplate", "showControl", "items", "look"], outputs: ["onValueChanged", "onBlur", "onFocus"] }, { kind: "component", type: AXNumberBoxComponent, selector: "ax-number-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "minValue", "maxValue", "showSpinButtons", "thousandsSeparator", "decimals", "changeOnScroll", "step"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "thousandsSeparatorChange"] }, { kind: "component", type: AXDateTimeBoxComponent, selector: "ax-datetime-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "depth", "id", "type", "look", "holidayDates", "allowTyping", "picker", "calendar", "weekend", "weekdays", "format"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "onOpened", "onClosed", "readonlyChange", "disabledChange", "formatChange"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
1483
|
+
}
|
|
1484
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerEndConditionSelectorComponent, decorators: [{
|
|
1485
|
+
type: Component,
|
|
1486
|
+
args: [{ selector: 'ax-scheduler-picker-end-condition-selector', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
1487
|
+
FormsModule,
|
|
1488
|
+
AXSelectionListModule,
|
|
1489
|
+
AXNumberBoxComponent,
|
|
1490
|
+
AXDateTimeBoxComponent,
|
|
1491
|
+
AXTranslatorPipe,
|
|
1492
|
+
AsyncPipe,
|
|
1493
|
+
], template: "<div class=\"ax-scheduler-picker-end-condition-selector\">\n <label class=\"ax-scheduler-picker-label\">\n {{ '@acorex:schedulerPicker.labels.endCondition' | translate | async }}\n </label>\n\n <ax-selection-list\n [items]=\"endTypeItems\"\n [multiple]=\"false\"\n [showControl]=\"true\"\n [look]=\"'solid'\"\n [direction]=\"'horizontal'\"\n [value]=\"selectedType()\"\n (onValueChanged)=\"onTypeChange($event)\"\n />\n\n @if (selectedType() === 'afterOccurrences') {\n <div class=\"ax-scheduler-picker-input-group\">\n <label class=\"ax-scheduler-picker-sublabel\">\n {{ '@acorex:schedulerPicker.labels.numberOfOccurrences' | translate | async }}\n </label>\n <ax-number-box [value]=\"occurrences()\" (valueChange)=\"onOccurrencesChange($event)\" />\n </div>\n }\n\n @if (selectedType() === 'byDate') {\n <div class=\"ax-scheduler-picker-input-group\">\n <label class=\"ax-scheduler-picker-sublabel\">\n {{ '@acorex:schedulerPicker.labels.endDate' | translate | async }}\n </label>\n <ax-datetime-box [value]=\"endDate()\" mode=\"date\" (valueChange)=\"onDateChange($event)\" />\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-end-condition-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-input-group{display:flex;flex-direction:column;gap:.375rem;padding-left:.5rem}.ax-scheduler-picker-label,.ax-scheduler-picker-sublabel{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}ax-selection-list{width:100%}\n"] }]
|
|
1494
|
+
}], ctorParameters: () => [], propDecorators: { endCondition: [{ type: i0.Input, args: [{ isSignal: true, alias: "endCondition", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], endConditionChange: [{ type: i0.Output, args: ["endConditionChange"] }] } });
|
|
1495
|
+
|
|
1496
|
+
class AXSchedulerPickerExclusionManagerComponent {
|
|
1497
|
+
constructor() {
|
|
1498
|
+
this.exclusions = input(...(ngDevMode ? [undefined, { debugName: "exclusions" }] : []));
|
|
1499
|
+
this.config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : []));
|
|
1500
|
+
this.exclusionsChange = output();
|
|
1501
|
+
this.newExclusionDate = signal(null, ...(ngDevMode ? [{ debugName: "newExclusionDate" }] : []));
|
|
1502
|
+
this.exclusionList = signal([], ...(ngDevMode ? [{ debugName: "exclusionList" }] : []));
|
|
1503
|
+
// Sync input with internal list
|
|
1504
|
+
effect(() => {
|
|
1505
|
+
const exclusions = this.exclusions();
|
|
1506
|
+
this.exclusionList.set(exclusions || []);
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
addExclusion() {
|
|
1510
|
+
const date = this.newExclusionDate();
|
|
1511
|
+
if (date) {
|
|
1512
|
+
// Normalize date to midnight
|
|
1513
|
+
const normalized = normalizeDate(date);
|
|
1514
|
+
// Check for duplicates
|
|
1515
|
+
if (!dateExistsInArray(normalized, this.exclusionList())) {
|
|
1516
|
+
const updated = [...this.exclusionList(), normalized];
|
|
1517
|
+
this.exclusionList.set(updated);
|
|
1518
|
+
this.exclusionsChange.emit(updated);
|
|
1519
|
+
}
|
|
1520
|
+
this.newExclusionDate.set(null);
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
removeExclusion(date) {
|
|
1524
|
+
const normalized = normalizeDate(date);
|
|
1525
|
+
const updated = this.exclusionList().filter((d) => normalizeDate(d).getTime() !== normalized.getTime());
|
|
1526
|
+
this.exclusionList.set(updated);
|
|
1527
|
+
this.exclusionsChange.emit(updated);
|
|
1528
|
+
}
|
|
1529
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerExclusionManagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1530
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerExclusionManagerComponent, isStandalone: true, selector: "ax-scheduler-picker-exclusion-manager", inputs: { exclusions: { classPropertyName: "exclusions", publicName: "exclusions", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { exclusionsChange: "exclusionsChange" }, host: { classAttribute: "ax-scheduler-picker-exclusion-manager-host" }, ngImport: i0, template: `
|
|
1531
|
+
<div class="ax-scheduler-picker-exclusion-manager">
|
|
1532
|
+
<div class="ax-scheduler-picker-section-header">
|
|
1533
|
+
<label class="ax-scheduler-picker-label">
|
|
1534
|
+
<i class="ax-icon ax-icon-calendar-remove"></i>
|
|
1535
|
+
{{ '@acorex:schedulerPicker.labels.excludeDates' | translate | async }}
|
|
1536
|
+
</label>
|
|
1537
|
+
@if (exclusionList().length > 0) {
|
|
1538
|
+
<ax-badge [text]="exclusionList().length.toString()"></ax-badge>
|
|
1539
|
+
}
|
|
1540
|
+
</div>
|
|
1541
|
+
|
|
1542
|
+
<div class="ax-scheduler-picker-add-section">
|
|
1543
|
+
<ax-datetime-box
|
|
1544
|
+
class="ax-scheduler-picker-date-input"
|
|
1545
|
+
[value]="newExclusionDate()"
|
|
1546
|
+
mode="date"
|
|
1547
|
+
(valueChange)="newExclusionDate.set($event)"
|
|
1548
|
+
[placeholder]="'@acorex:schedulerPicker.placeholders.selectExclusionDate' | translate | async"
|
|
1549
|
+
/>
|
|
1550
|
+
<ax-button
|
|
1551
|
+
mode="success"
|
|
1552
|
+
[text]="'@acorex:common.actions.add' | translate | async"
|
|
1553
|
+
(click)="addExclusion()"
|
|
1554
|
+
[disabled]="!newExclusionDate()"
|
|
1555
|
+
>
|
|
1556
|
+
<ax-prefix>
|
|
1557
|
+
<i class="ax-icon ax-icon-plus"></i>
|
|
1558
|
+
</ax-prefix>
|
|
1559
|
+
</ax-button>
|
|
1560
|
+
</div>
|
|
1561
|
+
|
|
1562
|
+
@if (exclusionList().length > 0) {
|
|
1563
|
+
<div class="ax-scheduler-picker-chips-container">
|
|
1564
|
+
@for (date of exclusionList(); track date.getTime()) {
|
|
1565
|
+
<ax-chips [text]="date | date: 'mediumDate'" color="danger" (click)="removeExclusion(date)">
|
|
1566
|
+
<ax-prefix>
|
|
1567
|
+
<i class="ax-icon ax-icon-calendar"></i>
|
|
1568
|
+
</ax-prefix>
|
|
1569
|
+
<ax-suffix>
|
|
1570
|
+
<i class="ax-icon ax-icon-close"></i>
|
|
1571
|
+
</ax-suffix>
|
|
1572
|
+
</ax-chips>
|
|
1573
|
+
}
|
|
1574
|
+
</div>
|
|
1575
|
+
} @else {
|
|
1576
|
+
<div class="ax-scheduler-picker-empty-state">
|
|
1577
|
+
<i class="ax-icon ax-icon-calendar-check"></i>
|
|
1578
|
+
<span>{{ '@acorex:schedulerPicker.messages.noExcludedDates' | translate | async }}</span>
|
|
1579
|
+
</div>
|
|
1580
|
+
}
|
|
1581
|
+
</div>
|
|
1582
|
+
`, isInline: true, styles: [".ax-scheduler-picker-exclusion-manager{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-section-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:.375rem}.ax-scheduler-picker-label{display:flex;align-items:center;gap:.375rem;color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight)}.ax-scheduler-picker-label .ax-icon{font-size:1.125rem;color:rgb(var(--ax-sys-color-danger-500))}.ax-scheduler-picker-add-section{display:flex;gap:.5rem;align-items:stretch}.ax-scheduler-picker-date-input{flex:1}.ax-scheduler-picker-chips-container{display:flex;flex-wrap:wrap;gap:.375rem}.ax-scheduler-picker-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.375rem;padding:.75rem .5rem;border:1px dashed rgb(var(--ax-sys-color-border-light-surface));border-radius:var(--ax-sys-border-radius-md);color:rgb(var(--ax-sys-color-on-darker-surface));font-size:.875rem}.ax-scheduler-picker-empty-state .ax-icon{font-size:1.5rem;opacity:.4}\n"], dependencies: [{ kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXChipsModule }, { kind: "component", type: i3.AXChipsComponent, selector: "ax-chips", inputs: ["tabIndex", "color", "text", "look", "size"], outputs: ["textChange", "lookChange", "sizeChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: AXDateTimeBoxComponent, selector: "ax-datetime-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "depth", "id", "type", "look", "holidayDates", "allowTyping", "picker", "calendar", "weekend", "weekdays", "format"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "onOpened", "onClosed", "readonlyChange", "disabledChange", "formatChange"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
1583
|
+
}
|
|
1584
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerExclusionManagerComponent, decorators: [{
|
|
1585
|
+
type: Component,
|
|
1586
|
+
args: [{ selector: 'ax-scheduler-picker-exclusion-manager', template: `
|
|
1587
|
+
<div class="ax-scheduler-picker-exclusion-manager">
|
|
1588
|
+
<div class="ax-scheduler-picker-section-header">
|
|
1589
|
+
<label class="ax-scheduler-picker-label">
|
|
1590
|
+
<i class="ax-icon ax-icon-calendar-remove"></i>
|
|
1591
|
+
{{ '@acorex:schedulerPicker.labels.excludeDates' | translate | async }}
|
|
1592
|
+
</label>
|
|
1593
|
+
@if (exclusionList().length > 0) {
|
|
1594
|
+
<ax-badge [text]="exclusionList().length.toString()"></ax-badge>
|
|
1595
|
+
}
|
|
1596
|
+
</div>
|
|
1597
|
+
|
|
1598
|
+
<div class="ax-scheduler-picker-add-section">
|
|
1599
|
+
<ax-datetime-box
|
|
1600
|
+
class="ax-scheduler-picker-date-input"
|
|
1601
|
+
[value]="newExclusionDate()"
|
|
1602
|
+
mode="date"
|
|
1603
|
+
(valueChange)="newExclusionDate.set($event)"
|
|
1604
|
+
[placeholder]="'@acorex:schedulerPicker.placeholders.selectExclusionDate' | translate | async"
|
|
1605
|
+
/>
|
|
1606
|
+
<ax-button
|
|
1607
|
+
mode="success"
|
|
1608
|
+
[text]="'@acorex:common.actions.add' | translate | async"
|
|
1609
|
+
(click)="addExclusion()"
|
|
1610
|
+
[disabled]="!newExclusionDate()"
|
|
1611
|
+
>
|
|
1612
|
+
<ax-prefix>
|
|
1613
|
+
<i class="ax-icon ax-icon-plus"></i>
|
|
1614
|
+
</ax-prefix>
|
|
1615
|
+
</ax-button>
|
|
1616
|
+
</div>
|
|
1617
|
+
|
|
1618
|
+
@if (exclusionList().length > 0) {
|
|
1619
|
+
<div class="ax-scheduler-picker-chips-container">
|
|
1620
|
+
@for (date of exclusionList(); track date.getTime()) {
|
|
1621
|
+
<ax-chips [text]="date | date: 'mediumDate'" color="danger" (click)="removeExclusion(date)">
|
|
1622
|
+
<ax-prefix>
|
|
1623
|
+
<i class="ax-icon ax-icon-calendar"></i>
|
|
1624
|
+
</ax-prefix>
|
|
1625
|
+
<ax-suffix>
|
|
1626
|
+
<i class="ax-icon ax-icon-close"></i>
|
|
1627
|
+
</ax-suffix>
|
|
1628
|
+
</ax-chips>
|
|
1629
|
+
}
|
|
1630
|
+
</div>
|
|
1631
|
+
} @else {
|
|
1632
|
+
<div class="ax-scheduler-picker-empty-state">
|
|
1633
|
+
<i class="ax-icon ax-icon-calendar-check"></i>
|
|
1634
|
+
<span>{{ '@acorex:schedulerPicker.messages.noExcludedDates' | translate | async }}</span>
|
|
1635
|
+
</div>
|
|
1636
|
+
}
|
|
1637
|
+
</div>
|
|
1638
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
1639
|
+
AXDecoratorModule,
|
|
1640
|
+
AXBadgeModule,
|
|
1641
|
+
AXChipsModule,
|
|
1642
|
+
FormsModule,
|
|
1643
|
+
AXDateTimeBoxComponent,
|
|
1644
|
+
AXButtonComponent,
|
|
1645
|
+
AXTranslatorPipe,
|
|
1646
|
+
AsyncPipe,
|
|
1647
|
+
DatePipe,
|
|
1648
|
+
], host: {
|
|
1649
|
+
class: 'ax-scheduler-picker-exclusion-manager-host',
|
|
1650
|
+
}, styles: [".ax-scheduler-picker-exclusion-manager{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-section-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:.375rem}.ax-scheduler-picker-label{display:flex;align-items:center;gap:.375rem;color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight)}.ax-scheduler-picker-label .ax-icon{font-size:1.125rem;color:rgb(var(--ax-sys-color-danger-500))}.ax-scheduler-picker-add-section{display:flex;gap:.5rem;align-items:stretch}.ax-scheduler-picker-date-input{flex:1}.ax-scheduler-picker-chips-container{display:flex;flex-wrap:wrap;gap:.375rem}.ax-scheduler-picker-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.375rem;padding:.75rem .5rem;border:1px dashed rgb(var(--ax-sys-color-border-light-surface));border-radius:var(--ax-sys-border-radius-md);color:rgb(var(--ax-sys-color-on-darker-surface));font-size:.875rem}.ax-scheduler-picker-empty-state .ax-icon{font-size:1.5rem;opacity:.4}\n"] }]
|
|
1651
|
+
}], ctorParameters: () => [], propDecorators: { exclusions: [{ type: i0.Input, args: [{ isSignal: true, alias: "exclusions", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], exclusionsChange: [{ type: i0.Output, args: ["exclusionsChange"] }] } });
|
|
1652
|
+
|
|
1653
|
+
class AXSchedulerPickerInclusionManagerComponent {
|
|
1654
|
+
constructor() {
|
|
1655
|
+
this.inclusions = input(...(ngDevMode ? [undefined, { debugName: "inclusions" }] : []));
|
|
1656
|
+
this.inclusionsChange = output();
|
|
1657
|
+
this.newInclusionDate = signal(null, ...(ngDevMode ? [{ debugName: "newInclusionDate" }] : []));
|
|
1658
|
+
this.inclusionList = signal([], ...(ngDevMode ? [{ debugName: "inclusionList" }] : []));
|
|
1659
|
+
// Sync input with internal list
|
|
1660
|
+
effect(() => {
|
|
1661
|
+
const inclusions = this.inclusions();
|
|
1662
|
+
this.inclusionList.set(inclusions || []);
|
|
1663
|
+
});
|
|
1664
|
+
}
|
|
1665
|
+
addInclusion() {
|
|
1666
|
+
const date = this.newInclusionDate();
|
|
1667
|
+
if (date) {
|
|
1668
|
+
// Normalize date to midnight
|
|
1669
|
+
const normalized = normalizeDate(date);
|
|
1670
|
+
// Check for duplicates
|
|
1671
|
+
if (!dateExistsInArray(normalized, this.inclusionList())) {
|
|
1672
|
+
const updated = [...this.inclusionList(), normalized];
|
|
1673
|
+
this.inclusionList.set(updated);
|
|
1674
|
+
this.inclusionsChange.emit(updated);
|
|
1675
|
+
}
|
|
1676
|
+
this.newInclusionDate.set(null);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
removeInclusion(date) {
|
|
1680
|
+
const normalized = normalizeDate(date);
|
|
1681
|
+
const updated = this.inclusionList().filter((d) => normalizeDate(d).getTime() !== normalized.getTime());
|
|
1682
|
+
this.inclusionList.set(updated);
|
|
1683
|
+
this.inclusionsChange.emit(updated);
|
|
1684
|
+
}
|
|
1685
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerInclusionManagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1686
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerInclusionManagerComponent, isStandalone: true, selector: "ax-scheduler-picker-inclusion-manager", inputs: { inclusions: { classPropertyName: "inclusions", publicName: "inclusions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { inclusionsChange: "inclusionsChange" }, host: { classAttribute: "ax-scheduler-picker-inclusion-manager-host" }, ngImport: i0, template: `
|
|
1687
|
+
<div class="ax-scheduler-picker-inclusion-manager">
|
|
1688
|
+
<div class="ax-scheduler-picker-section-header">
|
|
1689
|
+
<label class="ax-scheduler-picker-label">
|
|
1690
|
+
<i class="ax-icon ax-icon-calendar-add"></i>
|
|
1691
|
+
{{ '@acorex:schedulerPicker.labels.includeDates' | translate | async }}
|
|
1692
|
+
</label>
|
|
1693
|
+
@if (inclusionList().length > 0) {
|
|
1694
|
+
<ax-badge [text]="inclusionList().length.toString()"></ax-badge>
|
|
1695
|
+
}
|
|
1696
|
+
</div>
|
|
1697
|
+
|
|
1698
|
+
<div class="ax-scheduler-picker-add-section">
|
|
1699
|
+
<ax-datetime-box
|
|
1700
|
+
class="ax-scheduler-picker-date-input"
|
|
1701
|
+
[value]="newInclusionDate()"
|
|
1702
|
+
mode="date"
|
|
1703
|
+
(valueChange)="newInclusionDate.set($event)"
|
|
1704
|
+
[placeholder]="'@acorex:schedulerPicker.placeholders.selectInclusionDate' | translate | async"
|
|
1705
|
+
/>
|
|
1706
|
+
<ax-button
|
|
1707
|
+
mode="success"
|
|
1708
|
+
(click)="addInclusion()"
|
|
1709
|
+
[disabled]="!newInclusionDate()"
|
|
1710
|
+
[text]="'@acorex:common.actions.add' | translate | async"
|
|
1711
|
+
>
|
|
1712
|
+
<ax-prefix>
|
|
1713
|
+
<i class="ax-icon ax-icon-plus"></i>
|
|
1714
|
+
</ax-prefix>
|
|
1715
|
+
</ax-button>
|
|
1716
|
+
</div>
|
|
1717
|
+
|
|
1718
|
+
@if (inclusionList().length > 0) {
|
|
1719
|
+
<div class="ax-scheduler-picker-chips-container">
|
|
1720
|
+
@for (date of inclusionList(); track date.getTime()) {
|
|
1721
|
+
<ax-chips [text]="date | date: 'mediumDate'" color="success" (click)="removeInclusion(date)">
|
|
1722
|
+
<ax-prefix>
|
|
1723
|
+
<i class="ax-icon ax-icon-calendar"></i>
|
|
1724
|
+
</ax-prefix>
|
|
1725
|
+
<ax-suffix>
|
|
1726
|
+
<i class="ax-icon ax-icon-close"></i>
|
|
1727
|
+
</ax-suffix>
|
|
1728
|
+
</ax-chips>
|
|
1729
|
+
}
|
|
1730
|
+
</div>
|
|
1731
|
+
} @else {
|
|
1732
|
+
<div class="ax-scheduler-picker-empty-state">
|
|
1733
|
+
<i class="ax-icon ax-icon-calendar-check"></i>
|
|
1734
|
+
<span>{{ '@acorex:schedulerPicker.messages.noIncludedDates' | translate | async }}</span>
|
|
1735
|
+
</div>
|
|
1736
|
+
}
|
|
1737
|
+
</div>
|
|
1738
|
+
`, isInline: true, styles: [".ax-scheduler-picker-inclusion-manager{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-section-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:.375rem}.ax-scheduler-picker-label{display:flex;align-items:center;gap:.375rem;color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight)}.ax-scheduler-picker-label .ax-icon{font-size:1.125rem;color:rgb(var(--ax-sys-color-success-500))}.ax-scheduler-picker-add-section{display:flex;gap:.5rem;align-items:stretch}.ax-scheduler-picker-date-input{flex:1}.ax-scheduler-picker-chips-container{display:flex;flex-wrap:wrap;gap:.375rem}.ax-scheduler-picker-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.375rem;padding:.75rem .5rem;border:1px dashed rgb(var(--ax-sys-color-border-light-surface));border-radius:var(--ax-sys-border-radius-md);color:rgb(var(--ax-sys-color-on-darker-surface));font-size:.875rem}.ax-scheduler-picker-empty-state .ax-icon{font-size:1.5rem;opacity:.4}\n"], dependencies: [{ kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXChipsModule }, { kind: "component", type: i3.AXChipsComponent, selector: "ax-chips", inputs: ["tabIndex", "color", "text", "look", "size"], outputs: ["textChange", "lookChange", "sizeChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: AXDateTimeBoxComponent, selector: "ax-datetime-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "depth", "id", "type", "look", "holidayDates", "allowTyping", "picker", "calendar", "weekend", "weekdays", "format"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "onOpened", "onClosed", "readonlyChange", "disabledChange", "formatChange"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
1739
|
+
}
|
|
1740
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerInclusionManagerComponent, decorators: [{
|
|
1741
|
+
type: Component,
|
|
1742
|
+
args: [{ selector: 'ax-scheduler-picker-inclusion-manager', template: `
|
|
1743
|
+
<div class="ax-scheduler-picker-inclusion-manager">
|
|
1744
|
+
<div class="ax-scheduler-picker-section-header">
|
|
1745
|
+
<label class="ax-scheduler-picker-label">
|
|
1746
|
+
<i class="ax-icon ax-icon-calendar-add"></i>
|
|
1747
|
+
{{ '@acorex:schedulerPicker.labels.includeDates' | translate | async }}
|
|
1748
|
+
</label>
|
|
1749
|
+
@if (inclusionList().length > 0) {
|
|
1750
|
+
<ax-badge [text]="inclusionList().length.toString()"></ax-badge>
|
|
1751
|
+
}
|
|
1752
|
+
</div>
|
|
1753
|
+
|
|
1754
|
+
<div class="ax-scheduler-picker-add-section">
|
|
1755
|
+
<ax-datetime-box
|
|
1756
|
+
class="ax-scheduler-picker-date-input"
|
|
1757
|
+
[value]="newInclusionDate()"
|
|
1758
|
+
mode="date"
|
|
1759
|
+
(valueChange)="newInclusionDate.set($event)"
|
|
1760
|
+
[placeholder]="'@acorex:schedulerPicker.placeholders.selectInclusionDate' | translate | async"
|
|
1761
|
+
/>
|
|
1762
|
+
<ax-button
|
|
1763
|
+
mode="success"
|
|
1764
|
+
(click)="addInclusion()"
|
|
1765
|
+
[disabled]="!newInclusionDate()"
|
|
1766
|
+
[text]="'@acorex:common.actions.add' | translate | async"
|
|
1767
|
+
>
|
|
1768
|
+
<ax-prefix>
|
|
1769
|
+
<i class="ax-icon ax-icon-plus"></i>
|
|
1770
|
+
</ax-prefix>
|
|
1771
|
+
</ax-button>
|
|
1772
|
+
</div>
|
|
1773
|
+
|
|
1774
|
+
@if (inclusionList().length > 0) {
|
|
1775
|
+
<div class="ax-scheduler-picker-chips-container">
|
|
1776
|
+
@for (date of inclusionList(); track date.getTime()) {
|
|
1777
|
+
<ax-chips [text]="date | date: 'mediumDate'" color="success" (click)="removeInclusion(date)">
|
|
1778
|
+
<ax-prefix>
|
|
1779
|
+
<i class="ax-icon ax-icon-calendar"></i>
|
|
1780
|
+
</ax-prefix>
|
|
1781
|
+
<ax-suffix>
|
|
1782
|
+
<i class="ax-icon ax-icon-close"></i>
|
|
1783
|
+
</ax-suffix>
|
|
1784
|
+
</ax-chips>
|
|
1785
|
+
}
|
|
1786
|
+
</div>
|
|
1787
|
+
} @else {
|
|
1788
|
+
<div class="ax-scheduler-picker-empty-state">
|
|
1789
|
+
<i class="ax-icon ax-icon-calendar-check"></i>
|
|
1790
|
+
<span>{{ '@acorex:schedulerPicker.messages.noIncludedDates' | translate | async }}</span>
|
|
1791
|
+
</div>
|
|
1792
|
+
}
|
|
1793
|
+
</div>
|
|
1794
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
1795
|
+
AXDecoratorModule,
|
|
1796
|
+
AXBadgeModule,
|
|
1797
|
+
AXChipsModule,
|
|
1798
|
+
FormsModule,
|
|
1799
|
+
AXDateTimeBoxComponent,
|
|
1800
|
+
AXButtonComponent,
|
|
1801
|
+
AXTranslatorPipe,
|
|
1802
|
+
AsyncPipe,
|
|
1803
|
+
DatePipe,
|
|
1804
|
+
], host: {
|
|
1805
|
+
class: 'ax-scheduler-picker-inclusion-manager-host',
|
|
1806
|
+
}, styles: [".ax-scheduler-picker-inclusion-manager{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-section-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:.375rem}.ax-scheduler-picker-label{display:flex;align-items:center;gap:.375rem;color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight)}.ax-scheduler-picker-label .ax-icon{font-size:1.125rem;color:rgb(var(--ax-sys-color-success-500))}.ax-scheduler-picker-add-section{display:flex;gap:.5rem;align-items:stretch}.ax-scheduler-picker-date-input{flex:1}.ax-scheduler-picker-chips-container{display:flex;flex-wrap:wrap;gap:.375rem}.ax-scheduler-picker-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.375rem;padding:.75rem .5rem;border:1px dashed rgb(var(--ax-sys-color-border-light-surface));border-radius:var(--ax-sys-border-radius-md);color:rgb(var(--ax-sys-color-on-darker-surface));font-size:.875rem}.ax-scheduler-picker-empty-state .ax-icon{font-size:1.5rem;opacity:.4}\n"] }]
|
|
1807
|
+
}], ctorParameters: () => [], propDecorators: { inclusions: [{ type: i0.Input, args: [{ isSignal: true, alias: "inclusions", required: false }] }], inclusionsChange: [{ type: i0.Output, args: ["inclusionsChange"] }] } });
|
|
1808
|
+
|
|
1809
|
+
/**
|
|
1810
|
+
* A powerful, fully customizable scheduler picker component for creating recurrence patterns
|
|
1811
|
+
*
|
|
1812
|
+
* ## Features
|
|
1813
|
+
* - Supports 5 modes: hourly, daily, weekly, monthly, and yearly
|
|
1814
|
+
* - Flexible start and end conditions
|
|
1815
|
+
* - Date exclusions and inclusions
|
|
1816
|
+
* - Natural language summary generation
|
|
1817
|
+
* - Export to Cron and RRule (iCalendar) formats
|
|
1818
|
+
* - Full i18n support
|
|
1819
|
+
* - Type-safe configuration
|
|
1820
|
+
*
|
|
1821
|
+
* ## Basic Usage
|
|
1822
|
+
* ```typescript
|
|
1823
|
+
* <ax-scheduler-picker
|
|
1824
|
+
* [config]="{ mode: 'daily', showEndConditions: true }"
|
|
1825
|
+
* [(value)]="pattern"
|
|
1826
|
+
* (summaryChange)="onSummaryChange($event)"
|
|
1827
|
+
* />
|
|
1828
|
+
* ```
|
|
1829
|
+
*
|
|
1830
|
+
* ## Public API
|
|
1831
|
+
* - `validatePattern()` - Manually trigger validation
|
|
1832
|
+
* - `getPreview(count)` - Get next N occurrences
|
|
1833
|
+
* - `toCron()` - Convert to cron expression
|
|
1834
|
+
* - `toRRule()` - Convert to RRule string
|
|
1835
|
+
* - `reset()` - Reset to default pattern
|
|
1836
|
+
* - `clear()` - Clear all data
|
|
1837
|
+
* - `validationErrors` - Signal containing current validation errors
|
|
1838
|
+
*
|
|
1839
|
+
* @category Components
|
|
1840
|
+
*/
|
|
1841
|
+
class AXSchedulerPickerComponent extends MXValueComponent {
|
|
1842
|
+
internalValueChanged(value) {
|
|
1843
|
+
if (value) {
|
|
1844
|
+
this.pattern.set(value);
|
|
1845
|
+
}
|
|
1846
|
+
else {
|
|
1847
|
+
this.initializeDefaultValue();
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
constructor() {
|
|
1851
|
+
super();
|
|
1852
|
+
/**
|
|
1853
|
+
* Settings for the scheduler picker
|
|
1854
|
+
* Controls which options are visible and behavior
|
|
1855
|
+
*/
|
|
1856
|
+
this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
1857
|
+
/**
|
|
1858
|
+
* Emits when the human-readable summary changes
|
|
1859
|
+
*/
|
|
1860
|
+
this.summaryChange = output();
|
|
1861
|
+
this.service = inject(AXSchedulerPickerService);
|
|
1862
|
+
/**
|
|
1863
|
+
* Internal pattern value
|
|
1864
|
+
*/
|
|
1865
|
+
this.pattern = signal(null, ...(ngDevMode ? [{ debugName: "pattern" }] : []));
|
|
1866
|
+
/**
|
|
1867
|
+
* Current mode derived from config
|
|
1868
|
+
*/
|
|
1869
|
+
this.mode = computed(() => this.config().mode, ...(ngDevMode ? [{ debugName: "mode" }] : []));
|
|
1870
|
+
/**
|
|
1871
|
+
* Effect run counter to prevent stale async updates
|
|
1872
|
+
*/
|
|
1873
|
+
this.effectRunId = 0;
|
|
1874
|
+
/**
|
|
1875
|
+
* Merged configuration with defaults
|
|
1876
|
+
*/
|
|
1877
|
+
this.mergedConfig = computed(() => {
|
|
1878
|
+
const defaultConfig = getDefaultSchedulerPickerConfig(this.config().mode);
|
|
1879
|
+
return {
|
|
1880
|
+
...defaultConfig,
|
|
1881
|
+
...this.config(),
|
|
1882
|
+
options: {
|
|
1883
|
+
...defaultConfig.options,
|
|
1884
|
+
...this.config().options,
|
|
1885
|
+
},
|
|
1886
|
+
};
|
|
1887
|
+
}, ...(ngDevMode ? [{ debugName: "mergedConfig" }] : []));
|
|
1888
|
+
/**
|
|
1889
|
+
* Validation errors (public for external access)
|
|
1890
|
+
*/
|
|
1891
|
+
this.validationErrors = signal([], ...(ngDevMode ? [{ debugName: "validationErrors" }] : []));
|
|
1892
|
+
/**
|
|
1893
|
+
* Human-readable summary of the pattern
|
|
1894
|
+
*/
|
|
1895
|
+
this.summary = signal('', ...(ngDevMode ? [{ debugName: "summary" }] : []));
|
|
1896
|
+
// Effect to update summary when pattern changes
|
|
1897
|
+
effect(() => {
|
|
1898
|
+
const currentPattern = this.pattern();
|
|
1899
|
+
if (currentPattern) {
|
|
1900
|
+
const runId = ++this.effectRunId;
|
|
1901
|
+
this.service.toNaturalLanguage(currentPattern, this.mergedConfig().locale).then((result) => {
|
|
1902
|
+
// Only update if this is still the latest run
|
|
1903
|
+
if (runId === this.effectRunId) {
|
|
1904
|
+
this.summary.set(result);
|
|
1905
|
+
this.summaryChange.emit(result);
|
|
1906
|
+
}
|
|
1907
|
+
});
|
|
1908
|
+
}
|
|
1909
|
+
else {
|
|
1910
|
+
this.summary.set('');
|
|
1911
|
+
this.summaryChange.emit('');
|
|
1912
|
+
}
|
|
1913
|
+
});
|
|
1914
|
+
}
|
|
1915
|
+
/**
|
|
1916
|
+
* Initialize with default value based on mode
|
|
1917
|
+
*/
|
|
1918
|
+
initializeDefaultValue() {
|
|
1919
|
+
if (!this.value) {
|
|
1920
|
+
const defaultValue = {
|
|
1921
|
+
mode: this.config().mode,
|
|
1922
|
+
interval: this.config().defaultInterval || 1,
|
|
1923
|
+
startCondition: {
|
|
1924
|
+
type: 'now',
|
|
1925
|
+
startDate: new Date(),
|
|
1926
|
+
},
|
|
1927
|
+
recurrence: {},
|
|
1928
|
+
endCondition: {
|
|
1929
|
+
type: 'never',
|
|
1930
|
+
},
|
|
1931
|
+
};
|
|
1932
|
+
this.value = defaultValue;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
/**
|
|
1936
|
+
* Update pattern value
|
|
1937
|
+
*/
|
|
1938
|
+
updatePattern(updates) {
|
|
1939
|
+
const currentPattern = this.pattern();
|
|
1940
|
+
if (currentPattern) {
|
|
1941
|
+
const newPattern = this.mergePatternUpdates(currentPattern, updates);
|
|
1942
|
+
this.pattern.set(newPattern);
|
|
1943
|
+
this.value = newPattern;
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
/**
|
|
1947
|
+
* Deep merge pattern updates with current pattern
|
|
1948
|
+
* Preserves nested object properties that aren't being updated
|
|
1949
|
+
*/
|
|
1950
|
+
mergePatternUpdates(current, updates) {
|
|
1951
|
+
return {
|
|
1952
|
+
...current,
|
|
1953
|
+
...updates,
|
|
1954
|
+
// Deep merge recurrence to preserve existing properties
|
|
1955
|
+
recurrence: updates.recurrence
|
|
1956
|
+
? {
|
|
1957
|
+
...current.recurrence,
|
|
1958
|
+
...updates.recurrence,
|
|
1959
|
+
}
|
|
1960
|
+
: current.recurrence,
|
|
1961
|
+
// Deep merge startCondition to preserve existing properties
|
|
1962
|
+
startCondition: updates.startCondition
|
|
1963
|
+
? {
|
|
1964
|
+
...current.startCondition,
|
|
1965
|
+
...updates.startCondition,
|
|
1966
|
+
}
|
|
1967
|
+
: current.startCondition,
|
|
1968
|
+
// Deep merge endCondition to preserve existing properties
|
|
1969
|
+
endCondition: updates.endCondition
|
|
1970
|
+
? {
|
|
1971
|
+
...current.endCondition,
|
|
1972
|
+
...updates.endCondition,
|
|
1973
|
+
}
|
|
1974
|
+
: current.endCondition,
|
|
1975
|
+
};
|
|
1976
|
+
}
|
|
1977
|
+
/**
|
|
1978
|
+
* Manually validate the current pattern
|
|
1979
|
+
*
|
|
1980
|
+
* Validates the pattern against configured rules and constraints.
|
|
1981
|
+
* Updates the `validationErrors` signal and component state.
|
|
1982
|
+
*
|
|
1983
|
+
* @returns Promise resolving to `true` if pattern is valid, `false` otherwise
|
|
1984
|
+
*
|
|
1985
|
+
* @example
|
|
1986
|
+
* ```typescript
|
|
1987
|
+
* const isValid = await schedulerPicker.validatePattern();
|
|
1988
|
+
* if (!isValid) {
|
|
1989
|
+
* const errors = schedulerPicker.validationErrors();
|
|
1990
|
+
* console.log('Validation errors:', errors);
|
|
1991
|
+
* }
|
|
1992
|
+
* ```
|
|
1993
|
+
*/
|
|
1994
|
+
async validatePattern() {
|
|
1995
|
+
const currentPattern = this.pattern();
|
|
1996
|
+
if (!currentPattern) {
|
|
1997
|
+
return false;
|
|
1998
|
+
}
|
|
1999
|
+
const errors = await this.service.validatePattern(currentPattern, this.mergedConfig());
|
|
2000
|
+
const errorMessages = errors.map((e) => e.message);
|
|
2001
|
+
this.validationErrors.set(errorMessages);
|
|
2002
|
+
if (errors.length > 0) {
|
|
2003
|
+
this.setState('error');
|
|
2004
|
+
return false;
|
|
2005
|
+
}
|
|
2006
|
+
else {
|
|
2007
|
+
this.setState('clear');
|
|
2008
|
+
return true;
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
/**
|
|
2012
|
+
* Get preview of next N occurrences based on the current pattern
|
|
2013
|
+
*
|
|
2014
|
+
* @param count - Number of occurrences to return (default: 10)
|
|
2015
|
+
* @param startFrom - Optional starting date (default: now)
|
|
2016
|
+
* @returns Promise resolving to array of dates representing next occurrences
|
|
2017
|
+
* @returns Empty array if pattern is invalid or not set
|
|
2018
|
+
*
|
|
2019
|
+
* @example
|
|
2020
|
+
* ```typescript
|
|
2021
|
+
* const dates = await schedulerPicker.getPreview(5);
|
|
2022
|
+
* console.log('Next 5 occurrences:', dates);
|
|
2023
|
+
* ```
|
|
2024
|
+
*/
|
|
2025
|
+
async getPreview(count = 10, startFrom) {
|
|
2026
|
+
const currentPattern = this.pattern();
|
|
2027
|
+
if (!currentPattern) {
|
|
2028
|
+
return [];
|
|
2029
|
+
}
|
|
2030
|
+
return await this.service.calculateOccurrences(currentPattern, count, startFrom);
|
|
2031
|
+
}
|
|
2032
|
+
/**
|
|
2033
|
+
* Convert current pattern to cron expression
|
|
2034
|
+
*
|
|
2035
|
+
* @returns Promise resolving to cron expression string
|
|
2036
|
+
* @returns Empty string if pattern is not set or invalid
|
|
2037
|
+
*
|
|
2038
|
+
* @example
|
|
2039
|
+
* ```typescript
|
|
2040
|
+
* const cron = await schedulerPicker.toCron();
|
|
2041
|
+
* console.log('Cron expression:', cron); // "0 9 * * 1-5"
|
|
2042
|
+
* ```
|
|
2043
|
+
*/
|
|
2044
|
+
async toCron() {
|
|
2045
|
+
const currentPattern = this.pattern();
|
|
2046
|
+
if (!currentPattern) {
|
|
2047
|
+
return '';
|
|
2048
|
+
}
|
|
2049
|
+
return await this.service.toCronExpression(currentPattern);
|
|
2050
|
+
}
|
|
2051
|
+
/**
|
|
2052
|
+
* Convert current pattern to RRule string (iCalendar format)
|
|
2053
|
+
*
|
|
2054
|
+
* @returns Promise resolving to RRule string
|
|
2055
|
+
* @returns Empty string if pattern is not set or invalid
|
|
2056
|
+
*
|
|
2057
|
+
* @example
|
|
2058
|
+
* ```typescript
|
|
2059
|
+
* const rrule = await schedulerPicker.toRRule();
|
|
2060
|
+
* console.log('RRule:', rrule); // "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR"
|
|
2061
|
+
* ```
|
|
2062
|
+
*/
|
|
2063
|
+
async toRRule() {
|
|
2064
|
+
const currentPattern = this.pattern();
|
|
2065
|
+
if (!currentPattern) {
|
|
2066
|
+
return '';
|
|
2067
|
+
}
|
|
2068
|
+
return await this.service.toRRule(currentPattern);
|
|
2069
|
+
}
|
|
2070
|
+
/**
|
|
2071
|
+
* Reset pattern to default value based on current mode
|
|
2072
|
+
* Clears current pattern and re-initializes with mode-specific defaults
|
|
2073
|
+
*
|
|
2074
|
+
* @param e - Optional event parameter (inherited from base class)
|
|
2075
|
+
*
|
|
2076
|
+
* @example
|
|
2077
|
+
* ```typescript
|
|
2078
|
+
* schedulerPicker.reset();
|
|
2079
|
+
* // Pattern is now reset to default for the configured mode
|
|
2080
|
+
* ```
|
|
2081
|
+
*/
|
|
2082
|
+
reset(e = false) {
|
|
2083
|
+
super.reset(e);
|
|
2084
|
+
this.pattern.set(null);
|
|
2085
|
+
this.initializeDefaultValue();
|
|
2086
|
+
}
|
|
2087
|
+
/**
|
|
2088
|
+
* Clear pattern completely
|
|
2089
|
+
* Removes all pattern data, summary, and validation errors
|
|
2090
|
+
* Sets component state to 'clear'
|
|
2091
|
+
*
|
|
2092
|
+
* @example
|
|
2093
|
+
* ```typescript
|
|
2094
|
+
* schedulerPicker.clear();
|
|
2095
|
+
* // All data cleared, component is now empty
|
|
2096
|
+
* ```
|
|
2097
|
+
*/
|
|
2098
|
+
clear() {
|
|
2099
|
+
this.pattern.set(null);
|
|
2100
|
+
this.value = null;
|
|
2101
|
+
this.summary.set('');
|
|
2102
|
+
this.validationErrors.set([]);
|
|
2103
|
+
this.setState('clear');
|
|
2104
|
+
}
|
|
2105
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2106
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerComponent, isStandalone: true, selector: "ax-scheduler-picker", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: false, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: false, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: false, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: false, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: false, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { valueChange: "valueChange", stateChange: "stateChange", onValueChanged: "onValueChanged", onBlur: "onBlur", onFocus: "onFocus", summaryChange: "summaryChange" }, providers: [
|
|
2107
|
+
{ provide: AXComponent, useExisting: AXSchedulerPickerComponent },
|
|
2108
|
+
{ provide: AXFocusableComponent, useExisting: AXSchedulerPickerComponent },
|
|
2109
|
+
{ provide: AXValuableComponent, useExisting: AXSchedulerPickerComponent },
|
|
2110
|
+
{
|
|
2111
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2112
|
+
useExisting: forwardRef(() => AXSchedulerPickerComponent),
|
|
2113
|
+
multi: true,
|
|
2114
|
+
},
|
|
2115
|
+
], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-scheduler-picker\" [class.ax-disabled]=\"disabled\" [class.ax-readonly]=\"readonly\">\n <!-- Mode-specific panel -->\n <div class=\"ax-scheduler-picker-panel\">\n @switch (mode()) {\n @case ('hourly') {\n <ax-scheduler-picker-hourly-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n @case ('daily') {\n <ax-scheduler-picker-daily-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n @case ('weekly') {\n <ax-scheduler-picker-weekly-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n @case ('monthly') {\n <ax-scheduler-picker-monthly-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n @case ('yearly') {\n <ax-scheduler-picker-yearly-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n }\n </div>\n\n <!-- Start condition -->\n @if (mergedConfig().showStartCondition && pattern()) {\n <div class=\"ax-scheduler-picker-start-conditions\">\n <ax-scheduler-picker-start-condition-selector\n [startCondition]=\"pattern()!.startCondition\"\n [config]=\"mergedConfig()\"\n (startConditionChange)=\"updatePattern({ startCondition: $event })\"\n />\n </div>\n }\n\n <!-- End conditions -->\n @if (mergedConfig().showEndConditions && pattern()) {\n <div class=\"ax-scheduler-picker-end-conditions\">\n <ax-scheduler-picker-end-condition-selector\n [endCondition]=\"pattern()!.endCondition\"\n [config]=\"mergedConfig()\"\n (endConditionChange)=\"updatePattern({ endCondition: $event })\"\n />\n </div>\n }\n\n <!-- Exclusions -->\n @if (mergedConfig().showExclusions && pattern()) {\n <div class=\"ax-scheduler-picker-exclusions\">\n <ax-scheduler-picker-exclusion-manager\n [exclusions]=\"pattern()!.exclusions || []\"\n [config]=\"mergedConfig()\"\n (exclusionsChange)=\"updatePattern({ exclusions: $event })\"\n />\n </div>\n }\n\n <!-- Inclusions -->\n @if (mergedConfig().showInclusions && pattern()) {\n <div class=\"ax-scheduler-picker-inclusions\">\n <ax-scheduler-picker-inclusion-manager\n [inclusions]=\"pattern()!.inclusions || []\"\n (inclusionsChange)=\"updatePattern({ inclusions: $event })\"\n />\n </div>\n }\n</div>\n", styles: [":root{--ax-comp-scheduler-picker-border: 1px solid rgb(var(--ax-sys-color-border-lighter-surface));--ax-comp-scheduler-picker-border-radius: var(--ax-sys-border-radius-md);--ax-comp-scheduler-picker-padding: .5rem;--ax-comp-scheduler-picker-gap: .5rem;--ax-comp-scheduler-picker-label-color: rgb(var(--ax-sys-color-on-lighter-surface));--ax-comp-scheduler-picker-label-font-size: .875rem;--ax-comp-scheduler-picker-label-font-weight: 500;--ax-comp-scheduler-picker-summary-color: rgb(var(--ax-sys-color-on-darker-surface));--ax-comp-scheduler-picker-summary-padding: .375rem .5rem;--ax-comp-scheduler-picker-error-color: rgb(var(--ax-sys-color-danger-500));--ax-comp-scheduler-picker-error-padding: .375rem .5rem}.ax-scheduler-picker{display:flex;flex-direction:column;gap:var(--ax-comp-scheduler-picker-gap);padding:var(--ax-comp-scheduler-picker-padding)}.ax-scheduler-picker.ax-disabled{opacity:.6;pointer-events:none}.ax-scheduler-picker.ax-readonly{pointer-events:none}.ax-scheduler-picker-summary{display:flex;align-items:center;gap:.375rem;padding:var(--ax-comp-scheduler-picker-summary-padding);color:var(--ax-comp-scheduler-picker-summary-color);font-size:.875rem}.ax-scheduler-picker-summary .ax-scheduler-picker-summary-label{font-weight:var(--ax-comp-scheduler-picker-label-font-weight)}.ax-scheduler-picker-errors{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-error{padding:var(--ax-comp-scheduler-picker-error-padding);color:var(--ax-comp-scheduler-picker-error-color);font-size:.875rem}\n"], dependencies: [{ kind: "component", type: AXSchedulerPickerHourlyPanelComponent, selector: "ax-scheduler-picker-hourly-panel", inputs: ["pattern", "config"], outputs: ["patternChange"] }, { kind: "component", type: AXSchedulerPickerDailyPanelComponent, selector: "ax-scheduler-picker-daily-panel", inputs: ["pattern", "config"], outputs: ["patternChange"] }, { kind: "component", type: AXSchedulerPickerWeeklyPanelComponent, selector: "ax-scheduler-picker-weekly-panel", inputs: ["pattern", "config"], outputs: ["patternChange"] }, { kind: "component", type: AXSchedulerPickerMonthlyPanelComponent, selector: "ax-scheduler-picker-monthly-panel", inputs: ["pattern", "config"], outputs: ["patternChange"] }, { kind: "component", type: AXSchedulerPickerYearlyPanelComponent, selector: "ax-scheduler-picker-yearly-panel", inputs: ["pattern", "config"], outputs: ["patternChange"] }, { kind: "component", type: AXSchedulerPickerStartConditionSelectorComponent, selector: "ax-scheduler-picker-start-condition-selector", inputs: ["startCondition", "config"], outputs: ["startConditionChange"] }, { kind: "component", type: AXSchedulerPickerEndConditionSelectorComponent, selector: "ax-scheduler-picker-end-condition-selector", inputs: ["endCondition", "config"], outputs: ["endConditionChange"] }, { kind: "component", type: AXSchedulerPickerExclusionManagerComponent, selector: "ax-scheduler-picker-exclusion-manager", inputs: ["exclusions", "config"], outputs: ["exclusionsChange"] }, { kind: "component", type: AXSchedulerPickerInclusionManagerComponent, selector: "ax-scheduler-picker-inclusion-manager", inputs: ["inclusions"], outputs: ["inclusionsChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
2116
|
+
}
|
|
2117
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerComponent, decorators: [{
|
|
2118
|
+
type: Component,
|
|
2119
|
+
args: [{ selector: 'ax-scheduler-picker', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, inputs: ['disabled', 'readonly', 'tabIndex', 'value', 'state', 'name', 'id'], outputs: ['valueChange', 'stateChange', 'onValueChanged', 'onBlur', 'onFocus'], providers: [
|
|
2120
|
+
{ provide: AXComponent, useExisting: AXSchedulerPickerComponent },
|
|
2121
|
+
{ provide: AXFocusableComponent, useExisting: AXSchedulerPickerComponent },
|
|
2122
|
+
{ provide: AXValuableComponent, useExisting: AXSchedulerPickerComponent },
|
|
2123
|
+
{
|
|
2124
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2125
|
+
useExisting: forwardRef(() => AXSchedulerPickerComponent),
|
|
2126
|
+
multi: true,
|
|
2127
|
+
},
|
|
2128
|
+
], imports: [
|
|
2129
|
+
AXSchedulerPickerHourlyPanelComponent,
|
|
2130
|
+
AXSchedulerPickerDailyPanelComponent,
|
|
2131
|
+
AXSchedulerPickerWeeklyPanelComponent,
|
|
2132
|
+
AXSchedulerPickerMonthlyPanelComponent,
|
|
2133
|
+
AXSchedulerPickerYearlyPanelComponent,
|
|
2134
|
+
AXSchedulerPickerStartConditionSelectorComponent,
|
|
2135
|
+
AXSchedulerPickerEndConditionSelectorComponent,
|
|
2136
|
+
AXSchedulerPickerExclusionManagerComponent,
|
|
2137
|
+
AXSchedulerPickerInclusionManagerComponent,
|
|
2138
|
+
], template: "<div class=\"ax-scheduler-picker\" [class.ax-disabled]=\"disabled\" [class.ax-readonly]=\"readonly\">\n <!-- Mode-specific panel -->\n <div class=\"ax-scheduler-picker-panel\">\n @switch (mode()) {\n @case ('hourly') {\n <ax-scheduler-picker-hourly-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n @case ('daily') {\n <ax-scheduler-picker-daily-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n @case ('weekly') {\n <ax-scheduler-picker-weekly-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n @case ('monthly') {\n <ax-scheduler-picker-monthly-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n @case ('yearly') {\n <ax-scheduler-picker-yearly-panel\n [pattern]=\"pattern()\"\n [config]=\"$any(mergedConfig())\"\n (patternChange)=\"updatePattern($event)\"\n />\n }\n }\n </div>\n\n <!-- Start condition -->\n @if (mergedConfig().showStartCondition && pattern()) {\n <div class=\"ax-scheduler-picker-start-conditions\">\n <ax-scheduler-picker-start-condition-selector\n [startCondition]=\"pattern()!.startCondition\"\n [config]=\"mergedConfig()\"\n (startConditionChange)=\"updatePattern({ startCondition: $event })\"\n />\n </div>\n }\n\n <!-- End conditions -->\n @if (mergedConfig().showEndConditions && pattern()) {\n <div class=\"ax-scheduler-picker-end-conditions\">\n <ax-scheduler-picker-end-condition-selector\n [endCondition]=\"pattern()!.endCondition\"\n [config]=\"mergedConfig()\"\n (endConditionChange)=\"updatePattern({ endCondition: $event })\"\n />\n </div>\n }\n\n <!-- Exclusions -->\n @if (mergedConfig().showExclusions && pattern()) {\n <div class=\"ax-scheduler-picker-exclusions\">\n <ax-scheduler-picker-exclusion-manager\n [exclusions]=\"pattern()!.exclusions || []\"\n [config]=\"mergedConfig()\"\n (exclusionsChange)=\"updatePattern({ exclusions: $event })\"\n />\n </div>\n }\n\n <!-- Inclusions -->\n @if (mergedConfig().showInclusions && pattern()) {\n <div class=\"ax-scheduler-picker-inclusions\">\n <ax-scheduler-picker-inclusion-manager\n [inclusions]=\"pattern()!.inclusions || []\"\n (inclusionsChange)=\"updatePattern({ inclusions: $event })\"\n />\n </div>\n }\n</div>\n", styles: [":root{--ax-comp-scheduler-picker-border: 1px solid rgb(var(--ax-sys-color-border-lighter-surface));--ax-comp-scheduler-picker-border-radius: var(--ax-sys-border-radius-md);--ax-comp-scheduler-picker-padding: .5rem;--ax-comp-scheduler-picker-gap: .5rem;--ax-comp-scheduler-picker-label-color: rgb(var(--ax-sys-color-on-lighter-surface));--ax-comp-scheduler-picker-label-font-size: .875rem;--ax-comp-scheduler-picker-label-font-weight: 500;--ax-comp-scheduler-picker-summary-color: rgb(var(--ax-sys-color-on-darker-surface));--ax-comp-scheduler-picker-summary-padding: .375rem .5rem;--ax-comp-scheduler-picker-error-color: rgb(var(--ax-sys-color-danger-500));--ax-comp-scheduler-picker-error-padding: .375rem .5rem}.ax-scheduler-picker{display:flex;flex-direction:column;gap:var(--ax-comp-scheduler-picker-gap);padding:var(--ax-comp-scheduler-picker-padding)}.ax-scheduler-picker.ax-disabled{opacity:.6;pointer-events:none}.ax-scheduler-picker.ax-readonly{pointer-events:none}.ax-scheduler-picker-summary{display:flex;align-items:center;gap:.375rem;padding:var(--ax-comp-scheduler-picker-summary-padding);color:var(--ax-comp-scheduler-picker-summary-color);font-size:.875rem}.ax-scheduler-picker-summary .ax-scheduler-picker-summary-label{font-weight:var(--ax-comp-scheduler-picker-label-font-weight)}.ax-scheduler-picker-errors{display:flex;flex-direction:column;gap:.375rem}.ax-scheduler-picker-error{padding:var(--ax-comp-scheduler-picker-error-padding);color:var(--ax-comp-scheduler-picker-error-color);font-size:.875rem}\n"] }]
|
|
2139
|
+
}], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], summaryChange: [{ type: i0.Output, args: ["summaryChange"] }] } });
|
|
2140
|
+
|
|
2141
|
+
class AXSchedulerPickerTimeSelectorComponent {
|
|
2142
|
+
constructor() {
|
|
2143
|
+
this.time = input(...(ngDevMode ? [undefined, { debugName: "time" }] : []));
|
|
2144
|
+
this.timeChange = output();
|
|
2145
|
+
}
|
|
2146
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerTimeSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2147
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.9", type: AXSchedulerPickerTimeSelectorComponent, isStandalone: true, selector: "ax-scheduler-picker-time-selector", inputs: { time: { classPropertyName: "time", publicName: "time", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timeChange: "timeChange" }, ngImport: i0, template: `
|
|
2148
|
+
<div class="ax-scheduler-picker-time-selector">
|
|
2149
|
+
<label class="ax-scheduler-picker-label">
|
|
2150
|
+
{{ '@acorex:schedulerPicker.labels.time' | translate | async }}
|
|
2151
|
+
</label>
|
|
2152
|
+
<ax-datetime-box
|
|
2153
|
+
[value]="time() || '09:00'"
|
|
2154
|
+
[picker]="'time'"
|
|
2155
|
+
(valueChange)="timeChange.emit($event)"
|
|
2156
|
+
/>
|
|
2157
|
+
</div>
|
|
2158
|
+
`, isInline: true, styles: [".ax-scheduler-picker-time-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: AXDateTimeBoxComponent, selector: "ax-datetime-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "depth", "id", "type", "look", "holidayDates", "allowTyping", "picker", "calendar", "weekend", "weekdays", "format"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "onOpened", "onClosed", "readonlyChange", "disabledChange", "formatChange"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
2159
|
+
}
|
|
2160
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerTimeSelectorComponent, decorators: [{
|
|
2161
|
+
type: Component,
|
|
2162
|
+
args: [{ selector: 'ax-scheduler-picker-time-selector', template: `
|
|
2163
|
+
<div class="ax-scheduler-picker-time-selector">
|
|
2164
|
+
<label class="ax-scheduler-picker-label">
|
|
2165
|
+
{{ '@acorex:schedulerPicker.labels.time' | translate | async }}
|
|
2166
|
+
</label>
|
|
2167
|
+
<ax-datetime-box
|
|
2168
|
+
[value]="time() || '09:00'"
|
|
2169
|
+
[picker]="'time'"
|
|
2170
|
+
(valueChange)="timeChange.emit($event)"
|
|
2171
|
+
/>
|
|
2172
|
+
</div>
|
|
2173
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [FormsModule, AXDateTimeBoxComponent, AXTranslatorPipe, AsyncPipe], styles: [".ax-scheduler-picker-time-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight);margin:0}\n"] }]
|
|
2174
|
+
}], propDecorators: { time: [{ type: i0.Input, args: [{ isSignal: true, alias: "time", required: false }] }], timeChange: [{ type: i0.Output, args: ["timeChange"] }] } });
|
|
2175
|
+
|
|
2176
|
+
class AXSchedulerPickerTimezoneSelectorComponent {
|
|
2177
|
+
constructor() {
|
|
2178
|
+
/**
|
|
2179
|
+
* Current timezone value
|
|
2180
|
+
*/
|
|
2181
|
+
this.timezone = input(...(ngDevMode ? [undefined, { debugName: "timezone" }] : []));
|
|
2182
|
+
/**
|
|
2183
|
+
* Emits when timezone selection changes
|
|
2184
|
+
*/
|
|
2185
|
+
this.timezoneChange = output();
|
|
2186
|
+
this.timezones = [
|
|
2187
|
+
{ value: 'UTC', text: 'UTC' },
|
|
2188
|
+
{ value: 'America/New_York', text: 'Eastern Time (ET)' },
|
|
2189
|
+
{ value: 'America/Chicago', text: 'Central Time (CT)' },
|
|
2190
|
+
{ value: 'America/Denver', text: 'Mountain Time (MT)' },
|
|
2191
|
+
{ value: 'America/Los_Angeles', text: 'Pacific Time (PT)' },
|
|
2192
|
+
{ value: 'Europe/London', text: 'London (GMT)' },
|
|
2193
|
+
{ value: 'Europe/Paris', text: 'Paris (CET)' },
|
|
2194
|
+
{ value: 'Asia/Dubai', text: 'Dubai (GST)' },
|
|
2195
|
+
{ value: 'Asia/Tehran', text: 'Tehran (IRST)' },
|
|
2196
|
+
{ value: 'Asia/Tokyo', text: 'Tokyo (JST)' },
|
|
2197
|
+
{ value: 'Australia/Sydney', text: 'Sydney (AEDT)' },
|
|
2198
|
+
];
|
|
2199
|
+
}
|
|
2200
|
+
/**
|
|
2201
|
+
* Handle timezone selection change
|
|
2202
|
+
*/
|
|
2203
|
+
onTimezoneChange(event) {
|
|
2204
|
+
this.timezoneChange.emit(event.value);
|
|
2205
|
+
}
|
|
2206
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerTimezoneSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2207
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.9", type: AXSchedulerPickerTimezoneSelectorComponent, isStandalone: true, selector: "ax-scheduler-picker-timezone-selector", inputs: { timezone: { classPropertyName: "timezone", publicName: "timezone", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timezoneChange: "timezoneChange" }, ngImport: i0, template: `
|
|
2208
|
+
<div class="ax-scheduler-picker-timezone-selector">
|
|
2209
|
+
<label class="ax-scheduler-picker-label">
|
|
2210
|
+
{{ '@acorex:schedulerPicker.labels.timezone' | translate | async }}
|
|
2211
|
+
</label>
|
|
2212
|
+
<ax-select-box
|
|
2213
|
+
[value]="timezone() || 'UTC'"
|
|
2214
|
+
[dataSource]="timezones"
|
|
2215
|
+
textField="text"
|
|
2216
|
+
valueField="value"
|
|
2217
|
+
(onValueChanged)="onTimezoneChange($event)"
|
|
2218
|
+
/>
|
|
2219
|
+
</div>
|
|
2220
|
+
`, isInline: true, styles: [".ax-scheduler-picker-timezone-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
2221
|
+
}
|
|
2222
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerTimezoneSelectorComponent, decorators: [{
|
|
2223
|
+
type: Component,
|
|
2224
|
+
args: [{ selector: 'ax-scheduler-picker-timezone-selector', template: `
|
|
2225
|
+
<div class="ax-scheduler-picker-timezone-selector">
|
|
2226
|
+
<label class="ax-scheduler-picker-label">
|
|
2227
|
+
{{ '@acorex:schedulerPicker.labels.timezone' | translate | async }}
|
|
2228
|
+
</label>
|
|
2229
|
+
<ax-select-box
|
|
2230
|
+
[value]="timezone() || 'UTC'"
|
|
2231
|
+
[dataSource]="timezones"
|
|
2232
|
+
textField="text"
|
|
2233
|
+
valueField="value"
|
|
2234
|
+
(onValueChanged)="onTimezoneChange($event)"
|
|
2235
|
+
/>
|
|
2236
|
+
</div>
|
|
2237
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [FormsModule, AXSelectBoxComponent, AXTranslatorPipe, AsyncPipe], styles: [".ax-scheduler-picker-timezone-selector{display:flex;flex-direction:column;gap:.5rem}.ax-scheduler-picker-label{color:var(--ax-comp-scheduler-picker-label-color);font-size:var(--ax-comp-scheduler-picker-label-font-size);font-weight:var(--ax-comp-scheduler-picker-label-font-weight)}\n"] }]
|
|
2238
|
+
}], propDecorators: { timezone: [{ type: i0.Input, args: [{ isSignal: true, alias: "timezone", required: false }] }], timezoneChange: [{ type: i0.Output, args: ["timezoneChange"] }] } });
|
|
2239
|
+
|
|
2240
|
+
/**
|
|
2241
|
+
* Demo configuration panel for scheduler picker
|
|
2242
|
+
* Provides interactive controls to customize scheduler picker settings
|
|
2243
|
+
*/
|
|
2244
|
+
class AXSchedulerPickerConfigComponent {
|
|
2245
|
+
constructor() {
|
|
2246
|
+
// Outputs
|
|
2247
|
+
this.configChange = output();
|
|
2248
|
+
this.modeChange = output();
|
|
2249
|
+
// Mode selection
|
|
2250
|
+
this.selectedMode = signal('daily', ...(ngDevMode ? [{ debugName: "selectedMode" }] : []));
|
|
2251
|
+
this.modeOptions = [
|
|
2252
|
+
{ value: 'hourly', text: 'Hourly' },
|
|
2253
|
+
{ value: 'daily', text: 'Daily' },
|
|
2254
|
+
{ value: 'weekly', text: 'Weekly' },
|
|
2255
|
+
{ value: 'monthly', text: 'Monthly' },
|
|
2256
|
+
{ value: 'yearly', text: 'Yearly' },
|
|
2257
|
+
];
|
|
2258
|
+
// Configuration controls - Global
|
|
2259
|
+
this.showInterval = signal(true, ...(ngDevMode ? [{ debugName: "showInterval" }] : []));
|
|
2260
|
+
this.showStartCondition = signal(true, ...(ngDevMode ? [{ debugName: "showStartCondition" }] : []));
|
|
2261
|
+
this.showEndConditions = signal(true, ...(ngDevMode ? [{ debugName: "showEndConditions" }] : []));
|
|
2262
|
+
this.showExclusions = signal(false, ...(ngDevMode ? [{ debugName: "showExclusions" }] : []));
|
|
2263
|
+
this.showInclusions = signal(false, ...(ngDevMode ? [{ debugName: "showInclusions" }] : []));
|
|
2264
|
+
// Configuration controls - Mode specific
|
|
2265
|
+
this.showWeekdaysOnly = signal(false, ...(ngDevMode ? [{ debugName: "showWeekdaysOnly" }] : []));
|
|
2266
|
+
this.showWeekdaySelection = signal(true, ...(ngDevMode ? [{ debugName: "showWeekdaySelection" }] : []));
|
|
2267
|
+
this.monthlyRecurrenceMode = signal('specificDays', ...(ngDevMode ? [{ debugName: "monthlyRecurrenceMode" }] : []));
|
|
2268
|
+
this.yearlyRecurrenceMode = signal('specificDate', ...(ngDevMode ? [{ debugName: "yearlyRecurrenceMode" }] : []));
|
|
2269
|
+
this.showMonthSelection = signal(true, ...(ngDevMode ? [{ debugName: "showMonthSelection" }] : []));
|
|
2270
|
+
// Dynamic configuration based on selected mode
|
|
2271
|
+
this.config = computed(() => {
|
|
2272
|
+
const mode = this.selectedMode();
|
|
2273
|
+
const baseConfig = {
|
|
2274
|
+
mode,
|
|
2275
|
+
showStartCondition: this.showStartCondition(),
|
|
2276
|
+
showEndConditions: this.showEndConditions(),
|
|
2277
|
+
showExclusions: this.showExclusions(),
|
|
2278
|
+
showInclusions: this.showInclusions(),
|
|
2279
|
+
};
|
|
2280
|
+
switch (mode) {
|
|
2281
|
+
case 'hourly':
|
|
2282
|
+
baseConfig.options = {
|
|
2283
|
+
showInterval: this.showInterval(),
|
|
2284
|
+
};
|
|
2285
|
+
break;
|
|
2286
|
+
case 'daily':
|
|
2287
|
+
baseConfig.options = {
|
|
2288
|
+
showInterval: this.showInterval(),
|
|
2289
|
+
showWeekdaysOnly: this.showWeekdaysOnly(),
|
|
2290
|
+
};
|
|
2291
|
+
break;
|
|
2292
|
+
case 'weekly':
|
|
2293
|
+
baseConfig.options = {
|
|
2294
|
+
showInterval: this.showInterval(),
|
|
2295
|
+
showWeekdaySelection: this.showWeekdaySelection(),
|
|
2296
|
+
};
|
|
2297
|
+
break;
|
|
2298
|
+
case 'monthly':
|
|
2299
|
+
baseConfig.options = {
|
|
2300
|
+
showInterval: this.showInterval(),
|
|
2301
|
+
recurrenceMode: this.monthlyRecurrenceMode(),
|
|
2302
|
+
};
|
|
2303
|
+
break;
|
|
2304
|
+
case 'yearly':
|
|
2305
|
+
baseConfig.options = {
|
|
2306
|
+
showInterval: this.showInterval(),
|
|
2307
|
+
recurrenceMode: this.yearlyRecurrenceMode(),
|
|
2308
|
+
showMonthSelection: this.showMonthSelection(),
|
|
2309
|
+
};
|
|
2310
|
+
break;
|
|
2311
|
+
}
|
|
2312
|
+
return baseConfig;
|
|
2313
|
+
}, ...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
2314
|
+
// Emit config changes whenever any signal changes
|
|
2315
|
+
effect(() => {
|
|
2316
|
+
const currentConfig = this.config();
|
|
2317
|
+
this.configChange.emit(currentConfig);
|
|
2318
|
+
});
|
|
2319
|
+
}
|
|
2320
|
+
onModeChange(mode) {
|
|
2321
|
+
this.selectedMode.set(mode);
|
|
2322
|
+
this.modeChange.emit(mode);
|
|
2323
|
+
}
|
|
2324
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2325
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXSchedulerPickerConfigComponent, isStandalone: true, selector: "ax-scheduler-picker-config", outputs: { configChange: "configChange", modeChange: "modeChange" }, ngImport: i0, template: "<div class=\"ax-scheduler-picker-config\">\n <h3>Configuration</h3>\n\n <!-- Mode Selector -->\n <div class=\"control-group\">\n <label>Mode</label>\n <ax-select-box\n [dataSource]=\"modeOptions\"\n [textField]=\"'text'\"\n [valueField]=\"'value'\"\n [value]=\"selectedMode()\"\n (onValueChanged)=\"onModeChange($event.value)\"\n />\n </div>\n\n <!-- Global Options -->\n <div class=\"control-group\">\n <label>Global Options</label>\n <div class=\"switch-group\">\n <span>Show Interval</span>\n <ax-switch [(value)]=\"showInterval\" />\n </div>\n <div class=\"switch-group\">\n <span>Show Start Condition</span>\n <ax-switch [(value)]=\"showStartCondition\" />\n </div>\n <div class=\"switch-group\">\n <span>Show End Conditions</span>\n <ax-switch [(value)]=\"showEndConditions\" />\n </div>\n <div class=\"switch-group\">\n <span>Show Exclusions</span>\n <ax-switch [(value)]=\"showExclusions\" />\n </div>\n <div class=\"switch-group\">\n <span>Show Inclusions</span>\n <ax-switch [(value)]=\"showInclusions\" />\n </div>\n </div>\n\n <!-- Mode-Specific Options -->\n @if (selectedMode() === 'daily') {\n <div class=\"control-group\">\n <label>Daily Options</label>\n <div class=\"switch-group\">\n <span>Show Weekdays Only</span>\n <ax-switch [(value)]=\"showWeekdaysOnly\" />\n </div>\n </div>\n }\n \n @if (selectedMode() === 'weekly') {\n <div class=\"control-group\">\n <label>Weekly Options</label>\n <div class=\"switch-group\">\n <span>Show Weekday Selection</span>\n <ax-switch [(value)]=\"showWeekdaySelection\" />\n </div>\n </div>\n }\n \n @if (selectedMode() === 'monthly') {\n <div class=\"control-group\">\n <label>Monthly Options</label>\n <div class=\"control-subgroup\">\n <label>Recurrence Mode</label>\n <ax-select-box\n [dataSource]=\"[\n { value: 'none', text: 'None' },\n { value: 'specificDays', text: 'Specific Days' },\n { value: 'occurrence', text: 'Occurrence' }\n ]\"\n [textField]=\"'text'\"\n [valueField]=\"'value'\"\n [value]=\"monthlyRecurrenceMode()\"\n (onValueChanged)=\"monthlyRecurrenceMode.set($event.value)\"\n />\n </div>\n </div>\n }\n \n @if (selectedMode() === 'yearly') {\n <div class=\"control-group\">\n <label>Yearly Options</label>\n <div class=\"control-subgroup\">\n <label>Recurrence Mode</label>\n <ax-select-box\n [dataSource]=\"[\n { value: 'none', text: 'None' },\n { value: 'specificDate', text: 'Specific Date' },\n { value: 'occurrence', text: 'Occurrence' }\n ]\"\n [textField]=\"'text'\"\n [valueField]=\"'value'\"\n [value]=\"yearlyRecurrenceMode()\"\n (onValueChanged)=\"yearlyRecurrenceMode.set($event.value)\"\n />\n </div>\n <div class=\"switch-group\">\n <span>Show Month Selection</span>\n <ax-switch [(value)]=\"showMonthSelection\" />\n </div>\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-config{background:var(--ax-sys-color-surface-container);padding:1.25rem;border-radius:var(--ax-sys-border-radius-md)}.ax-scheduler-picker-config h3{margin:0 0 1.25rem;font-size:1rem;font-weight:600;color:var(--ax-sys-color-on-surface)}.ax-scheduler-picker-config .control-group{margin-bottom:1.25rem}.ax-scheduler-picker-config .control-group:last-child{margin-bottom:0}.ax-scheduler-picker-config .control-group>label{display:block;font-size:.875rem;font-weight:500;color:var(--ax-sys-color-on-surface-variant);margin-bottom:.5rem}.ax-scheduler-picker-config .control-group ax-select-box{width:100%}.ax-scheduler-picker-config .control-subgroup{margin-bottom:.75rem}.ax-scheduler-picker-config .control-subgroup label{display:block;font-size:.8125rem;font-weight:500;color:var(--ax-sys-color-on-surface-variant);margin-bottom:.375rem}.ax-scheduler-picker-config .control-subgroup ax-select-box{width:100%}.ax-scheduler-picker-config .switch-group{display:flex;align-items:center;justify-content:space-between;padding:.5rem 0;gap:.75rem}.ax-scheduler-picker-config .switch-group span{font-size:.875rem;color:var(--ax-sys-color-on-surface)}.ax-scheduler-picker-config .switch-group ax-switch{flex-shrink:0}\n"], dependencies: [{ kind: "component", type: AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "component", type: AXSwitchComponent, selector: "ax-switch", inputs: ["disabled", "readonly", "color", "tabIndex", "value", "name", "isLoading"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged", "readonlyChange", "disabledChange"] }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
2326
|
+
}
|
|
2327
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXSchedulerPickerConfigComponent, decorators: [{
|
|
2328
|
+
type: Component,
|
|
2329
|
+
args: [{ selector: 'ax-scheduler-picker-config', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [AXSelectBoxComponent, AXSwitchComponent, FormsModule], template: "<div class=\"ax-scheduler-picker-config\">\n <h3>Configuration</h3>\n\n <!-- Mode Selector -->\n <div class=\"control-group\">\n <label>Mode</label>\n <ax-select-box\n [dataSource]=\"modeOptions\"\n [textField]=\"'text'\"\n [valueField]=\"'value'\"\n [value]=\"selectedMode()\"\n (onValueChanged)=\"onModeChange($event.value)\"\n />\n </div>\n\n <!-- Global Options -->\n <div class=\"control-group\">\n <label>Global Options</label>\n <div class=\"switch-group\">\n <span>Show Interval</span>\n <ax-switch [(value)]=\"showInterval\" />\n </div>\n <div class=\"switch-group\">\n <span>Show Start Condition</span>\n <ax-switch [(value)]=\"showStartCondition\" />\n </div>\n <div class=\"switch-group\">\n <span>Show End Conditions</span>\n <ax-switch [(value)]=\"showEndConditions\" />\n </div>\n <div class=\"switch-group\">\n <span>Show Exclusions</span>\n <ax-switch [(value)]=\"showExclusions\" />\n </div>\n <div class=\"switch-group\">\n <span>Show Inclusions</span>\n <ax-switch [(value)]=\"showInclusions\" />\n </div>\n </div>\n\n <!-- Mode-Specific Options -->\n @if (selectedMode() === 'daily') {\n <div class=\"control-group\">\n <label>Daily Options</label>\n <div class=\"switch-group\">\n <span>Show Weekdays Only</span>\n <ax-switch [(value)]=\"showWeekdaysOnly\" />\n </div>\n </div>\n }\n \n @if (selectedMode() === 'weekly') {\n <div class=\"control-group\">\n <label>Weekly Options</label>\n <div class=\"switch-group\">\n <span>Show Weekday Selection</span>\n <ax-switch [(value)]=\"showWeekdaySelection\" />\n </div>\n </div>\n }\n \n @if (selectedMode() === 'monthly') {\n <div class=\"control-group\">\n <label>Monthly Options</label>\n <div class=\"control-subgroup\">\n <label>Recurrence Mode</label>\n <ax-select-box\n [dataSource]=\"[\n { value: 'none', text: 'None' },\n { value: 'specificDays', text: 'Specific Days' },\n { value: 'occurrence', text: 'Occurrence' }\n ]\"\n [textField]=\"'text'\"\n [valueField]=\"'value'\"\n [value]=\"monthlyRecurrenceMode()\"\n (onValueChanged)=\"monthlyRecurrenceMode.set($event.value)\"\n />\n </div>\n </div>\n }\n \n @if (selectedMode() === 'yearly') {\n <div class=\"control-group\">\n <label>Yearly Options</label>\n <div class=\"control-subgroup\">\n <label>Recurrence Mode</label>\n <ax-select-box\n [dataSource]=\"[\n { value: 'none', text: 'None' },\n { value: 'specificDate', text: 'Specific Date' },\n { value: 'occurrence', text: 'Occurrence' }\n ]\"\n [textField]=\"'text'\"\n [valueField]=\"'value'\"\n [value]=\"yearlyRecurrenceMode()\"\n (onValueChanged)=\"yearlyRecurrenceMode.set($event.value)\"\n />\n </div>\n <div class=\"switch-group\">\n <span>Show Month Selection</span>\n <ax-switch [(value)]=\"showMonthSelection\" />\n </div>\n </div>\n }\n</div>\n", styles: [".ax-scheduler-picker-config{background:var(--ax-sys-color-surface-container);padding:1.25rem;border-radius:var(--ax-sys-border-radius-md)}.ax-scheduler-picker-config h3{margin:0 0 1.25rem;font-size:1rem;font-weight:600;color:var(--ax-sys-color-on-surface)}.ax-scheduler-picker-config .control-group{margin-bottom:1.25rem}.ax-scheduler-picker-config .control-group:last-child{margin-bottom:0}.ax-scheduler-picker-config .control-group>label{display:block;font-size:.875rem;font-weight:500;color:var(--ax-sys-color-on-surface-variant);margin-bottom:.5rem}.ax-scheduler-picker-config .control-group ax-select-box{width:100%}.ax-scheduler-picker-config .control-subgroup{margin-bottom:.75rem}.ax-scheduler-picker-config .control-subgroup label{display:block;font-size:.8125rem;font-weight:500;color:var(--ax-sys-color-on-surface-variant);margin-bottom:.375rem}.ax-scheduler-picker-config .control-subgroup ax-select-box{width:100%}.ax-scheduler-picker-config .switch-group{display:flex;align-items:center;justify-content:space-between;padding:.5rem 0;gap:.75rem}.ax-scheduler-picker-config .switch-group span{font-size:.875rem;color:var(--ax-sys-color-on-surface)}.ax-scheduler-picker-config .switch-group ax-switch{flex-shrink:0}\n"] }]
|
|
2330
|
+
}], ctorParameters: () => [], propDecorators: { configChange: [{ type: i0.Output, args: ["configChange"] }], modeChange: [{ type: i0.Output, args: ["modeChange"] }] } });
|
|
2331
|
+
|
|
2332
|
+
// Main component
|
|
2333
|
+
|
|
2334
|
+
/**
|
|
2335
|
+
* Generated bundle index. Do not edit.
|
|
2336
|
+
*/
|
|
2337
|
+
|
|
2338
|
+
export { AXSchedulerPickerComponent, AXSchedulerPickerConfigComponent, AXSchedulerPickerDailyDefaultConfig, AXSchedulerPickerDailyPanelComponent, AXSchedulerPickerDaySelectorComponent, AXSchedulerPickerEndConditionSelectorComponent, AXSchedulerPickerExclusionManagerComponent, AXSchedulerPickerHourlyDefaultConfig, AXSchedulerPickerHourlyPanelComponent, AXSchedulerPickerInclusionManagerComponent, AXSchedulerPickerIntervalSelectorComponent, AXSchedulerPickerMonthSelectorComponent, AXSchedulerPickerMonthlyDefaultConfig, AXSchedulerPickerMonthlyPanelComponent, AXSchedulerPickerOccurrenceSelectorComponent, AXSchedulerPickerService, AXSchedulerPickerStartConditionSelectorComponent, AXSchedulerPickerTimeSelectorComponent, AXSchedulerPickerTimezoneSelectorComponent, AXSchedulerPickerWeeklyDefaultConfig, AXSchedulerPickerWeeklyPanelComponent, AXSchedulerPickerYearlyDefaultConfig, AXSchedulerPickerYearlyPanelComponent, AX_SCHEDULER_PICKER_DAILY_CONFIG, AX_SCHEDULER_PICKER_DAYS_OF_WEEK, AX_SCHEDULER_PICKER_DAY_TRANSLATION_KEYS, AX_SCHEDULER_PICKER_DEFAULT_FIRST_DAY_OF_WEEK, AX_SCHEDULER_PICKER_DEFAULT_LOCALE, AX_SCHEDULER_PICKER_DEFAULT_OCCURRENCES, AX_SCHEDULER_PICKER_DEFAULT_TIME_FORMAT, AX_SCHEDULER_PICKER_DEFAULT_TIME_PRECISION, AX_SCHEDULER_PICKER_HOURLY_CONFIG, AX_SCHEDULER_PICKER_MONTHLY_CONFIG, AX_SCHEDULER_PICKER_MONTHS, AX_SCHEDULER_PICKER_MONTH_TRANSLATION_KEYS, AX_SCHEDULER_PICKER_OCCURRENCE_POSITIONS, AX_SCHEDULER_PICKER_RRULE_DAY_KEYS, AX_SCHEDULER_PICKER_WEEKDAY_END, AX_SCHEDULER_PICKER_WEEKDAY_START, AX_SCHEDULER_PICKER_WEEKLY_CONFIG, AX_SCHEDULER_PICKER_YEARLY_CONFIG, dateExistsInArray, getDayTranslationKey, getDefaultSchedulerPickerConfig, getMonthTranslationKey, getRRuleDayKey, isSameDate, normalizeDate, reorderDaysByFirstDay };
|
|
2339
|
+
//# sourceMappingURL=acorex-components-scheduler-picker.mjs.map
|