File

src/app/shared/components/forms/audit-form/audit-form.component.ts

Extends

AbstractFormComponent

Implements

OnInit

Metadata

selector app-audit-form
styleUrls ./audit-form.component.scss
templateUrl ./audit-form.component.html

Index

Properties
Methods
Inputs
Outputs
Accessors

Constructor

constructor(formBuilder: FormBuilder, dialogService: NbDialogService, store: Store)
Parameters :
Name Type Optional
formBuilder FormBuilder No
dialogService NbDialogService No
store Store No

Inputs

audit
Type : Audit
cancelButtonName
Type : string
Inherited from AbstractFormComponent
submitButtonName
Type : string
Inherited from AbstractFormComponent

Outputs

formSubmitted
Type : EventEmitter
cancelled
Type : EventEmitter
Inherited from AbstractFormComponent

Methods

checkedFacCrits
checkedFacCrits()
Returns : {}
ngOnInit
ngOnInit()
Returns : void
onSubmit
onSubmit()
Returns : void
toggleCriteriaChecked
toggleCriteriaChecked(factorId: string, checked)
Parameters :
Name Type Optional
factorId string No
checked No
Returns : void
onCancel
onCancel()
Inherited from AbstractFormComponent
Returns : void

Properties

contactPersons$
Type : Observable<ContactPerson[]>
Decorators :
@Select(ContactPersonState.contactPersons)
facCrits$
Type : Observable<FacCrit[]>
Decorators :
@Select(AuditState.facCrits)
formGroup
Type : FormGroup
Inherited from AbstractFormComponent

Accessors

name
getname()
startDate
getstartDate()
endDate
getendDate()
contactPersonsControl
getcontactPersonsControl()
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { Validators, FormBuilder, FormControl } from '@angular/forms';
import { Audit, AuditStatus } from 'src/app/core/data/models/audit.model';
import { NbDialogService } from '@nebular/theme';
import { dateRangeValidator } from 'src/app/shared/helpers/form-helpers';
import { ContactPerson } from 'src/app/core/data/models/contact-person.model';
import { FacCrit } from 'src/app/core/data/models/faccrit.model';
import { Select, Store } from '@ngxs/store';
import { AuditState } from 'src/app/core/ngxs/audit.state';
import { Observable } from 'rxjs';
import { AbstractFormComponent } from '../abstract-form-component';
import { ContactPersonState } from 'src/app/core/ngxs/contact-person.state';

const defaultScopeComplement = [8, 14];

@Component({
  selector: 'app-audit-form',
  templateUrl: './audit-form.component.html',
  styleUrls: ['./audit-form.component.scss'],
})
export class AuditFormComponent extends AbstractFormComponent implements OnInit {
  @Input() audit: Audit;
  @Output() formSubmitted = new EventEmitter<Partial<Audit>>();

  @Select(ContactPersonState.contactPersons) contactPersons$: Observable<ContactPerson[]>;
  @Select(AuditState.facCrits) facCrits$: Observable<FacCrit[]>;

  constructor(
    private formBuilder: FormBuilder,
    protected dialogService: NbDialogService,
    private store: Store,
  ) {
    super(dialogService);
  }

  get name() {
    return this.formGroup.get('name');
  }

  get startDate() {
    return this.formGroup.get('startDate');
  }

  get endDate() {
    return this.formGroup.get('endDate');
  }

  get contactPersonsControl() {
    return this.formGroup.get('contactPersons');
  }

  ngOnInit() {
    const contactPersonsSnapshot = this.store.selectSnapshot(ContactPersonState.contactPersons);

    const defaultStartDate = new Date();
    defaultStartDate.setHours(0, 0, 0, 0);

    this.formGroup = this.formBuilder.group(
      {
        name: [this.audit?.name, Validators.required],
        startDate: [this.audit?.startDate ?? defaultStartDate, Validators.required],
        endDate: [this.audit?.endDate],
        contactPersons: [
          contactPersonsSnapshot?.filter(x => this.audit?.contactPersons.find(f => f.id === x.id)),
        ],
      },
      { validator: dateRangeValidator('startDate', 'endDate') },
    );

    this.facCrits$.subscribe(facCrits => {
      for (const facCrit of facCrits) {
        const inAudit = this.audit
          ? this.audit.scope.findIndex(x => x.id === facCrit.id) != -1
          : defaultScopeComplement.includes(facCrit.id) ||
            defaultScopeComplement.includes(facCrit.referenceId)
          ? false
          : true;

        this.formGroup.addControl(String(facCrit.id), new FormControl(inAudit));
      }
    });
  }

  onSubmit() {
    const audit: Partial<Audit> = {
      name: this.name.value,
      endDate: this.endDate.value,
      startDate: this.startDate.value,
      status: this.audit?.status ?? AuditStatus.Planned,
      contactPersons: this.contactPersonsControl.value,
      scope: this.checkedFacCrits(),
    };

    this.formSubmitted.emit(audit);
  }

  checkedFacCrits() {
    const result: FacCrit[] = [];

    this.facCrits$.subscribe(facCrits => {
      for (const crit of facCrits) {
        const checked = this.formGroup.get(String(crit.id)).value;

        if (checked) {
          result.push(crit);
        }
      }
    });

    return result;
  }

  toggleCriteriaChecked(factorId: string, checked: true) {
    this.store.select(AuditState.criteriaByFactorId(+factorId)).subscribe(x => {
      for (const crit of x) {
        this.formGroup.get(String(crit.id)).setValue(checked);
      }
    });
  }
}
<form [formGroup]="formGroup" data-cy="audit-data-form">
  <nb-card>
    <nb-card-header>Audit Daten</nb-card-header>
    <nb-card-body>
      <div class="mb-2">
        <label class="label">Auditname</label>
        <input [status]="name.invalid && name.touched ? 'danger' : 'basic'" formControlName="name" nbInput fullWidth data-cy="audit-name-input" />
        <div *ngIf="name.invalid && name.touched">
          <label class="label text-danger" data-cy="auditname-missing-label">Auditnamen eintragen</label>
        </div>
      </div>
      <div class="grid-1-1 mb-2">
        <div class="form-item">
          <label class="label">Startdatum</label>
          <input formControlName="startDate" readonly nbInput fullWidth [nbDatepicker]="datePickerStart" data-cy="audit-start-input" />
          <nb-datepicker #datePickerStart></nb-datepicker>
        </div>
        <div class="form-item">
          <label class="label">Enddatum</label>
          <input [status]="formGroup.errors?.dateRangeValidator ? 'danger' : 'basic'" formControlName="endDate" readonly nbInput fullWidth [nbDatepicker]="datePickerEnd" data-cy="audit-end-input" />
          <nb-datepicker #datePickerEnd></nb-datepicker>
          <div *ngIf="formGroup.errors?.dateRangeValidator">
            <label class="label text-danger">Startdatum muss vor Enddatum liegen</label>
          </div>
        </div>
      </div>
      <div class="mb-2">
        <label class="label">Kontaktpersonen</label>
        <nb-select formControlName="contactPersons" multiple fullWidth data-cy="audit-contacts">
          <nb-option *ngFor="let contactPerson of contactPersons$ | async" [value]="contactPerson" data-cy="audit-contact">{{ contactPerson.forename + ' ' + contactPerson.surname }}</nb-option>
        </nb-select>
      </div>
      <hr style="border-bottom: 3px dotted rgb(228, 233, 242);" />
      <nb-accordion>
        <nb-accordion-item>
          <nb-accordion-item-header class="label" data-cy="audit-scope-header">ISO/IEC 25010 Faktoren / Kriterien</nb-accordion-item-header>
          <nb-accordion-item-body>
            <div class="wrapper-facCrits mt-2" data-cy="facCrits">
              <div *ngFor="let factor of facCrits$ | async | factors">
                <nb-checkbox [formControlName]="factor.id" (checkedChange)="toggleCriteriaChecked(factor.id, $event)" data-cy="factor-entry">{{ factor.name }}</nb-checkbox>
                <nb-checkbox
                  (checkedChange)="formGroup.get(factor.id).setValue(true)"
                  [formControlName]="criteria.id"
                  *ngFor="let criteria of facCrits$ | async | criterias: factor.id"
                  data-cy="criteria-entry"
                  >{{ criteria.name }}</nb-checkbox
                >
              </div>
            </div>
          </nb-accordion-item-body>
        </nb-accordion-item>
      </nb-accordion>
    </nb-card-body>
    <nb-card-footer data-cy="audit-data-buttons">
      <button (click)="onCancel()" hero nbButton data-cy="cancel-audit-data-form">
        abbrechen
      </button>
      <button (click)="onSubmit()" [disabled]="formGroup.invalid" status="primary" hero nbButton data-cy="submit-audit-data-form">
        {{ submitButtonName }}
      </button>
    </nb-card-footer>
  </nb-card>
</form>

./audit-form.component.scss

@import 'src/sass/utils';

nb-card-footer {
  display: flex;
  justify-content: space-between;
  border-radius: 0;
  padding: 10px 20px 10px 20px;
}

.wrapper-facCrits {
  max-width: 600px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;

  @media screen and(max-width: 500px) {
    grid-template-columns: 1fr;

    nb-checkbox {
      margin: 0px 10px 0px 0px;
    }
  }

  & > div {
    nb-checkbox {
      display: block;
    }

    & nb-checkbox:not(:first-child) {
      margin-left: 20px;
    }
  }
}

nb-accordion {
  box-shadow: none;
  border: 1px solid rgb(228, 233, 242);
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""