Skip to content

Commit 4114fc5

Browse files
authored
Merge pull request #354 from ioet/279-mark-selected-menu-option
feat: #279 Highlighting selected menu option
2 parents b42fc50 + c79cf44 commit 4114fc5

File tree

5 files changed

+72
-25
lines changed

5 files changed

+72
-25
lines changed

src/app/modules/shared/components/sidebar/models/item-sidebar.model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export interface ItemSidebar {
22
route: string;
33
icon: string;
44
text: string;
5+
active: boolean;
56
}

src/app/modules/shared/components/sidebar/sidebar.component.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
[routerLink]="item.route"
1111
routerLinkActive=""
1212
class="item-hover item"
13+
[ngClass]="{active: item.active}"
1314
>
14-
<i class="{{ item.icon }}"></i> {{ item.text }}</a
15-
>
15+
<i class="{{ item.icon }}"></i> {{ item.text }}
16+
</a>
1617
</div>
1718
</div>
1819
<!-- /#sidebar-wrapper -->

src/app/modules/shared/components/sidebar/sidebar.component.scss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,16 @@
2828
overflow-y: auto;
2929
}
3030

31-
.background-item-sidebar-active,
3231

3332
.item-hover:hover {
3433
color: #16BAC5;
3534
}
35+
36+
.active {
37+
color: #16BAC5;
38+
font-weight: bold;
39+
text-decoration: underline;
40+
}
3641
}
3742

3843
.container {

src/app/modules/shared/components/sidebar/sidebar.component.spec.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1-
import { AzureAdB2CService } from 'src/app/modules/login/services/azure.ad.b2c.service';
2-
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
1+
import {AzureAdB2CService} from 'src/app/modules/login/services/azure.ad.b2c.service';
2+
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
33

4-
import { SidebarComponent } from './sidebar.component';
4+
import {SidebarComponent} from './sidebar.component';
5+
import {RouterTestingModule} from '@angular/router/testing';
6+
import {Router, Routes} from '@angular/router';
7+
import {TimeClockComponent} from '../../../time-clock/pages/time-clock.component';
8+
import {provideMockStore} from '@ngrx/store/testing';
59

610
describe('SidebarComponent', () => {
711
let component: SidebarComponent;
812
let fixture: ComponentFixture<SidebarComponent>;
913
let azureAdB2CServiceStubInjected;
14+
let router;
15+
const routes: Routes = [
16+
{path: 'time-clock', component: TimeClockComponent}
17+
];
1018

1119
const azureAdB2CServiceStub = {
1220
isLogin() {
@@ -19,12 +27,15 @@ describe('SidebarComponent', () => {
1927

2028
beforeEach(async(() => {
2129
TestBed.configureTestingModule({
22-
declarations: [ SidebarComponent ],
30+
declarations: [SidebarComponent],
2331
providers: [
24-
{ providers: AzureAdB2CService, useValue: azureAdB2CServiceStub},
25-
]
32+
{providers: AzureAdB2CService, useValue: azureAdB2CServiceStub},
33+
provideMockStore({initialState: {}})
34+
],
35+
imports: [RouterTestingModule.withRoutes(routes)]
2636
})
27-
.compileComponents();
37+
.compileComponents();
38+
router = TestBed.inject(Router);
2839
}));
2940

3041
beforeEach(() => {
@@ -42,7 +53,7 @@ describe('SidebarComponent', () => {
4253
it('admin users have five menu items', () => {
4354
spyOn(azureAdB2CServiceStubInjected, 'isAdmin').and.returnValue(true);
4455

45-
component.getItemsSidebar();
56+
component.getSidebarItems();
4657
const menuItems = component.itemsSidebar;
4758

4859
expect(menuItems.length).toBe(5);
@@ -51,10 +62,21 @@ describe('SidebarComponent', () => {
5162
it('non admin users have two menu items', () => {
5263
spyOn(azureAdB2CServiceStubInjected, 'isAdmin').and.returnValue(false);
5364

54-
component.getItemsSidebar();
65+
component.getSidebarItems();
5566
const menuItems = component.itemsSidebar;
5667

5768
expect(menuItems.length).toBe(2);
5869
});
5970

71+
it('when item is selected is should be set as active and the others as inactive', () => {
72+
const route = 'time-clock';
73+
router.navigate([route]);
74+
75+
component.itemsSidebar.filter(item => item.route === `/${route}`).map(item => {
76+
expect(item.active).toBeTrue();
77+
});
78+
component.itemsSidebar.filter(item => item.route !== `/${route}`).map(item => {
79+
expect(item.active).toBeFalse();
80+
});
81+
});
6082
});
Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,52 @@
1-
import { AzureAdB2CService } from 'src/app/modules/login/services/azure.ad.b2c.service';
2-
import { Component, OnInit } from '@angular/core';
3-
import { ItemSidebar } from './models/item-sidebar.model';
1+
import {AzureAdB2CService} from 'src/app/modules/login/services/azure.ad.b2c.service';
2+
import {Component, OnInit} from '@angular/core';
3+
import {ItemSidebar} from './models/item-sidebar.model';
4+
import {NavigationStart, Router} from '@angular/router';
5+
import {Observable} from 'rxjs';
6+
import {filter} from 'rxjs/operators';
7+
48
@Component({
59
selector: 'app-sidebar',
610
templateUrl: './sidebar.component.html',
711
styleUrls: ['./sidebar.component.scss'],
812
})
913
export class SidebarComponent implements OnInit {
1014
itemsSidebar: ItemSidebar[] = [];
15+
navStart;
1116

12-
constructor(private azureAdB2CService: AzureAdB2CService) {}
17+
constructor(private azureAdB2CService: AzureAdB2CService, private router: Router) {
18+
this.navStart = this.router.events.pipe(
19+
filter(evt => evt instanceof NavigationStart)
20+
) as Observable<NavigationStart>;
21+
}
1322

1423
ngOnInit(): void {
15-
this.getItemsSidebar();
24+
this.getSidebarItems();
25+
this.highlightMenuOption(this.router.routerState.snapshot.url);
26+
this.navStart.subscribe(evt => {
27+
this.highlightMenuOption(evt.url);
28+
});
1629
}
1730

18-
getItemsSidebar() {
31+
getSidebarItems() {
1932
if (this.azureAdB2CService.isAdmin()) {
2033
this.itemsSidebar = [
21-
{ route: '/time-clock', icon: 'fas fa-clock', text: 'Time Clock' },
22-
{ route: '/time-entries', icon: 'fas fa-list-alt', text: 'Time Entries' },
23-
{ route: '/reports', icon: 'fas fa-chart-pie', text: 'Reports' },
24-
{ route: '/activities-management', icon: 'fas fa-file-alt', text: 'Activities' },
25-
{ route: '/customers-management', icon: 'fas fa-user', text: 'Customers' },
34+
{route: '/time-clock', icon: 'fas fa-clock', text: 'Time Clock', active: false},
35+
{route: '/time-entries', icon: 'fas fa-list-alt', text: 'Time Entries', active: false},
36+
{route: '/reports', icon: 'fas fa-chart-pie', text: 'Reports', active: false},
37+
{route: '/activities-management', icon: 'fas fa-file-alt', text: 'Activities', active: false},
38+
{route: '/customers-management', icon: 'fas fa-user', text: 'Customers', active: false},
2639
];
2740
} else {
2841
this.itemsSidebar = [
29-
{ route: '/time-clock', icon: 'fas fa-clock', text: 'Time Clock' },
30-
{ route: '/time-entries', icon: 'fas fa-list-alt', text: 'Time Entries' },
42+
{route: '/time-clock', icon: 'fas fa-clock', text: 'Time Clock', active: false},
43+
{route: '/time-entries', icon: 'fas fa-list-alt', text: 'Time Entries', active: false},
3144
];
3245
}
3346
}
47+
48+
highlightMenuOption(route) {
49+
this.itemsSidebar.map(item => item.active = false);
50+
this.itemsSidebar.filter(item => item.route === route).map(item => item.active = true);
51+
}
3452
}

0 commit comments

Comments
 (0)