@masterteam/system-settings 0.0.19 → 0.0.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.
@@ -205,8 +205,15 @@ class SystemSettingsTimeSheetSection {
205
205
  dayOptions = input([], ...(ngDevMode ? [{ debugName: "dayOptions" }] : /* istanbul ignore next */ []));
206
206
  frequencyOptions = input([], ...(ngDevMode ? [{ debugName: "frequencyOptions" }] : /* istanbul ignore next */ []));
207
207
  maxDailyBelowDaily = input(false, ...(ngDevMode ? [{ debugName: "maxDailyBelowDaily" }] : /* istanbul ignore next */ []));
208
+ /**
209
+ * Hides the Timesheet Policy card only. Global Working Hours always
210
+ * renders - it is host-relevant on its own (working days/hours feed
211
+ * scheduling and calendar logic beyond timesheets), so a host without a
212
+ * timesheet feature can still configure it.
213
+ */
214
+ hidePolicy = input(false, ...(ngDevMode ? [{ debugName: "hidePolicy" }] : /* istanbul ignore next */ []));
208
215
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettingsTimeSheetSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
209
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: SystemSettingsTimeSheetSection, isStandalone: true, selector: "mt-system-settings-timesheet-section", inputs: { policyForm: { classPropertyName: "policyForm", publicName: "policyForm", isSignal: true, isRequired: true, transformFunction: null }, globalWorkingHoursForm: { classPropertyName: "globalWorkingHoursForm", publicName: "globalWorkingHoursForm", isSignal: true, isRequired: true, transformFunction: null }, dayOptions: { classPropertyName: "dayOptions", publicName: "dayOptions", isSignal: true, isRequired: false, transformFunction: null }, frequencyOptions: { classPropertyName: "frequencyOptions", publicName: "frequencyOptions", isSignal: true, isRequired: false, transformFunction: null }, maxDailyBelowDaily: { classPropertyName: "maxDailyBelowDaily", publicName: "maxDailyBelowDaily", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\r\n <div class=\"grid gap-6 xl:grid-cols-2 mb-6\">\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"policyForm()\" class=\"space-y-5\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"general-card-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"general-card-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-select-field\r\n formControlName=\"frequency\"\r\n [options]=\"frequencyOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('frequency')\"\r\n [placeholder]=\"t('frequency-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-number-field\r\n formControlName=\"maxDailyHours\"\r\n [label]=\"t('max-daily-hours')\"\r\n [placeholder]=\"t('max-daily-hours-placeholder')\"\r\n [min]=\"1\"\r\n [max]=\"24\"\r\n [required]=\"true\"\r\n [hint]=\"maxDailyBelowDaily() ? t('max-daily-below-daily') : ''\"\r\n />\r\n\r\n <mt-number-field\r\n formControlName=\"submissionDeadlineDays\"\r\n [label]=\"t('submission-deadline-days')\"\r\n [placeholder]=\"t('submission-deadline-days-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"90\"\r\n [required]=\"true\"\r\n [hint]=\"t('submission-deadline-hint')\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid gap-3 md:grid-cols-2\">\r\n <mt-toggle-field\r\n formControlName=\"requireDescription\"\r\n [label]=\"t('require-description')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowFutureEntry\"\r\n [label]=\"t('allow-future-entry')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowBackdatedEntry\"\r\n [label]=\"t('allow-backdated-entry')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"autoLockOnApprove\"\r\n [label]=\"t('auto-lock-on-approve')\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"globalWorkingHoursForm()\" class=\"space-y-5\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"working-hours-card-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"working-hours-card-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-multi-select-field\r\n class=\"md:col-span-2\"\r\n formControlName=\"workingDays\"\r\n [options]=\"dayOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'dayNumber'\"\r\n [label]=\"t('working-days')\"\r\n [placeholder]=\"t('working-days-placeholder')\"\r\n [display]=\"'chip'\"\r\n [required]=\"true\"\r\n [showClear]=\"true\"\r\n />\r\n\r\n <mt-number-field\r\n class=\"md:col-span-2\"\r\n formControlName=\"hoursPerDay\"\r\n [label]=\"t('daily-working-hours')\"\r\n [placeholder]=\"t('daily-working-hours-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"24\"\r\n [required]=\"true\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
216
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: SystemSettingsTimeSheetSection, isStandalone: true, selector: "mt-system-settings-timesheet-section", inputs: { policyForm: { classPropertyName: "policyForm", publicName: "policyForm", isSignal: true, isRequired: true, transformFunction: null }, globalWorkingHoursForm: { classPropertyName: "globalWorkingHoursForm", publicName: "globalWorkingHoursForm", isSignal: true, isRequired: true, transformFunction: null }, dayOptions: { classPropertyName: "dayOptions", publicName: "dayOptions", isSignal: true, isRequired: false, transformFunction: null }, frequencyOptions: { classPropertyName: "frequencyOptions", publicName: "frequencyOptions", isSignal: true, isRequired: false, transformFunction: null }, maxDailyBelowDaily: { classPropertyName: "maxDailyBelowDaily", publicName: "maxDailyBelowDaily", isSignal: true, isRequired: false, transformFunction: null }, hidePolicy: { classPropertyName: "hidePolicy", publicName: "hidePolicy", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\r\n <div\r\n [class]=\"\r\n hidePolicy() ? 'grid gap-6 mb-6' : 'grid gap-6 xl:grid-cols-2 mb-6'\r\n \"\r\n >\r\n @if (!hidePolicy()) {\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"policyForm()\" class=\"space-y-5\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"general-card-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"general-card-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-select-field\r\n formControlName=\"frequency\"\r\n [options]=\"frequencyOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('frequency')\"\r\n [placeholder]=\"t('frequency-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-number-field\r\n formControlName=\"maxDailyHours\"\r\n [label]=\"t('max-daily-hours')\"\r\n [placeholder]=\"t('max-daily-hours-placeholder')\"\r\n [min]=\"1\"\r\n [max]=\"24\"\r\n [required]=\"true\"\r\n [hint]=\"maxDailyBelowDaily() ? t('max-daily-below-daily') : ''\"\r\n />\r\n\r\n <mt-number-field\r\n formControlName=\"submissionDeadlineDays\"\r\n [label]=\"t('submission-deadline-days')\"\r\n [placeholder]=\"t('submission-deadline-days-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"90\"\r\n [required]=\"true\"\r\n [hint]=\"t('submission-deadline-hint')\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid gap-3 md:grid-cols-2\">\r\n <mt-toggle-field\r\n formControlName=\"requireDescription\"\r\n [label]=\"t('require-description')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowFutureEntry\"\r\n [label]=\"t('allow-future-entry')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowBackdatedEntry\"\r\n [label]=\"t('allow-backdated-entry')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"autoLockOnApprove\"\r\n [label]=\"t('auto-lock-on-approve')\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"globalWorkingHoursForm()\" class=\"space-y-5\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"working-hours-card-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"working-hours-card-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-multi-select-field\r\n class=\"md:col-span-2\"\r\n formControlName=\"workingDays\"\r\n [options]=\"dayOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'dayNumber'\"\r\n [label]=\"t('working-days')\"\r\n [placeholder]=\"t('working-days-placeholder')\"\r\n [display]=\"'chip'\"\r\n [required]=\"true\"\r\n [showClear]=\"true\"\r\n />\r\n\r\n <mt-number-field\r\n class=\"md:col-span-2\"\r\n formControlName=\"hoursPerDay\"\r\n [label]=\"t('daily-working-hours')\"\r\n [placeholder]=\"t('daily-working-hours-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"24\"\r\n [required]=\"true\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
210
217
  }
211
218
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettingsTimeSheetSection, decorators: [{
212
219
  type: Component,
@@ -218,8 +225,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
218
225
  NumberField,
219
226
  SelectField,
220
227
  ToggleField,
221
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\r\n <div class=\"grid gap-6 xl:grid-cols-2 mb-6\">\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"policyForm()\" class=\"space-y-5\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"general-card-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"general-card-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-select-field\r\n formControlName=\"frequency\"\r\n [options]=\"frequencyOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('frequency')\"\r\n [placeholder]=\"t('frequency-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-number-field\r\n formControlName=\"maxDailyHours\"\r\n [label]=\"t('max-daily-hours')\"\r\n [placeholder]=\"t('max-daily-hours-placeholder')\"\r\n [min]=\"1\"\r\n [max]=\"24\"\r\n [required]=\"true\"\r\n [hint]=\"maxDailyBelowDaily() ? t('max-daily-below-daily') : ''\"\r\n />\r\n\r\n <mt-number-field\r\n formControlName=\"submissionDeadlineDays\"\r\n [label]=\"t('submission-deadline-days')\"\r\n [placeholder]=\"t('submission-deadline-days-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"90\"\r\n [required]=\"true\"\r\n [hint]=\"t('submission-deadline-hint')\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid gap-3 md:grid-cols-2\">\r\n <mt-toggle-field\r\n formControlName=\"requireDescription\"\r\n [label]=\"t('require-description')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowFutureEntry\"\r\n [label]=\"t('allow-future-entry')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowBackdatedEntry\"\r\n [label]=\"t('allow-backdated-entry')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"autoLockOnApprove\"\r\n [label]=\"t('auto-lock-on-approve')\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"globalWorkingHoursForm()\" class=\"space-y-5\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"working-hours-card-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"working-hours-card-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-multi-select-field\r\n class=\"md:col-span-2\"\r\n formControlName=\"workingDays\"\r\n [options]=\"dayOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'dayNumber'\"\r\n [label]=\"t('working-days')\"\r\n [placeholder]=\"t('working-days-placeholder')\"\r\n [display]=\"'chip'\"\r\n [required]=\"true\"\r\n [showClear]=\"true\"\r\n />\r\n\r\n <mt-number-field\r\n class=\"md:col-span-2\"\r\n formControlName=\"hoursPerDay\"\r\n [label]=\"t('daily-working-hours')\"\r\n [placeholder]=\"t('daily-working-hours-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"24\"\r\n [required]=\"true\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n </div>\r\n</ng-container>\r\n" }]
222
- }], propDecorators: { policyForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "policyForm", required: true }] }], globalWorkingHoursForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalWorkingHoursForm", required: true }] }], dayOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "dayOptions", required: false }] }], frequencyOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "frequencyOptions", required: false }] }], maxDailyBelowDaily: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDailyBelowDaily", required: false }] }] } });
228
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\r\n <div\r\n [class]=\"\r\n hidePolicy() ? 'grid gap-6 mb-6' : 'grid gap-6 xl:grid-cols-2 mb-6'\r\n \"\r\n >\r\n @if (!hidePolicy()) {\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"policyForm()\" class=\"space-y-5\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"general-card-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"general-card-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-select-field\r\n formControlName=\"frequency\"\r\n [options]=\"frequencyOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('frequency')\"\r\n [placeholder]=\"t('frequency-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-number-field\r\n formControlName=\"maxDailyHours\"\r\n [label]=\"t('max-daily-hours')\"\r\n [placeholder]=\"t('max-daily-hours-placeholder')\"\r\n [min]=\"1\"\r\n [max]=\"24\"\r\n [required]=\"true\"\r\n [hint]=\"maxDailyBelowDaily() ? t('max-daily-below-daily') : ''\"\r\n />\r\n\r\n <mt-number-field\r\n formControlName=\"submissionDeadlineDays\"\r\n [label]=\"t('submission-deadline-days')\"\r\n [placeholder]=\"t('submission-deadline-days-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"90\"\r\n [required]=\"true\"\r\n [hint]=\"t('submission-deadline-hint')\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid gap-3 md:grid-cols-2\">\r\n <mt-toggle-field\r\n formControlName=\"requireDescription\"\r\n [label]=\"t('require-description')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowFutureEntry\"\r\n [label]=\"t('allow-future-entry')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowBackdatedEntry\"\r\n [label]=\"t('allow-backdated-entry')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"autoLockOnApprove\"\r\n [label]=\"t('auto-lock-on-approve')\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"globalWorkingHoursForm()\" class=\"space-y-5\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"working-hours-card-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"working-hours-card-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-multi-select-field\r\n class=\"md:col-span-2\"\r\n formControlName=\"workingDays\"\r\n [options]=\"dayOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'dayNumber'\"\r\n [label]=\"t('working-days')\"\r\n [placeholder]=\"t('working-days-placeholder')\"\r\n [display]=\"'chip'\"\r\n [required]=\"true\"\r\n [showClear]=\"true\"\r\n />\r\n\r\n <mt-number-field\r\n class=\"md:col-span-2\"\r\n formControlName=\"hoursPerDay\"\r\n [label]=\"t('daily-working-hours')\"\r\n [placeholder]=\"t('daily-working-hours-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"24\"\r\n [required]=\"true\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n </div>\r\n</ng-container>\r\n" }]
229
+ }], propDecorators: { policyForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "policyForm", required: true }] }], globalWorkingHoursForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalWorkingHoursForm", required: true }] }], dayOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "dayOptions", required: false }] }], frequencyOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "frequencyOptions", required: false }] }], maxDailyBelowDaily: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDailyBelowDaily", required: false }] }], hidePolicy: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidePolicy", required: false }] }] } });
223
230
 
224
231
  /** The settings record General Configuration fields live in. */
225
232
  const GENERAL_CONFIGURATION_SETTING_KEY = 'Identity';
@@ -267,6 +274,11 @@ const EXPLORE_DEFAULT_VIEW_OPTIONS = [
267
274
  translationKey: 'explore-default-view-timeline',
268
275
  icon: 'time.clock',
269
276
  },
277
+ {
278
+ id: 'table',
279
+ translationKey: 'explore-default-view-table',
280
+ icon: 'layout.table',
281
+ },
270
282
  ];
271
283
  const DEFAULT_GENERAL_CONFIGURATION = {
272
284
  defaultExploreView: 'cards',
@@ -385,23 +397,61 @@ class SystemSettings {
385
397
  transloco = inject(TranslocoService);
386
398
  modal = inject(ModalService);
387
399
  toast = inject(ToastService);
388
- apiBasePath = input('settings', ...(ngDevMode ? [{ debugName: "apiBasePath" }] : /* istanbul ignore next */ []));
389
- backRoute = input('/control-panel/product-settings', ...(ngDevMode ? [{ debugName: "backRoute" }] : /* istanbul ignore next */ []));
400
+ /**
401
+ * Base path for the settings API. Safe to omit from a route's `data`
402
+ * even when the host uses `withComponentInputBinding()` - see
403
+ * `defaultWhenUndefined`.
404
+ */
405
+ apiBasePath = input('settings', { ...(ngDevMode ? { debugName: "apiBasePath" } : /* istanbul ignore next */ {}), transform: defaultWhenUndefined('settings') });
406
+ /**
407
+ * Route the page's back button navigates to; falsy (including an
408
+ * explicit `null`) disables it - see `goBack()`. Safe to omit from a
409
+ * route's `data` even when the host uses `withComponentInputBinding()`
410
+ * - see `defaultWhenUndefined`.
411
+ */
412
+ backRoute = input('/control-panel/product-settings', { ...(ngDevMode ? { debugName: "backRoute" } : /* istanbul ignore next */ {}), transform: defaultWhenUndefined('/control-panel/product-settings') });
390
413
  formatSchema = input(null, ...(ngDevMode ? [{ debugName: "formatSchema" }] : /* istanbul ignore next */ []));
391
- breadcrumbItems = [
392
- {
393
- label: '',
394
- icon: 'general.home-line',
395
- routerLink: '/control-panel/workspaces',
396
- },
397
- {
398
- label: this.transloco.translate('product-settings.product-settings'),
399
- routerLink: '/control-panel/product-settings',
400
- },
401
- {
402
- label: this.transloco.translate('system-settings.page-title'),
403
- },
404
- ];
414
+ /**
415
+ * Breadcrumb "home" link. `null` renders the crumb as non-navigable.
416
+ * Safe to omit from a route's `data` even when the host uses
417
+ * `withComponentInputBinding()` - see `defaultWhenUndefined`.
418
+ */
419
+ homeRoute = input('/control-panel/workspaces', { ...(ngDevMode ? { debugName: "homeRoute" } : /* istanbul ignore next */ {}), transform: defaultWhenUndefined('/control-panel/workspaces') });
420
+ /**
421
+ * Hides the Timesheet Policy card only - Global Working Hours stays
422
+ * visible and required, since it's host-relevant on its own (working
423
+ * days/hours feed scheduling and calendar logic beyond timesheets).
424
+ * TimeSheetPolicy's fields lose their validators and are excluded from
425
+ * save diffing while hidden; GlobalWorkingHours is unaffected.
426
+ */
427
+ hideTimeSheet = input(false, ...(ngDevMode ? [{ debugName: "hideTimeSheet" }] : /* istanbul ignore next */ []));
428
+ /**
429
+ * Restricts which Explore-default-view options are offered. `null` (the
430
+ * default) preserves pplus5's original two options (`'cards'`,
431
+ * `'timeline'`) - NOT the full catalog, since the catalog now also
432
+ * contains `'table'` (added for splus4) and an unset input must not
433
+ * silently surface it to hosts that never opted in. Pass the ids
434
+ * explicitly (e.g. `['cards', 'table']`, or all three) to get anything
435
+ * else.
436
+ */
437
+ exploreViewOptions = input(null, ...(ngDevMode ? [{ debugName: "exploreViewOptions" }] : /* istanbul ignore next */ []));
438
+ breadcrumbItems = computed(() => {
439
+ const homeRoute = this.homeRoute();
440
+ return [
441
+ {
442
+ label: '',
443
+ icon: 'general.home-line',
444
+ ...(homeRoute ? { routerLink: homeRoute } : {}),
445
+ },
446
+ {
447
+ label: this.transloco.translate('product-settings.product-settings'),
448
+ routerLink: '/control-panel/product-settings',
449
+ },
450
+ {
451
+ label: this.transloco.translate('system-settings.page-title'),
452
+ },
453
+ ];
454
+ }, ...(ngDevMode ? [{ debugName: "breadcrumbItems" }] : /* istanbul ignore next */ []));
405
455
  form = new FormGroup({
406
456
  generalConfiguration: new FormGroup({
407
457
  defaultExploreView: new FormControl('cards', {
@@ -425,36 +475,24 @@ class SystemSettings {
425
475
  days: new FormControl([], { nonNullable: true }),
426
476
  }),
427
477
  timeSheetPolicy: new FormGroup({
428
- frequency: new FormControl('Weekly', Validators.required),
429
- maxDailyHours: new FormControl(24, [
430
- Validators.required,
431
- Validators.min(1),
432
- Validators.max(24),
433
- ]),
478
+ frequency: new FormControl('Weekly', TIME_SHEET_FREQUENCY_VALIDATORS),
479
+ maxDailyHours: new FormControl(24, TIME_SHEET_MAX_DAILY_HOURS_VALIDATORS),
434
480
  requireDescription: new FormControl(false, { nonNullable: true }),
435
481
  allowFutureEntry: new FormControl(false, { nonNullable: true }),
436
482
  allowBackdatedEntry: new FormControl(true, { nonNullable: true }),
437
483
  autoLockOnApprove: new FormControl(true, { nonNullable: true }),
438
- submissionDeadlineDays: new FormControl(3, [
439
- Validators.required,
440
- Validators.min(0),
441
- Validators.max(90),
442
- ]),
484
+ submissionDeadlineDays: new FormControl(3, TIME_SHEET_SUBMISSION_DEADLINE_VALIDATORS),
443
485
  }),
444
486
  globalWorkingHours: new FormGroup({
445
- timeZoneId: new FormControl(null, Validators.required),
487
+ timeZoneId: new FormControl(null, GLOBAL_WORKING_HOURS_TIMEZONE_VALIDATORS),
446
488
  workingDays: new FormControl([0, 1, 2, 3, 4], {
447
489
  nonNullable: true,
448
- validators: [Validators.required],
490
+ validators: GLOBAL_WORKING_HOURS_WORKING_DAYS_VALIDATORS,
449
491
  }),
450
- hoursPerDay: new FormControl(8, [
451
- Validators.required,
452
- Validators.min(0),
453
- Validators.max(24),
454
- ]),
492
+ hoursPerDay: new FormControl(8, GLOBAL_WORKING_HOURS_HOURS_PER_DAY_VALIDATORS),
455
493
  holidaysCsv: new FormControl('', { nonNullable: true }),
456
494
  }),
457
- }, maxDailyHoursGteHoursPerDay);
495
+ }, maxDailyHoursGteHoursPerDay(() => this.hideTimeSheet()));
458
496
  settings = signal(null, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
459
497
  settingsLoading = signal(false, ...(ngDevMode ? [{ debugName: "settingsLoading" }] : /* istanbul ignore next */ []));
460
498
  settingsError = signal(null, ...(ngDevMode ? [{ debugName: "settingsError" }] : /* istanbul ignore next */ []));
@@ -525,9 +563,25 @@ class SystemSettings {
525
563
  name: this.transloco.translate(`system-settings.${day.translationKey}`),
526
564
  }));
527
565
  }, ...(ngDevMode ? [{ debugName: "dotnetDayOptions" }] : /* istanbul ignore next */ []));
566
+ /**
567
+ * The Explore-default-view ids actually offered, in the fixed catalog's
568
+ * order: `exploreViewOptions()` when the host sets it, else the legacy
569
+ * pplus5 pair (`DEFAULT_EXPLORE_VIEW_OPTIONS`) - deliberately NOT the full
570
+ * `EXPLORE_DEFAULT_VIEW_OPTIONS` catalog, since that now includes `'table'`
571
+ * and an unconfigured host must keep seeing exactly what it saw before.
572
+ * Filtered against the catalog either way, so an invalid/unknown id in a
573
+ * host's list is silently dropped rather than offered. Always non-empty
574
+ * unless a host passes an empty array.
575
+ */
576
+ allowedExploreDefaultViews = computed(() => {
577
+ const configured = this.exploreViewOptions() ?? DEFAULT_EXPLORE_VIEW_OPTIONS;
578
+ const configuredSet = new Set(configured);
579
+ return EXPLORE_DEFAULT_VIEW_OPTIONS.map((option) => option.id).filter((id) => configuredSet.has(id));
580
+ }, ...(ngDevMode ? [{ debugName: "allowedExploreDefaultViews" }] : /* istanbul ignore next */ []));
528
581
  exploreDefaultViewOptions = computed(() => {
529
582
  this.activeLang();
530
- return EXPLORE_DEFAULT_VIEW_OPTIONS.map((option) => ({
583
+ const allowed = new Set(this.allowedExploreDefaultViews());
584
+ return EXPLORE_DEFAULT_VIEW_OPTIONS.filter((option) => allowed.has(option.id)).map((option) => ({
531
585
  id: option.id,
532
586
  name: this.transloco.translate(`system-settings.${option.translationKey}`),
533
587
  icon: option.icon,
@@ -558,7 +612,12 @@ class SystemSettings {
558
612
  !this.areEqual(initial.timezone, current.timezone) ||
559
613
  !this.areEqual(initial.currency, current.currency) ||
560
614
  !this.areEqual(initial.weekend, current.weekend) ||
561
- !this.areEqual(initial.timeSheetPolicy, current.timeSheetPolicy) ||
615
+ // Mirrors onSave()'s exclusion below: while Timesheet Policy is
616
+ // hidden nothing in the UI can change these fields (the card isn't
617
+ // rendered), but keeping this guard symmetric with onSave() means
618
+ // hasChanges() and the actual save payload can never disagree.
619
+ (!this.hideTimeSheet() &&
620
+ !this.areEqual(initial.timeSheetPolicy, current.timeSheetPolicy)) ||
562
621
  !this.areEqual(initial.globalWorkingHours, current.globalWorkingHours));
563
622
  }, ...(ngDevMode ? [{ debugName: "hasChanges" }] : /* istanbul ignore next */ []));
564
623
  canSaveSettings = computed(() => !this.isLoading() &&
@@ -573,6 +632,30 @@ class SystemSettings {
573
632
  to: formatDateOnly(holiday.to),
574
633
  })), ...(ngDevMode ? [{ debugName: "holidayTableRows" }] : /* istanbul ignore next */ []));
575
634
  constructor() {
635
+ // Only Timesheet Policy is conditionally hidden - Global Working Hours
636
+ // keeps its validators unconditionally (set once at construction, see
637
+ // the form below), since that card is always visible.
638
+ effect(() => {
639
+ const hidden = this.hideTimeSheet();
640
+ const timeSheetPolicy = this.form.controls.timeSheetPolicy.controls;
641
+ if (hidden) {
642
+ timeSheetPolicy.frequency.clearValidators();
643
+ timeSheetPolicy.maxDailyHours.clearValidators();
644
+ timeSheetPolicy.submissionDeadlineDays.clearValidators();
645
+ }
646
+ else {
647
+ timeSheetPolicy.frequency.setValidators(TIME_SHEET_FREQUENCY_VALIDATORS);
648
+ timeSheetPolicy.maxDailyHours.setValidators(TIME_SHEET_MAX_DAILY_HOURS_VALIDATORS);
649
+ timeSheetPolicy.submissionDeadlineDays.setValidators(TIME_SHEET_SUBMISSION_DEADLINE_VALIDATORS);
650
+ }
651
+ for (const control of [
652
+ timeSheetPolicy.frequency,
653
+ timeSheetPolicy.maxDailyHours,
654
+ timeSheetPolicy.submissionDeadlineDays,
655
+ ]) {
656
+ control.updateValueAndValidity({ emitEvent: false });
657
+ }
658
+ });
576
659
  effect(() => {
577
660
  const version = [
578
661
  this.settingsLastUpdated() ?? 'none',
@@ -694,7 +777,8 @@ class SystemSettings {
694
777
  value: nextSnapshot.weekend,
695
778
  });
696
779
  }
697
- if (!this.areEqual(initialSnapshot.timeSheetPolicy, nextSnapshot.timeSheetPolicy)) {
780
+ if (!this.hideTimeSheet() &&
781
+ !this.areEqual(initialSnapshot.timeSheetPolicy, nextSnapshot.timeSheetPolicy)) {
698
782
  values.push({
699
783
  key: 'TimeSheetPolicy',
700
784
  value: nextSnapshot.timeSheetPolicy,
@@ -890,7 +974,7 @@ class SystemSettings {
890
974
  }
891
975
  buildGeneralConfigurationValue() {
892
976
  return {
893
- defaultExploreView: normalizeExploreDefaultView(this.form.controls.generalConfiguration.controls.defaultExploreView
977
+ defaultExploreView: this.normalizeExploreDefaultView(this.form.controls.generalConfiguration.controls.defaultExploreView
894
978
  .value),
895
979
  showDesignSwitcher: this.form.controls.generalConfiguration.controls.showDesignSwitcher
896
980
  .value === true,
@@ -932,7 +1016,7 @@ class SystemSettings {
932
1016
  return { ...DEFAULT_GENERAL_CONFIGURATION };
933
1017
  }
934
1018
  return {
935
- defaultExploreView: normalizeExploreDefaultView(setting.value['defaultExploreView'] ??
1019
+ defaultExploreView: this.normalizeExploreDefaultView(setting.value['defaultExploreView'] ??
936
1020
  setting.value['DefaultExploreView']),
937
1021
  showDesignSwitcher: normalizeShowDesignSwitcher(setting.value['showDesignSwitcher'] ??
938
1022
  setting.value['ShowDesignSwitcher']),
@@ -1086,10 +1170,24 @@ class SystemSettings {
1086
1170
  }
1087
1171
  normalizeGeneralConfigurationSnapshot(value) {
1088
1172
  return {
1089
- defaultExploreView: normalizeExploreDefaultView(value.defaultExploreView),
1173
+ defaultExploreView: this.normalizeExploreDefaultView(value.defaultExploreView),
1090
1174
  showDesignSwitcher: normalizeShowDesignSwitcher(value.showDesignSwitcher),
1091
1175
  };
1092
1176
  }
1177
+ /**
1178
+ * Resolves a stored/incoming value against the currently allowed Explore
1179
+ * views (`allowedExploreDefaultViews()`), not the full static catalog, so a
1180
+ * host-restricted `exploreViewOptions` is enforced on both hydration and
1181
+ * save. Falls back to the first allowed option - not a hardcoded 'cards' -
1182
+ * since a host may configure a subset that excludes it.
1183
+ */
1184
+ normalizeExploreDefaultView(value) {
1185
+ const allowed = this.allowedExploreDefaultViews();
1186
+ if (allowed.some((id) => id === value)) {
1187
+ return value;
1188
+ }
1189
+ return allowed[0] ?? DEFAULT_GENERAL_CONFIGURATION.defaultExploreView;
1190
+ }
1093
1191
  normalizeTimezoneSnapshot(value) {
1094
1192
  const defaults = this.getDefaultTimezoneValue();
1095
1193
  return {
@@ -1337,7 +1435,7 @@ class SystemSettings {
1337
1435
  return JSON.stringify(left) === JSON.stringify(right);
1338
1436
  }
1339
1437
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettings, deps: [], target: i0.ɵɵFactoryTarget.Component });
1340
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: SystemSettings, isStandalone: true, selector: "mt-system-settings", inputs: { apiBasePath: { classPropertyName: "apiBasePath", publicName: "apiBasePath", isSignal: true, isRequired: false, transformFunction: null }, backRoute: { classPropertyName: "backRoute", publicName: "backRoute", isSignal: true, isRequired: false, transformFunction: null }, formatSchema: { classPropertyName: "formatSchema", publicName: "formatSchema", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\r\n <mt-page\r\n [title]=\"t('page-title')\"\r\n [avatarIcon]=\"'general.settings-02'\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-emerald-100)',\r\n '--p-avatar-color': 'var(--p-emerald-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n >\r\n <div class=\"flex flex-col gap-3\">\r\n <div\r\n class=\"flex flex-col gap-4 md:flex-row md:items-end md:justify-between\"\r\n >\r\n <div>\r\n <h3 class=\"text-lg font-bold text-neutral-900\">\r\n {{ t(\"page-title\") }}\r\n </h3>\r\n <mt-breadcrumb\r\n [items]=\"breadcrumbItems\"\r\n [styleClass]=\"'flex justify-start mx-1'\"\r\n />\r\n </div>\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-01\"\r\n [tooltip]=\"t('save-tooltip')\"\r\n [badge]=\"hasChanges() ? '!' : ''\"\r\n badgeSeverity=\"warn\"\r\n [loading]=\"updating()\"\r\n [disabled]=\"!canSaveSettings()\"\r\n (onClick)=\"onSave()\"\r\n />\r\n </div>\r\n\r\n @if (isLoading()) {\r\n <div class=\"space-y-4\">\r\n <p-skeleton width=\"100%\" height=\"12rem\" borderRadius=\"0.75rem\" />\r\n <p-skeleton width=\"100%\" height=\"18rem\" borderRadius=\"0.75rem\" />\r\n <p-skeleton width=\"100%\" height=\"14rem\" borderRadius=\"0.75rem\" />\r\n </div>\r\n } @else {\r\n <!--\r\n BE/HTTP errors (timezonesError, settingsError, updateError) are already\r\n surfaced as toasts by the HTTP interceptor, so they are intentionally\r\n not rendered as top-of-page banners here to avoid duplicate messaging.\r\n -->\r\n <div class=\"space-y-6\">\r\n <mt-system-settings-general-section\r\n [generalConfigurationForm]=\"form.controls.generalConfiguration\"\r\n [timezoneForm]=\"form.controls.timezone\"\r\n [currencyForm]=\"form.controls.currency\"\r\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\r\n [dateFormatOptions]=\"dateFormatOptions()\"\r\n [timeFormatOptions]=\"timeFormatOptions()\"\r\n [currencyOptions]=\"currencyOptions()\"\r\n [currencyFormatOptions]=\"currencyFormatOptions()\"\r\n />\r\n\r\n <mt-system-settings-timesheet-section\r\n [policyForm]=\"form.controls.timeSheetPolicy\"\r\n [globalWorkingHoursForm]=\"form.controls.globalWorkingHours\"\r\n [dayOptions]=\"dotnetDayOptions()\"\r\n [frequencyOptions]=\"frequencyOptions()\"\r\n [maxDailyBelowDaily]=\"form.errors?.['maxDailyBelowDaily'] ?? false\"\r\n />\r\n\r\n <mt-system-settings-holidays-section\r\n [holidays]=\"holidayTableRows()\"\r\n (addHoliday)=\"openAddHoliday()\"\r\n (editHoliday)=\"editHoliday($event)\"\r\n (deleteHoliday)=\"deleteHoliday($event)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-page>\r\n</ng-container>\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Breadcrumb, selector: "mt-breadcrumb", inputs: ["items", "styleClass"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: SystemSettingsHolidaysSection, selector: "mt-system-settings-holidays-section", inputs: ["holidays"], outputs: ["addHoliday", "editHoliday", "deleteHoliday"] }, { kind: "component", type: SystemSettingsGeneralSection, selector: "mt-system-settings-general-section", inputs: ["generalConfigurationForm", "timezoneForm", "currencyForm", "exploreDefaultViewOptions", "dateFormatOptions", "timeFormatOptions", "currencyOptions", "currencyFormatOptions"] }, { kind: "component", type: SystemSettingsTimeSheetSection, selector: "mt-system-settings-timesheet-section", inputs: ["policyForm", "globalWorkingHoursForm", "dayOptions", "frequencyOptions", "maxDailyBelowDaily"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1438
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: SystemSettings, isStandalone: true, selector: "mt-system-settings", inputs: { apiBasePath: { classPropertyName: "apiBasePath", publicName: "apiBasePath", isSignal: true, isRequired: false, transformFunction: null }, backRoute: { classPropertyName: "backRoute", publicName: "backRoute", isSignal: true, isRequired: false, transformFunction: null }, formatSchema: { classPropertyName: "formatSchema", publicName: "formatSchema", isSignal: true, isRequired: false, transformFunction: null }, homeRoute: { classPropertyName: "homeRoute", publicName: "homeRoute", isSignal: true, isRequired: false, transformFunction: null }, hideTimeSheet: { classPropertyName: "hideTimeSheet", publicName: "hideTimeSheet", isSignal: true, isRequired: false, transformFunction: null }, exploreViewOptions: { classPropertyName: "exploreViewOptions", publicName: "exploreViewOptions", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\r\n <mt-page\r\n [title]=\"t('page-title')\"\r\n [avatarIcon]=\"'general.settings-02'\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-emerald-100)',\r\n '--p-avatar-color': 'var(--p-emerald-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n >\r\n <div class=\"flex flex-col gap-3\">\r\n <div\r\n class=\"flex flex-col gap-4 md:flex-row md:items-end md:justify-between\"\r\n >\r\n <div>\r\n <h3 class=\"text-lg font-bold text-neutral-900\">\r\n {{ t(\"page-title\") }}\r\n </h3>\r\n <mt-breadcrumb\r\n [items]=\"breadcrumbItems()\"\r\n [styleClass]=\"'flex justify-start mx-1'\"\r\n />\r\n </div>\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-01\"\r\n [tooltip]=\"t('save-tooltip')\"\r\n [badge]=\"hasChanges() ? '!' : ''\"\r\n badgeSeverity=\"warn\"\r\n [loading]=\"updating()\"\r\n [disabled]=\"!canSaveSettings()\"\r\n (onClick)=\"onSave()\"\r\n />\r\n </div>\r\n\r\n @if (isLoading()) {\r\n <div class=\"space-y-4\">\r\n <p-skeleton width=\"100%\" height=\"12rem\" borderRadius=\"0.75rem\" />\r\n <p-skeleton width=\"100%\" height=\"18rem\" borderRadius=\"0.75rem\" />\r\n <p-skeleton width=\"100%\" height=\"14rem\" borderRadius=\"0.75rem\" />\r\n </div>\r\n } @else {\r\n <!--\r\n BE/HTTP errors (timezonesError, settingsError, updateError) are already\r\n surfaced as toasts by the HTTP interceptor, so they are intentionally\r\n not rendered as top-of-page banners here to avoid duplicate messaging.\r\n -->\r\n <div class=\"space-y-6\">\r\n <mt-system-settings-general-section\r\n [generalConfigurationForm]=\"form.controls.generalConfiguration\"\r\n [timezoneForm]=\"form.controls.timezone\"\r\n [currencyForm]=\"form.controls.currency\"\r\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\r\n [dateFormatOptions]=\"dateFormatOptions()\"\r\n [timeFormatOptions]=\"timeFormatOptions()\"\r\n [currencyOptions]=\"currencyOptions()\"\r\n [currencyFormatOptions]=\"currencyFormatOptions()\"\r\n />\r\n\r\n <mt-system-settings-timesheet-section\r\n [policyForm]=\"form.controls.timeSheetPolicy\"\r\n [globalWorkingHoursForm]=\"form.controls.globalWorkingHours\"\r\n [dayOptions]=\"dotnetDayOptions()\"\r\n [frequencyOptions]=\"frequencyOptions()\"\r\n [maxDailyBelowDaily]=\"form.errors?.['maxDailyBelowDaily'] ?? false\"\r\n [hidePolicy]=\"hideTimeSheet()\"\r\n />\r\n\r\n <mt-system-settings-holidays-section\r\n [holidays]=\"holidayTableRows()\"\r\n (addHoliday)=\"openAddHoliday()\"\r\n (editHoliday)=\"editHoliday($event)\"\r\n (deleteHoliday)=\"deleteHoliday($event)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-page>\r\n</ng-container>\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Breadcrumb, selector: "mt-breadcrumb", inputs: ["items", "styleClass"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: SystemSettingsHolidaysSection, selector: "mt-system-settings-holidays-section", inputs: ["holidays"], outputs: ["addHoliday", "editHoliday", "deleteHoliday"] }, { kind: "component", type: SystemSettingsGeneralSection, selector: "mt-system-settings-general-section", inputs: ["generalConfigurationForm", "timezoneForm", "currencyForm", "exploreDefaultViewOptions", "dateFormatOptions", "timeFormatOptions", "currencyOptions", "currencyFormatOptions"] }, { kind: "component", type: SystemSettingsTimeSheetSection, selector: "mt-system-settings-timesheet-section", inputs: ["policyForm", "globalWorkingHoursForm", "dayOptions", "frequencyOptions", "maxDailyBelowDaily", "hidePolicy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1341
1439
  }
1342
1440
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettings, decorators: [{
1343
1441
  type: Component,
@@ -1352,8 +1450,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1352
1450
  SystemSettingsHolidaysSection,
1353
1451
  SystemSettingsGeneralSection,
1354
1452
  SystemSettingsTimeSheetSection,
1355
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\r\n <mt-page\r\n [title]=\"t('page-title')\"\r\n [avatarIcon]=\"'general.settings-02'\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-emerald-100)',\r\n '--p-avatar-color': 'var(--p-emerald-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n >\r\n <div class=\"flex flex-col gap-3\">\r\n <div\r\n class=\"flex flex-col gap-4 md:flex-row md:items-end md:justify-between\"\r\n >\r\n <div>\r\n <h3 class=\"text-lg font-bold text-neutral-900\">\r\n {{ t(\"page-title\") }}\r\n </h3>\r\n <mt-breadcrumb\r\n [items]=\"breadcrumbItems\"\r\n [styleClass]=\"'flex justify-start mx-1'\"\r\n />\r\n </div>\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-01\"\r\n [tooltip]=\"t('save-tooltip')\"\r\n [badge]=\"hasChanges() ? '!' : ''\"\r\n badgeSeverity=\"warn\"\r\n [loading]=\"updating()\"\r\n [disabled]=\"!canSaveSettings()\"\r\n (onClick)=\"onSave()\"\r\n />\r\n </div>\r\n\r\n @if (isLoading()) {\r\n <div class=\"space-y-4\">\r\n <p-skeleton width=\"100%\" height=\"12rem\" borderRadius=\"0.75rem\" />\r\n <p-skeleton width=\"100%\" height=\"18rem\" borderRadius=\"0.75rem\" />\r\n <p-skeleton width=\"100%\" height=\"14rem\" borderRadius=\"0.75rem\" />\r\n </div>\r\n } @else {\r\n <!--\r\n BE/HTTP errors (timezonesError, settingsError, updateError) are already\r\n surfaced as toasts by the HTTP interceptor, so they are intentionally\r\n not rendered as top-of-page banners here to avoid duplicate messaging.\r\n -->\r\n <div class=\"space-y-6\">\r\n <mt-system-settings-general-section\r\n [generalConfigurationForm]=\"form.controls.generalConfiguration\"\r\n [timezoneForm]=\"form.controls.timezone\"\r\n [currencyForm]=\"form.controls.currency\"\r\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\r\n [dateFormatOptions]=\"dateFormatOptions()\"\r\n [timeFormatOptions]=\"timeFormatOptions()\"\r\n [currencyOptions]=\"currencyOptions()\"\r\n [currencyFormatOptions]=\"currencyFormatOptions()\"\r\n />\r\n\r\n <mt-system-settings-timesheet-section\r\n [policyForm]=\"form.controls.timeSheetPolicy\"\r\n [globalWorkingHoursForm]=\"form.controls.globalWorkingHours\"\r\n [dayOptions]=\"dotnetDayOptions()\"\r\n [frequencyOptions]=\"frequencyOptions()\"\r\n [maxDailyBelowDaily]=\"form.errors?.['maxDailyBelowDaily'] ?? false\"\r\n />\r\n\r\n <mt-system-settings-holidays-section\r\n [holidays]=\"holidayTableRows()\"\r\n (addHoliday)=\"openAddHoliday()\"\r\n (editHoliday)=\"editHoliday($event)\"\r\n (deleteHoliday)=\"deleteHoliday($event)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-page>\r\n</ng-container>\r\n", styles: [":host{display:block}\n"] }]
1356
- }], ctorParameters: () => [], propDecorators: { apiBasePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "apiBasePath", required: false }] }], backRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "backRoute", required: false }] }], formatSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatSchema", required: false }] }] } });
1453
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\r\n <mt-page\r\n [title]=\"t('page-title')\"\r\n [avatarIcon]=\"'general.settings-02'\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-emerald-100)',\r\n '--p-avatar-color': 'var(--p-emerald-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n >\r\n <div class=\"flex flex-col gap-3\">\r\n <div\r\n class=\"flex flex-col gap-4 md:flex-row md:items-end md:justify-between\"\r\n >\r\n <div>\r\n <h3 class=\"text-lg font-bold text-neutral-900\">\r\n {{ t(\"page-title\") }}\r\n </h3>\r\n <mt-breadcrumb\r\n [items]=\"breadcrumbItems()\"\r\n [styleClass]=\"'flex justify-start mx-1'\"\r\n />\r\n </div>\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-01\"\r\n [tooltip]=\"t('save-tooltip')\"\r\n [badge]=\"hasChanges() ? '!' : ''\"\r\n badgeSeverity=\"warn\"\r\n [loading]=\"updating()\"\r\n [disabled]=\"!canSaveSettings()\"\r\n (onClick)=\"onSave()\"\r\n />\r\n </div>\r\n\r\n @if (isLoading()) {\r\n <div class=\"space-y-4\">\r\n <p-skeleton width=\"100%\" height=\"12rem\" borderRadius=\"0.75rem\" />\r\n <p-skeleton width=\"100%\" height=\"18rem\" borderRadius=\"0.75rem\" />\r\n <p-skeleton width=\"100%\" height=\"14rem\" borderRadius=\"0.75rem\" />\r\n </div>\r\n } @else {\r\n <!--\r\n BE/HTTP errors (timezonesError, settingsError, updateError) are already\r\n surfaced as toasts by the HTTP interceptor, so they are intentionally\r\n not rendered as top-of-page banners here to avoid duplicate messaging.\r\n -->\r\n <div class=\"space-y-6\">\r\n <mt-system-settings-general-section\r\n [generalConfigurationForm]=\"form.controls.generalConfiguration\"\r\n [timezoneForm]=\"form.controls.timezone\"\r\n [currencyForm]=\"form.controls.currency\"\r\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\r\n [dateFormatOptions]=\"dateFormatOptions()\"\r\n [timeFormatOptions]=\"timeFormatOptions()\"\r\n [currencyOptions]=\"currencyOptions()\"\r\n [currencyFormatOptions]=\"currencyFormatOptions()\"\r\n />\r\n\r\n <mt-system-settings-timesheet-section\r\n [policyForm]=\"form.controls.timeSheetPolicy\"\r\n [globalWorkingHoursForm]=\"form.controls.globalWorkingHours\"\r\n [dayOptions]=\"dotnetDayOptions()\"\r\n [frequencyOptions]=\"frequencyOptions()\"\r\n [maxDailyBelowDaily]=\"form.errors?.['maxDailyBelowDaily'] ?? false\"\r\n [hidePolicy]=\"hideTimeSheet()\"\r\n />\r\n\r\n <mt-system-settings-holidays-section\r\n [holidays]=\"holidayTableRows()\"\r\n (addHoliday)=\"openAddHoliday()\"\r\n (editHoliday)=\"editHoliday($event)\"\r\n (deleteHoliday)=\"deleteHoliday($event)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-page>\r\n</ng-container>\r\n", styles: [":host{display:block}\n"] }]
1454
+ }], ctorParameters: () => [], propDecorators: { apiBasePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "apiBasePath", required: false }] }], backRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "backRoute", required: false }] }], formatSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatSchema", required: false }] }], homeRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "homeRoute", required: false }] }], hideTimeSheet: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideTimeSheet", required: false }] }], exploreViewOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "exploreViewOptions", required: false }] }] } });
1357
1455
  function isRecord(value) {
1358
1456
  return typeof value === 'object' && value !== null && !Array.isArray(value);
1359
1457
  }
@@ -1421,11 +1519,6 @@ function getNumberArray(value) {
1421
1519
  function normalizeShowDesignSwitcher(value) {
1422
1520
  return value === true || value === 'true' || value === 'True';
1423
1521
  }
1424
- function normalizeExploreDefaultView(value) {
1425
- return EXPLORE_DEFAULT_VIEW_OPTIONS.some((option) => option.id === value)
1426
- ? value
1427
- : DEFAULT_GENERAL_CONFIGURATION.defaultExploreView;
1428
- }
1429
1522
  function normalizeWeekendDays(value) {
1430
1523
  if (!Array.isArray(value)) {
1431
1524
  return [];
@@ -1461,15 +1554,80 @@ function normalizeFrequency(value) {
1461
1554
  ? value
1462
1555
  : 'Weekly';
1463
1556
  }
1464
- function maxDailyHoursGteHoursPerDay(group) {
1465
- const maxDailyHours = group.get('timeSheetPolicy.maxDailyHours')?.value;
1466
- const hoursPerDay = group.get('globalWorkingHours.hoursPerDay')?.value;
1467
- if (typeof maxDailyHours === 'number' &&
1468
- typeof hoursPerDay === 'number' &&
1469
- maxDailyHours < hoursPerDay) {
1470
- return { maxDailyBelowDaily: true };
1471
- }
1472
- return null;
1557
+ /**
1558
+ * Restores an input's own default when the router's `withComponentInputBinding()`
1559
+ * wipes it. That feature calls `setInput(name, data[name])` for every
1560
+ * declared input on every route activation - including inputs a route's
1561
+ * `data` doesn't mention at all, which writes `undefined` and permanently
1562
+ * overwrites the `input()`'s own default the moment the route activates
1563
+ * (see `RoutedComponentInputBinder` in `@angular/router`). This substitutes
1564
+ * the fallback only for that specific "the router didn't supply it" case.
1565
+ *
1566
+ * Deliberately narrower than `delegations-list.ts`'s `defaultRouteInput`,
1567
+ * which also collapses an explicit `null` into the fallback: `homeRoute`'s
1568
+ * `null` is a meaningful, tested value ("non-navigable crumb"), not merely
1569
+ * "unset", so this only special-cases `undefined` and passes every other
1570
+ * value - including `null` - through untouched.
1571
+ */
1572
+ function defaultWhenUndefined(fallback) {
1573
+ return (value) => (value === undefined ? fallback : value);
1574
+ }
1575
+ /**
1576
+ * pplus5's original Explore-default-view offering, before `'table'` was
1577
+ * added to the catalog for splus4. This - not the full catalog - is what an
1578
+ * unset `exploreViewOptions` input resolves to, so existing hosts keep
1579
+ * seeing exactly the two options they always have.
1580
+ */
1581
+ const DEFAULT_EXPLORE_VIEW_OPTIONS = [
1582
+ 'cards',
1583
+ 'timeline',
1584
+ ];
1585
+ /**
1586
+ * Named validator sets for the six Timesheet/GlobalWorkingHours fields, kept
1587
+ * as constants so `hideTimeSheet` can restore the exact original validators
1588
+ * on toggle-back rather than re-declaring them inline in two places.
1589
+ */
1590
+ const TIME_SHEET_FREQUENCY_VALIDATORS = [Validators.required];
1591
+ const TIME_SHEET_MAX_DAILY_HOURS_VALIDATORS = [
1592
+ Validators.required,
1593
+ Validators.min(1),
1594
+ Validators.max(24),
1595
+ ];
1596
+ const TIME_SHEET_SUBMISSION_DEADLINE_VALIDATORS = [
1597
+ Validators.required,
1598
+ Validators.min(0),
1599
+ Validators.max(90),
1600
+ ];
1601
+ const GLOBAL_WORKING_HOURS_TIMEZONE_VALIDATORS = [Validators.required];
1602
+ const GLOBAL_WORKING_HOURS_WORKING_DAYS_VALIDATORS = [Validators.required];
1603
+ const GLOBAL_WORKING_HOURS_HOURS_PER_DAY_VALIDATORS = [
1604
+ Validators.required,
1605
+ Validators.min(0),
1606
+ Validators.max(24),
1607
+ ];
1608
+ /**
1609
+ * Cross-field validator comparing `timeSheetPolicy.maxDailyHours` against
1610
+ * `globalWorkingHours.hoursPerDay`. Takes the `hideTimeSheet` input as a
1611
+ * thunk (rather than reading it directly) so it stays a plain module-level
1612
+ * function while still skipping the comparison when Timesheet Policy is
1613
+ * hidden - Global Working Hours stays visible/editable on its own even
1614
+ * then, and a visible `hoursPerDay` must never be blocked by a comparison
1615
+ * against a `maxDailyHours` the user can no longer see or change.
1616
+ */
1617
+ function maxDailyHoursGteHoursPerDay(isTimeSheetHidden) {
1618
+ return (group) => {
1619
+ if (isTimeSheetHidden()) {
1620
+ return null;
1621
+ }
1622
+ const maxDailyHours = group.get('timeSheetPolicy.maxDailyHours')?.value;
1623
+ const hoursPerDay = group.get('globalWorkingHours.hoursPerDay')?.value;
1624
+ if (typeof maxDailyHours === 'number' &&
1625
+ typeof hoursPerDay === 'number' &&
1626
+ maxDailyHours < hoursPerDay) {
1627
+ return { maxDailyBelowDaily: true };
1628
+ }
1629
+ return null;
1630
+ };
1473
1631
  }
1474
1632
  function parseCsv(value) {
1475
1633
  return value
@@ -2677,7 +2835,7 @@ function isTestRequestConflict(error) {
2677
2835
  const EMAIL_DELIVERY_ROUTES = [
2678
2836
  {
2679
2837
  path: '',
2680
- loadComponent: () => import('./masterteam-system-settings-email-delivery-shell-Bf6EXLD2.mjs').then((module) => module.EmailDeliveryShell),
2838
+ loadComponent: () => import('./masterteam-system-settings-email-delivery-shell-CBPKuYXr.mjs').then((module) => module.EmailDeliveryShell),
2681
2839
  },
2682
2840
  { path: '**', redirectTo: '' },
2683
2841
  ];
@@ -2687,4 +2845,4 @@ const EMAIL_DELIVERY_ROUTES = [
2687
2845
  */
2688
2846
 
2689
2847
  export { DEFAULT_GENERAL_CONFIGURATION as D, EmailDeliveryFacade as E, FIXED_CURRENCIES as F, GENERAL_CONFIGURATION_SETTING_KEY as G, RATE_SOURCE_OPTIONS as R, SystemSettings as S, TIMESHEET_FREQUENCY_OPTIONS as T, WEEKEND_DAY_DEFINITIONS as W, EmailDeliveryStatus as a, EMAIL_DELIVERY_ATTEMPT_STATUSES as b, createEmailTestRequestId as c, areEmailTestRecipientsValid as d, isEmailTestRequestPending as e, EMAIL_DELIVERY_PERMISSIONS as f, getEmailDeliveryStatusMap as g, EXPLORE_DEFAULT_VIEW_OPTIONS as h, isConnectionTestAttempt as i, DEFAULT_DATE_FORMAT_OPTIONS as j, DEFAULT_TIME_FORMAT_OPTIONS as k, DOTNET_DAY_DEFINITIONS as l, SCHEDULE_ITEM_TYPE_OPTIONS as m, SystemSettingsHolidayEditor as n, DEFAULT_EMAIL_DELIVERY_OPTIONS as o, parseEmailTestRecipients as p, EMAIL_DELIVERY_OPTIONS as q, provideEmailDelivery as r, EmailDeliveryAccessService as s, collectEmailTemplatePlaceholders as t, buildEmailTemplatePlaceholderFields as u, EmailUserTestDialog as v, EMAIL_USER_INITIATED_TEST_OPERATION_KIND as w, EMAIL_DELIVERY_ROUTES as x };
2690
- //# sourceMappingURL=masterteam-system-settings-masterteam-system-settings-BjftcBn5.mjs.map
2848
+ //# sourceMappingURL=masterteam-system-settings-masterteam-system-settings-DbsjQ7c7.mjs.map