File

src/app/issue-detail/linked-issue-item.component.ts

Description

Displays a linked issue in a list.

By default, only information from #issueStub will be displayed. When the user expands the accordion card, the issue's body will be loaded separately.

Implements

OnInit OnDestroy

Metadata

selector app-issue-detail-linked-issue-item
styleUrls linked-issue-item.component.scss
templateUrl linked-issue-item.component.html

Index

Properties
Methods
Inputs

Constructor

constructor(dataService: DataService, router: Router)
Parameters :
Name Type Optional
dataService DataService No
router Router No

Inputs

issueStub
Type : Issue

Cursory information about the linked issue.

projectId
Type : string

The raw project ID.

Methods

didOpen
didOpen()

Event handler for when the accordion is opened. Loads the full issue if it hasn't been loaded yet.

Returns : void

Properties

Public fullIssueLink
Type : string

Link to the full issue page.

import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {Issue} from '../../generated/graphql-dgql';
import {DataNode} from '@app/data-dgql/query';
import DataService from '@app/data-dgql';
import {NodeType} from '@app/data-dgql/id';
import {Subscription} from 'rxjs';
import {Router} from '@angular/router';

/**
 * Displays a linked issue in a list.
 *
 * By default, only information from {@link #issueStub} will be displayed. When the user expands
 * the accordion card, the issue's body will be loaded separately.
 */
@Component({
  selector: 'app-issue-detail-linked-issue-item',
  templateUrl: 'linked-issue-item.component.html',
  styleUrls: ['linked-issue-item.component.scss']
})
export class LinkedIssueItemComponent implements OnInit, OnDestroy {
  /** The raw project ID. */
  @Input() projectId: string;
  /** Cursory information about the linked issue. */
  @Input() issueStub: Issue;

  /** Link to the full issue page. */
  public fullIssueLink: string;
  /** @ignore */
  public fullIssue?: DataNode<Issue>;
  /** @ignore */
  private fullIssueSub: Subscription;

  constructor(private dataService: DataService, private router: Router) {}

  ngOnInit() {
    this.fullIssueLink = this.router.serializeUrl(this.router.createUrlTree(['/projects', this.projectId, 'issues', this.issueStub.id]));
  }

  /** Event handler for when the accordion is opened. Loads the full issue if it hasn't been loaded yet. */
  didOpen(): void {
    if (!this.fullIssue) {
      this.fullIssue = this.dataService.getNode({
        type: NodeType.Issue,
        id: this.issueStub.id
      });
      this.fullIssueSub = this.fullIssue.subscribe();
    }
  }

  ngOnDestroy() {
    this.fullIssueSub?.unsubscribe();
  }
}
<mat-expansion-panel (opened)="didOpen()">
  <mat-expansion-panel-header>
    <mat-panel-title> {{ issueStub.title }} </mat-panel-title>
    <mat-panel-description class="linked-issue-components">
      <span class="linked-issue-component" *ngFor="let component of issueStub.components.nodes">{{ component.name }}</span>
    </mat-panel-description>
  </mat-expansion-panel-header>
  <div class="body-loading" *ngIf="fullIssue?.loading">Loading…</div>
  <app-markdown-preview *ngIf="fullIssue?.hasData" [displayedCode]="fullIssue.current.body"></app-markdown-preview>
  <div class="issue-buttons">
    <a mat-button [href]="fullIssueLink">View Issue <mat-icon>chevron_right</mat-icon></a>
  </div>
</mat-expansion-panel>

linked-issue-item.component.scss

.linked-issue-components {
  overflow: hidden;
  text-overflow: ellipsis;

  .linked-issue-component {
    &::after {
      content: ",";
      margin-right: 0.3em;
    }
    &:last-child::after {
      content: none;
    }
  }
}

.body-loading {
  min-height: 56px; // some sort of body height so that the animation doesn't glitch out *too* badly
  text-align: center;
  opacity: 0.7;
}

.issue-buttons {
  text-align: right;
  margin-top: 8px;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""