UI improvments
This commit is contained in:
1 parent
c9dbe82b79
commit
0ce33cc9d6
106 files changed
+72934
-1675
No files matched your search
@@ -1,9 +1,9 @@
|
||||
import {
|
||||
Component,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
inject,
|
||||
signal,
|
||||
Injectable,
|
||||
effect,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
@@ -25,37 +25,11 @@ import { MatInputModule } from '@angular/material/input';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { LiveAnnouncer } from '@angular/cdk/a11y';
|
||||
|
||||
import {
|
||||
DateAdapter,
|
||||
MAT_DATE_FORMATS,
|
||||
MAT_DATE_LOCALE,
|
||||
NativeDateAdapter,
|
||||
} from '@angular/material/core';
|
||||
import { CdkDragDrop, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
|
||||
|
||||
@Injectable()
|
||||
class CustomDateAdapter extends NativeDateAdapter {
|
||||
override format(date: Date, displayFormat: unknown): string {
|
||||
if (displayFormat === 'input') {
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
const year = date.getFullYear();
|
||||
return `${day}/${month}/${year}`;
|
||||
}
|
||||
return super.format(date, displayFormat as object);
|
||||
}
|
||||
}
|
||||
|
||||
const MY_DATE_FORMATS = {
|
||||
parse: { dateInput: 'input' },
|
||||
display: {
|
||||
dateInput: 'input',
|
||||
monthYearLabel: { year: 'numeric', month: 'short' },
|
||||
dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },
|
||||
monthYearA11yLabel: { year: 'numeric', month: 'long' },
|
||||
},
|
||||
};
|
||||
import { DateAdapter } from '@angular/material/core';
|
||||
import { DAY_FIRST_DATE_PROVIDERS } from '../../shared/day-first-date-adapter';
|
||||
import { CdkDragDrop, CdkDropList, CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
|
||||
|
||||
@Component({
|
||||
selector: 'app-rules-panel',
|
||||
@@ -71,20 +45,19 @@ const MY_DATE_FORMATS = {
|
||||
FormsModule,
|
||||
CdkDropList,
|
||||
CdkDrag,
|
||||
CdkDragHandle,
|
||||
],
|
||||
templateUrl: './rules-panel.html',
|
||||
styleUrl: './rules-panel.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [
|
||||
{ provide: DateAdapter, useClass: CustomDateAdapter },
|
||||
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' },
|
||||
{ provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMATS },
|
||||
],
|
||||
providers: DAY_FIRST_DATE_PROVIDERS,
|
||||
})
|
||||
export class RulesPanel {
|
||||
public ruleService = inject(RuleService);
|
||||
protected readonly translationService = inject(TranslationService);
|
||||
private readonly dateAdapter = inject(DateAdapter);
|
||||
private readonly liveAnnouncer = inject(LiveAnnouncer);
|
||||
private readonly changeDetector = inject(ChangeDetectorRef);
|
||||
|
||||
get tr() {
|
||||
return this.translationService.tr;
|
||||
@@ -145,16 +118,30 @@ export class RulesPanel {
|
||||
}
|
||||
|
||||
public drop(event: CdkDragDrop<VacationRule[]>) {
|
||||
if (event.previousIndex !== event.currentIndex) {
|
||||
this.ruleService.reorderRules(event.previousIndex, event.currentIndex);
|
||||
if (event.isPointerOverContainer && event.previousIndex !== event.currentIndex) {
|
||||
this.reorderRule(event.previousIndex, event.currentIndex);
|
||||
}
|
||||
// CDK restores the original DOM before this callback. Commit the final order
|
||||
// before the next paint so zoneless rendering doesn't flash the old position.
|
||||
this.changeDetector.detectChanges();
|
||||
}
|
||||
|
||||
public moveRule(index: number, offset: -1 | 1, event: Event) {
|
||||
event.stopPropagation();
|
||||
const destination = index + offset;
|
||||
if (destination >= 0 && destination < this.rules.length)
|
||||
this.ruleService.reorderRules(index, destination);
|
||||
this.reorderRule(index, destination);
|
||||
}
|
||||
|
||||
private reorderRule(from: number, to: number) {
|
||||
const rule = this.rules[from];
|
||||
this.ruleService.reorderRules(from, to);
|
||||
void this.liveAnnouncer.announce(
|
||||
this.tr()
|
||||
.rules.ruleMoved.replace('{name}', rule.name)
|
||||
.replace('{position}', String(to + 1))
|
||||
.replace('{count}', String(this.rules.length)),
|
||||
);
|
||||
}
|
||||
|
||||
public toggleRule(id: string) {
|
||||
@@ -229,7 +216,6 @@ 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 ?? '';
|
||||
@@ -241,13 +227,13 @@ export class RulesPanel {
|
||||
.toLowerCase();
|
||||
const rewardTypeLabel = this.getDayTypeLabel(ifThen.rewardType);
|
||||
|
||||
return `[${forceLabel}] ${tr.rules.ifThenTemplate
|
||||
return 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);
|
||||
@@ -258,11 +244,11 @@ export class RulesPanel {
|
||||
this.translationService.locale(),
|
||||
);
|
||||
|
||||
return `[${forceLabel}] ${tr.rules.timeWindowTemplate
|
||||
return 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