Skip to content

Commit d487989

Browse files
Add issues
1 parent 11daf27 commit d487989

File tree

19 files changed

+186
-115
lines changed

19 files changed

+186
-115
lines changed

e2e/specs/administration/predefinedResolutions.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,8 @@ describe('Predefined Resolution:', () => {
144144

145145
const result = results.find(x => x.fail_reason === 'step was skippedstep was skipped');
146146
if (result) {
147-
expect(result.assigned_user.user.user_name).toBe(usersTestData.localAdmin.user_name, 'Assignee was not filled!');
148-
expect(result.test_resolution.name).toBe(edit.resolution.name, 'Resolution was not filled!');
149-
expect(result.comment).toBe(edit.comment, 'Comment was not filled!');
147+
expect(result.issue.resolution.name).toBe(edit.resolution.name, 'Resolution was not filled!');
148+
expect(result.issue.title).toBe(edit.comment, 'Comment was not filled!');
150149
} else {
151150
expect(result).toBeDefined('The imported results do not contain expected result!');
152151
}

e2e/specs/administration/projectSettings/projectSettings.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ describe('Administartion: Project Settings:', () => {
9696
const results: TestResult[] = await projectHelper.editorAPI
9797
.getResults({ test_run_id: imported[0].id, project_id: projectHelper.project.id });
9898
results.forEach(result => {
99-
expect(result.test.resolution_colors).toBe(`${result.test_resolution.color}`, 'resolution_colors is wrong!');
99+
expect(result.test.resolution_colors).toBe(`${result.issue.resolution.color}`, 'resolution_colors is wrong!');
100100
expect(result.test.result_colors).toBe(`${result.final_result.color}`, 'result_colors is wrong!');
101101
expect(result.test.result_ids).toBe(`${result.id}`, 'result_ids is wrong!');
102102
});
@@ -118,7 +118,7 @@ describe('Administartion: Project Settings:', () => {
118118
result.test_resolution_id = 4;
119119
result = await projectHelper.editorAPI.createResult(result);
120120
result = (await projectHelper.editorAPI.getResults(result))[0];
121-
expect(result.test.resolution_colors).toBe(`${result.test_resolution.color},3,3,3,3`, 'resolution_colors is wrong!');
121+
expect(result.test.resolution_colors).toBe(`${result.issue.resolution.color},3,3,3,3`, 'resolution_colors is wrong!');
122122
expect(result.test.result_colors).toBe(`${result.final_result.color},4,4,4,4`, 'result_colors is wrong!');
123123
expect(result.test.result_ids.startsWith(`${result.id}`)).toBe(true, 'result_ids is wrong!');
124124
});

src/app/pages/project/issue/issue-create.modal/issue-create.modal.component.css

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,14 @@
2222
.update-results-label {
2323
position: absolute;
2424
top: 0;
25-
left: 60;
25+
left: 40;
26+
text-transform: none;
27+
}
28+
29+
.row-with-switch {
30+
margin-top: 10px;
31+
}
32+
33+
#issue-description {
34+
min-height: 233px !important;
2635
}

src/app/pages/project/issue/issue-create.modal/issue-create.modal.component.html

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,10 @@ <h4 class="modal-title">Create Issue</h4>
2121
</div>
2222

2323
<div class="row">
24-
<div *ngIf="issue.expression" class="col-sm-12">
25-
<ui-switch class="clearfix" size="small" [(ngModel)]="updateResults" id="update-results"></ui-switch>
26-
<label class="update-results-label" for="update-results">Assigne to Results that fit the expression</label>
27-
</div>
2824
<div class="col-sm-8">
2925
<label for="issue-description">Description:</label>
3026
<textarea id="issue-description" class="form-control" placeholder="Description" name="description"
31-
id="issue-desciption" cols="30" rows="12" [(ngModel)]="issue.description"></textarea>
27+
[(ngModel)]="issue.description"></textarea>
3228
</div>
3329
<div class="col-sm-4 issue-fields">
3430
<div class="col-sm-12 no-padding">
@@ -47,15 +43,32 @@ <h4 class="modal-title">Create Issue</h4>
4743
</div>
4844
<div class="col-sm-12 no-padding">
4945
<label for="issue-expression">Regular Expression:</label>
50-
<input id="issue-expression" type="text" class="form-control" placeholder="Regular Expression"
51-
[(ngModel)]="issue.expression">
46+
<input id="issue-expression" type="text" class="form-control" placeholder="Regular Expression" [ngClass]="{
47+
'is-valid': isExpressionOverlapped(),
48+
'is-invalid': isExpressionOverlapped()
49+
}" [(ngModel)]="issue.expression" (keyup)="onExpressionUpdate($event)">
50+
<div class="invalid-feedback">
51+
Expression is overlapped!
52+
</div>
53+
</div>
54+
<div *ngIf="issue.expression" class="col-sm-12 no-padding row-with-switch" title="Assign this issue to all results where Fail Reason fits the Expression and without assigned issue">
55+
<ui-switch class="clearfix" size="small" [(ngModel)]="updateResults" id="update-results"></ui-switch>
56+
<label class="update-results-label" for="update-results">Add to Results without issue</label>
5257
</div>
5358
<div class="col-sm-12 no-padding">
5459
<label for="issue-external-url">External Issue:</label>
5560
<input id="issue-external-url" type="text" class="form-control" placeholder="External Issue"
5661
[(ngModel)]="issue.external_url">
5762
</div>
5863
</div>
64+
65+
</div>
66+
67+
<div class="col-sm-12 no-padding" *ngIf="overlappedIssues && columns && overlappedIssues.length > 0">
68+
<p>The Regular Expression is overlapped with:</p>
69+
<table-filter id="overlapped-issues-table" [data]="overlappedIssues" [columns]="columns" rowsOnPage="3"
70+
[hidePageSets]="true" [hideFilter]="true" [columnManagement]="false">
71+
</table-filter>
5972
</div>
6073

6174
<div class="col-sm-12 modal-footer modal-buttons">

src/app/pages/project/issue/issue-create.modal/issue-create.modal.component.ts

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { User } from '../../../../shared/models/user';
66
import { IssueService } from '../../../../services/issue.service';
77
import { ActivatedRoute } from '@angular/router';
88
import { UserService } from '../../../../services/user.services';
9+
import { TFColumn, TFColumnType } from '../../../../elements/table/tfColumn';
910

1011
@Component({
1112
selector: 'issue-create-modal',
@@ -14,27 +15,50 @@ import { UserService } from '../../../../services/user.services';
1415
})
1516
export class CreateIssueModalComponent extends BasePopupComponent implements OnInit {
1617
@Input() resolutions: ResultResolution[];
18+
@Input() existingIssues: Issue[];
1719
@Input() users: User[];
1820
@Input() title: string;
1921
issue: Issue;
2022
updateResults = true;
23+
overlappedIssues: Issue[] = [];
24+
validateExpressionTimeout = null;
25+
columns: TFColumn[] = [
26+
{
27+
name: 'Id',
28+
property: 'id',
29+
sorting: true,
30+
type: TFColumnType.text,
31+
class: 'fit',
32+
}, {
33+
name: 'Title',
34+
property: 'title',
35+
filter: true,
36+
sorting: true,
37+
type: TFColumnType.text
38+
}, {
39+
name: 'Expression',
40+
property: 'expression',
41+
type: TFColumnType.text,
42+
class: 'ft-width-250'
43+
}
44+
];
2145

2246
constructor(
2347
public userService: UserService,
2448
private route: ActivatedRoute,
2549
private issueService: IssueService
2650
) {
2751
super();
28-
}
29-
30-
ngOnInit() {
3152
this.buttons = [{
3253
name: 'Create',
3354
execute: true
3455
}, {
3556
name: 'Cancel',
3657
execute: false
3758
}];
59+
}
60+
61+
async ngOnInit() {
3862
this.issue = new Issue();
3963
if (this.title) {
4064
this.issue.title = this.title;
@@ -43,6 +67,9 @@ export class CreateIssueModalComponent extends BasePopupComponent implements OnI
4367
this.issue.creator_id = this.userService.currentUser().id;
4468
this.issue.status_id = 1;
4569
this.updateResolution(this.resolutions.find(x => x.id === 1));
70+
if (!this.existingIssues) {
71+
this.existingIssues = await this.issueService.getIssues({ project_id: this.issue.project_id });
72+
}
4673
}
4774

4875
updateResolution(resolution: ResultResolution) {
@@ -55,14 +82,35 @@ export class CreateIssueModalComponent extends BasePopupComponent implements OnI
5582
this.issue.assignee_id = user.id;
5683
}
5784

85+
onExpressionUpdate() {
86+
clearTimeout(this.validateExpressionTimeout);
87+
this.validateExpressionTimeout = setTimeout(() => {
88+
if (this.issue.expression) {
89+
const newIssueRegExp = new RegExp(this.issue.expression);
90+
this.overlappedIssues = this.existingIssues.filter(existingIssue => existingIssue.expression
91+
? newIssueRegExp.test(existingIssue.expression) || new RegExp(existingIssue.expression).test(this.issue.expression)
92+
: false);
93+
} else {
94+
this.overlappedIssues = [];
95+
}
96+
}, 1000);
97+
}
98+
5899
async doAction(execute: boolean) {
59100
if (execute) {
60-
if (this.isIssueValid()) {
61-
const issue = await this.issueService.createIssue(this.issue, this.updateResults);
62-
this.execute.emit({ executed: true, result: issue });
63-
} else {
101+
if (!this.isIssueValid()) {
64102
this.issueService.handleSimpleError('Fill all required fields!', 'You should fill Title and Resolution fields!');
103+
return;
65104
}
105+
106+
if (this.isExpressionOverlapped()) {
107+
this.issueService.handleSimpleError('Expression is overlapped!',
108+
'The Regular Expression sould not be overlapped with other issues!');
109+
return;
110+
}
111+
112+
const issue = await this.issueService.createIssue(this.issue, this.updateResults);
113+
this.execute.emit({ executed: true, result: issue });
66114
} else {
67115
this.execute.emit({ executed: false });
68116
}
@@ -75,4 +123,8 @@ export class CreateIssueModalComponent extends BasePopupComponent implements OnI
75123

76124
return true;
77125
}
126+
127+
isExpressionOverlapped() {
128+
return this.overlappedIssues.length > 0;
129+
}
78130
}

src/app/pages/project/issue/issue-list/issue-list.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ <h2 id="issues-list">Issues</h2>
1010
</div>
1111

1212
<div class="panel-body">
13-
<issue-create-modal *ngIf="!hideCreateModal" (execute)="execute($event)" (closed)="wasClosed()" [resolutions]="resolutions" [users]="users" ></issue-create-modal>
13+
<issue-create-modal *ngIf="!hideCreateModal" (execute)="execute($event)" (closed)="wasClosed()" [resolutions]="resolutions" [users]="users"
14+
[existingIssues]="issues"></issue-create-modal>
1415
<table-filter id="issues-table" *ngIf="issues && columns" [data]="issues" [columns]="columns"
1516
[hiddenColumns]="hiddenColumns" [defaultSortBy]="defSort" (action)="handleAction($event)" [queryParams]="true"
1617
(dataChange)="updateIssue($event)" (rowClick)="rowClicked($event)" rowsOnPage="20">

src/app/pages/project/milestone/view-milestone/view-milestone.component.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export class ViewMilestoneComponent implements OnInit, OnDestroy {
158158
}
159159

160160
hideTableValue(entity: ViewData, property: string) {
161-
if ((property === 'test_resolution.name') && entity.result.final_result.color === 5) {
161+
if ((property === 'issue.resolution.name') && entity.result.final_result.color === 5) {
162162
return true;
163163
}
164164
return false;
@@ -233,8 +233,7 @@ export class ViewMilestoneComponent implements OnInit, OnDestroy {
233233
private getNotExecutedResult(): TestResult {
234234
return {
235235
final_result: this.finalResults.find(x => x.id === 3),
236-
test_resolution: this.resolutions.find(x => x.id === 1),
237-
comment: undefined,
236+
issue: { resolution: this.resolutions.find(x => x.id === 1) },
238237
start_date: undefined
239238
};
240239
}
@@ -276,18 +275,18 @@ export class ViewMilestoneComponent implements OnInit, OnDestroy {
276275
class: 'fit'
277276
}, {
278277
name: 'Resolution',
279-
property: 'test_resolution.name',
278+
property: 'issue.resolution.name',
280279
filter: true,
281280
sorting: true,
282281
type: TFColumnType.colored,
283282
lookup: {
284-
entity: 'result.test_resolution',
283+
entity: 'result.issue.resolution',
285284
values: this.resolutions,
286285
propToShow: ['name']
287286
},
288287
class: 'fit'
289288
},
290-
{ name: 'Comment', property: 'result.comment', filter: true, type: TFColumnType.text, class: 'ft-width-150' },
289+
{ name: 'Issue', property: 'result.issue.title', filter: true, type: TFColumnType.text, class: 'ft-width-150' },
291290
{ name: 'Finished', property: 'result.finish_date', filter: true, sorting: true, type: TFColumnType.date, class: 'fit' }
292291
];
293292
}

src/app/pages/project/results/results-grid/results.grid.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
[resolutions]="listOfResolutions"
99
[users]="users"
1010
[title]="newIssueTitle"
11+
[existingIssues]="listOfIssues"
1112
></issue-create-modal>
1213
<table-filter id="resultsGridMain" *ngIf="tbCols"
1314
[hide]="hideVal"

src/app/pages/project/results/results-grid/results.grid.component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ export class ResultGridComponent implements OnInit {
8585
this.testResults.forEach(result => {
8686
result['developer'] = this.users.find(x => x.id === result.test.developer_id);
8787
result['testrun'] = testruns.find(x => x.id === result.test_run_id);
88-
if (result.final_result.color === 5) { result.test_resolution = undefined; }
8988
result['duration'] = this.calculateDuration(result);
9089
result['combinedLastResults'] = this.testService.combineLastResults(result.test);
9190
});
@@ -164,7 +163,7 @@ export class ResultGridComponent implements OnInit {
164163
}
165164

166165
hideVal(entity: TestResult, property: string) {
167-
if ((property === 'test_resolution.name' || property === 'issue') && entity.final_result.color === 5) {
166+
if ((property === 'issue.resolution.name' || property === 'issue') && entity.final_result.color === 5) {
168167
return true;
169168
}
170169
return false;

src/app/pages/project/results/results-searcher/results.searcher.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,12 @@ export class ResultSearcherComponent {
9292
},
9393
{
9494
name: 'Resolution',
95-
property: 'test_resolution.name',
95+
property: 'issue.resolution.name',
9696
filter: true,
9797
sorting: true,
9898
type: TFColumnType.colored,
9999
lookup: {
100-
entity: 'test_resolution',
100+
entity: 'issue.resolution',
101101
values: this.listOfResolutions,
102102
propToShow: ['name']
103103
},

0 commit comments

Comments
 (0)