Skip to content

Commit

Permalink
Merge pull request #346 from KnowWhereGraph/breadcrumbs
Browse files Browse the repository at this point in the history
Add breadcrumbs and page title to the navigation area
  • Loading branch information
ThomasThelen authored Jun 14, 2023
2 parents 0ee22a0 + fed825f commit e67ab40
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 8 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 src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import { Component } from '@angular/core'
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
title = 'faceted-search'
title = 'Knowledge Explorer'
}
2 changes: 1 addition & 1 deletion src/app/header/header.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<header [ngStyle]="{ height: router.url === '/' ? 'auto' : '200px' }">
<header [ngStyle]="{ height: router.url === '/' ? 'auto' : '220px' }">
<div class="home">
<div class="container" *ngIf="router.url === '/'">
<h1>Knowledge Explorer: Discovery begins here.</h1>
Expand Down
4 changes: 4 additions & 0 deletions src/app/nav/nav.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,8 @@
</li>
</ul>
</div>
<div class="nav-display">
<label class="breadcrumb">{{ breadcrumb }}</label>
<label class="pagename">{{ pageName }}</label>
</div>
</section>
17 changes: 17 additions & 0 deletions src/app/nav/nav.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,21 @@
}
}
}

.nav-display {
.breadcrumb {
position: absolute;
// Aligns under the logo, left justified
left: 0rem;
top: 7rem;
opacity: 50%;
}
.pagename {
position: absolute;
// Aligns under the logo, left justified
left: 0rem;
top: 10rem;
font-size: x-large;
}
}
}
36 changes: 34 additions & 2 deletions src/app/nav/nav.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Component, OnInit } from '@angular/core'
import { NavInfoService } from '../services/nav.service'
import { Subscription } from 'rxjs/internal/Subscription'

/**
* Component for the navigation bar. This component encompasses the navigation
Expand All @@ -10,13 +12,43 @@ import { Component, OnInit } from '@angular/core'
styleUrls: ['./nav.component.scss'],
})
export class NavComponent implements OnInit {
breadcrumb: string = ''
pageName: string = ''
navChangedSub: Subscription

/**
* An empty constructor; this class is just markup and styling.
* Creates a new nav component.
*
* @param navInfoService: Service with a stream that contains new data to display in the nav area
*/
constructor() {}
constructor(private navInfoService: NavInfoService) {
this.navChangedSub = navInfoService.onNavChanged.subscribe((event) => {
this.onNavigationChange(event)
})
}

/**
* An empty ngOnInit to satisfy the constraints from OnInit.
*/
ngOnInit(): void {}

/**
* Triggered when a page changes in a way that requires the navigation
* display to be updated. The new relative path and full path should be
* included in the fired event.
*
* @param event The navigation change event, carrying the new state information
*/
onNavigationChange(event: NavEvent) {
this.breadcrumb = event.fullPath
this.pageName = event.relativePath
}
}

/**
* Template for a new navigation state
*/
export interface NavEvent {
relativePath: string
fullPath: string
}
41 changes: 39 additions & 2 deletions src/app/search/search.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { ActivatedRoute, Router } from '@angular/router'
import { Component, OnInit, ChangeDetectorRef, ViewChild } from '@angular/core'
import {
Component,
OnInit,
ChangeDetectorRef,
ViewChild,
Output,
EventEmitter,
} from '@angular/core'
import { MatTabChangeEvent } from '@angular/material/tabs'
import { MatDialog, MatDialogConfig } from '@angular/material/dialog'
import { ErrorModalComponent } from '../error-modal/error-modal.component'
import { NavEvent } from '../nav/nav.component'
import { NavInfoService } from '../services/nav.service'
import { Location } from '@angular/common'

/**
Expand Down Expand Up @@ -45,6 +54,8 @@ export class SearchComponent implements OnInit {
// Reference to the facets component
@ViewChild('appfacets')
public appfacets: any
// Event that emitted to the parent component, to tell the navigation component to update
@Output() navChange = new EventEmitter<NavEvent>()

/**
* Called when a facet changes
Expand Down Expand Up @@ -75,6 +86,7 @@ export class SearchComponent implements OnInit {
* @param cd The change detector reference to catch events
* @param route: The activated route for this page
* @param router: The global router
* @param navInfoService: Service for sending information to the nav component
* @param errorModal: A reference to the error modal dialog
* @param location: Angular's 'Location' object for this path
*/
Expand All @@ -83,11 +95,13 @@ export class SearchComponent implements OnInit {
private route: ActivatedRoute,
private router: Router,
private errorModal: MatDialog,
private navInfoService: NavInfoService,
private location: Location
) {
this.totalSize = 0
this.isCounting = true
this.isSearching = true
this.navInfoService = navInfoService
this.location = location
}

Expand Down Expand Up @@ -147,17 +161,31 @@ export class SearchComponent implements OnInit {
case 2:
clickedTabName = 'person'
}

this.navInfoService.onNavChanged.next({
fullPath: `search/${clickedTabName}`,
relativePath: this.capitalizeFirstLetter(clickedTabName),
})

const queryParams = { tab: clickedTabName }
this.location.replaceState(`search?tab=${clickedTabName}`)
}

/**
* When the initialization is ready, check to see if a particular tab should be
* navigated to.
* navigated to and update the nav.
*/
ngOnInit(): void {
// Check to see if a particular tab should be loaded
let tab = this.route.snapshot.queryParamMap.get('tab')
if (!tab) {
console.error('Failed to get the tab contents')
return
}
this.navInfoService.onNavChanged.next({
fullPath: `search/${tab}`,
relativePath: this.capitalizeFirstLetter(tab),
})

switch (tab) {
case 'place':
Expand Down Expand Up @@ -219,4 +247,13 @@ export class SearchComponent implements OnInit {
dialogConfig.height = '200px'
this.errorModal.open(ErrorModalComponent, dialogConfig)
}

/**
* Makes the first letter in a prase upper cased
* @param phrase: The phrase being capitalized
* @returns 'phrase' but with the first letter of the first word upper cased
*/
capitalizeFirstLetter(phrase: string) {
return phrase.charAt(0).toUpperCase() + phrase.slice(1)
}
}
18 changes: 18 additions & 0 deletions src/app/services/nav.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Injectable } from '@angular/core'
import { Subject } from 'rxjs/internal/Subject'

/**
* Service for passing navigation page information from components to
* the navigation component. This is required because the navigation component
* lives in the app root, while other components are rendered conditionally through
* the router which makes it difficult to pass data to the parent app root.
*/
@Injectable({
providedIn: 'root',
})
export class NavInfoService {
// Event stream that holds new nav state
onNavChanged = new Subject<any>()

constructor() {}
}

0 comments on commit e67ab40

Please sign in to comment.