Skip to content

Commit

Permalink
Add my absences #185
Browse files Browse the repository at this point in the history
  • Loading branch information
hupf committed Sep 16, 2020
1 parent f738b92 commit 8cf8e2d
Show file tree
Hide file tree
Showing 55 changed files with 1,484 additions and 106 deletions.
8 changes: 8 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ const routes: Routes = [
(m) => m.EvaluateAbsencesModule
),
},
{
path: 'my-absences',
canActivate: [AuthGuard],
loadChildren: () =>
import('./my-absences/my-absences.module').then(
(m) => m.MyAbsencesModule
),
},
{
path: 'my-profile',
canActivate: [AuthGuard],
Expand Down
1 change: 1 addition & 0 deletions src/app/home.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe('HomeComponent', () => {
'/open-absences',
'/edit-absences',
'/evaluate-absences',
'/my-absences',
'/my-profile',
]);
});
Expand Down
1 change: 1 addition & 0 deletions src/app/home.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class HomeComponent {
'open-absences',
'edit-absences',
'evaluate-absences',
'my-absences',
'my-profile',
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<div class="erz-container erz-container-padding-y">
<div
class="mb-3 pb-3 border-bottom"
*erzLet="(selectionService.selection$ | async)?.length as selectedCount"
>
{{
(selectedCount === 1
? 'my-absences.confirm.lesson-selected'
: 'my-absences.confirm.lessons-selected'
) | translate: { count: selectedCount }
}}
</div>
<form [formGroup]="formGroup" (ngSubmit)="onSubmit()">
<div class="form-group mb-4">
<label
>{{ 'my-absences.confirm.choose-presence-type' | translate }}:</label
>
<div
*ngFor="let type of absenceTypes$ | async; index as i"
class="form-check my-3"
>
<input
type="radio"
class="form-check-input"
[class.is-invalid]="(absenceTypeIdErrors$ | async).length > 0"
[id]="'absence-type-' + i"
formControlName="absenceTypeId"
[value]="type.Id"
/>
<label class="form-check-label" [for]="'absence-type-' + i">
{{ type.Designation }}
</label>
<ng-container *ngIf="(absenceTypes$ | async)?.length - 1 === i">
<div
*ngFor="let error of absenceTypeIdErrors$ | async"
class="invalid-feedback"
>
{{
'global.validation-errors.' + error.error
| translate: error.params
}}
</div>
</ng-container>
</div>
</div>
<div class="remark">
{{ 'my-absences.confirm.remark' | translate }}
</div>

<div class="d-flex justify-content-end">
<button
type="button"
class="btn btn-secondary"
[disabled]="saving$ | async"
(click)="cancel()"
>
{{ 'my-absences.confirm.cancel' | translate }}
</button>
<button
type="submit"
class="btn btn-primary ml-2"
[disabled]="saving$ | async"
>
{{ 'my-absences.confirm.save' | translate }}
<div
*ngIf="saving$ | async"
class="spinner-border spinner-border-sm align-middle"
role="status"
>
<span class="sr-only">Loading...</span>
</div>
</button>
</div>
</form>
</div>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { of } from 'rxjs';

import { MyAbsencesConfirmComponent } from './my-absences-confirm.component';
import { buildTestModuleMetadata } from 'src/spec-helpers';
import { MyAbsencesService } from '../../services/my-absences.service';

describe('MyAbsencesConfirmComponent', () => {
let component: MyAbsencesConfirmComponent;
let fixture: ComponentFixture<MyAbsencesConfirmComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule(
buildTestModuleMetadata({
declarations: [MyAbsencesConfirmComponent],
providers: [
{
provide: MyAbsencesService,
useValue: {
openAbsences$: of([]),
counts$: of({}),
},
},
],
})
).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(MyAbsencesConfirmComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import {
Component,
OnInit,
ChangeDetectionStrategy,
Inject,
} from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { ToastrService } from 'ngx-toastr';
import { TranslateService } from '@ngx-translate/core';
import { BehaviorSubject, combineLatest } from 'rxjs';
import {
take,
switchMap,
finalize,
map,
filter,
startWith,
} from 'rxjs/operators';

import { ConfirmAbsencesSelectionService } from 'src/app/shared/services/confirm-absences-selection.service';
import { LessonPresencesUpdateRestService } from 'src/app/shared/services/lesson-presences-update-rest.service';
import { PresenceTypesService } from 'src/app/shared/services/presence-types.service';
import { getValidationErrors } from 'src/app/shared/utils/form';
import { SETTINGS, Settings } from 'src/app/settings';
import { MyAbsencesService } from '../../services/my-absences.service';

@Component({
selector: 'erz-my-absences-confirm',
templateUrl: './my-absences-confirm.component.html',
styleUrls: ['./my-absences-confirm.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyAbsencesConfirmComponent implements OnInit {
formGroup = this.createFormGroup();

saving$ = new BehaviorSubject(false);
private submitted$ = new BehaviorSubject(false);

absenceTypes$ = this.presenceTypesService.confirmationTypes$.pipe(
map((types) => types.filter((t) => t.IsAbsence && !t.IsHalfDay))
);

absenceTypeIdErrors$ = combineLatest([
getValidationErrors(this.formGroup.get('absenceTypeId')),
this.submitted$,
]).pipe(
filter((v) => v[1]),
map((v) => v[0]),
startWith([])
);

constructor(
private fb: FormBuilder,
private router: Router,
private toastr: ToastrService,
private translate: TranslateService,
private presenceTypesService: PresenceTypesService,
private updateService: LessonPresencesUpdateRestService,
private myAbsencesService: MyAbsencesService,
@Inject(SETTINGS) private settings: Settings,
public selectionService: ConfirmAbsencesSelectionService
) {}

ngOnInit(): void {
this.selectionService.selectedIds$
.pipe(take(1))
.subscribe((selectedIds) => {
if (selectedIds.length === 0) {
// Nothing to confirm if no entries are selected
this.navigateBack();
}
});
}

onSubmit(): void {
this.submitted$.next(true);
if (this.formGroup.valid) {
const { absenceTypeId } = this.formGroup.value;
this.save(absenceTypeId);
}
}

cancel(): void {
this.navigateBack();
}

private createFormGroup(): FormGroup {
return this.fb.group({
absenceTypeId: [null, Validators.required],
});
}

private save(absenceTypeId: number): void {
this.saving$.next(true);

this.selectionService.selectedIds$
.pipe(
take(1),
switchMap((selectedIds) =>
combineLatest(
selectedIds.map(({ lessonIds, personIds }) =>
this.updateService.editLessonPresences(
lessonIds,
personIds,
absenceTypeId,
this.settings.unconfirmedAbsenceStateId
)
)
)
),
finalize(() => this.saving$.next(false))
)
.subscribe(this.onSaveSuccess.bind(this));
}

private onSaveSuccess(): void {
this.myAbsencesService.reset();
this.toastr.success(
this.translate.instant('my-absences.confirm.save-success')
);
this.navigateBack();
}

private navigateBack(): void {
this.router.navigate(['/my-absences']);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<h5 class="m-0">
{{ 'my-absences.show.report-absence-link' | translate }}
</h5>
<a [routerLink]="['/my-absences/report']" class="btn btn-link p-0" #link>
<div class="d-flex align-items-center">
<i class="material-icons">keyboard_arrow_right</i>
</div>
</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@import "../../../../bootstrap-variables";

:host {
display: flex;
align-items: center;
justify-content: space-between;
padding: $spacer;
cursor: pointer;
}

.btn {
color: $body-color;
text-decoration: none;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { MyAbsencesReportLinkComponent } from '../my-absences-report-link/my-absences-report-link.component';
import { buildTestModuleMetadata } from 'src/spec-helpers';

describe('MyAbsencesEditLinkComponent', () => {
let component: MyAbsencesReportLinkComponent;
let fixture: ComponentFixture<MyAbsencesReportLinkComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule(
buildTestModuleMetadata({
declarations: [MyAbsencesReportLinkComponent],
})
).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(MyAbsencesReportLinkComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
Component,
OnInit,
ChangeDetectionStrategy,
HostListener,
ViewChild,
ElementRef,
} from '@angular/core';

@Component({
selector: 'erz-my-absences-report-link',
templateUrl: './my-absences-report-link.component.html',
styleUrls: ['./my-absences-report-link.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyAbsencesReportLinkComponent implements OnInit {
@ViewChild('link') link: ElementRef<HTMLElement>;

@HostListener('click', ['$event'])
onClick(): void {
this.link.nativeElement.click();
}

constructor() {}

ngOnInit(): void {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>my-absences-edit works!</p>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { MyAbsencesReportComponent } from './my-absences-report.component';
import { buildTestModuleMetadata } from 'src/spec-helpers';

describe('MyAbsencesReportComponent', () => {
let component: MyAbsencesReportComponent;
let fixture: ComponentFixture<MyAbsencesReportComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule(
buildTestModuleMetadata({
declarations: [MyAbsencesReportComponent],
})
).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(MyAbsencesReportComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';

@Component({
selector: 'erz-my-absences-report',
templateUrl: './my-absences-report.component.html',
styleUrls: ['./my-absences-report.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyAbsencesReportComponent implements OnInit {
constructor() {}

ngOnInit(): void {}
}
Loading

0 comments on commit 8cf8e2d

Please sign in to comment.