@masterteam/system-settings 0.0.18 → 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.
@@ -15,7 +15,6 @@ import { ToastService } from '@masterteam/components/toast';
15
15
  import * as i1$1 from 'primeng/skeleton';
16
16
  import { SkeletonModule } from 'primeng/skeleton';
17
17
  import { Card } from '@masterteam/components/card';
18
- import { MultiSelectField } from '@masterteam/components/multi-select-field';
19
18
  import { SelectField } from '@masterteam/components/select-field';
20
19
  import { RadioCardsField } from '@masterteam/components/radio-cards-field';
21
20
  import { ToggleField } from '@masterteam/components/toggle-field';
@@ -23,9 +22,10 @@ import { ModalRef } from '@masterteam/components/dialog';
23
22
  import { DateField } from '@masterteam/components/date-field';
24
23
  import { TextField } from '@masterteam/components/text-field';
25
24
  import { Table } from '@masterteam/components/table';
25
+ import { MultiSelectField } from '@masterteam/components/multi-select-field';
26
26
  import { NumberField } from '@masterteam/components/number-field';
27
- import { TextareaField } from '@masterteam/components/textarea-field';
28
27
  import { of, map, tap, catchError, throwError, finalize, shareReplay, mergeMap, switchMap, forkJoin, timer } from 'rxjs';
28
+ import { TextareaField } from '@masterteam/components/textarea-field';
29
29
  import { EntityStatus } from '@masterteam/components/entities';
30
30
 
31
31
  /**
@@ -54,15 +54,13 @@ class SystemSettingsGeneralSection {
54
54
  generalConfigurationForm = input.required(...(ngDevMode ? [{ debugName: "generalConfigurationForm" }] : /* istanbul ignore next */ []));
55
55
  timezoneForm = input.required(...(ngDevMode ? [{ debugName: "timezoneForm" }] : /* istanbul ignore next */ []));
56
56
  currencyForm = input.required(...(ngDevMode ? [{ debugName: "currencyForm" }] : /* istanbul ignore next */ []));
57
- weekendForm = input.required(...(ngDevMode ? [{ debugName: "weekendForm" }] : /* istanbul ignore next */ []));
58
57
  exploreDefaultViewOptions = input([], ...(ngDevMode ? [{ debugName: "exploreDefaultViewOptions" }] : /* istanbul ignore next */ []));
59
58
  dateFormatOptions = input([], ...(ngDevMode ? [{ debugName: "dateFormatOptions" }] : /* istanbul ignore next */ []));
60
59
  timeFormatOptions = input([], ...(ngDevMode ? [{ debugName: "timeFormatOptions" }] : /* istanbul ignore next */ []));
61
60
  currencyOptions = input([], ...(ngDevMode ? [{ debugName: "currencyOptions" }] : /* istanbul ignore next */ []));
62
61
  currencyFormatOptions = input([], ...(ngDevMode ? [{ debugName: "currencyFormatOptions" }] : /* istanbul ignore next */ []));
63
- weekendOptions = input([], ...(ngDevMode ? [{ debugName: "weekendOptions" }] : /* istanbul ignore next */ []));
64
62
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettingsGeneralSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
65
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: SystemSettingsGeneralSection, isStandalone: true, selector: "mt-system-settings-general-section", inputs: { generalConfigurationForm: { classPropertyName: "generalConfigurationForm", publicName: "generalConfigurationForm", isSignal: true, isRequired: true, transformFunction: null }, timezoneForm: { classPropertyName: "timezoneForm", publicName: "timezoneForm", isSignal: true, isRequired: true, transformFunction: null }, currencyForm: { classPropertyName: "currencyForm", publicName: "currencyForm", isSignal: true, isRequired: true, transformFunction: null }, weekendForm: { classPropertyName: "weekendForm", publicName: "weekendForm", isSignal: true, isRequired: true, transformFunction: null }, exploreDefaultViewOptions: { classPropertyName: "exploreDefaultViewOptions", publicName: "exploreDefaultViewOptions", isSignal: true, isRequired: false, transformFunction: null }, dateFormatOptions: { classPropertyName: "dateFormatOptions", publicName: "dateFormatOptions", isSignal: true, isRequired: false, transformFunction: null }, timeFormatOptions: { classPropertyName: "timeFormatOptions", publicName: "timeFormatOptions", isSignal: true, isRequired: false, transformFunction: null }, currencyOptions: { classPropertyName: "currencyOptions", publicName: "currencyOptions", isSignal: true, isRequired: false, transformFunction: null }, currencyFormatOptions: { classPropertyName: "currencyFormatOptions", publicName: "currencyFormatOptions", isSignal: true, isRequired: false, transformFunction: null }, weekendOptions: { classPropertyName: "weekendOptions", publicName: "weekendOptions", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\n <div class=\"grid gap-6 xl:grid-cols-3\">\n <mt-card class=\"block\">\n <div class=\"space-y-4\">\n <div class=\"space-y-1\">\n <h4 class=\"text-base font-semibold text-neutral-900\">\n {{ t(\"date-time-weekend-title\") }}\n </h4>\n <p class=\"text-sm text-neutral-600\">\n {{ t(\"date-time-weekend-description\") }}\n </p>\n </div>\n\n <div [formGroup]=\"timezoneForm()\" class=\"grid gap-4 md:grid-cols-2\">\n <mt-select-field\n formControlName=\"dateFormat\"\n [options]=\"dateFormatOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('date-format')\"\n [placeholder]=\"t('date-format-placeholder')\"\n [required]=\"true\"\n />\n\n <mt-select-field\n formControlName=\"timeFormat\"\n [options]=\"timeFormatOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('time-format')\"\n [placeholder]=\"t('time-format-placeholder')\"\n [required]=\"true\"\n />\n </div>\n\n <div [formGroup]=\"weekendForm()\">\n <mt-multi-select-field\n formControlName=\"days\"\n [options]=\"weekendOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'dayNumber'\"\n [label]=\"t('weekend-days')\"\n [placeholder]=\"t('weekend-placeholder')\"\n [display]=\"'chip'\"\n [filter]=\"false\"\n [showClear]=\"true\"\n [maxSelectedLabels]=\"3\"\n />\n </div>\n </div>\n </mt-card>\n\n <mt-card class=\"block\">\n <div [formGroup]=\"currencyForm()\" class=\"space-y-4\">\n <div class=\"space-y-1\">\n <h4 class=\"text-base font-semibold text-neutral-900\">\n {{ t(\"currency-title\") }}\n </h4>\n <p class=\"text-sm text-neutral-600\">\n {{ t(\"currency-description\") }}\n </p>\n </div>\n\n <mt-select-field\n formControlName=\"code\"\n [options]=\"currencyOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('currency')\"\n [placeholder]=\"t('currency-placeholder')\"\n [required]=\"true\"\n />\n\n <mt-select-field\n formControlName=\"format\"\n [options]=\"currencyFormatOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('currency-format')\"\n [placeholder]=\"t('currency-format-placeholder')\"\n [required]=\"true\"\n />\n </div>\n </mt-card>\n\n <mt-system-settings-general-config-section\n class=\"block\"\n [generalConfigurationForm]=\"generalConfigurationForm()\"\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\n />\n </div>\n</ng-container>\n", styles: [":host{display:block}\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: 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: 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: SystemSettingsGeneralConfigSection, selector: "mt-system-settings-general-config-section", inputs: ["generalConfigurationForm", "exploreDefaultViewOptions"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
63
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: SystemSettingsGeneralSection, isStandalone: true, selector: "mt-system-settings-general-section", inputs: { generalConfigurationForm: { classPropertyName: "generalConfigurationForm", publicName: "generalConfigurationForm", isSignal: true, isRequired: true, transformFunction: null }, timezoneForm: { classPropertyName: "timezoneForm", publicName: "timezoneForm", isSignal: true, isRequired: true, transformFunction: null }, currencyForm: { classPropertyName: "currencyForm", publicName: "currencyForm", isSignal: true, isRequired: true, transformFunction: null }, exploreDefaultViewOptions: { classPropertyName: "exploreDefaultViewOptions", publicName: "exploreDefaultViewOptions", isSignal: true, isRequired: false, transformFunction: null }, dateFormatOptions: { classPropertyName: "dateFormatOptions", publicName: "dateFormatOptions", isSignal: true, isRequired: false, transformFunction: null }, timeFormatOptions: { classPropertyName: "timeFormatOptions", publicName: "timeFormatOptions", isSignal: true, isRequired: false, transformFunction: null }, currencyOptions: { classPropertyName: "currencyOptions", publicName: "currencyOptions", isSignal: true, isRequired: false, transformFunction: null }, currencyFormatOptions: { classPropertyName: "currencyFormatOptions", publicName: "currencyFormatOptions", 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-3\">\r\n <mt-card class=\"block\">\r\n <div class=\"space-y-4\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"date-time-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"date-time-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div [formGroup]=\"timezoneForm()\" class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-select-field\r\n formControlName=\"dateFormat\"\r\n [options]=\"dateFormatOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('date-format')\"\r\n [placeholder]=\"t('date-format-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-select-field\r\n formControlName=\"timeFormat\"\r\n [options]=\"timeFormatOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('time-format')\"\r\n [placeholder]=\"t('time-format-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"currencyForm()\" class=\"space-y-4\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"currency-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"currency-description\") }}\r\n </p>\r\n </div>\r\n\r\n <mt-select-field\r\n formControlName=\"code\"\r\n [options]=\"currencyOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('currency')\"\r\n [placeholder]=\"t('currency-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-select-field\r\n formControlName=\"format\"\r\n [options]=\"currencyFormatOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('currency-format')\"\r\n [placeholder]=\"t('currency-format-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n </div>\r\n </mt-card>\r\n\r\n <mt-system-settings-general-config-section\r\n class=\"block\"\r\n [generalConfigurationForm]=\"generalConfigurationForm()\"\r\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", styles: [":host{display:block}\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: 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: SystemSettingsGeneralConfigSection, selector: "mt-system-settings-general-config-section", inputs: ["generalConfigurationForm", "exploreDefaultViewOptions"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
66
64
  }
67
65
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettingsGeneralSection, decorators: [{
68
66
  type: Component,
@@ -71,10 +69,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
71
69
  TranslocoDirective,
72
70
  Card,
73
71
  SelectField,
74
- MultiSelectField,
75
72
  SystemSettingsGeneralConfigSection,
76
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\n <div class=\"grid gap-6 xl:grid-cols-3\">\n <mt-card class=\"block\">\n <div class=\"space-y-4\">\n <div class=\"space-y-1\">\n <h4 class=\"text-base font-semibold text-neutral-900\">\n {{ t(\"date-time-weekend-title\") }}\n </h4>\n <p class=\"text-sm text-neutral-600\">\n {{ t(\"date-time-weekend-description\") }}\n </p>\n </div>\n\n <div [formGroup]=\"timezoneForm()\" class=\"grid gap-4 md:grid-cols-2\">\n <mt-select-field\n formControlName=\"dateFormat\"\n [options]=\"dateFormatOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('date-format')\"\n [placeholder]=\"t('date-format-placeholder')\"\n [required]=\"true\"\n />\n\n <mt-select-field\n formControlName=\"timeFormat\"\n [options]=\"timeFormatOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('time-format')\"\n [placeholder]=\"t('time-format-placeholder')\"\n [required]=\"true\"\n />\n </div>\n\n <div [formGroup]=\"weekendForm()\">\n <mt-multi-select-field\n formControlName=\"days\"\n [options]=\"weekendOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'dayNumber'\"\n [label]=\"t('weekend-days')\"\n [placeholder]=\"t('weekend-placeholder')\"\n [display]=\"'chip'\"\n [filter]=\"false\"\n [showClear]=\"true\"\n [maxSelectedLabels]=\"3\"\n />\n </div>\n </div>\n </mt-card>\n\n <mt-card class=\"block\">\n <div [formGroup]=\"currencyForm()\" class=\"space-y-4\">\n <div class=\"space-y-1\">\n <h4 class=\"text-base font-semibold text-neutral-900\">\n {{ t(\"currency-title\") }}\n </h4>\n <p class=\"text-sm text-neutral-600\">\n {{ t(\"currency-description\") }}\n </p>\n </div>\n\n <mt-select-field\n formControlName=\"code\"\n [options]=\"currencyOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('currency')\"\n [placeholder]=\"t('currency-placeholder')\"\n [required]=\"true\"\n />\n\n <mt-select-field\n formControlName=\"format\"\n [options]=\"currencyFormatOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('currency-format')\"\n [placeholder]=\"t('currency-format-placeholder')\"\n [required]=\"true\"\n />\n </div>\n </mt-card>\n\n <mt-system-settings-general-config-section\n class=\"block\"\n [generalConfigurationForm]=\"generalConfigurationForm()\"\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\n />\n </div>\n</ng-container>\n", styles: [":host{display:block}\n"] }]
77
- }], propDecorators: { generalConfigurationForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "generalConfigurationForm", required: true }] }], timezoneForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "timezoneForm", required: true }] }], currencyForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencyForm", required: true }] }], weekendForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekendForm", required: true }] }], exploreDefaultViewOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "exploreDefaultViewOptions", required: false }] }], dateFormatOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormatOptions", required: false }] }], timeFormatOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeFormatOptions", required: false }] }], currencyOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencyOptions", required: false }] }], currencyFormatOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencyFormatOptions", required: false }] }], weekendOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekendOptions", required: false }] }] } });
73
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\r\n <div class=\"grid gap-6 xl:grid-cols-3\">\r\n <mt-card class=\"block\">\r\n <div class=\"space-y-4\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"date-time-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"date-time-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div [formGroup]=\"timezoneForm()\" class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-select-field\r\n formControlName=\"dateFormat\"\r\n [options]=\"dateFormatOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('date-format')\"\r\n [placeholder]=\"t('date-format-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-select-field\r\n formControlName=\"timeFormat\"\r\n [options]=\"timeFormatOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('time-format')\"\r\n [placeholder]=\"t('time-format-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n\r\n <mt-card class=\"block\">\r\n <div [formGroup]=\"currencyForm()\" class=\"space-y-4\">\r\n <div class=\"space-y-1\">\r\n <h4 class=\"text-base font-semibold text-neutral-900\">\r\n {{ t(\"currency-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"currency-description\") }}\r\n </p>\r\n </div>\r\n\r\n <mt-select-field\r\n formControlName=\"code\"\r\n [options]=\"currencyOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('currency')\"\r\n [placeholder]=\"t('currency-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-select-field\r\n formControlName=\"format\"\r\n [options]=\"currencyFormatOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('currency-format')\"\r\n [placeholder]=\"t('currency-format-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n </div>\r\n </mt-card>\r\n\r\n <mt-system-settings-general-config-section\r\n class=\"block\"\r\n [generalConfigurationForm]=\"generalConfigurationForm()\"\r\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", styles: [":host{display:block}\n"] }]
74
+ }], propDecorators: { generalConfigurationForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "generalConfigurationForm", required: true }] }], timezoneForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "timezoneForm", required: true }] }], currencyForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencyForm", required: true }] }], exploreDefaultViewOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "exploreDefaultViewOptions", required: false }] }], dateFormatOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormatOptions", required: false }] }], timeFormatOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeFormatOptions", required: false }] }], currencyOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencyOptions", required: false }] }], currencyFormatOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencyFormatOptions", required: false }] }] } });
78
75
 
79
76
  class SystemSettingsHolidayEditor {
80
77
  ref = inject(ModalRef);
@@ -207,10 +204,16 @@ class SystemSettingsTimeSheetSection {
207
204
  globalWorkingHoursForm = input.required(...(ngDevMode ? [{ debugName: "globalWorkingHoursForm" }] : /* istanbul ignore next */ []));
208
205
  dayOptions = input([], ...(ngDevMode ? [{ debugName: "dayOptions" }] : /* istanbul ignore next */ []));
209
206
  frequencyOptions = input([], ...(ngDevMode ? [{ debugName: "frequencyOptions" }] : /* istanbul ignore next */ []));
210
- timezoneOptions = input([], ...(ngDevMode ? [{ debugName: "timezoneOptions" }] : /* istanbul ignore next */ []));
211
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 */ []));
212
215
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettingsTimeSheetSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
213
- 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 }, timezoneOptions: { classPropertyName: "timezoneOptions", publicName: "timezoneOptions", 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'\">\n <div class=\"grid gap-6 xl:grid-cols-2 mb-6\">\n <mt-card class=\"block\">\n <div [formGroup]=\"policyForm()\" class=\"space-y-5\">\n <div class=\"space-y-1\">\n <h4 class=\"text-base font-semibold text-neutral-900\">\n {{ t(\"general-card-title\") }}\n </h4>\n <p class=\"text-sm text-neutral-600\">\n {{ t(\"general-card-description\") }}\n </p>\n </div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <mt-select-field\n formControlName=\"frequency\"\n [options]=\"frequencyOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('frequency')\"\n [placeholder]=\"t('frequency-placeholder')\"\n [required]=\"true\"\n />\n\n <mt-number-field\n formControlName=\"maxDailyHours\"\n [label]=\"t('max-daily-hours')\"\n [placeholder]=\"t('max-daily-hours-placeholder')\"\n [min]=\"1\"\n [max]=\"24\"\n [required]=\"true\"\n [hint]=\"maxDailyBelowDaily() ? t('max-daily-below-daily') : ''\"\n />\n\n <mt-number-field\n formControlName=\"submissionDeadlineDays\"\n [label]=\"t('submission-deadline-days')\"\n [placeholder]=\"t('submission-deadline-days-placeholder')\"\n [min]=\"0\"\n [max]=\"90\"\n [required]=\"true\"\n [hint]=\"t('submission-deadline-hint')\"\n />\n </div>\n\n <div class=\"grid gap-3 md:grid-cols-2\">\n <mt-toggle-field\n formControlName=\"requireDescription\"\n [label]=\"t('require-description')\"\n />\n <mt-toggle-field\n formControlName=\"allowFutureEntry\"\n [label]=\"t('allow-future-entry')\"\n />\n <mt-toggle-field\n formControlName=\"allowBackdatedEntry\"\n [label]=\"t('allow-backdated-entry')\"\n />\n <mt-toggle-field\n formControlName=\"autoLockOnApprove\"\n [label]=\"t('auto-lock-on-approve')\"\n />\n </div>\n </div>\n </mt-card>\n\n <mt-card class=\"block\">\n <div [formGroup]=\"globalWorkingHoursForm()\" class=\"space-y-5\">\n <div class=\"space-y-1\">\n <h4 class=\"text-base font-semibold text-neutral-900\">\n {{ t(\"working-hours-card-title\") }}\n </h4>\n <p class=\"text-sm text-neutral-600\">\n {{ t(\"working-hours-card-description\") }}\n </p>\n </div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <mt-select-field\n class=\"md:col-span-2\"\n formControlName=\"timeZoneId\"\n [options]=\"timezoneOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('global-timezone')\"\n [placeholder]=\"t('global-timezone-placeholder')\"\n [filter]=\"true\"\n [required]=\"true\"\n />\n\n <mt-multi-select-field\n class=\"md:col-span-2\"\n formControlName=\"workingDays\"\n [options]=\"dayOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'dayNumber'\"\n [label]=\"t('working-days')\"\n [placeholder]=\"t('working-days-placeholder')\"\n [display]=\"'chip'\"\n [required]=\"true\"\n [showClear]=\"true\"\n />\n\n <mt-number-field\n class=\"md:col-span-2\"\n formControlName=\"hoursPerDay\"\n [label]=\"t('daily-working-hours')\"\n [placeholder]=\"t('daily-working-hours-placeholder')\"\n [min]=\"0\"\n [max]=\"24\"\n [required]=\"true\"\n />\n\n <mt-textarea-field\n class=\"md:col-span-2\"\n formControlName=\"holidaysCsv\"\n [label]=\"t('global-holidays')\"\n [placeholder]=\"t('global-holidays-placeholder')\"\n rows=\"3\"\n />\n </div>\n </div>\n </mt-card>\n </div>\n</ng-container>\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: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { 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 });
214
217
  }
215
218
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettingsTimeSheetSection, decorators: [{
216
219
  type: Component,
@@ -221,10 +224,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
221
224
  MultiSelectField,
222
225
  NumberField,
223
226
  SelectField,
224
- TextareaField,
225
227
  ToggleField,
226
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\n <div class=\"grid gap-6 xl:grid-cols-2 mb-6\">\n <mt-card class=\"block\">\n <div [formGroup]=\"policyForm()\" class=\"space-y-5\">\n <div class=\"space-y-1\">\n <h4 class=\"text-base font-semibold text-neutral-900\">\n {{ t(\"general-card-title\") }}\n </h4>\n <p class=\"text-sm text-neutral-600\">\n {{ t(\"general-card-description\") }}\n </p>\n </div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <mt-select-field\n formControlName=\"frequency\"\n [options]=\"frequencyOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('frequency')\"\n [placeholder]=\"t('frequency-placeholder')\"\n [required]=\"true\"\n />\n\n <mt-number-field\n formControlName=\"maxDailyHours\"\n [label]=\"t('max-daily-hours')\"\n [placeholder]=\"t('max-daily-hours-placeholder')\"\n [min]=\"1\"\n [max]=\"24\"\n [required]=\"true\"\n [hint]=\"maxDailyBelowDaily() ? t('max-daily-below-daily') : ''\"\n />\n\n <mt-number-field\n formControlName=\"submissionDeadlineDays\"\n [label]=\"t('submission-deadline-days')\"\n [placeholder]=\"t('submission-deadline-days-placeholder')\"\n [min]=\"0\"\n [max]=\"90\"\n [required]=\"true\"\n [hint]=\"t('submission-deadline-hint')\"\n />\n </div>\n\n <div class=\"grid gap-3 md:grid-cols-2\">\n <mt-toggle-field\n formControlName=\"requireDescription\"\n [label]=\"t('require-description')\"\n />\n <mt-toggle-field\n formControlName=\"allowFutureEntry\"\n [label]=\"t('allow-future-entry')\"\n />\n <mt-toggle-field\n formControlName=\"allowBackdatedEntry\"\n [label]=\"t('allow-backdated-entry')\"\n />\n <mt-toggle-field\n formControlName=\"autoLockOnApprove\"\n [label]=\"t('auto-lock-on-approve')\"\n />\n </div>\n </div>\n </mt-card>\n\n <mt-card class=\"block\">\n <div [formGroup]=\"globalWorkingHoursForm()\" class=\"space-y-5\">\n <div class=\"space-y-1\">\n <h4 class=\"text-base font-semibold text-neutral-900\">\n {{ t(\"working-hours-card-title\") }}\n </h4>\n <p class=\"text-sm text-neutral-600\">\n {{ t(\"working-hours-card-description\") }}\n </p>\n </div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <mt-select-field\n class=\"md:col-span-2\"\n formControlName=\"timeZoneId\"\n [options]=\"timezoneOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'id'\"\n [label]=\"t('global-timezone')\"\n [placeholder]=\"t('global-timezone-placeholder')\"\n [filter]=\"true\"\n [required]=\"true\"\n />\n\n <mt-multi-select-field\n class=\"md:col-span-2\"\n formControlName=\"workingDays\"\n [options]=\"dayOptions()\"\n [optionLabel]=\"'name'\"\n [optionValue]=\"'dayNumber'\"\n [label]=\"t('working-days')\"\n [placeholder]=\"t('working-days-placeholder')\"\n [display]=\"'chip'\"\n [required]=\"true\"\n [showClear]=\"true\"\n />\n\n <mt-number-field\n class=\"md:col-span-2\"\n formControlName=\"hoursPerDay\"\n [label]=\"t('daily-working-hours')\"\n [placeholder]=\"t('daily-working-hours-placeholder')\"\n [min]=\"0\"\n [max]=\"24\"\n [required]=\"true\"\n />\n\n <mt-textarea-field\n class=\"md:col-span-2\"\n formControlName=\"holidaysCsv\"\n [label]=\"t('global-holidays')\"\n [placeholder]=\"t('global-holidays-placeholder')\"\n rows=\"3\"\n />\n </div>\n </div>\n </mt-card>\n </div>\n</ng-container>\n" }]
227
- }], 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 }] }], timezoneOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "timezoneOptions", 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 }] }] } });
228
230
 
229
231
  /** The settings record General Configuration fields live in. */
230
232
  const GENERAL_CONFIGURATION_SETTING_KEY = 'Identity';
@@ -272,6 +274,11 @@ const EXPLORE_DEFAULT_VIEW_OPTIONS = [
272
274
  translationKey: 'explore-default-view-timeline',
273
275
  icon: 'time.clock',
274
276
  },
277
+ {
278
+ id: 'table',
279
+ translationKey: 'explore-default-view-table',
280
+ icon: 'layout.table',
281
+ },
275
282
  ];
276
283
  const DEFAULT_GENERAL_CONFIGURATION = {
277
284
  defaultExploreView: 'cards',
@@ -390,23 +397,61 @@ class SystemSettings {
390
397
  transloco = inject(TranslocoService);
391
398
  modal = inject(ModalService);
392
399
  toast = inject(ToastService);
393
- apiBasePath = input('settings', ...(ngDevMode ? [{ debugName: "apiBasePath" }] : /* istanbul ignore next */ []));
394
- 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') });
395
413
  formatSchema = input(null, ...(ngDevMode ? [{ debugName: "formatSchema" }] : /* istanbul ignore next */ []));
396
- breadcrumbItems = [
397
- {
398
- label: '',
399
- icon: 'general.home-line',
400
- routerLink: '/control-panel/workspaces',
401
- },
402
- {
403
- label: this.transloco.translate('product-settings.product-settings'),
404
- routerLink: '/control-panel/product-settings',
405
- },
406
- {
407
- label: this.transloco.translate('system-settings.page-title'),
408
- },
409
- ];
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 */ []));
410
455
  form = new FormGroup({
411
456
  generalConfiguration: new FormGroup({
412
457
  defaultExploreView: new FormControl('cards', {
@@ -430,36 +475,24 @@ class SystemSettings {
430
475
  days: new FormControl([], { nonNullable: true }),
431
476
  }),
432
477
  timeSheetPolicy: new FormGroup({
433
- frequency: new FormControl('Weekly', Validators.required),
434
- maxDailyHours: new FormControl(24, [
435
- Validators.required,
436
- Validators.min(1),
437
- Validators.max(24),
438
- ]),
478
+ frequency: new FormControl('Weekly', TIME_SHEET_FREQUENCY_VALIDATORS),
479
+ maxDailyHours: new FormControl(24, TIME_SHEET_MAX_DAILY_HOURS_VALIDATORS),
439
480
  requireDescription: new FormControl(false, { nonNullable: true }),
440
481
  allowFutureEntry: new FormControl(false, { nonNullable: true }),
441
482
  allowBackdatedEntry: new FormControl(true, { nonNullable: true }),
442
483
  autoLockOnApprove: new FormControl(true, { nonNullable: true }),
443
- submissionDeadlineDays: new FormControl(3, [
444
- Validators.required,
445
- Validators.min(0),
446
- Validators.max(90),
447
- ]),
484
+ submissionDeadlineDays: new FormControl(3, TIME_SHEET_SUBMISSION_DEADLINE_VALIDATORS),
448
485
  }),
449
486
  globalWorkingHours: new FormGroup({
450
- timeZoneId: new FormControl(null, Validators.required),
487
+ timeZoneId: new FormControl(null, GLOBAL_WORKING_HOURS_TIMEZONE_VALIDATORS),
451
488
  workingDays: new FormControl([0, 1, 2, 3, 4], {
452
489
  nonNullable: true,
453
- validators: [Validators.required],
490
+ validators: GLOBAL_WORKING_HOURS_WORKING_DAYS_VALIDATORS,
454
491
  }),
455
- hoursPerDay: new FormControl(8, [
456
- Validators.required,
457
- Validators.min(0),
458
- Validators.max(24),
459
- ]),
492
+ hoursPerDay: new FormControl(8, GLOBAL_WORKING_HOURS_HOURS_PER_DAY_VALIDATORS),
460
493
  holidaysCsv: new FormControl('', { nonNullable: true }),
461
494
  }),
462
- }, maxDailyHoursGteHoursPerDay);
495
+ }, maxDailyHoursGteHoursPerDay(() => this.hideTimeSheet()));
463
496
  settings = signal(null, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
464
497
  settingsLoading = signal(false, ...(ngDevMode ? [{ debugName: "settingsLoading" }] : /* istanbul ignore next */ []));
465
498
  settingsError = signal(null, ...(ngDevMode ? [{ debugName: "settingsError" }] : /* istanbul ignore next */ []));
@@ -509,10 +542,6 @@ class SystemSettings {
509
542
  timeFormats: schema?.timeFormats ?? DEFAULT_TIME_FORMAT_OPTIONS,
510
543
  };
511
544
  }, ...(ngDevMode ? [{ debugName: "resolvedFormatSchema" }] : /* istanbul ignore next */ []));
512
- timezoneOptions = computed(() => this.timezones().map((timezone) => ({
513
- ...timezone,
514
- name: timezone.name ?? timezone.displayName,
515
- })), ...(ngDevMode ? [{ debugName: "timezoneOptions" }] : /* istanbul ignore next */ []));
516
545
  dateFormatOptions = computed(() => this.mapFormatOptions(this.resolvedFormatSchema().dateFormats, this.selectedDateFormat()), ...(ngDevMode ? [{ debugName: "dateFormatOptions" }] : /* istanbul ignore next */ []));
517
546
  timeFormatOptions = computed(() => this.mapFormatOptions(this.resolvedFormatSchema().timeFormats, this.selectedTimeFormat()), ...(ngDevMode ? [{ debugName: "timeFormatOptions" }] : /* istanbul ignore next */ []));
518
547
  currencyOptions = computed(() => {
@@ -526,14 +555,6 @@ class SystemSettings {
526
555
  const currency = FIXED_CURRENCIES.find((item) => item.code === this.selectedCurrencyCode());
527
556
  return this.buildCurrencyFormatOptions(currency);
528
557
  }, ...(ngDevMode ? [{ debugName: "currencyFormatOptions" }] : /* istanbul ignore next */ []));
529
- weekendOptions = computed(() => {
530
- this.activeLang();
531
- return WEEKEND_DAY_DEFINITIONS.map((day) => ({
532
- id: `${day.dayNumber}`,
533
- dayNumber: day.dayNumber,
534
- name: this.transloco.translate(`system-settings.${day.translationKey}`),
535
- }));
536
- }, ...(ngDevMode ? [{ debugName: "weekendOptions" }] : /* istanbul ignore next */ []));
537
558
  dotnetDayOptions = computed(() => {
538
559
  this.activeLang();
539
560
  return DOTNET_DAY_DEFINITIONS.map((day) => ({
@@ -542,9 +563,25 @@ class SystemSettings {
542
563
  name: this.transloco.translate(`system-settings.${day.translationKey}`),
543
564
  }));
544
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 */ []));
545
581
  exploreDefaultViewOptions = computed(() => {
546
582
  this.activeLang();
547
- 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) => ({
548
585
  id: option.id,
549
586
  name: this.transloco.translate(`system-settings.${option.translationKey}`),
550
587
  icon: option.icon,
@@ -575,7 +612,12 @@ class SystemSettings {
575
612
  !this.areEqual(initial.timezone, current.timezone) ||
576
613
  !this.areEqual(initial.currency, current.currency) ||
577
614
  !this.areEqual(initial.weekend, current.weekend) ||
578
- !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)) ||
579
621
  !this.areEqual(initial.globalWorkingHours, current.globalWorkingHours));
580
622
  }, ...(ngDevMode ? [{ debugName: "hasChanges" }] : /* istanbul ignore next */ []));
581
623
  canSaveSettings = computed(() => !this.isLoading() &&
@@ -590,6 +632,30 @@ class SystemSettings {
590
632
  to: formatDateOnly(holiday.to),
591
633
  })), ...(ngDevMode ? [{ debugName: "holidayTableRows" }] : /* istanbul ignore next */ []));
592
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
+ });
593
659
  effect(() => {
594
660
  const version = [
595
661
  this.settingsLastUpdated() ?? 'none',
@@ -711,7 +777,8 @@ class SystemSettings {
711
777
  value: nextSnapshot.weekend,
712
778
  });
713
779
  }
714
- if (!this.areEqual(initialSnapshot.timeSheetPolicy, nextSnapshot.timeSheetPolicy)) {
780
+ if (!this.hideTimeSheet() &&
781
+ !this.areEqual(initialSnapshot.timeSheetPolicy, nextSnapshot.timeSheetPolicy)) {
715
782
  values.push({
716
783
  key: 'TimeSheetPolicy',
717
784
  value: nextSnapshot.timeSheetPolicy,
@@ -907,7 +974,7 @@ class SystemSettings {
907
974
  }
908
975
  buildGeneralConfigurationValue() {
909
976
  return {
910
- defaultExploreView: normalizeExploreDefaultView(this.form.controls.generalConfiguration.controls.defaultExploreView
977
+ defaultExploreView: this.normalizeExploreDefaultView(this.form.controls.generalConfiguration.controls.defaultExploreView
911
978
  .value),
912
979
  showDesignSwitcher: this.form.controls.generalConfiguration.controls.showDesignSwitcher
913
980
  .value === true,
@@ -949,7 +1016,7 @@ class SystemSettings {
949
1016
  return { ...DEFAULT_GENERAL_CONFIGURATION };
950
1017
  }
951
1018
  return {
952
- defaultExploreView: normalizeExploreDefaultView(setting.value['defaultExploreView'] ??
1019
+ defaultExploreView: this.normalizeExploreDefaultView(setting.value['defaultExploreView'] ??
953
1020
  setting.value['DefaultExploreView']),
954
1021
  showDesignSwitcher: normalizeShowDesignSwitcher(setting.value['showDesignSwitcher'] ??
955
1022
  setting.value['ShowDesignSwitcher']),
@@ -1103,10 +1170,24 @@ class SystemSettings {
1103
1170
  }
1104
1171
  normalizeGeneralConfigurationSnapshot(value) {
1105
1172
  return {
1106
- defaultExploreView: normalizeExploreDefaultView(value.defaultExploreView),
1173
+ defaultExploreView: this.normalizeExploreDefaultView(value.defaultExploreView),
1107
1174
  showDesignSwitcher: normalizeShowDesignSwitcher(value.showDesignSwitcher),
1108
1175
  };
1109
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
+ }
1110
1191
  normalizeTimezoneSnapshot(value) {
1111
1192
  const defaults = this.getDefaultTimezoneValue();
1112
1193
  return {
@@ -1354,7 +1435,7 @@ class SystemSettings {
1354
1435
  return JSON.stringify(left) === JSON.stringify(right);
1355
1436
  }
1356
1437
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettings, deps: [], target: i0.ɵɵFactoryTarget.Component });
1357
- 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 [weekendForm]=\"form.controls.weekend\"\r\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\r\n [dateFormatOptions]=\"dateFormatOptions()\"\r\n [timeFormatOptions]=\"timeFormatOptions()\"\r\n [currencyOptions]=\"currencyOptions()\"\r\n [currencyFormatOptions]=\"currencyFormatOptions()\"\r\n [weekendOptions]=\"weekendOptions()\"\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 [timezoneOptions]=\"timezoneOptions()\"\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", "weekendForm", "exploreDefaultViewOptions", "dateFormatOptions", "timeFormatOptions", "currencyOptions", "currencyFormatOptions", "weekendOptions"] }, { kind: "component", type: SystemSettingsTimeSheetSection, selector: "mt-system-settings-timesheet-section", inputs: ["policyForm", "globalWorkingHoursForm", "dayOptions", "frequencyOptions", "timezoneOptions", "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 });
1358
1439
  }
1359
1440
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettings, decorators: [{
1360
1441
  type: Component,
@@ -1369,8 +1450,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1369
1450
  SystemSettingsHolidaysSection,
1370
1451
  SystemSettingsGeneralSection,
1371
1452
  SystemSettingsTimeSheetSection,
1372
- ], 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 [weekendForm]=\"form.controls.weekend\"\r\n [exploreDefaultViewOptions]=\"exploreDefaultViewOptions()\"\r\n [dateFormatOptions]=\"dateFormatOptions()\"\r\n [timeFormatOptions]=\"timeFormatOptions()\"\r\n [currencyOptions]=\"currencyOptions()\"\r\n [currencyFormatOptions]=\"currencyFormatOptions()\"\r\n [weekendOptions]=\"weekendOptions()\"\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 [timezoneOptions]=\"timezoneOptions()\"\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"] }]
1373
- }], 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 }] }] } });
1374
1455
  function isRecord(value) {
1375
1456
  return typeof value === 'object' && value !== null && !Array.isArray(value);
1376
1457
  }
@@ -1438,11 +1519,6 @@ function getNumberArray(value) {
1438
1519
  function normalizeShowDesignSwitcher(value) {
1439
1520
  return value === true || value === 'true' || value === 'True';
1440
1521
  }
1441
- function normalizeExploreDefaultView(value) {
1442
- return EXPLORE_DEFAULT_VIEW_OPTIONS.some((option) => option.id === value)
1443
- ? value
1444
- : DEFAULT_GENERAL_CONFIGURATION.defaultExploreView;
1445
- }
1446
1522
  function normalizeWeekendDays(value) {
1447
1523
  if (!Array.isArray(value)) {
1448
1524
  return [];
@@ -1478,15 +1554,80 @@ function normalizeFrequency(value) {
1478
1554
  ? value
1479
1555
  : 'Weekly';
1480
1556
  }
1481
- function maxDailyHoursGteHoursPerDay(group) {
1482
- const maxDailyHours = group.get('timeSheetPolicy.maxDailyHours')?.value;
1483
- const hoursPerDay = group.get('globalWorkingHours.hoursPerDay')?.value;
1484
- if (typeof maxDailyHours === 'number' &&
1485
- typeof hoursPerDay === 'number' &&
1486
- maxDailyHours < hoursPerDay) {
1487
- return { maxDailyBelowDaily: true };
1488
- }
1489
- 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
+ };
1490
1631
  }
1491
1632
  function parseCsv(value) {
1492
1633
  return value
@@ -2694,7 +2835,7 @@ function isTestRequestConflict(error) {
2694
2835
  const EMAIL_DELIVERY_ROUTES = [
2695
2836
  {
2696
2837
  path: '',
2697
- loadComponent: () => import('./masterteam-system-settings-email-delivery-shell-Bjwtj5Ic.mjs').then((module) => module.EmailDeliveryShell),
2838
+ loadComponent: () => import('./masterteam-system-settings-email-delivery-shell-CBPKuYXr.mjs').then((module) => module.EmailDeliveryShell),
2698
2839
  },
2699
2840
  { path: '**', redirectTo: '' },
2700
2841
  ];
@@ -2704,4 +2845,4 @@ const EMAIL_DELIVERY_ROUTES = [
2704
2845
  */
2705
2846
 
2706
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 };
2707
- //# sourceMappingURL=masterteam-system-settings-masterteam-system-settings-CO-XTJOi.mjs.map
2848
+ //# sourceMappingURL=masterteam-system-settings-masterteam-system-settings-DbsjQ7c7.mjs.map