Skip to content

Commit

Permalink
Affected Tests Amount and Test Runs columns on Issues list (#165)
Browse files Browse the repository at this point in the history
* Error handling for Last Audit Created Date

* feat: Added affected tests column to the issues list

* Added test runs into filter

* linting and formatting

* testing fixes

* single quote formatting
  • Loading branch information
kknqqq authored Jun 5, 2023
1 parent ba72cd5 commit 24de28d
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 60 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aquality-tracking-ui",
"version": "1.4.1",
"version": "1.4.2",
"scripts": {
"ng": "ng",
"start": "ng serve",
Expand Down
69 changes: 41 additions & 28 deletions src/app/pages/audit/audit-list/audit.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,23 @@ export class AuditComponent implements OnInit {
auditors: User[];
auditsList: Audit[];
defSort = { property: 'last_created_due_date', order: TFOrder.desc };
rowColors: any[] = [{
property: 'last_created_due_date',
color: 'warning',
higher: new Date(new Date(new Date().setDate(new Date().getDate() - 1)).setHours(0, 0, 0, 0)),
lower: new Date(new Date(new Date().setDate(new Date().getDate() + 15)).setHours(0, 0, 0, 0))
}, {
property: 'hasOpened',
color: 'none'
}, {
property: 'last_created_due_date',
color: 'danger',
lower: new Date(new Date(new Date().setDate(new Date().getDate())).setHours(0, 0, 0, 0))
}];
rowColors: Object[] = [
{
property: 'last_created_due_date',
color: 'warning',
higher: new Date(new Date(new Date().setDate(new Date().getDate() - 1)).setHours(0, 0, 0, 0)),
lower: new Date(new Date(new Date().setDate(new Date().getDate() + 15)).setHours(0, 0, 0, 0))
},
{
property: 'hasOpened',
color: 'none'
},
{
property: 'last_created_due_date',
color: 'danger',
lower: new Date(new Date(new Date().setDate(new Date().getDate())).setHours(0, 0, 0, 0))
}
];
columns: TFColumn[];
linkNames: string[] = [];

Expand All @@ -41,7 +45,7 @@ export class AuditComponent implements OnInit {
public auditService: AuditService,
public userService: UserService,
private permissions: PermissionsService
) { }
) {}

async ngOnInit() {
const isAuditAdmin = await this.permissions.hasPermissions([EGlobalPermissions.audit_admin]);
Expand All @@ -51,27 +55,36 @@ export class AuditComponent implements OnInit {
isAuditAdmin ? this.linkNames.push('Create New') : this.linkNames.push('Not created');
this.stats.forEach(async (stat) => {
if (stat.last_submitted_date || stat.last_created_due_date) {
stat.last_created_due_date = stat.last_submitted_id !== stat.last_created_id
? new Date(stat.last_created_due_date)
: this.auditService.createDueDate(new Date(stat.last_submitted_date));
stat.last_created_due_date =
stat.last_submitted_id !== stat.last_created_id
? new Date(stat.last_created_due_date)
: this.auditService.createDueDate(new Date(stat.last_submitted_date));
} else {
stat.last_created_due_date = this.auditService.createDueDate(new Date(stat.created));
}

if (stat.last_created_id && (stat.last_submitted_id !== stat.last_created_id)) {
if (stat.last_created_id && stat.last_submitted_id !== stat.last_created_id) {
stat['next_action'] = { text: stat.status_name, link: `/audit/${stat.id}/info/${stat.last_created_id}` };
if (stat.status_name !== 'Open') { stat['hasOpened'] = true; }
if (!this.linkNames.includes(stat.status_name) && stat.status_name) { this.linkNames.push(stat.status_name); }
if (stat.status_name !== 'Open') {
stat['hasOpened'] = true;
}
if (!this.linkNames.includes(stat.status_name) && stat.status_name) {
this.linkNames.push(stat.status_name);
}
} else if (isAuditAdmin) {
stat['next_action'] = { text: 'Create New', link: `/audit/${stat.id}/create` };
} else {
stat['next_action'] = { text: 'Not created' };
}

this.auditsList = await this.auditService.getAudits({ project: { id: stat.id } } );
let datesArray: (Date|string|number)[] = [];
this.auditsList.forEach(audit => {datesArray.push(audit.created)});
stat.last_audit_created_date = new Date(Math.max.apply(null, datesArray));
this.auditsList = await this.auditService.getAudits({ project: { id: stat.id } });
const datesArray: (Date | string | number)[] = [];
this.auditsList.forEach((audit) => {
datesArray.push(audit.created);
});
stat.last_audit_created_date = isFinite(Math.max.apply(null, datesArray))
? new Date(Math.max.apply(null, datesArray))
: undefined;
});
this.services = await this.auditService.getServices();
this.createColumns();
Expand Down Expand Up @@ -99,7 +112,7 @@ export class AuditComponent implements OnInit {
type: TFColumnType.autocomplete,
lookup: {
propToShow: ['first_name', 'second_name'],
values: this.coordinators,
values: this.coordinators
},
class: 'ft-width-150'
},
Expand Down Expand Up @@ -151,7 +164,7 @@ export class AuditComponent implements OnInit {
type: TFColumnType.multiselect,
lookup: {
propToShow: ['first_name', 'second_name'],
values: this.auditors,
values: this.auditors
},
class: 'ft-width-250'
},
Expand Down Expand Up @@ -185,10 +198,10 @@ export class AuditComponent implements OnInit {
type: TFColumnType.multiselect,
lookup: {
propToShow: ['first_name', 'second_name'],
values: this.auditors,
values: this.auditors
},
class: 'ft-width-250'
},
}
];
}
}
108 changes: 82 additions & 26 deletions src/app/pages/project/issue/issue-list/issue-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,38 @@ import { Router, ActivatedRoute } from '@angular/router';
import { Issue } from '../../../../shared/models/issue';
import { Label } from '../../../../shared/models/general';
import { User } from '../../../../shared/models/user';
import { TestRun } from 'src/app/shared/models/testrun';
import { UserService } from 'src/app/services/user/user.services';
import { IssueService } from 'src/app/services/issue/issue.service';
import { PermissionsService, EGlobalPermissions, ELocalPermissions } from 'src/app/services/permissions/current-permissions.service';
import { ProjectService } from '../../../../services/project/project.service';
import { TestResultService } from 'src/app/services/test-result/test-result.service';
import { TestRunService } from 'src/app/services/testrun/testrun.service';
import {
PermissionsService,
EGlobalPermissions,
ELocalPermissions
} from 'src/app/services/permissions/current-permissions.service';
import { ResultResolutionService } from 'src/app/services/result-resolution/result-resolution.service';
import { TFColumn, TFSorting, TFOrder, TFColumnType } from 'src/app/elements/table-filter/tfColumn';
import { ResultResolution } from 'src/app/shared/models/result-resolution';
import { LocalPermissions } from 'src/app/shared/models/local-permissions';
import {ProjectService} from '../../../../services/project/project.service';

@Component({
templateUrl: './issue-list.component.html',
styleUrls: ['./issue-list.component.scss']
})
export class IssueListComponent implements OnInit {

constructor(
public userService: UserService,
private router: Router,
private route: ActivatedRoute,
private issueService: IssueService,
private permissions: PermissionsService,
private resolutionService: ResultResolutionService,
private projectService: ProjectService
) { }
private projectService: ProjectService,
private testResultService: TestResultService,
private testRunService: TestRunService
) {}

projectId: number;
issues: Issue[];
Expand All @@ -40,32 +48,51 @@ export class IssueListComponent implements OnInit {
defSort: TFSorting = { property: 'created', order: TFOrder.asc };
hideCreateModal = true;
isAiOn: boolean;
testRuns: TestRun[];

async ngOnInit() {
this.projectId = this.route.snapshot.params.projectId;
[this.issues, this.resolutions, this.canEdit, this.projectUsers, this.statuses, this.isAiOn] = await Promise.all([
this.issueService.getIssues({ project_id: this.projectId }),
this.resolutionService.getResolution(this.projectId),
this.permissions.hasProjectPermissions(this.projectId,
[EGlobalPermissions.manager], [ELocalPermissions.manager, ELocalPermissions.engineer]),
this.permissions.hasProjectPermissions(
this.projectId,
[EGlobalPermissions.manager],
[ELocalPermissions.manager, ELocalPermissions.engineer]
),
this.userService.getProjectUsers(this.projectId),
this.issueService.getIssueStatuses(),
((await this.projectService.getProject(this.projectId)).ai_resolutions === 1)
(await this.projectService.getProject(this.projectId)).ai_resolutions === 1
]);
this.projectUsers = this.projectUsers.filter(user => user.admin === 1 || user.manager === 1 || user.engineer === 1);
this.users = this.projectUsers.map(x => x.user);
this.projectUsers = this.projectUsers.filter(
(user) => user.admin === 1 || user.manager === 1 || user.engineer === 1
);
this.users = this.projectUsers.map((x) => x.user);
this.testRuns = await this.testRunService.getTestRun({ project_id: this.projectId });
this.addLinks();
this.addAffectedTestsAndRuns();
this.createColumns();
}

async addLinks() {
this.issues.forEach(issue => {
issue['external_link'] = issue.external_url
? { text: 'Open', link: issue.external_url }
: {};
this.issues.forEach((issue) => {
issue['external_link'] = issue.external_url ? { text: 'Open', link: issue.external_url } : {};
});
}

async addAffectedTestsAndRuns() {
const testResults = await this.testResultService.getTestResultsStat(this.projectId, null, null);
for (const issue of this.issues) {
const affectedTestsArray = testResults.filter((result) => Number(result.issue_id) === issue.id);
issue['affected_tests_amount'] = affectedTestsArray.length;
issue['test_runs'] = [];
for (const test of affectedTestsArray) {
issue['test_runs'].push(this.testRuns.find((run) => run.id === test.test_run_id));
}
issue['test_runs'] = [...new Set(issue['test_runs'])];
}
}

async updateIssue(issue: Issue) {
if (issue.resolution) {
issue.resolution_id = issue.resolution.id;
Expand All @@ -87,7 +114,7 @@ export class IssueListComponent implements OnInit {
this.issueService.getAiIssues(this.projectId);
}

async execute(result: {executed: boolean, result?: Issue}) {
async execute(result: { executed: boolean; result?: Issue }) {
this.hideCreateModal = true;
if (result.executed) {
await this.updateList();
Expand All @@ -99,12 +126,13 @@ export class IssueListComponent implements OnInit {
}

rowClicked(issue: Issue) {
return this.router.navigate(['/project/' + this.route.snapshot.params['projectId'] + '/issue/' + issue.id]);
return this.router.navigate([`/project/${this.route.snapshot.params['projectId']}/issue/${issue.id}`]);
}

private async updateList() {
this.issues = await this.issueService.getIssues({ project_id: this.projectId });
this.addLinks();
this.addAffectedTestsAndRuns();
}

private createColumns() {
Expand All @@ -114,8 +142,9 @@ export class IssueListComponent implements OnInit {
property: 'id',
sorting: true,
type: TFColumnType.text,
class: 'fit',
}, {
class: 'fit'
},
{
name: 'Status',
property: 'status',
filter: true,
Expand All @@ -127,7 +156,8 @@ export class IssueListComponent implements OnInit {
propToShow: ['name']
},
class: 'fit'
}, {
},
{
name: 'Resolution',
property: 'resolution',
filter: true,
Expand All @@ -139,7 +169,8 @@ export class IssueListComponent implements OnInit {
propToShow: ['name']
},
class: 'fit'
}, {
},
{
name: 'Title',
property: 'title',
filter: true,
Expand All @@ -150,7 +181,29 @@ export class IssueListComponent implements OnInit {
creationLength: 500,
required: true
}
}, {
},
{
name: 'Affected Tests Amount',
property: 'affected_tests_amount',
sorting: true,
type: TFColumnType.number,
class: 'ft-width-175'
},
{
name: 'Test Runs',
property: 'test_runs',
filter: true,
type: TFColumnType.multiselect,
lookup: {
propToShow: ['build_name'],
values: this.testRuns
},
editable: false,
bulkEdit: true,
sorting: true,
class: 'ft-width-250'
},
{
name: 'Assignee',
property: 'assignee',
type: TFColumnType.autocomplete,
Expand All @@ -163,17 +216,19 @@ export class IssueListComponent implements OnInit {
propToShow: ['first_name', 'second_name']
},
class: 'fit'
}, {
},
{
name: 'Created',
property: 'created',
type: TFColumnType.date,
class: 'fit'
}, {
},
{
name: 'External Issue',
property: 'external_link',
type: TFColumnType.externalLink,
class: 'ft-width-250'
},
}
];

this.hiddenColumns = [
Expand All @@ -182,12 +237,13 @@ export class IssueListComponent implements OnInit {
property: 'description',
type: TFColumnType.longtext,
class: 'ft-width-250'
}, {
},
{
name: 'Expression',
property: 'expression',
type: TFColumnType.text,
class: 'ft-width-250'
},
}
];
}
}
5 changes: 2 additions & 3 deletions src/app/shared/models/test-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ export class TestResultStat {
name?: string;
status?: string;
resolution?: string;
assignee?: string;
developer?: string;
comment?: string;
issue_id?: string;
issue_title?: string;
}

export class TestResultAttachment {
Expand Down

0 comments on commit 24de28d

Please sign in to comment.