File

src/app/issue-detail/comment/comment.component.ts

Description

This component displays an issue comment. The comment will be subscribed to lazily (see DataNode).

Implements

OnInit OnDestroy

Metadata

selector app-comment
styleUrls ./comment.component.scss
templateUrl ./comment.component.html

Index

Properties
Methods
Inputs

Constructor

constructor(dataService: DataService, dialog: MatDialog, notify: UserNotifyService)
Parameters :
Name Type Optional
dataService DataService No
dialog MatDialog No
notify UserNotifyService No

Inputs

commentId
Type : NodeId

The comment or issue ID. If this is an issue ID, set to true.

isIssueBody
Type : boolean

If true, this comment component is actually editing an issue's body.

issueId
Type : NodeId

The issue this comment belongs to.

Methods

Public deleteComment
deleteComment()

Deletes the current comment.

Returns : void
Public editComment
editComment(body: string)

Edits the description of the current comment.

Parameters :
Name Type Optional Description
body string No
  • The new description of the current issue or comment.
Returns : void

Properties

Public editBody
Default value : false

True if the comment body is being edited.

Public savingBody
Default value : false

True if the comment body is being saved.

Public timeFormatter
Default value : new TimeFormatter()

Used to format time.

import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {IssueComment} from '../../../generated/graphql-dgql';
import {TimeFormatter} from '@app/issue-detail/time-formatter';
import DataService from '@app/data-dgql';
import {NodeId} from '@app/data-dgql/id';
import {DataNode} from '@app/data-dgql/query';
import {Subscription} from 'rxjs';
import {RemoveDialogComponent} from '@app/dialogs/remove-dialog/remove-dialog.component';
import {MatDialog} from '@angular/material/dialog';
import {UserNotifyService} from '@app/user-notify/user-notify.service';

/**
 * This component displays an issue comment.
 * The comment will be subscribed to lazily (see {@link DataNode#subscribeLazy}).
 */
@Component({
  selector: 'app-comment',
  templateUrl: './comment.component.html',
  styleUrls: ['./comment.component.scss']
})
export class CommentComponent implements OnInit, OnDestroy {
  /** If true, this comment component is actually editing an issue's body. */
  @Input() isIssueBody: boolean;
  /** The comment or issue ID. If this is an issue ID, set {@link #isIssueBody} to true. */
  @Input() commentId: NodeId;
  /** The issue this comment belongs to. */
  @Input() issueId: NodeId;

  /** Used to format time. */
  public timeFormatter = new TimeFormatter();
  /** True if the comment body is being edited. */
  public editBody = false;
  /** True if the comment body is being saved. */
  public savingBody = false;

  /**
   * @ignore
   * Internal: comment data node view.
   */
  comment$: DataNode<IssueComment>;
  /**
   * @ignore
   * Internal: subscription to comment$.
   */
  commentSub: Subscription;

  constructor(private dataService: DataService, private dialog: MatDialog, private notify: UserNotifyService) {}

  ngOnInit() {
    this.comment$ = this.dataService.getNode(this.commentId);
    this.commentSub = this.comment$.subscribeLazy();
  }

  ngOnDestroy() {
    this.commentSub?.unsubscribe();
  }

  /**
   * Edits the description of the current comment.
   *
   * @param body - The new description of the current issue or comment.
   */
  public editComment(body: string): void {
    this.savingBody = true;
    this.dataService.mutations
      .updateIssueComment(Math.random().toString(), this.commentId, body)
      .then(() => {
        // only exit if successful
        this.editBody = false;
      })
      .finally(() => {
        this.savingBody = false;
      });
  }

  /**
   * Deletes the current comment.
   */
  public deleteComment(): void {
    const confirmDeleteDialogRef = this.dialog.open(RemoveDialogComponent, {
      data: {
        title: 'Really delete comment ?',
        messages: ['Are you sure you want to delete this comment ?', 'This action cannot be undone!']
      }
    });

    confirmDeleteDialogRef.afterClosed().subscribe(
      (del) => {
        if (del) {
          // User confirmed deletion
          this.dataService.mutations.deleteIssueComment(Math.random().toString(), this.issueId, this.commentId).then(() => {
            this.notify.notifyInfo('Successfully deleted comment');
          });
        }
      },
      (error) => this.notify.notifyError('Failed to delete project!', error)
    );
  }
}
<div class="timeline-item">
  <div class="item-box" *ngIf="comment$.hasData && comment$.current as comment">
    <div class="item-header">
      <h3 class="item-title">
        <!-- Comment title, with user name and creation time -->
        <app-user-item [short]="true" [user]="comment.createdBy"></app-user-item>
        commented
        <time [dateTime]="comment.createdAt" [title]="this.timeFormatter.formatTime(comment.createdAt)">
          {{ this.timeFormatter.formatTimeDifference(comment.createdAt) }}
        </time>
        <span class="item-edited" *ngIf="comment.lastEditedAt !== comment.createdAt">
          &sdot;<app-user-item [short]="true" [user]="comment.editedBy?.nodes[0]"></app-user-item>
          edited
          <time [dateTime]="comment.lastEditedAt" [title]="this.timeFormatter.formatTime(comment.lastEditedAt)">
            {{ this.timeFormatter.formatTimeDifference(comment.lastEditedAt) }}
          </time>
        </span>
      </h3>

      <!-- Edit and delete comment buttons -->
      <!-- Delete button is only for comments and not for issue description displayed -->
      <button *ngIf="!this.editBody && !this.isIssueBody" class="item-edit" color="warn" mat-flat-button (click)="this.deleteComment()">
        Delete
      </button>
      <button
        *ngIf="!this.editBody"
        class="item-edit"
        style="margin-left: 6px"
        color="primary"
        mat-flat-button
        (click)="this.editBody = !this.editBody"
      >
        Edit
      </button>
    </div>

    <!-- Comment body -->
    <div *ngIf="!this.editBody" class="item-body">
      <app-markdown-preview [displayedCode]="comment.body"></app-markdown-preview>
    </div>

    <!-- Comment body during editing -->
    <div *ngIf="this.editBody" class="item-body is-editing" [ngStyle]="{ height: this.editBody ? '280px' : 'auto' }">
      <app-markdown-editor #bodyEdit [code]="comment.body"></app-markdown-editor>

      <!-- Save/Cancel buttons -->
      <div class="edit-body-buttons">
        <button mat-raised-button (click)="this.editBody = !this.editBody">Cancel</button>
        <button mat-raised-button style="margin-left: 6px" color="accent" [class.spinner]="savingBody" (click)="editComment(bodyEdit.code)">
          Save
        </button>
      </div>
    </div>
  </div>
</div>

./comment.component.scss

@import "../issue-contents.component";
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""