Skip to content

Commit 8b5dce7

Browse files
committed
Merge branch 'master' of https://github.com/ioet/time-tracker-ui into Time-Clock-Timer-Component
2 parents 7803290 + 62d84f8 commit 8b5dce7

15 files changed

+296
-32
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
2+
# More GitHub Actions for Azure: https://github.com/Azure/actions
3+
4+
name: Build and deploy Node.js app to Azure Web App - time-tracker-ui
5+
6+
on:
7+
push:
8+
branches:
9+
- master
10+
11+
jobs:
12+
build-and-deploy:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- uses: actions/checkout@master
17+
18+
- name: Set up Node.js version
19+
uses: actions/setup-node@v1
20+
with:
21+
node-version: '12.x'
22+
23+
- name: npm install, build, and test
24+
run: |
25+
npm install
26+
npm run build --if-present
27+
# npm run test --if-present
28+
29+
- name: 'Deploy to Azure Web App'
30+
uses: azure/webapps-deploy@v1
31+
with:
32+
app-name: 'time-tracker-ui'
33+
slot-name: 'production'
34+
publish-profile: ${{ secrets.AzureAppService_PublishProfile_728dc744f9384bf38e8a0446aaaee29d }}
35+
package: dist/time-tracker

karma.conf.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ module.exports = function (config) {
1818
coverageIstanbulReporter: {
1919
dir: require('path').join(__dirname, './coverage/time-tracker'),
2020
reports: ['html', 'lcovonly', 'text-summary'],
21-
fixWebpackSourcePaths: true
21+
fixWebpackSourcePaths: true,
22+
thresholds: {
23+
statements: 80,
24+
lines: 80,
25+
branches: 80,
26+
functions: 80
27+
}
2228
},
2329
reporters: ['progress', 'kjhtml'],
2430
port: 9876,

src/app/app.module.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
22
import { BrowserModule } from '@angular/platform-browser';
33
import { NgModule } from '@angular/core';
44
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
5+
import { HttpClientModule } from '@angular/common/http';
56

67
import { AppRoutingModule } from './app-routing.module';
78

@@ -16,8 +17,7 @@ import { ProjectListComponent } from './components/shared/project-list/project-l
1617
import { CreateProjectComponent } from './components/shared/create-project/create-project.component';
1718
import { DetailsFieldsComponent } from './components/shared/details-fields/details-fields.component';
1819
import { ProjectListHoverComponent } from './components/shared/project-list-hover/project-list-hover.component';
19-
20-
20+
import { ModalComponent } from './components/shared/modal/modal.component';
2121
@NgModule({
2222
declarations: [
2323
AppComponent,
@@ -32,13 +32,15 @@ import { ProjectListHoverComponent } from './components/shared/project-list-hove
3232
TimeClockComponent,
3333
DetailsFieldsComponent,
3434
ProjectListHoverComponent,
35+
ModalComponent
3536
],
3637
imports: [
3738
CommonModule,
3839
BrowserModule,
3940
AppRoutingModule,
4041
FormsModule,
41-
ReactiveFormsModule
42+
ReactiveFormsModule,
43+
HttpClientModule
4244
],
4345
providers: [],
4446
bootstrap: [AppComponent]

src/app/components/options-sidebar/project-management/project-management.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<app-project-list class="item"
1212
[projects] = "projects"
1313
(editProject) = "editProject($event)"
14+
(deleteProject) = "deleteProject($event)"
1415
>
1516
</app-project-list>
1617
</div>

src/app/components/options-sidebar/project-management/project-management.component.spec.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
1+
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
22

33
import { ProjectManagementComponent } from './project-management.component';
44
import { Project } from '../../../interfaces/project';
5+
import { ProjectService } from '../../../services/project.service';
6+
import { of } from 'rxjs';
57

68
describe('ProjectManagementComponent', () => {
79
let component: ProjectManagementComponent;
810
let fixture: ComponentFixture<ProjectManagementComponent>;
11+
let projectService: ProjectService;
12+
913
const projects: Project[] = [{
1014
id: 1,
1115
name: 'app 1',
@@ -29,9 +33,17 @@ describe('ProjectManagementComponent', () => {
2933
}
3034
];
3135

36+
const projectServiceStub = {
37+
getProjects() {
38+
const projectsMock = projects;
39+
return of(projectsMock);
40+
}
41+
};
42+
3243
beforeEach(async(() => {
3344
TestBed.configureTestingModule({
34-
declarations: [ ProjectManagementComponent ]
45+
declarations: [ ProjectManagementComponent ],
46+
providers: [ { provide: ProjectService, useValue: projectServiceStub }]
3547
})
3648
.compileComponents();
3749
}));
@@ -40,9 +52,18 @@ describe('ProjectManagementComponent', () => {
4052
fixture = TestBed.createComponent(ProjectManagementComponent);
4153
component = fixture.componentInstance;
4254
fixture.detectChanges();
55+
56+
projectService = TestBed.inject(ProjectService);
4357
component.projects = projects;
4458
});
4559

60+
61+
it('Service injected via inject(...) and TestBed.get(...) should be the same instance',
62+
inject([ProjectService], (injectService: ProjectService) => {
63+
expect(injectService).toBe(projectService);
64+
})
65+
);
66+
4667
it('should create', () => {
4768
expect(component).toBeTruthy();
4869
});
@@ -97,4 +118,34 @@ describe('ProjectManagementComponent', () => {
97118
component.cancelForm();
98119
expect(component.project).toBe(null);
99120
});
121+
122+
it('should call getProjects method on init', () => {
123+
const preojectServiceSpy = spyOn(projectService, 'getProjects').and.callThrough();
124+
const componentSpy = spyOn(component, 'getProjects').and.callThrough();
125+
126+
expect(preojectServiceSpy).not.toHaveBeenCalled();
127+
expect(componentSpy).not.toHaveBeenCalled();
128+
129+
component.ngOnInit();
130+
131+
expect(preojectServiceSpy).toHaveBeenCalledTimes(1);
132+
expect(componentSpy).toHaveBeenCalledTimes(1);
133+
});
134+
135+
136+
it('should call getProjects and return a list of projects', async(() => {
137+
138+
spyOn(projectService, 'getProjects').and.returnValue(of(projects));
139+
140+
component.ngOnInit();
141+
142+
expect(component.projects).toEqual(projects);
143+
}));
144+
145+
it('should delete a project #deleteProject', () => {
146+
const projectId = 1;
147+
148+
component.deleteProject(projectId);
149+
expect(component.projects.length).toEqual(2);
150+
});
100151
});

src/app/components/options-sidebar/project-management/project-management.component.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Component, OnInit } from '@angular/core';
22
import { Project } from '../../../interfaces/project';
3-
import { Input } from '@angular/core';
4-
import { Output, EventEmitter } from '@angular/core';
3+
import { ProjectService } from '../../../services/project.service';
4+
55
@Component({
66
selector: 'app-project-management',
77
templateUrl: './project-management.component.html',
@@ -13,14 +13,13 @@ export class ProjectManagementComponent implements OnInit {
1313

1414
project: Project;
1515

16-
projects: Project[] = [
17-
{ id: 1, name: 'GoSpace', details: 'Improve workspaces', status: 'Active', completed: false},
18-
{ id: 2, name: 'MidoPlay', details: 'Lottery', status: 'Inactive', completed: true}
19-
];
16+
projects: Project[] = [];
2017

21-
constructor() { }
18+
constructor(private projectService: ProjectService) {
19+
}
2220

2321
ngOnInit(): void {
22+
this.getProjects();
2423
}
2524

2625
updateProject(projectData): void {
@@ -44,7 +43,17 @@ export class ProjectManagementComponent implements OnInit {
4443
this.project = this.projects.filter((project) => project.id === projectId)[0];
4544
}
4645

46+
deleteProject(projectId): void {
47+
this.projects = this.projects.filter((project) => project.id !== projectId);
48+
}
49+
4750
cancelForm() {
4851
this.project = null;
4952
}
53+
54+
getProjects() {
55+
this.projectService.getProjects().subscribe(data => {
56+
this.projects = data;
57+
});
58+
}
5059
}

src/app/components/shared/modal/modal.component.css

Whitespace-only changes.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<div class="modal-dialog" role="document">
2+
<div class="modal-content" *ngIf="project">
3+
<div class="modal-header">
4+
<h5 class="modal-title" id="exampleModalLabel">Delete Project</h5>
5+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
6+
<span aria-hidden="true">&times;</span>
7+
</button>
8+
</div>
9+
<div class="modal-body">
10+
Are you sure you want to delete {{project.name}} project?
11+
</div>
12+
<div class="modal-footer">
13+
<button #cancelDeleteModal type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
14+
<button (click)="removedProject(project.id)" type="button" class="btn btn-primary">Delete</button>
15+
</div>
16+
</div>
17+
</div>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { ModalComponent } from './modal.component';
4+
5+
describe('ModalComponent', () => {
6+
let component: ModalComponent;
7+
let fixture: ComponentFixture<ModalComponent>;
8+
9+
beforeEach(async(() => {
10+
TestBed.configureTestingModule({
11+
declarations: [ ModalComponent ]
12+
})
13+
.compileComponents();
14+
}));
15+
16+
beforeEach(() => {
17+
fixture = TestBed.createComponent(ModalComponent);
18+
component = fixture.componentInstance;
19+
fixture.detectChanges();
20+
});
21+
22+
it('should create', () => {
23+
expect(component).toBeTruthy();
24+
});
25+
});
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
2+
import { Output, EventEmitter } from '@angular/core';
3+
import { Input } from '@angular/core';
4+
import { Project } from '../../../interfaces/project'
5+
@Component({
6+
selector: 'app-modal',
7+
templateUrl: './modal.component.html',
8+
styleUrls: ['./modal.component.css']
9+
})
10+
export class ModalComponent implements OnInit {
11+
12+
@Input() project: Project;
13+
@Output() removeProject = new EventEmitter();
14+
15+
@ViewChild('cancelDeleteModal') cancelDeleteModal: ElementRef;
16+
17+
constructor() { }
18+
19+
ngOnInit(): void {
20+
}
21+
22+
removedProject(projectId) {
23+
this.removeProject.emit(projectId);
24+
this.cancelDeleteModal.nativeElement.click();
25+
}
26+
}

0 commit comments

Comments
 (0)