import {AfterViewInit, Component, Input, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Subscription} from 'rxjs';
import {MatTableDataSource} from '@angular/material/table';
import {MatPaginator} from '@angular/material/paginator';
import {MatSort, MatSortable} from '@angular/material/sort';
import {CreateIssueDialogComponent} from '@app/dialogs/create-issue-dialog/create-issue-dialog.component';
import {MatDialog} from '@angular/material/dialog';
import {FormControl} from '@angular/forms';
import DataService from '@app/data-dgql';
import {ListId, ListType, NodeId, NodeType} from '@app/data-dgql/id';
import {DataList, DataNode} from '@app/data-dgql/query';
import {Component as IComponent, ComponentInterface, Issue, IssueCategory, IssueFilter} from '../../generated/graphql-dgql';
import {QueryComponent} from '@app/utils/query-component/query.component';
@Component({
selector: 'app-issue-list',
templateUrl: './issue-list.component.html',
styleUrls: ['./issue-list.component.scss']
})
export class IssueListComponent implements OnInit, AfterViewInit, OnDestroy {
@Input() listId: ListId;
@Input() projectId: string;
public queryParamFilter = '';
public list$?: DataList<Issue, IssueFilter>;
public component$?: DataNode<IComponent>;
private componentSub?: Subscription;
public componentInterface$?: DataNode<ComponentInterface>;
private componentInterfaceSub?: Subscription;
public componentInterfaceProvider: NodeId;
public canCreateNewIssue = false;
public allLabelsList: ListId;
dataSource: MatTableDataSource<any>;
columnsToDisplay = ['title', 'author', 'assignees', 'labels', 'category'];
searchIssuesDataArray: any;
validationFilter = new FormControl('');
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
@ViewChild(QueryComponent) query: QueryComponent;
constructor(
private activatedRoute: ActivatedRoute,
private dialog: MatDialog,
private router: Router,
private dataService: DataService
) {}
formatCategoryIcon(issue: Issue): string {
switch (issue.category) {
case IssueCategory.Bug:
return issue.isOpen ? 'issue-bug' : 'issue-bug-closed';
case IssueCategory.FeatureRequest:
return issue.isOpen ? 'issue-feature' : 'issue-feature-closed';
case IssueCategory.Unclassified:
return issue.isOpen ? 'issue-uncategorized' : 'issue-uncategorized-closed';
}
}
formatCategoryDescription(category: IssueCategory): string {
switch (category) {
case IssueCategory.Bug:
return 'Bug';
case IssueCategory.FeatureRequest:
return 'Feature request';
case IssueCategory.Unclassified:
return 'Unclassified';
}
}
ngOnInit(): void {
this.allLabelsList = {
node: this.listId.node,
type: ListType.Labels
};
if (this.listId.node.type === NodeType.Component) {
this.canCreateNewIssue = true;
this.component$ = this.dataService.getNode(this.listId.node);
this.componentSub = this.component$.subscribe();
} else if (this.listId.node.type === NodeType.ComponentInterface) {
this.canCreateNewIssue = true;
this.componentInterface$ = this.dataService.getNode(this.listId.node);
this.componentInterfaceSub = this.componentInterface$.subscribe();
this.componentInterface$.dataAsPromise().then((data) => {
this.componentInterfaceProvider = {
type: NodeType.Component,
id: data.component.id
};
});
}
if (this.listId.node.type === NodeType.ComponentInterface) {
const interfaceNode = this.dataService.getNode<ComponentInterface>(this.listId.node);
interfaceNode.dataAsPromise().then((data) => {
this.allLabelsList = {
node: {type: NodeType.Component, id: data.component.id},
type: ListType.Labels
};
});
}
this.list$ = this.dataService.getList(this.listId);
this.list$.count = 25;
}
ngAfterViewInit() {
this.query.listenTo(this.list$, (data) => {
this.dataSource = new MatTableDataSource<any>(data ? [...data.values()] : []);
this.sort.sort({id: 'category', start: 'asc'} as MatSortable);
this.dataSource.sort = this.sort;
this.dataSource.filter = this.getQueryParamFilter();
this.validationFilter.setValue(this.getQueryParamFilter());
this.prepareIssueArray();
});
}
ngOnDestroy() {
this.componentSub?.unsubscribe();
this.componentInterfaceSub?.unsubscribe();
}
private getQueryParamFilter(): string {
let returnedFilter = '';
this.activatedRoute.queryParams.subscribe((params) => {
if (params.filter) {
this.queryParamFilter = params.filter;
returnedFilter = params.filter;
}
else {
returnedFilter = '';
}
});
return returnedFilter;
}
applyFilter(filter: IssueFilter): void {
this.list$.filter = filter;
}
clickedOnRow(row: any): void {
this.router.navigate(['/projects', this.projectId, 'issues', row.id]);
}
private prepareIssueArray() {
if (!this.list$.hasData) {
return;
}
this.searchIssuesDataArray = [...this.list$.current.values()];
for (const issue of this.searchIssuesDataArray) {
let additionalSearchString = '';
issue.assigneesString = '';
issue.labelsString = '';
for (const assignee of issue.assignees.nodes) {
additionalSearchString += ' ' + assignee.displayName;
issue.assigneesString += ' ' + assignee.displayName;
}
for (const label of issue.labels.nodes) {
additionalSearchString += ' ' + label.name;
issue.labelsString += ' ' + label.name;
}
additionalSearchString += ' ' + issue.createdBy.displayName;
issue.search = additionalSearchString;
}
}
onAddClick(): void {
if (this.listId.node.type === NodeType.Component) {
this.dialog.open(CreateIssueDialogComponent, {
data: {
projectId: this.projectId,
components: [this.component$.id]
},
width: '600px'
});
}
else if (this.listId.node.type === NodeType.ComponentInterface) {
this.dialog.open(CreateIssueDialogComponent, {
data: {
projectId: this.projectId,
components: [this.componentInterfaceProvider],
locations: [this.componentInterface$.id]
},
width: '600px'
});
}
}
}