@masterteam/system-settings 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/assets/i18n/ar.json +18 -0
- package/assets/i18n/en.json +18 -0
- package/assets/system-settings.css +1 -1
- package/fesm2022/masterteam-system-settings.mjs +130 -162
- package/fesm2022/masterteam-system-settings.mjs.map +1 -1
- package/package.json +2 -2
- package/types/masterteam-system-settings.d.ts +37 -60
|
@@ -189,13 +189,11 @@ class SystemSettingsTimeSheetSection {
|
|
|
189
189
|
policyForm = input.required(...(ngDevMode ? [{ debugName: "policyForm" }] : /* istanbul ignore next */ []));
|
|
190
190
|
globalWorkingHoursForm = input.required(...(ngDevMode ? [{ debugName: "globalWorkingHoursForm" }] : /* istanbul ignore next */ []));
|
|
191
191
|
dayOptions = input([], ...(ngDevMode ? [{ debugName: "dayOptions" }] : /* istanbul ignore next */ []));
|
|
192
|
-
|
|
193
|
-
rateSourceOptions = input([], ...(ngDevMode ? [{ debugName: "rateSourceOptions" }] : /* istanbul ignore next */ []));
|
|
192
|
+
frequencyOptions = input([], ...(ngDevMode ? [{ debugName: "frequencyOptions" }] : /* istanbul ignore next */ []));
|
|
194
193
|
timezoneOptions = input([], ...(ngDevMode ? [{ debugName: "timezoneOptions" }] : /* istanbul ignore next */ []));
|
|
195
|
-
|
|
196
|
-
costEnabledControl = computed(() => this.policyForm().get('costEnabled'), ...(ngDevMode ? [{ debugName: "costEnabledControl" }] : /* istanbul ignore next */ []));
|
|
194
|
+
maxDailyBelowDaily = input(false, ...(ngDevMode ? [{ debugName: "maxDailyBelowDaily" }] : /* istanbul ignore next */ []));
|
|
197
195
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettingsTimeSheetSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
198
|
-
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 }, scheduleItemTypeOptions: { classPropertyName: "scheduleItemTypeOptions", publicName: "scheduleItemTypeOptions", isSignal: true, isRequired: false, transformFunction: null }, rateSourceOptions: { classPropertyName: "rateSourceOptions", publicName: "rateSourceOptions", isSignal: true, isRequired: false, transformFunction: null }, timezoneOptions: { classPropertyName: "timezoneOptions", publicName: "timezoneOptions", 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(\"timesheet-policy-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"timesheet-policy-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div\r\n class=\"rounded-lg border border-sky-200 bg-sky-50 px-4 py-3 text-sm text-sky-800\"\r\n >\r\n {{ t(\"timesheet-policy-workflow-note\") }}\r\n </div>\r\n\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-select-field\r\n formControlName=\"weekStartDay\"\r\n [options]=\"dayOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'dayNumber'\"\r\n [label]=\"t('week-start-day')\"\r\n [placeholder]=\"t('week-start-day-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-multi-select-field\r\n formControlName=\"allowedScheduleItemTypes\"\r\n [options]=\"scheduleItemTypeOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'itemType'\"\r\n [label]=\"t('allowed-schedule-item-types')\"\r\n [placeholder]=\"t('allowed-schedule-item-types-placeholder')\"\r\n [display]=\"'chip'\"\r\n [required]=\"true\"\r\n [showClear]=\"true\"\r\n />\r\n\r\n <mt-number-field\r\n formControlName=\"regularDailyHours\"\r\n [label]=\"t('regular-daily-hours')\"\r\n [placeholder]=\"t('regular-daily-hours-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"24\"\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 />\r\n\r\n <mt-number-field\r\n formControlName=\"pastEntryLockDays\"\r\n [label]=\"t('past-entry-lock-days')\"\r\n [placeholder]=\"t('past-entry-lock-days-placeholder')\"\r\n [min]=\"0\"\r\n [max]=\"3650\"\r\n />\r\n\r\n <mt-select-field\r\n formControlName=\"rateSource\"\r\n [options]=\"rateSourceOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('rate-source')\"\r\n [placeholder]=\"t('rate-source-placeholder')\"\r\n [required]=\"true\"\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=\"generationEnabled\"\r\n [label]=\"t('generation-enabled')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"manualGenerationEnabled\"\r\n [label]=\"t('manual-generation-enabled')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowOvertime\"\r\n [label]=\"t('allow-overtime')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"requireOvertimeReason\"\r\n [label]=\"t('require-overtime-reason')\"\r\n />\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=\"assignedItemsOnly\"\r\n [label]=\"t('assigned-items-only')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"allowZeroHourSubmit\"\r\n [label]=\"t('allow-zero-hour-submit')\"\r\n />\r\n <mt-toggle-field\r\n formControlName=\"costEnabled\"\r\n [label]=\"t('cost-enabled')\"\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(\"global-working-hours-title\") }}\r\n </h4>\r\n <p class=\"text-sm text-neutral-600\">\r\n {{ t(\"global-working-hours-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 class=\"md:col-span-2\"\r\n formControlName=\"timeZoneId\"\r\n [options]=\"timezoneOptions()\"\r\n [optionLabel]=\"'name'\"\r\n [optionValue]=\"'id'\"\r\n [label]=\"t('global-timezone')\"\r\n [placeholder]=\"t('global-timezone-placeholder')\"\r\n [filter]=\"true\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-text-field\r\n formControlName=\"workDayStart\"\r\n type=\"time\"\r\n [label]=\"t('work-day-start')\"\r\n [placeholder]=\"t('work-day-start-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\r\n <mt-text-field\r\n formControlName=\"workDayEnd\"\r\n type=\"time\"\r\n [label]=\"t('work-day-end')\"\r\n [placeholder]=\"t('work-day-end-placeholder')\"\r\n [required]=\"true\"\r\n />\r\n\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-textarea-field\r\n class=\"md:col-span-2\"\r\n formControlName=\"holidaysCsv\"\r\n [label]=\"t('global-holidays')\"\r\n [placeholder]=\"t('global-holidays-placeholder')\"\r\n rows=\"3\"\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: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { 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 });
|
|
196
|
+
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 });
|
|
199
197
|
}
|
|
200
198
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettingsTimeSheetSection, decorators: [{
|
|
201
199
|
type: Component,
|
|
@@ -207,10 +205,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
207
205
|
NumberField,
|
|
208
206
|
SelectField,
|
|
209
207
|
TextareaField,
|
|
210
|
-
TextField,
|
|
211
208
|
ToggleField,
|
|
212
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'system-settings'\">\
|
|
213
|
-
}], 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 }] }],
|
|
209
|
+
], 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" }]
|
|
210
|
+
}], 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 }] }] } });
|
|
214
211
|
|
|
215
212
|
const FIXED_CURRENCIES = [
|
|
216
213
|
{
|
|
@@ -303,6 +300,12 @@ const DOTNET_DAY_DEFINITIONS = [
|
|
|
303
300
|
{ dayNumber: 5, translationKey: 'friday' },
|
|
304
301
|
{ dayNumber: 6, translationKey: 'saturday' },
|
|
305
302
|
];
|
|
303
|
+
const TIMESHEET_FREQUENCY_OPTIONS = [
|
|
304
|
+
{ id: 'Daily', translationKey: 'frequency-daily' },
|
|
305
|
+
{ id: 'Weekly', translationKey: 'frequency-weekly' },
|
|
306
|
+
{ id: 'BiWeekly', translationKey: 'frequency-biweekly' },
|
|
307
|
+
{ id: 'Monthly', translationKey: 'frequency-monthly' },
|
|
308
|
+
];
|
|
306
309
|
const SCHEDULE_ITEM_TYPE_OPTIONS = [
|
|
307
310
|
{ itemType: 'Task', translationKey: 'schedule-item-task' },
|
|
308
311
|
{ itemType: 'Milestone', translationKey: 'schedule-item-milestone' },
|
|
@@ -313,6 +316,35 @@ const RATE_SOURCE_OPTIONS = [
|
|
|
313
316
|
{ id: 'None', translationKey: 'rate-source-none' },
|
|
314
317
|
];
|
|
315
318
|
|
|
319
|
+
const SYSTEM_SETTINGS_STORAGE_KEY = 'systemSettings.settings';
|
|
320
|
+
function serializeSystemSettings(settings) {
|
|
321
|
+
return JSON.stringify(settings);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Persists the canonical settings array consumed by host-level formatters.
|
|
325
|
+
* Storage failures must not turn a successful API request into a UI failure.
|
|
326
|
+
*/
|
|
327
|
+
function synchronizeSystemSettingsStorage(storage, settings) {
|
|
328
|
+
if (!storage) {
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
try {
|
|
332
|
+
storage.setItem(SYSTEM_SETTINGS_STORAGE_KEY, serializeSystemSettings(settings));
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function resolveBrowserLocalStorage() {
|
|
340
|
+
try {
|
|
341
|
+
return globalThis.localStorage ?? null;
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
316
348
|
class SystemSettings {
|
|
317
349
|
http = inject(HttpClient);
|
|
318
350
|
router = inject(Router);
|
|
@@ -357,53 +389,36 @@ class SystemSettings {
|
|
|
357
389
|
port: new FormControl('', { nonNullable: true }),
|
|
358
390
|
}),
|
|
359
391
|
timeSheetPolicy: new FormGroup({
|
|
360
|
-
|
|
361
|
-
generationEnabled: new FormControl(true, { nonNullable: true }),
|
|
362
|
-
manualGenerationEnabled: new FormControl(true, { nonNullable: true }),
|
|
363
|
-
regularDailyHours: new FormControl(8, [
|
|
364
|
-
Validators.required,
|
|
365
|
-
Validators.min(0),
|
|
366
|
-
Validators.max(24),
|
|
367
|
-
]),
|
|
392
|
+
frequency: new FormControl('Weekly', Validators.required),
|
|
368
393
|
maxDailyHours: new FormControl(24, [
|
|
369
394
|
Validators.required,
|
|
370
395
|
Validators.min(1),
|
|
371
396
|
Validators.max(24),
|
|
372
397
|
]),
|
|
373
|
-
allowOvertime: new FormControl(true, { nonNullable: true }),
|
|
374
|
-
requireOvertimeReason: new FormControl(false, { nonNullable: true }),
|
|
375
398
|
requireDescription: new FormControl(false, { nonNullable: true }),
|
|
376
|
-
allowFutureEntry: new FormControl(
|
|
377
|
-
|
|
399
|
+
allowFutureEntry: new FormControl(false, { nonNullable: true }),
|
|
400
|
+
allowBackdatedEntry: new FormControl(true, { nonNullable: true }),
|
|
401
|
+
autoLockOnApprove: new FormControl(true, { nonNullable: true }),
|
|
402
|
+
submissionDeadlineDays: new FormControl(3, [
|
|
403
|
+
Validators.required,
|
|
378
404
|
Validators.min(0),
|
|
379
|
-
Validators.max(
|
|
405
|
+
Validators.max(90),
|
|
380
406
|
]),
|
|
381
|
-
allowedScheduleItemTypes: new FormControl(['Deliverable'], {
|
|
382
|
-
nonNullable: true,
|
|
383
|
-
validators: [Validators.required],
|
|
384
|
-
}),
|
|
385
|
-
assignedItemsOnly: new FormControl(false, { nonNullable: true }),
|
|
386
|
-
allowZeroHourSubmit: new FormControl(true, { nonNullable: true }),
|
|
387
|
-
costEnabled: new FormControl(true, { nonNullable: true }),
|
|
388
|
-
rateSource: new FormControl('UserHourlyRate', Validators.required),
|
|
389
407
|
}),
|
|
390
408
|
globalWorkingHours: new FormGroup({
|
|
391
409
|
timeZoneId: new FormControl(null, Validators.required),
|
|
392
|
-
workDayStart: new FormControl('08:00', {
|
|
393
|
-
nonNullable: true,
|
|
394
|
-
validators: [Validators.required],
|
|
395
|
-
}),
|
|
396
|
-
workDayEnd: new FormControl('16:00', {
|
|
397
|
-
nonNullable: true,
|
|
398
|
-
validators: [Validators.required],
|
|
399
|
-
}),
|
|
400
410
|
workingDays: new FormControl([0, 1, 2, 3, 4], {
|
|
401
411
|
nonNullable: true,
|
|
402
412
|
validators: [Validators.required],
|
|
403
413
|
}),
|
|
414
|
+
hoursPerDay: new FormControl(8, [
|
|
415
|
+
Validators.required,
|
|
416
|
+
Validators.min(0),
|
|
417
|
+
Validators.max(24),
|
|
418
|
+
]),
|
|
404
419
|
holidaysCsv: new FormControl('', { nonNullable: true }),
|
|
405
420
|
}),
|
|
406
|
-
});
|
|
421
|
+
}, maxDailyHoursGteHoursPerDay);
|
|
407
422
|
settings = signal(null, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
|
|
408
423
|
settingsLoading = signal(false, ...(ngDevMode ? [{ debugName: "settingsLoading" }] : /* istanbul ignore next */ []));
|
|
409
424
|
settingsError = signal(null, ...(ngDevMode ? [{ debugName: "settingsError" }] : /* istanbul ignore next */ []));
|
|
@@ -481,21 +496,13 @@ class SystemSettings {
|
|
|
481
496
|
name: this.transloco.translate(`system-settings.${day.translationKey}`),
|
|
482
497
|
}));
|
|
483
498
|
}, ...(ngDevMode ? [{ debugName: "dotnetDayOptions" }] : /* istanbul ignore next */ []));
|
|
484
|
-
|
|
485
|
-
this.activeLang();
|
|
486
|
-
return SCHEDULE_ITEM_TYPE_OPTIONS.map((item) => ({
|
|
487
|
-
id: item.itemType,
|
|
488
|
-
itemType: item.itemType,
|
|
489
|
-
name: this.transloco.translate(`system-settings.${item.translationKey}`),
|
|
490
|
-
}));
|
|
491
|
-
}, ...(ngDevMode ? [{ debugName: "scheduleItemTypeOptions" }] : /* istanbul ignore next */ []));
|
|
492
|
-
rateSourceOptions = computed(() => {
|
|
499
|
+
frequencyOptions = computed(() => {
|
|
493
500
|
this.activeLang();
|
|
494
|
-
return
|
|
501
|
+
return TIMESHEET_FREQUENCY_OPTIONS.map((item) => ({
|
|
495
502
|
id: item.id,
|
|
496
503
|
name: this.transloco.translate(`system-settings.${item.translationKey}`),
|
|
497
504
|
}));
|
|
498
|
-
}, ...(ngDevMode ? [{ debugName: "
|
|
505
|
+
}, ...(ngDevMode ? [{ debugName: "frequencyOptions" }] : /* istanbul ignore next */ []));
|
|
499
506
|
isReady = computed(() => this.hydrationVersion() !== null && this.initialSnapshot() !== null, ...(ngDevMode ? [{ debugName: "isReady" }] : /* istanbul ignore next */ []));
|
|
500
507
|
isLoading = computed(() => this.settingsLoading() || this.timezonesLoading() || !this.isReady(), ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
501
508
|
hasChanges = computed(() => {
|
|
@@ -668,7 +675,9 @@ class SystemSettings {
|
|
|
668
675
|
.get(this.buildEndpoint('getsystemsettings'))
|
|
669
676
|
.subscribe({
|
|
670
677
|
next: (response) => {
|
|
671
|
-
|
|
678
|
+
const settings = response.data ?? [];
|
|
679
|
+
this.settings.set(settings);
|
|
680
|
+
synchronizeSystemSettingsStorage(resolveBrowserLocalStorage(), settings);
|
|
672
681
|
this.settingsLoading.set(false);
|
|
673
682
|
this.settingsLastUpdated.set(new Date().toISOString());
|
|
674
683
|
},
|
|
@@ -706,6 +715,7 @@ class SystemSettings {
|
|
|
706
715
|
next: () => {
|
|
707
716
|
const nextSettings = this.applyUpdatedSettings(this.settings() ?? [], values);
|
|
708
717
|
this.settings.set(nextSettings);
|
|
718
|
+
synchronizeSystemSettingsStorage(resolveBrowserLocalStorage(), nextSettings);
|
|
709
719
|
this.updating.set(false);
|
|
710
720
|
this.updateError.set(null);
|
|
711
721
|
this.settingsLastUpdated.set(new Date().toISOString());
|
|
@@ -722,8 +732,8 @@ class SystemSettings {
|
|
|
722
732
|
const currency = this.normalizeCurrencySnapshot(this.extractCurrencyValue(currencySetting));
|
|
723
733
|
const weekend = this.normalizeWeekendSnapshot(this.extractWeekendValue(weekendSetting));
|
|
724
734
|
const smtp = this.normalizeSmtpSnapshot(this.extractSmtpValue(smtpSetting));
|
|
725
|
-
const timeSheetPolicy = this.normalizeTimeSheetPolicySnapshot(this.extractTimeSheetPolicyValue(timeSheetPolicySetting));
|
|
726
735
|
const globalWorkingHours = this.normalizeGlobalWorkingHoursSnapshot(this.extractGlobalWorkingHoursValue(globalWorkingHoursSetting));
|
|
736
|
+
const timeSheetPolicy = this.normalizeTimeSheetPolicySnapshot(this.extractTimeSheetPolicyValue(timeSheetPolicySetting), globalWorkingHours.hoursPerDay);
|
|
727
737
|
this.holidayItems.set(holidays.data);
|
|
728
738
|
this.form.controls.timezone.setValue({
|
|
729
739
|
regionId: timezone.region?.id ?? null,
|
|
@@ -745,27 +755,18 @@ class SystemSettings {
|
|
|
745
755
|
port: smtp.port === null ? '' : String(smtp.port),
|
|
746
756
|
});
|
|
747
757
|
this.form.controls.timeSheetPolicy.setValue({
|
|
748
|
-
|
|
749
|
-
generationEnabled: timeSheetPolicy.generationEnabled,
|
|
750
|
-
manualGenerationEnabled: timeSheetPolicy.manualGenerationEnabled,
|
|
751
|
-
regularDailyHours: timeSheetPolicy.regularDailyHours,
|
|
758
|
+
frequency: timeSheetPolicy.frequency,
|
|
752
759
|
maxDailyHours: timeSheetPolicy.maxDailyHours,
|
|
753
|
-
allowOvertime: timeSheetPolicy.allowOvertime,
|
|
754
|
-
requireOvertimeReason: timeSheetPolicy.requireOvertimeReason,
|
|
755
760
|
requireDescription: timeSheetPolicy.requireDescription,
|
|
756
761
|
allowFutureEntry: timeSheetPolicy.allowFutureEntry,
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
allowZeroHourSubmit: timeSheetPolicy.allowZeroHourSubmit,
|
|
761
|
-
costEnabled: timeSheetPolicy.costEnabled,
|
|
762
|
-
rateSource: timeSheetPolicy.rateSource,
|
|
762
|
+
allowBackdatedEntry: timeSheetPolicy.allowBackdatedEntry,
|
|
763
|
+
autoLockOnApprove: timeSheetPolicy.autoLockOnApprove,
|
|
764
|
+
submissionDeadlineDays: timeSheetPolicy.submissionDeadlineDays,
|
|
763
765
|
});
|
|
764
766
|
this.form.controls.globalWorkingHours.setValue({
|
|
765
767
|
timeZoneId: globalWorkingHours.timeZoneId,
|
|
766
|
-
workDayStart: minutesToTime(globalWorkingHours.workDayStartMinute),
|
|
767
|
-
workDayEnd: minutesToTime(globalWorkingHours.workDayEndMinute),
|
|
768
768
|
workingDays: globalWorkingHours.workingDays,
|
|
769
|
+
hoursPerDay: globalWorkingHours.hoursPerDay,
|
|
769
770
|
holidaysCsv: globalWorkingHours.holidays.join(', '),
|
|
770
771
|
});
|
|
771
772
|
this.form.markAsPristine();
|
|
@@ -854,35 +855,23 @@ class SystemSettings {
|
|
|
854
855
|
}
|
|
855
856
|
buildTimeSheetPolicyValue() {
|
|
856
857
|
const policyForm = this.form.controls.timeSheetPolicy.getRawValue();
|
|
858
|
+
const hoursPerDay = clampNumber(this.form.controls.globalWorkingHours.controls.hoursPerDay.value ?? 8, 0, 24);
|
|
857
859
|
return {
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
manualGenerationEnabled: policyForm.manualGenerationEnabled,
|
|
861
|
-
regularDailyHours: policyForm.regularDailyHours ?? 8,
|
|
862
|
-
maxDailyHours: policyForm.maxDailyHours ?? 24,
|
|
863
|
-
allowOvertime: policyForm.allowOvertime,
|
|
864
|
-
requireOvertimeReason: policyForm.allowOvertime
|
|
865
|
-
? policyForm.requireOvertimeReason
|
|
866
|
-
: false,
|
|
860
|
+
frequency: normalizeFrequency(policyForm.frequency),
|
|
861
|
+
maxDailyHours: Math.max(hoursPerDay, clampNumber(policyForm.maxDailyHours ?? 24, 1, 24)),
|
|
867
862
|
requireDescription: policyForm.requireDescription,
|
|
868
863
|
allowFutureEntry: policyForm.allowFutureEntry,
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
allowZeroHourSubmit: policyForm.allowZeroHourSubmit,
|
|
873
|
-
costEnabled: policyForm.costEnabled,
|
|
874
|
-
rateSource: policyForm.costEnabled
|
|
875
|
-
? (policyForm.rateSource ?? 'UserHourlyRate')
|
|
876
|
-
: 'None',
|
|
864
|
+
allowBackdatedEntry: policyForm.allowBackdatedEntry,
|
|
865
|
+
autoLockOnApprove: policyForm.autoLockOnApprove,
|
|
866
|
+
submissionDeadlineDays: clampNumber(policyForm.submissionDeadlineDays ?? 0, 0, 90),
|
|
877
867
|
};
|
|
878
868
|
}
|
|
879
869
|
buildGlobalWorkingHoursValue() {
|
|
880
870
|
const globalForm = this.form.controls.globalWorkingHours.getRawValue();
|
|
881
871
|
return {
|
|
882
872
|
timeZoneId: globalForm.timeZoneId ?? 'UTC',
|
|
883
|
-
workDayStartMinute: timeToMinutes(globalForm.workDayStart),
|
|
884
|
-
workDayEndMinute: timeToMinutes(globalForm.workDayEnd),
|
|
885
873
|
workingDays: normalizeDotnetDays(globalForm.workingDays),
|
|
874
|
+
hoursPerDay: clampNumber(globalForm.hoursPerDay ?? 8, 0, 24),
|
|
886
875
|
holidays: parseCsv(globalForm.holidaysCsv),
|
|
887
876
|
};
|
|
888
877
|
}
|
|
@@ -956,47 +945,36 @@ class SystemSettings {
|
|
|
956
945
|
if (!isRecord(setting.value)) {
|
|
957
946
|
return this.getDefaultTimeSheetPolicyValue();
|
|
958
947
|
}
|
|
948
|
+
const value = setting.value;
|
|
959
949
|
const defaults = this.getDefaultTimeSheetPolicyValue();
|
|
960
950
|
return {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
defaults.
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
regularDailyHours: getNumber(setting.value['regularDailyHours']) ??
|
|
967
|
-
defaults.regularDailyHours,
|
|
968
|
-
maxDailyHours: getNumber(setting.value['maxDailyHours']) ?? defaults.maxDailyHours,
|
|
969
|
-
allowOvertime: getBoolean(setting.value['allowOvertime']) ?? defaults.allowOvertime,
|
|
970
|
-
requireOvertimeReason: getBoolean(setting.value['requireOvertimeReason']) ??
|
|
971
|
-
defaults.requireOvertimeReason,
|
|
972
|
-
requireDescription: getBoolean(setting.value['requireDescription']) ??
|
|
973
|
-
defaults.requireDescription,
|
|
974
|
-
allowFutureEntry: getBoolean(setting.value['allowFutureEntry']) ??
|
|
951
|
+
frequency: normalizeFrequency(value['frequency'] ?? value['Frequency']),
|
|
952
|
+
maxDailyHours: getNumber(value['maxDailyHours'] ?? value['MaxDailyHours']) ??
|
|
953
|
+
defaults.maxDailyHours,
|
|
954
|
+
requireDescription: getBoolean(value['requireDescription'] ?? value['RequireDescription']) ?? defaults.requireDescription,
|
|
955
|
+
allowFutureEntry: getBoolean(value['allowFutureEntry'] ?? value['AllowFutureEntry']) ??
|
|
975
956
|
defaults.allowFutureEntry,
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
defaults.
|
|
979
|
-
|
|
980
|
-
defaults.assignedItemsOnly,
|
|
981
|
-
allowZeroHourSubmit: getBoolean(setting.value['allowZeroHourSubmit']) ??
|
|
982
|
-
defaults.allowZeroHourSubmit,
|
|
983
|
-
costEnabled: getBoolean(setting.value['costEnabled']) ?? defaults.costEnabled,
|
|
984
|
-
rateSource: getString(setting.value['rateSource']) ?? defaults.rateSource,
|
|
957
|
+
allowBackdatedEntry: getBoolean(value['allowBackdatedEntry'] ?? value['AllowBackdatedEntry']) ?? defaults.allowBackdatedEntry,
|
|
958
|
+
autoLockOnApprove: getBoolean(value['autoLockOnApprove'] ?? value['AutoLockOnApprove']) ??
|
|
959
|
+
defaults.autoLockOnApprove,
|
|
960
|
+
submissionDeadlineDays: getNumber(value['submissionDeadlineDays'] ?? value['SubmissionDeadlineDays']) ?? defaults.submissionDeadlineDays,
|
|
985
961
|
};
|
|
986
962
|
}
|
|
987
963
|
extractGlobalWorkingHoursValue(setting) {
|
|
988
964
|
if (!isRecord(setting.value)) {
|
|
989
965
|
return this.getDefaultGlobalWorkingHoursValue();
|
|
990
966
|
}
|
|
967
|
+
const value = setting.value;
|
|
991
968
|
const defaults = this.getDefaultGlobalWorkingHoursValue();
|
|
992
969
|
return {
|
|
993
|
-
timeZoneId: getString(
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
holidays: getStringArray(
|
|
970
|
+
timeZoneId: getString(value['timeZoneId'] ?? value['TimeZoneId']) ??
|
|
971
|
+
defaults.timeZoneId,
|
|
972
|
+
workingDays: getNumberArray(value['workingDays'] ?? value['WorkingDays']) ??
|
|
973
|
+
defaults.workingDays,
|
|
974
|
+
hoursPerDay: getNumber(value['hoursPerDay'] ?? value['HoursPerDay']) ??
|
|
975
|
+
defaults.hoursPerDay,
|
|
976
|
+
holidays: getStringArray(value['holidays'] ?? value['Holidays']) ??
|
|
977
|
+
defaults.holidays,
|
|
1000
978
|
};
|
|
1001
979
|
}
|
|
1002
980
|
normalizeHolidayItem(value) {
|
|
@@ -1092,33 +1070,23 @@ class SystemSettings {
|
|
|
1092
1070
|
port: value.port,
|
|
1093
1071
|
};
|
|
1094
1072
|
}
|
|
1095
|
-
normalizeTimeSheetPolicySnapshot(value) {
|
|
1096
|
-
const defaults = this.getDefaultTimeSheetPolicyValue();
|
|
1097
|
-
const regularDailyHours = clampNumber(value.regularDailyHours, 0, 24);
|
|
1098
|
-
const maxDailyHours = Math.max(regularDailyHours, clampNumber(value.maxDailyHours, 1, 24));
|
|
1099
|
-
const allowedScheduleItemTypes = value.allowedScheduleItemTypes.length
|
|
1100
|
-
? value.allowedScheduleItemTypes
|
|
1101
|
-
: defaults.allowedScheduleItemTypes;
|
|
1073
|
+
normalizeTimeSheetPolicySnapshot(value, hoursPerDay) {
|
|
1102
1074
|
return {
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
: clampNumber(value.pastEntryLockDays, 0, 3650),
|
|
1111
|
-
allowedScheduleItemTypes,
|
|
1112
|
-
rateSource: value.rateSource || defaults.rateSource,
|
|
1075
|
+
frequency: normalizeFrequency(value.frequency),
|
|
1076
|
+
maxDailyHours: Math.max(clampNumber(hoursPerDay, 0, 24), clampNumber(value.maxDailyHours, 1, 24)),
|
|
1077
|
+
requireDescription: value.requireDescription,
|
|
1078
|
+
allowFutureEntry: value.allowFutureEntry,
|
|
1079
|
+
allowBackdatedEntry: value.allowBackdatedEntry,
|
|
1080
|
+
autoLockOnApprove: value.autoLockOnApprove,
|
|
1081
|
+
submissionDeadlineDays: clampNumber(value.submissionDeadlineDays, 0, 90),
|
|
1113
1082
|
};
|
|
1114
1083
|
}
|
|
1115
1084
|
normalizeGlobalWorkingHoursSnapshot(value) {
|
|
1116
1085
|
const defaults = this.getDefaultGlobalWorkingHoursValue();
|
|
1117
1086
|
return {
|
|
1118
1087
|
timeZoneId: value.timeZoneId || defaults.timeZoneId,
|
|
1119
|
-
workDayStartMinute: clampNumber(value.workDayStartMinute, 0, 1439),
|
|
1120
|
-
workDayEndMinute: clampNumber(value.workDayEndMinute, 1, 1440),
|
|
1121
1088
|
workingDays: normalizeDotnetDays(value.workingDays),
|
|
1089
|
+
hoursPerDay: clampNumber(value.hoursPerDay, 0, 24),
|
|
1122
1090
|
holidays: value.holidays,
|
|
1123
1091
|
};
|
|
1124
1092
|
}
|
|
@@ -1203,29 +1171,20 @@ class SystemSettings {
|
|
|
1203
1171
|
}
|
|
1204
1172
|
getDefaultTimeSheetPolicyValue() {
|
|
1205
1173
|
return {
|
|
1206
|
-
|
|
1207
|
-
generationEnabled: true,
|
|
1208
|
-
manualGenerationEnabled: true,
|
|
1209
|
-
regularDailyHours: 8,
|
|
1174
|
+
frequency: 'Weekly',
|
|
1210
1175
|
maxDailyHours: 24,
|
|
1211
|
-
allowOvertime: true,
|
|
1212
|
-
requireOvertimeReason: false,
|
|
1213
1176
|
requireDescription: false,
|
|
1214
|
-
allowFutureEntry:
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
allowZeroHourSubmit: true,
|
|
1219
|
-
costEnabled: true,
|
|
1220
|
-
rateSource: 'UserHourlyRate',
|
|
1177
|
+
allowFutureEntry: false,
|
|
1178
|
+
allowBackdatedEntry: true,
|
|
1179
|
+
autoLockOnApprove: true,
|
|
1180
|
+
submissionDeadlineDays: 3,
|
|
1221
1181
|
};
|
|
1222
1182
|
}
|
|
1223
1183
|
getDefaultGlobalWorkingHoursValue() {
|
|
1224
1184
|
return {
|
|
1225
1185
|
timeZoneId: this.timezones()[0]?.id ?? 'UTC',
|
|
1226
|
-
workDayStartMinute: 480,
|
|
1227
|
-
workDayEndMinute: 960,
|
|
1228
1186
|
workingDays: [0, 1, 2, 3, 4],
|
|
1187
|
+
hoursPerDay: 8,
|
|
1229
1188
|
holidays: [],
|
|
1230
1189
|
};
|
|
1231
1190
|
}
|
|
@@ -1343,7 +1302,7 @@ class SystemSettings {
|
|
|
1343
1302
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
1344
1303
|
}
|
|
1345
1304
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettings, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1346
|
-
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-holidays-section\r\n [holidays]=\"holidayTableRows()\"\r\n (addHoliday)=\"openAddHoliday()\"\r\n (editHoliday)=\"editHoliday($event)\"\r\n (deleteHoliday)=\"deleteHoliday($event)\"\r\n />\r\n\r\n <mt-system-settings-general-section\r\n [timezoneForm]=\"form.controls.timezone\"\r\n [currencyForm]=\"form.controls.currency\"\r\n [weekendForm]=\"form.controls.weekend\"\r\n [timezoneOptions]=\"timezoneOptions()\"\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 [
|
|
1305
|
+
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-holidays-section\r\n [holidays]=\"holidayTableRows()\"\r\n (addHoliday)=\"openAddHoliday()\"\r\n (editHoliday)=\"editHoliday($event)\"\r\n (deleteHoliday)=\"deleteHoliday($event)\"\r\n />\r\n\r\n <mt-system-settings-general-section\r\n [timezoneForm]=\"form.controls.timezone\"\r\n [currencyForm]=\"form.controls.currency\"\r\n [weekendForm]=\"form.controls.weekend\"\r\n [timezoneOptions]=\"timezoneOptions()\"\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-smtp-section [smtpForm]=\"form.controls.smtp\" />\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"], 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: ["timezoneForm", "currencyForm", "weekendForm", "timezoneOptions", "dateFormatOptions", "timeFormatOptions", "currencyOptions", "currencyFormatOptions", "weekendOptions"] }, { kind: "component", type: SystemSettingsSmtpSection, selector: "mt-system-settings-smtp-section", inputs: ["smtpForm"] }, { kind: "component", type: SystemSettingsTimeSheetSection, selector: "mt-system-settings-timesheet-section", inputs: ["policyForm", "globalWorkingHoursForm", "dayOptions", "frequencyOptions", "timezoneOptions", "maxDailyBelowDaily"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1347
1306
|
}
|
|
1348
1307
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SystemSettings, decorators: [{
|
|
1349
1308
|
type: Component,
|
|
@@ -1359,7 +1318,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1359
1318
|
SystemSettingsGeneralSection,
|
|
1360
1319
|
SystemSettingsSmtpSection,
|
|
1361
1320
|
SystemSettingsTimeSheetSection,
|
|
1362
|
-
], 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-holidays-section\r\n [holidays]=\"holidayTableRows()\"\r\n (addHoliday)=\"openAddHoliday()\"\r\n (editHoliday)=\"editHoliday($event)\"\r\n (deleteHoliday)=\"deleteHoliday($event)\"\r\n />\r\n\r\n <mt-system-settings-general-section\r\n [timezoneForm]=\"form.controls.timezone\"\r\n [currencyForm]=\"form.controls.currency\"\r\n [weekendForm]=\"form.controls.weekend\"\r\n [timezoneOptions]=\"timezoneOptions()\"\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 [
|
|
1321
|
+
], 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-holidays-section\r\n [holidays]=\"holidayTableRows()\"\r\n (addHoliday)=\"openAddHoliday()\"\r\n (editHoliday)=\"editHoliday($event)\"\r\n (deleteHoliday)=\"deleteHoliday($event)\"\r\n />\r\n\r\n <mt-system-settings-general-section\r\n [timezoneForm]=\"form.controls.timezone\"\r\n [currencyForm]=\"form.controls.currency\"\r\n [weekendForm]=\"form.controls.weekend\"\r\n [timezoneOptions]=\"timezoneOptions()\"\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-smtp-section [smtpForm]=\"form.controls.smtp\" />\r\n </div>\r\n }\r\n </div>\r\n </mt-page>\r\n</ng-container>\r\n", styles: [":host{display:block}\n"] }]
|
|
1363
1322
|
}], 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 }] }] } });
|
|
1364
1323
|
function isRecord(value) {
|
|
1365
1324
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
@@ -1452,18 +1411,27 @@ function clampNumber(value, min, max) {
|
|
|
1452
1411
|
}
|
|
1453
1412
|
return Math.min(Math.max(value, min), max);
|
|
1454
1413
|
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1414
|
+
const TIMESHEET_FREQUENCIES = [
|
|
1415
|
+
'Daily',
|
|
1416
|
+
'Weekly',
|
|
1417
|
+
'BiWeekly',
|
|
1418
|
+
'Monthly',
|
|
1419
|
+
];
|
|
1420
|
+
function normalizeFrequency(value) {
|
|
1421
|
+
return typeof value === 'string' &&
|
|
1422
|
+
TIMESHEET_FREQUENCIES.includes(value)
|
|
1423
|
+
? value
|
|
1424
|
+
: 'Weekly';
|
|
1461
1425
|
}
|
|
1462
|
-
function
|
|
1463
|
-
const
|
|
1464
|
-
const
|
|
1465
|
-
|
|
1466
|
-
|
|
1426
|
+
function maxDailyHoursGteHoursPerDay(group) {
|
|
1427
|
+
const maxDailyHours = group.get('timeSheetPolicy.maxDailyHours')?.value;
|
|
1428
|
+
const hoursPerDay = group.get('globalWorkingHours.hoursPerDay')?.value;
|
|
1429
|
+
if (typeof maxDailyHours === 'number' &&
|
|
1430
|
+
typeof hoursPerDay === 'number' &&
|
|
1431
|
+
maxDailyHours < hoursPerDay) {
|
|
1432
|
+
return { maxDailyBelowDaily: true };
|
|
1433
|
+
}
|
|
1434
|
+
return null;
|
|
1467
1435
|
}
|
|
1468
1436
|
function parseCsv(value) {
|
|
1469
1437
|
return value
|
|
@@ -1510,5 +1478,5 @@ function formatDateOnly(value) {
|
|
|
1510
1478
|
* Generated bundle index. Do not edit.
|
|
1511
1479
|
*/
|
|
1512
1480
|
|
|
1513
|
-
export { DEFAULT_DATE_FORMAT_OPTIONS, DEFAULT_TIME_FORMAT_OPTIONS, DOTNET_DAY_DEFINITIONS, FIXED_CURRENCIES, RATE_SOURCE_OPTIONS, SCHEDULE_ITEM_TYPE_OPTIONS, SystemSettings, SystemSettingsHolidayEditor, WEEKEND_DAY_DEFINITIONS };
|
|
1481
|
+
export { DEFAULT_DATE_FORMAT_OPTIONS, DEFAULT_TIME_FORMAT_OPTIONS, DOTNET_DAY_DEFINITIONS, FIXED_CURRENCIES, RATE_SOURCE_OPTIONS, SCHEDULE_ITEM_TYPE_OPTIONS, SystemSettings, SystemSettingsHolidayEditor, TIMESHEET_FREQUENCY_OPTIONS, WEEKEND_DAY_DEFINITIONS };
|
|
1514
1482
|
//# sourceMappingURL=masterteam-system-settings.mjs.map
|