File

src/app/dialogs/create-label-dialog/create-edit-label-dialog.component.ts

Description

This dialog creates or edits a label.

See CreateEditLabelDialogData for parameters.

Implements

OnInit

Metadata

selector app-create-edit-label-dialog-component
styleUrls ./create-edit-label-dialog.component.scss
templateUrl ./create-edit-label-dialog.component.html

Index

Properties
Methods

Constructor

constructor(dialog: MatDialogRef<CreateEditLabelDialogComponent | Label>, dataService: DataService, data: CreateEditLabelDialogData, notify: UserNotifyService)
Parameters :
Name Type Optional
dialog MatDialogRef<CreateEditLabelDialogComponent | Label> No
dataService DataService No
data CreateEditLabelDialogData No
notify UserNotifyService No

Methods

onConfirmClick
onConfirmClick(name: string, description?: string)

When the user confirms their changes, attempt to mutate and return with the label data.

Parameters :
Name Type Optional
name string No
description string Yes
Returns : void
onLabelCancelClick
onLabelCancelClick()

When the user cancels label creation or editing, close and return with null.

Returns : void
randomizeColor
randomizeColor()

Randomizes the label color.

Returns : void

Properties

allComponentsList
Type : ListId

Source list of all components.

color
Type : string
Default value : '#000000'

Color state.

componentList
Type : NodeId[] | ListId
Default value : []

Component list to be edited. For new labels, this is a list of node IDs. For existing labels, this is a ListId.

Public data
Type : CreateEditLabelDialogData
Decorators :
@Inject(MAT_DIALOG_DATA)
loading
Default value : false

If true, the label that is to be edited is still loading.

validationLabelDescription
Default value : new FormControl('', CCIMSValidators.contentValidator)

Validator for the label description.

validationLabelName
Default value : new FormControl('', [Validators.required, Validators.maxLength(30)])

Validator for the label name.

import {Component, Inject, OnInit} from '@angular/core';
import {FormControl, Validators} from '@angular/forms';
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import {UserNotifyService} from '@app/user-notify/user-notify.service';
import {CCIMSValidators} from '@app/utils/validators';
import {encodeNodeId, ListId, ListType, NodeId} from '@app/data-dgql/id';
import DataService from '@app/data-dgql';
import {ComponentFilter, Label} from '../../../generated/graphql-dgql';

/** Parameters for the create/edit label dialog component. */
export interface CreateEditLabelDialogData {
  /** The raw project id. */
  projectId: NodeId;
  /** If set, will edit an existing label instead of creating a new one. */
  editExisting?: NodeId;
  /** If set, will select all components of this issue */
  issueId?: NodeId[];
}

/**
 * This dialog creates or edits a label.
 *
 * See {@link CreateEditLabelDialogData} for parameters.
 */
@Component({
  selector: 'app-create-edit-label-dialog-component',
  templateUrl: './create-edit-label-dialog.component.html',
  styleUrls: ['./create-edit-label-dialog.component.scss']
})
export class CreateEditLabelDialogComponent implements OnInit {
  /** Validator for the label name. */
  validationLabelName = new FormControl('', [Validators.required, Validators.maxLength(30)]);
  /** Validator for the label description. */
  validationLabelDescription = new FormControl('', CCIMSValidators.contentValidator);
  /** Color state. */
  color = '#000000';
  /** If true, the label that is to be edited is still loading. */
  loading = false;

  /** Component list to be edited. For new labels, this is a list of node IDs. For existing labels, this is a ListId. */
  componentList: NodeId[] | ListId = [];
  /** Source list of all components. */
  allComponentsList: ListId;

  constructor(
    private dialog: MatDialogRef<CreateEditLabelDialogComponent, Label>,
    private dataService: DataService,
    @Inject(MAT_DIALOG_DATA) public data: CreateEditLabelDialogData,
    private notify: UserNotifyService
  ) {}

  ngOnInit() {
    if (this.data.editExisting) {
      this.componentList = {
        node: this.data.editExisting,
        type: ListType.Components
      };

      this.loading = true;
      const node = this.dataService.getNode<Label>(this.data.editExisting);
      // reload data from source
      node.invalidate();
      node.load();
      node
        .dataAsPromise()
        .then((data) => {
          this.validationLabelName.setValue(data.name);
          this.color = data.color;
          this.validationLabelDescription.setValue(data.description);
        })
        .catch(() => {
          this.notify.notifyError('Could not load label data for editing');
          this.dialog.close(null);
        })
        .finally(() => {
          this.loading = false;
        });
    } else {
      this.randomizeColor();

      if (this.data.issueId) {
        this.componentList = this.data.issueId;
      }
    }

    this.allComponentsList = {
      node: this.data.projectId,
      type: ListType.Components
    };
  }

  /** @ignore used for set editor */
  makeComponentFilter(search): ComponentFilter {
    return {name: search};
  }
  /** @ignore used for set editor */
  applyComponentChangeset = async (additions: NodeId[], deletions: NodeId[]): Promise<void> => {
    if (Array.isArray(this.componentList)) {
      const keySet = new Set(this.componentList.map((id) => encodeNodeId(id)));
      for (const item of additions) {
        if (!keySet.has(encodeNodeId(item))) {
          this.componentList.push(item);
          keySet.add(encodeNodeId(item));
        }
      }
      for (const item of deletions) {
        if (keySet.has(encodeNodeId(item))) {
          this.componentList.splice(this.componentList.indexOf(item), 1);
          keySet.delete(encodeNodeId(item));
        }
      }
    } else {
      for (const item of additions) {
        await this.dataService.mutations.addLabelToComponent(Math.random().toString(), this.data.editExisting, item);
      }
      for (const item of deletions) {
        await this.dataService.mutations.removeLabelFromComponent(Math.random().toString(), this.data.editExisting, item);
      }
    }
  };

  /** When the user cancels label creation or editing, close and return with null. */
  onLabelCancelClick(): void {
    this.dialog.close(null);
  }

  /** When the user confirms their changes, attempt to mutate and return with the label data. */
  onConfirmClick(name: string, description?: string): void {
    this.loading = true;

    if (this.data.editExisting) {
      this.dataService.mutations
        .updateLabel(Math.random().toString(), this.data.editExisting, name, this.color, description)
        .then(() => {
          this.dialog.close({
            id: this.data.editExisting.id,
            name,
            color: this.color,
            description
          } as Label);
        })
        .catch((error) => {
          this.notify.notifyError('Failed to update label!', error);
        })
        .finally(() => {
          this.loading = false;
        });
    } else {
      this.dataService.mutations
        .createLabel(Math.random().toString(), this.componentList as NodeId[], name, this.color, description)
        .then((created) => {
          this.dialog.close(created as Label);
        })
        .catch((error) => {
          this.notify.notifyError('Failed to create label!', error);
        })
        .finally(() => {
          this.loading = false;
        });
    }
  }

  /** Randomizes the label color. */
  randomizeColor(): void {
    const r = `00${(Math.random() * 0xff).toString(16)}`.slice(-2);
    const g = `00${(Math.random() * 0xff).toString(16)}`.slice(-2);
    const b = `00${(Math.random() * 0xff).toString(16)}`.slice(-2);

    this.color = '#' + r + g + b;
  }
}
<h1 mat-dialog-title>
  <ng-container *ngIf="data.editExisting"> Update label </ng-container>
  <ng-container *ngIf="!data.editExisting"> Create a new label </ng-container>
</h1>
<div mat-dialog-content>
  <app-set-editor
    class="component-selector"
    [makeFilter]="makeComponentFilter"
    [scoreKeys]="['name']"
    [listSet]="componentList"
    [listAll]="allComponentsList"
    [applyChangeset]="applyComponentChangeset"
    #list
  >
    <span title>Components</span>
    <span if-empty style="color: red">Assign the label to a component</span>
    <ng-container *appItem="let item">
      <div>{{ item.name }}</div>
    </ng-container>
  </app-set-editor>

  <mat-form-field class="new-label-input" appearance="outline">
    <mat-label>Label Name</mat-label>
    <input #labelName required matInput [formControl]="validationLabelName" />
    <mat-error *ngIf="validationLabelName.invalid">Invalid name</mat-error>
  </mat-form-field>

  <mat-form-field class="new-label-input" appearance="outline">
    <mat-label>Description</mat-label>
    <input #labelDescription matInput [formControl]="validationLabelDescription" />
  </mat-form-field>

  <mat-form-field class="new-label-input" floatLabel="always" appearance="outline">
    <mat-label>Color</mat-label>
    <input
      matInput
      readonly
      [style.background]="color"
      autocomplete="off"
      [(colorPicker)]="this.color"
      [cpAlphaChannel]="'disabled'"
      [cpPosition]="'bottom'"
    />
    <button mat-icon-button class="color-randomize-button" matSuffix (click)="this.randomizeColor()">
      <mat-icon>refresh</mat-icon>
    </button>
  </mat-form-field>
</div>

<div mat-dialog-actions class="actions">
  <button mat-raised-button color="warn" (click)="this.onLabelCancelClick()">Cancel</button>
  <button
    mat-raised-button
    color="success"
    [disabled]="loading || validationLabelName.invalid || !list.totalCount"
    (click)="this.onConfirmClick(labelName.value, labelDescription.value)"
  >
    <ng-container *ngIf="data.editExisting"> Apply </ng-container>
    <ng-container *ngIf="!data.editExisting"> Create </ng-container>
  </button>
</div>

./create-edit-label-dialog.component.scss

.component-selector {
  margin-bottom: 16px;
}

.new-label-input {
  padding: 6px;
  width: 100%;
}

.error-label-create {
  background-color: rgb(204, 58, 58);
  color: white;
  margin-top: 5px;
}

.color-randomize-button {
  margin-left: 4px;
}

.mat-success {
  background-color: green;
  color: #fff;
}

.actions {
  float: right;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""