feat(planning): implement constraint-first leave planner
This commit is contained in:
1 parent
ba8dbe92d9
commit
7ceaf1a57a
32 files changed
+4842
-880
No files matched your search
@@ -37,12 +37,17 @@
|
||||
>
|
||||
</mat-slide-toggle>
|
||||
<div class="rule-actions">
|
||||
<button mat-icon-button (click)="startEdit(rule, $event)">
|
||||
<button
|
||||
mat-icon-button
|
||||
[aria-label]="tr().rules.editRule"
|
||||
(click)="startEdit(rule, $event)"
|
||||
>
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
color="warn"
|
||||
[aria-label]="tr().rules.deleteRule"
|
||||
(click)="deleteRule(rule.id, $event)"
|
||||
>
|
||||
<mat-icon>delete</mat-icon>
|
||||
@@ -59,6 +64,16 @@
|
||||
<mat-label>{{ tr().rules.ruleName }}</mat-label>
|
||||
<input matInput [(ngModel)]="$any(editBuffer).name" required />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="full-width">
|
||||
<mat-label>{{ tr().rules.force }}</mat-label>
|
||||
<mat-select [(ngModel)]="$any(editBuffer).force">
|
||||
@for (option of forceOptions; track option.value) {
|
||||
<mat-option [value]="option.value">{{
|
||||
option.label()
|
||||
}}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
@if ($any(editBuffer).type === RuleType.IF_THEN) {
|
||||
<div class="editor-row">
|
||||
@@ -210,6 +225,14 @@
|
||||
<mat-label>{{ tr().rules.ruleName }}</mat-label>
|
||||
<input matInput [(ngModel)]="$any(editBuffer).name" required />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="full-width">
|
||||
<mat-label>{{ tr().rules.force }}</mat-label>
|
||||
<mat-select [(ngModel)]="$any(editBuffer).force">
|
||||
@for (option of forceOptions; track option.value) {
|
||||
<mat-option [value]="option.value">{{ option.label() }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
@if (newRuleType() === RuleType.IF_THEN) {
|
||||
<div class="editor-row">
|
||||
|
||||
@@ -101,6 +101,10 @@ export class RulesPanel {
|
||||
protected readonly rewardDayTypes = Object.values(SelectableDayType).filter(
|
||||
(t) => t !== SelectableDayType.ANY,
|
||||
);
|
||||
protected readonly forceOptions = [
|
||||
{ value: 'obligation' as const, label: () => this.tr().rules.obligation },
|
||||
{ value: 'preference' as const, label: () => this.tr().rules.preference },
|
||||
];
|
||||
|
||||
protected get daysOfWeek() {
|
||||
const tr = this.tr();
|
||||
@@ -186,6 +190,7 @@ export class RulesPanel {
|
||||
this.editBuffer = {
|
||||
name: this.tr().rules.defaultNewRuleName,
|
||||
type: RuleType.IF_THEN,
|
||||
force: 'preference',
|
||||
dayOfWeek: 6,
|
||||
placeDays: 2,
|
||||
placeType: SelectableDayType.CP,
|
||||
@@ -197,6 +202,7 @@ export class RulesPanel {
|
||||
this.editBuffer = {
|
||||
name: this.tr().rules.defaultNewPeriodName,
|
||||
type: RuleType.TIME_WINDOW,
|
||||
force: 'preference',
|
||||
startDate: new Date(),
|
||||
endDate: new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000),
|
||||
placeDays: 5,
|
||||
@@ -212,6 +218,7 @@ export class RulesPanel {
|
||||
|
||||
public getRuleSummary(rule: VacationRule): string {
|
||||
const tr = this.tr();
|
||||
const forceLabel = rule.force === 'obligation' ? tr.rules.obligation : tr.rules.preference;
|
||||
if (rule.type === RuleType.IF_THEN) {
|
||||
const ifThen = rule as IfThenRule;
|
||||
const dayLabel = this.daysOfWeek.find((d) => d.value === ifThen.dayOfWeek)?.label ?? '';
|
||||
@@ -223,13 +230,13 @@ export class RulesPanel {
|
||||
.toLowerCase();
|
||||
const rewardTypeLabel = this.getDayTypeLabel(ifThen.rewardType);
|
||||
|
||||
return tr.rules.ifThenTemplate
|
||||
return `[${forceLabel}] ${tr.rules.ifThenTemplate
|
||||
.replace('{day}', dayLabel)
|
||||
.replace('{placeDays}', String(ifThen.placeDays))
|
||||
.replace('{placeType}', placeTypeLabel)
|
||||
.replace('{placement}', placementLabel)
|
||||
.replace('{rewardDays}', String(ifThen.rewardDays))
|
||||
.replace('{rewardType}', rewardTypeLabel);
|
||||
.replace('{rewardType}', rewardTypeLabel)}`;
|
||||
} else {
|
||||
const timeWindow = rule as TimeWindowRule;
|
||||
const placeTypeLabel = this.getDayTypeLabel(timeWindow.placeType);
|
||||
@@ -240,11 +247,11 @@ export class RulesPanel {
|
||||
this.translationService.locale(),
|
||||
);
|
||||
|
||||
return tr.rules.timeWindowTemplate
|
||||
return `[${forceLabel}] ${tr.rules.timeWindowTemplate
|
||||
.replace('{placeDays}', String(timeWindow.placeDays))
|
||||
.replace('{placeType}', placeTypeLabel)
|
||||
.replace('{startDate}', startDateStr)
|
||||
.replace('{endDate}', endDateStr);
|
||||
.replace('{endDate}', endDateStr)}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user