Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/CD-time-tracker-ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,26 @@ jobs:
with:
node-version: '12.x'

- name: Inject Secrets
shell: python
env:
SCOPES: ${{ secrets.scopes }}
CLIENT_ID: ${{ secrets.client_id }}
AUTHORITY: ${{ secrets.authority }}
BASE_PATH: "src/environments/"
run: |
import os
import json
data = {}
base_path = os.environ.get('BASE_PATH', 'src/environments/')
with open(base_path + "keys.example.json", "r+") as jsonFileRead:
data = json.load(jsonFileRead)
data["scopes"] = str(os.environ['SCOPES']).split(",")
data["client_id"] = os.environ['CLIENT_ID']
data["authority"] = os.environ['AUTHORITY']
with open(base_path + ".keys.json", "w+") as jsonFileWrite:
json.dump(data, jsonFileWrite)

- name: 'run: npm install and build'
run: |
npm install
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/CI-time-tracker-ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,25 @@ jobs:
- name: Install dependencies
run: npm install

- name: Inject Secrets
shell: python
env:
SCOPES: ${{ secrets.scopes }}
CLIENT_ID: ${{ secrets.client_id }}
AUTHORITY: ${{ secrets.authority }}
BASE_PATH: "src/environments/"
run: |
import os
import json
data = {}
base_path = os.environ.get('BASE_PATH', 'src/environments/')
with open(base_path + "keys.example.json", "r+") as jsonFileRead:
data = json.load(jsonFileRead)
data["scopes"] = str(os.environ['SCOPES']).split(",")
data["client_id"] = os.environ['CLIENT_ID']
data["authority"] = os.environ['AUTHORITY']
with open(base_path + ".keys.json", "w+") as jsonFileWrite:
json.dump(data, jsonFileWrite)

- name: Run the test
run: npm run ci-test --if-present
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ npm-debug.log
yarn-error.log
testem.log
/typings

.keys.json
# System Files
.DS_Store
Thumbs.db
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ Run `npm install` to install the required node_modules for this project.
Run `ng serve` to run the app in dev mode. After executing this command, you can navigate to `http://localhost:4200/` to see the app working.
The app will automatically reload if you change anything in the source files.

## Prepare your environment for vscode
## Prepare your environment

### Set environment variables
Create file .keys.json from keys.example.ts into environments folder with the content pinned in our slack channel

### Prepare your environment for vscode
Install the following extensions:

- `EditorConfig for Visual Studio Code`.
Expand Down
8 changes: 8 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"bootstrap": "^4.4.1",
"jquery": "^3.4.1",
"minimist": "^1.2.5",
"msal": "^1.2.1",
"rxjs": "~6.5.4",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
Expand Down
23 changes: 16 additions & 7 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { AzureGuardService } from './guards/azure-guard.service';
import { ReportsComponent } from './modules/reports/pages/reports.component';
import { TimeClockComponent } from './modules/time-clock/pages/time-clock.component';
import { TimeEntriesComponent } from './modules/time-entries/pages/time-entries.component';
import { ProjectManagementComponent } from './modules/project-management/pages/project-management.component';
import { ActivitiesManagementComponent } from './modules/activities-management/pages/activities-management.component';
import { HomeComponent } from './modules/home/home.component';
import { LoginComponent } from './modules/login/login.component';

const routes: Routes = [
{path: 'reports', component: ReportsComponent},
{path: 'time-clock', component: TimeClockComponent},
{path: 'time-entries', component: TimeEntriesComponent},
{path: 'project-management', component: ProjectManagementComponent},
{path: 'activities-management', component: ActivitiesManagementComponent},
{path: '', pathMatch: 'full', redirectTo: 'time-clock'},
{path: '**', pathMatch: 'full', redirectTo: 'time-clock'},

{ path: '', component: HomeComponent, canActivate: [AzureGuardService],
children: [
{ path: 'reports', component: ReportsComponent },
{ path: 'time-clock', component: TimeClockComponent },
{ path: 'time-entries', component: TimeEntriesComponent },
{ path: 'project-management', component: ProjectManagementComponent },
{ path: 'activities-management', component: ActivitiesManagementComponent },
{path: '', pathMatch: 'full', redirectTo: 'time-clock'},
]
},
{ path: 'login', component: LoginComponent },
];

@NgModule({
Expand Down
6 changes: 1 addition & 5 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
<app-navbar></app-navbar>

<app-sidebar>
<router-outlet></router-outlet>
</app-sidebar>
<router-outlet></router-outlet>
6 changes: 5 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { ActivitiesManagementComponent } from './modules/activities-management/p
import { ActivityListComponent } from './modules/activities-management/components/activity-list/activity-list.component';
import { CreateActivityComponent } from './modules/activities-management/components/create-activity/create-activity.component';

import { HomeComponent } from './modules/home/home.component';
import { LoginComponent } from './modules/login/login.component';

@NgModule({
declarations: [
Expand All @@ -47,7 +49,9 @@ import { CreateActivityComponent } from './modules/activities-management/compone
GroupByDatePipe,
ActivitiesManagementComponent,
CreateActivityComponent,
ActivityListComponent
ActivityListComponent,
HomeComponent,
LoginComponent
],
imports: [
CommonModule,
Expand Down
48 changes: 48 additions & 0 deletions src/app/guards/azure-guard.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { TestBed, inject } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';

import { AzureAdB2CService } from '../modules/login/services/azure.ad.b2c.service';
import { AzureGuardService } from './azure-guard.service';


describe('AzureGuardService', () => {
let service: AzureGuardService;
let azureAdB2CService: AzureAdB2CService;
const azureAdB2CServiceStub = {
isLogin() {
return true;
}
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ RouterTestingModule ],
providers: [
{ providers: AzureAdB2CService, useValue: azureAdB2CServiceStub},
]
});
service = TestBed.inject(AzureGuardService);
azureAdB2CService = TestBed.inject(AzureAdB2CService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});

it('can activate the route when user is logged-in', () => {
spyOn(azureAdB2CService, 'isLogin').and.returnValue(true);
const canActivate = service.canActivate();
expect(azureAdB2CService.isLogin).toHaveBeenCalled();
expect(canActivate).toEqual(true);
});

it('can not active the route and is redirected to login if user is not logged-in', inject([Router], (router: Router) => {
spyOn(azureAdB2CService, 'isLogin').and.returnValue(false);
spyOn(router, 'navigate').and.stub();
const canActivate = service.canActivate();
expect(azureAdB2CService.isLogin).toHaveBeenCalled();
expect(canActivate).toEqual(false);
expect(router.navigate).toHaveBeenCalledWith(['login']);
}));

});
20 changes: 20 additions & 0 deletions src/app/guards/azure-guard.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AzureAdB2CService } from '../modules/login/services/azure.ad.b2c.service';

@Injectable({
providedIn: 'root'
})
export class AzureGuardService implements CanActivate {

constructor(private azureAdB2CService: AzureAdB2CService, private router: Router) { }

canActivate() {
if (this.azureAdB2CService.isLogin()) {
return true;
} else {
this.router.navigate(['login']);
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ describe('CreateActivityComponent', () => {

let component: CreateActivityComponent;

const data = {
name: '',
description: ''
};

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CreateActivityComponent],
Expand All @@ -19,4 +24,28 @@ describe('CreateActivityComponent', () => {
expect(component).toBeTruthy();
});

it('should reset form onSubmit', () => {
spyOn(component.activityForm, 'reset');

component.onSubmit(data);

expect(component.activityForm.reset).toHaveBeenCalled();
});

it('should get name using activityForm', () => {
spyOn(component.activityForm, 'get');
// tslint:disable-next-line:no-unused-expression
component.name;
expect(component.activityForm.get).toHaveBeenCalledWith('name');
});

it('should get description using activityForm', () => {
spyOn(component.activityForm, 'get');

// tslint:disable-next-line:no-unused-expression
component.description;

expect(component.activityForm.get).toHaveBeenCalledWith('description');
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('ActivitiesManagementComponent', () => {
providers: [ ActivityService, HttpClient, HttpHandler ]
});
component = TestBed.createComponent(ActivitiesManagementComponent).componentInstance;
activityService = TestBed.get(ActivityService);
activityService = TestBed.inject(ActivityService);
spyOn(activityService, 'getActivities').and.returnValue(of(activitiesFromApi));
}));

Expand Down
5 changes: 5 additions & 0 deletions src/app/modules/home/home.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<app-navbar></app-navbar>

<app-sidebar>
<router-outlet></router-outlet>
</app-sidebar>
Empty file.
25 changes: 25 additions & 0 deletions src/app/modules/home/home.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { HomeComponent } from './home.component';

describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HomeComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should be created', () => {
expect(component).toBeTruthy();
});
});
15 changes: 15 additions & 0 deletions src/app/modules/home/home.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

constructor() { }

ngOnInit(): void {
}

}
1 change: 1 addition & 0 deletions src/app/modules/login/login.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<button (click)="login()">login</button>
Empty file.
Loading