Takumon/mean-blog

View on GitHub
src/app/articles/search-condition/search-condition.dialog.ts

Summary

Maintainability
C
1 day
Test Coverage
import { Component, Inject, OnInit} from '@angular/core';
import {
  FormGroup,
  FormControl,
  FormArray,
  Validators,
  FormBuilder,
} from '@angular/forms';
import {
  MatDialogRef,
  MAT_DIALOG_DATA,
  DateAdapter,
  NativeDateAdapter,
} from '@angular/material';
import * as moment from 'moment';

import { Constant } from '../../shared/constant';
import { DATE_RANGE_PATTERN } from '../../shared/enum/date-range-pattern.enum';
import {
  AuthenticationService,
  MessageService, ErrorStateMatcherContainParentGroup,
  MessageBarService,
  UserService,

} from '../../shared/services';


import { SearchConditionService } from '../shared/search-condition.service';

export interface UserListFactor {
  _id: string;
  user: {
    _id: string;
    userId: string;
  };
}

@Component({
  selector: 'app-search-condition-dialog',
  templateUrl: './search-condition.dialog.html',
  styleUrls: ['./search-condition.dialog.scss'],
})
export class SearchConditionDialogComponent implements OnInit {
  /** 定数クラス、HTMLで使用するのでコンポーネントのメンバとしている */
  public Constant = Constant;

  public searchUserId: string;
  // formグループ化したい
  public form: FormGroup;
  public checkUserList: Array<UserListFactor>;
  public unCheckUserList: Array<UserListFactor>;
  public dateRangePatterns: typeof DATE_RANGE_PATTERN = DATE_RANGE_PATTERN;

  constructor(
    public dialogRef: MatDialogRef<SearchConditionDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: any,
    private fb: FormBuilder,
    public auth: AuthenticationService,
    public messageService: MessageService,
    private messageBarService: MessageBarService,
    public errorStateMatcherContainParentGroup: ErrorStateMatcherContainParentGroup,
    private userService: UserService,
    private searchConditionService: SearchConditionService,
    private dateAdapter: DateAdapter<NativeDateAdapter>
  ) {
      dateAdapter.setLocale('ja');
  }

  ngOnInit() {
    this.cerateForm();
    this.setForm();
  }

  cerateForm() {
    this.form = this.fb.group({
      name: ['', [
        Validators.required,
        Validators.maxLength(30),
      ]],
      users: this.fb.array([]),
      dateSearchPatternGroup: new FormGroup(
        {
          dateSearchPattern: this.fb.control('', [
          Validators.pattern(/[0123456]+/)
          ]),
          dateTo: this.fb.control('', [
            MessageService.validation.isDate
          ]),
          dateFrom: this.fb.control('', [
            MessageService.validation.isDate
          ])
        },
        Validators.compose([
          MessageService.validation.isExistDateRange,
          MessageService.validation.isCollectedDateRange,
        ])
      )
    });
  }

  get name(): FormControl { return this.form.get('name') as FormControl; }
  get users(): FormArray { return this.form.get('users') as FormArray; }
  get dateSearchPatternGroup(): FormGroup { return this.form.get('dateSearchPatternGroup') as FormGroup; }
    get dateSearchPattern(): FormControl { return this.dateSearchPatternGroup.get('dateSearchPattern') as FormControl; }
    get dateFrom(): FormControl { return this.dateSearchPatternGroup.get('dateFrom') as FormControl; }
    get dateTo(): FormControl { return this.dateSearchPatternGroup.get('dateTo') as FormControl; }


  setForm() {

    // TODO ページング
    if (this.data.idForUpdate) {
      // 更新時
      const withUser = false;

      this.searchConditionService
        .getById(this.data.idForUpdate, withUser)
        .subscribe(condition => {
          this.form.patchValue({
            _id: condition._id,
            name: condition.name,
            dateSearchPatternGroup: {
              dateSearchPattern: condition.dateSearchPattern,
              dateFrom: condition.dateFrom && new Date(condition.dateFrom),
              dateTo: condition.dateTo && new Date(condition.dateTo),
            },
            users: condition.users || []
          });

          const checkedUsers: Array<string> = condition.users || [];

          this.userService.get()
            .subscribe(users => {
              this.checkUserList = [];
              this.unCheckUserList = [];

              users.forEach(user => {
                const _id = user._id.toString();

                if (checkedUsers.indexOf(_id) === -1) {
                  this.unCheckUserList.push({
                    _id: _id,
                    user: {
                      _id: user._id,
                      userId: user.userId,
                    }
                  });
                } else {
                  this.checkUserList.push({
                    _id: _id,
                    user: {
                      _id: user._id,
                      userId: user.userId,
                    }
                  });
                }
              });

              this.checkUserList.forEach(u => this.users.push(new FormControl(u._id)));
            });
        });
    } else {
      // 新規登録時
      this.userService.get()
        .subscribe(users => {
          this.checkUserList = [];
          this.unCheckUserList = users.map(user => {
            return {
              _id: user._id,
              user: {
                _id: user._id,
                userId: user.userId,
              }
            };
          });
        });
    }
  }

  trackByUserList(index: UserListFactor, item) {
    return item._id;
  }

  moveToUnCheckList(checkInfo: UserListFactor): void {
    const list = this.checkUserList;
    const index = list.indexOf(checkInfo);
    if (index !== -1) {
      list.splice(index, 1);

      this.unCheckUserList.push(checkInfo);
    }

    const controls = this.users.controls;
    const len = controls.length;
    for (let i = 0; i < len; i++ ) {
      if (controls[i].value === checkInfo._id) {
        this.users.removeAt(i);
        break;
      }
    }
  }

  moveToCheckList(checkInfo: UserListFactor): void {
    const list = this.unCheckUserList;
    const index = list.indexOf(checkInfo);
    if (index !== -1) {
      list.splice(index, 1);

      this.checkUserList.push(checkInfo);
    }

    this.users.push(new FormControl(checkInfo._id));
  }

  upsert() {
    const searchCondition: any = {};
    searchCondition.name = this.form.value.name;
    searchCondition.author = this.auth.loginUser._id;
    searchCondition.users = this.form.value.users;
    searchCondition.dateSearchPattern = this.form.value.dateSearchPatternGroup.dateSearchPattern;
    searchCondition.dateFrom = this.form.value.dateSearchPatternGroup.dateFrom;
    searchCondition.dateTo = this.form.value.dateSearchPatternGroup.dateTo;


    if (this.data.idForUpdate) {
      searchCondition._id = this.data.idForUpdate;
    }

    if (searchCondition.dateFrom) {
      searchCondition.dateFrom = moment(searchCondition.dateFrom).startOf('date').toString();
    }
    if (searchCondition.dateTo) {
      searchCondition.dateTo = moment(searchCondition.dateTo).endOf('date').toString();
    }

    if (searchCondition._id) {
      this.searchConditionService
      .update(searchCondition)
      .subscribe(
        res => this.dialogRef.close(res['obj']),
        this.onValidationError.bind(this));
    } else {
      this.searchConditionService
      .register(searchCondition)
      .subscribe(
        res => this.dialogRef.close(res.obj),
        this.onValidationError.bind(this));
    }
  }

  // TODO 共通化できるか検討
  private onValidationError(error: any): void {
    const noControlErrors = [];

    for (const e of error['errors']) {
      // getterからformControllを取得
      const param =  ['dateSearchPattern', 'dateTo', 'dateFrom'].indexOf(e.param) === -1
        ? e.param
        : 'dateSearchPatternGroup';

      const control: FormControl | FormGroup = this[param];
      if (!control) {
        // 該当するfromがないものはスナックバーで表示
        noControlErrors.push(e);
        continue;
      }

      const messages = control.getError('remote');
      if (messages) {
        messages.push(e.msg);
      } else {
        control.setErrors({remote: [e.msg]});
      }
    }

    if (noControlErrors.length > 0) {
      this.messageBarService.showValidationError({errors: noControlErrors});
    }
  }

  close(): void {
    this.dialogRef.close();
  }

  resetDateSearchPattern() {
    this.form.patchValue({
      dateSearchPatternGroup: {
        dateSearchPattern: null,
        dateFrom: null,
        dateTo: null,
      }
    });
    this.dateSearchPatternGroup.markAsDirty();
  }

  isSpecificDateRange(value: string) {
    return DATE_RANGE_PATTERN.期間指定 === Number(value);
  }
}