Skip to content

Commit

Permalink
Add new navigation for search pages to home-page above the old naviga…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
ommann committed Apr 4, 2024
1 parent 9f82eb6 commit 29deb1c
Show file tree
Hide file tree
Showing 11 changed files with 1,345 additions and 1,007 deletions.
522 changes: 263 additions & 259 deletions src/app/portal/components/home-page/home-page.component.html

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,8 @@ export class Publications2Component implements OnDestroy {
aggregations$ = this.publications2Service.getAggregations();

yearAdditions$ = this.aggregations$.pipe(
map(aggs =>
getYearAdditions(aggs).map(
(bucket: any) => ({ year: bucket.key.toString(), count: bucket.doc_count })
) ?? []
),
map(aggs => getYearAdditions(aggs)
.map((bucket: any) => ({ year: bucket.key.toString(), count: bucket.doc_count })) ?? []),
map(aggs => aggs.sort((a, b) => b.year - a.year))
);

Expand Down
12 changes: 12 additions & 0 deletions src/app/portal/components/tab-button/tab-button.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<a class='tab-button-layout2 link-button' [routerLink]='route' style='text-decoration: none'>

<div style='display: flex'>
<fa-icon [icon]="_icon" style='margin-right: 12px'></fa-icon>

<div>{{ label }}</div>
</div>

<!--<div class='animated-number'>{{ count | number:'1.0-0' }}</div>-->
<div [countUp]="count" [options]="countOps">
</div>
</a>
56 changes: 56 additions & 0 deletions src/app/portal/components/tab-button/tab-button.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
.tab-button-layout2 {
display: flex;
justify-content: space-between;
align-items: center;

background-color: white;

width: 280px;
height: 45px;

padding: 12px 18px 12px 12px;
border: none;
box-shadow: 0 0 4px 0 #00000040;

font-size: 1rem;
font-weight: bold;
line-height: 1.5;
color: #4546B9;

font-variant-numeric: tabular-nums;

outline: none;
user-select: none;

&:hover {
background: #E8E8F5;
border: none;
}

/*&:focus {
border: 1px solid red; // #4546B9
}
&:focus-visible {
border: 10px solid red; // #4546B9
}*/

&:active {
background: #E8E8F5;
box-shadow: none;

// border: 1px solid purple;
}
}

/* TODO: Replace with Design Token */
.link-button {
font-size: 1rem;
font-weight: bold;
line-height: 1.5;
color: #4546B9;
}

.animated-number {
font-variant-numeric: tabular-nums;
}
52 changes: 52 additions & 0 deletions src/app/portal/components/tab-button/tab-button.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import {
faAlignLeft,
faBriefcase,
faBullhorn,
faCalculator,
faFileAlt,
faFileLines,
faUniversity,
faUsers
} from '@fortawesome/free-solid-svg-icons';
import { CountUpModule } from 'ngx-countup';
import { RouterLinkWithHref } from '@angular/router';

@Component({
selector: 'app-tab-button',
standalone: true,
imports: [CommonModule, FontAwesomeModule, CountUpModule, RouterLinkWithHref],
templateUrl: './tab-button.component.html',
styleUrls: ['./tab-button.component.scss']
})
export class TabButtonComponent {
@Input() label: string;
@Input() count: number;
@Input() route: string;

countOps = {
duration: 0.5,
separator: ' ',
};

protected _icon = faFileLines;

private iconMap = {
'faFileLines': faFileLines,
'faFileAlt': faFileAlt,
'faUsers': faUsers,
'faBriefcase': faBriefcase,
'faAlignLeft': faAlignLeft,
'faBullhorn': faBullhorn,
'faCalculator': faCalculator,
'faUniversity': faUniversity,
};

@Input() set icon(iconName: string) {
if (this.iconMap[iconName]) {
this._icon = this.iconMap[iconName];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<div style='display: flex; justify-content: center; align-items: center; padding: 10px'>
<div class='navigation-layout'>

<ng-container *ngIf='responsiveOrder$ | async as defaultOrderButtons'>
<ng-container *ngFor='let button of defaultOrderButtons | slice: 0:(end$ | async); trackBy: trackByLabel'>

<app-tab-button [icon]='button.icon' [label]='button.label' [count]='button.count' [route]='button.route'></app-tab-button>

</ng-container>
</ng-container>

</div>
</div>

<ng-container *ngIf='(isDesktop$ | async) === false'>
<ng-container *ngIf='(showAll$ | async) === false'>
<div class="expand-text" (click)='toggleAll()'>
<div style='margin-right: 0.25rem'>Näytä lisää</div>
<i class='fa-solid fa-caret-down'></i>
</div>
</ng-container>

<ng-container *ngIf='(showAll$ | async) === true'>
<div class='expand-text' (click)='toggleAll()'>
<div style='margin-right: 0.25rem'>Näytä vähemmän</div>
<i class='fa-solid fa-caret-up'></i>
</div>
</ng-container>
</ng-container>





Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.navigation-layout {
display: grid;
grid-template-columns: repeat(1, 1fr);
grid-column-gap: 16px;
grid-row-gap: 7px;

@media (min-width: 768px) {
grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 990px) {
grid-template-columns: repeat(3, 1fr);
}

@media (min-width: 1200px) {
grid-template-columns: repeat(4, 1fr);
}
}

.expand-text {
display: flex;
justify-content: center;
align-items: center;

font-size: 1rem;
font-weight: 700;
line-height: 1.5;
color: #4546B9;

margin-top: 1rem;
}
154 changes: 154 additions & 0 deletions src/app/portal/components/tab-navigation/tab-navigation.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TabButtonComponent } from '@portal/components/tab-button/tab-button.component';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
import { AppConfigService } from '@shared/services/app-config-service.service';
import { BreakpointObserver } from '@angular/cdk/layout';

type IndexCounts = { [index: string]: number };
type ButtonData = { label: string, icon: string, route: string, count: number };

@Component({
selector: 'app-tab-navigation',
standalone: true,
imports: [CommonModule, TabButtonComponent],
templateUrl: './tab-navigation.component.html',
styleUrls: ['./tab-navigation.component.scss']
})
export class TabNavigationComponent {
http = inject(HttpClient);
breakpointObserver = inject(BreakpointObserver);
appConfigService = inject(AppConfigService);

url = this.appConfigService.apiUrl + "publication,person,funding,dataset,funding-call,infrastructure,organization/_search?request_cache=true";
body = {
"size": 0,
"aggs": {
"_index": {
"filters": {
"filters": {
"publications": {
"match": {
"_index": "publication"
}
},
"persons": {
"match": {
"_index": "person"
}
},
"fundings": {
"match": {
"_index": "funding"
}
},
"datasets": {
"bool": {
"must": [
{
"match": {
"_index": "dataset"
}
},
{
"term": {
"isLatestVersion": 1
}
}
]
}
},
"infrastructures": {
"match": {
"_index": "infrastructure"
}
},
"organizations": {
"match": {
"_index": "organization"
}
},
"fundingCalls": {
"match": {
"_index": "funding-call"
}
}
}
}
}
}
}

// showAll = false;
showAll$ = new BehaviorSubject(false);

counts$: Observable<IndexCounts> = this.http.post(this.url, this.body).pipe(
map((response: any) => response.aggregations),
map(aggregations => Object.entries(aggregations._index.buckets)),
map(buckets => buckets.reduce((acc, [key, value]) => ({ ...acc, [key]: (value as any).doc_count }), {}))
);

/*defaultOrderButtons = [
{ label: 'Publications', icon: 'faFileLines', route: "/results/publications", count$: this.counts$.pipe(map(counts => counts.publications)) },
{ label: 'Persons', icon: 'faUsers', route: "/results/persons", count$: this.counts$.pipe(map(counts => counts.persons)) },
{ label: 'Fundings', icon: 'faBriefcase', route: "/results/fundings", count$: this.counts$.pipe(map(counts => counts.fundings)) },
{ label: 'Datasets', icon: 'faFileAlt', route: "/results/datasets", count$: this.counts$.pipe(map(counts => counts.datasets)) },
{ label: 'Funding Calls', icon: 'faBullhorn', route: "/results/funding-calls", count$: this.counts$.pipe(map(counts => counts.fundingCalls)) },
{ label: 'Infrastructures', icon: 'faUniversity', route: "/results/infrastructures", count$: this.counts$.pipe(map(counts => counts.infrastructures)) },
{ label: 'Organizations', icon: 'faCalculator', route: "/results/organizations", count$: this.counts$.pipe(map(counts => counts.organizations)) },
];*/

defaultOrderButtons$: Observable<ButtonData[]> = this.counts$.pipe(
map(counts => [
{ label: 'Publications', icon: 'faFileLines', route: "/results/publications", count: counts.publications },
{ label: 'Persons', icon: 'faUsers', route: "/results/persons", count: counts.persons },
{ label: 'Fundings', icon: 'faBriefcase', route: "/results/fundings", count: counts.fundings },
{ label: 'Datasets', icon: 'faFileAlt', route: "/results/datasets", count: counts.datasets },
{ label: 'Funding Calls', icon: 'faBullhorn', route: "/results/funding-calls", count: counts.fundingCalls },
{ label: 'Infrastructures', icon: 'faUniversity', route: "/results/infrastructures", count: counts.infrastructures },
{ label: 'Organizations', icon: 'faCalculator', route: "/results/organizations", count: counts.organizations },
])
);

// Buttons sorted by the count value
sortedButtons$: Observable<ButtonData[]> = this.defaultOrderButtons$.pipe(
map(buttons => buttons.sort((a, b) => b.count - a.count))
);

// If the narrowest 768px breakpoint is active use the sorted buttons, otherwise use the default order
responsiveOrder$: Observable<ButtonData[]> = this.breakpointObserver.observe(['(max-width: 768px)']).pipe(
switchMap(result => result.matches ? this.sortedButtons$ : this.defaultOrderButtons$)
);

responsiveSize$: Observable<number> = this.breakpointObserver.observe(['(min-width: 1200px)', '(min-width: 990px)', '(min-width: 768px)']).pipe(
map(result => {
if (result.breakpoints['(min-width: 1200px)']) {
return 8;
} else if (result.breakpoints['(min-width: 990px)']) {
return 3;
} else if (result.breakpoints['(min-width: 768px)']) {
return 3;
} else {
return 3;
}
})
);

end$ = combineLatest([this.showAll$, this.responsiveSize$, this.defaultOrderButtons$]).pipe(
map<[boolean, number, ButtonData[]], number>(([showAll, end, buttons]) => showAll ? buttons.length : end)
);

isDesktop$ = this.breakpointObserver.observe(['(min-width: 1200px)']).pipe(
map(result => result.matches)
);

toggleAll() {
this.showAll$.next(!this.showAll$.value);
}

trackByLabel(index: number, button: ButtonData) {
return button.label;
}
}
4 changes: 3 additions & 1 deletion src/app/portal/portal.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ import { PersonGroupAdditionalComponent } from './components/single/single-perso
import { FooterComponent } from '../layout/footer/footer.component';
import { SearchBar2Component } from '@portal/search-bar2/search-bar2.component';
import { FixExternalUrlPipe } from '@portal/pipes/fix-external-url.pipe';
import { TabNavigationComponent } from '@portal/components/tab-navigation/tab-navigation.component';

@NgModule({
declarations: [
Expand Down Expand Up @@ -291,7 +292,8 @@ import { FixExternalUrlPipe } from '@portal/pipes/fix-external-url.pipe';
MatSortModule,
FooterComponent,
SearchBar2Component,
FixExternalUrlPipe
FixExternalUrlPipe,
TabNavigationComponent
],
exports: [DatasetAuthorComponent, FiltersComponent],
providers: [
Expand Down
4 changes: 0 additions & 4 deletions src/app/portal/services/publication2.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -754,8 +754,6 @@ function generateAggregationStep(name: SearchParamKey, lookup: Record<string, {f
const global = searchParams[name] != null

if (global) {
// console.log("global", name);

return {
[topLevelPath]: {
global: {},
Expand All @@ -781,8 +779,6 @@ function generateAggregationStep(name: SearchParamKey, lookup: Record<string, {f
}
};
} else {
// console.log("local", name);

return {
[topLevelPath]: {
filter: {
Expand Down
Loading

0 comments on commit 29deb1c

Please sign in to comment.