Skip to content

Commit fea2c02

Browse files
authored
Merge pull request #104 from CenterForOpenScience/feat/199-other-pages
Feat/199 other pages
2 parents 4562f2d + 4859031 commit fea2c02

File tree

44 files changed

+535
-191
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+535
-191
lines changed

src/app/app.routes.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const routes: Routes = [
4444
{
4545
path: 'home',
4646
loadComponent: () => import('./features/home/home.component').then((mod) => mod.HomeComponent),
47+
data: { skipBreadcrumbs: true },
4748
},
4849
{
4950
path: 'home-logged-out',
@@ -193,11 +194,26 @@ export const routes: Routes = [
193194
{
194195
path: 'confirm/:userId/:emailId',
195196
loadComponent: () => import('./features/home/home.component').then((mod) => mod.HomeComponent),
197+
data: { skipBreadcrumbs: true },
198+
},
199+
{
200+
path: 'forbidden',
201+
loadComponent: () =>
202+
import('./core/components/forbidden-page/forbidden-page.component').then((mod) => mod.ForbiddenPageComponent),
203+
data: { skipBreadcrumbs: true },
204+
},
205+
{
206+
path: 'request-access/:projectId',
207+
loadComponent: () =>
208+
import('./core/components/request-access/request-access.component').then((mod) => mod.RequestAccessComponent),
209+
data: { skipBreadcrumbs: true },
210+
},
211+
{
212+
path: '**',
213+
loadComponent: () =>
214+
import('./core/components/page-not-found/page-not-found.component').then((mod) => mod.PageNotFoundComponent),
215+
data: { skipBreadcrumbs: true },
196216
},
197217
],
198218
},
199-
{
200-
path: '**',
201-
redirectTo: 'home',
202-
},
203219
];

src/app/core/components/breadcrumb/breadcrumb.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@if (!parsedUrl()[0].includes('home') && !parsedUrl()[0].includes('confirm')) {
1+
@if (showBreadcrumb()) {
22
<div class="breadcrumbs flex align-items-center gap-2 md:p-5 md:pb-0 xl:p-0">
33
<osf-icon iconClass="fas fa-home"></osf-icon>
44
<p>/</p>
Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
import { Component, computed, DestroyRef, inject, signal } from '@angular/core';
2-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3-
import { NavigationEnd, Router } from '@angular/router';
1+
import { filter, map, startWith } from 'rxjs';
42

3+
import { Component, computed, inject } from '@angular/core';
4+
import { toSignal } from '@angular/core/rxjs-interop';
5+
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
6+
7+
import { RouteData } from '@osf/core/models';
58
import { IconComponent } from '@osf/shared/components';
69

710
@Component({
@@ -11,22 +14,44 @@ import { IconComponent } from '@osf/shared/components';
1114
styleUrl: './breadcrumb.component.scss',
1215
})
1316
export class BreadcrumbComponent {
14-
#router = inject(Router);
15-
#destroyRef = inject(DestroyRef);
16-
protected readonly url = signal(this.#router.url);
17-
protected readonly parsedUrl = computed(() => {
18-
return this.url()
17+
private readonly router = inject(Router);
18+
private readonly route = inject(ActivatedRoute);
19+
20+
protected readonly url = toSignal(
21+
this.router.events.pipe(
22+
filter((event) => event instanceof NavigationEnd),
23+
map(() => this.router.url),
24+
startWith(this.router.url)
25+
),
26+
{ initialValue: this.router.url }
27+
);
28+
29+
protected readonly routeData = toSignal(
30+
this.router.events.pipe(
31+
filter((event) => event instanceof NavigationEnd),
32+
map(() => this.getCurrentRouteData()),
33+
startWith(this.getCurrentRouteData())
34+
),
35+
{ initialValue: { skipBreadcrumbs: false } as RouteData }
36+
);
37+
38+
protected readonly showBreadcrumb = computed(() => this.routeData()?.skipBreadcrumbs !== true);
39+
40+
protected readonly parsedUrl = computed(() =>
41+
this.url()
1942
.split('?')[0]
2043
.split('/')
2144
.filter(Boolean)
22-
.map((segment) => segment.replace(/-/g, ' '));
23-
});
24-
25-
constructor() {
26-
this.#router.events.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe((event) => {
27-
if (event instanceof NavigationEnd) {
28-
this.url.set(this.#router.url);
29-
}
30-
});
45+
.map((segment) => segment.replace(/-/g, ' '))
46+
);
47+
48+
private getCurrentRouteData(): RouteData {
49+
let currentRoute = this.route;
50+
51+
while (currentRoute.firstChild) {
52+
currentRoute = currentRoute.firstChild;
53+
}
54+
55+
return currentRoute.snapshot.data as RouteData;
3156
}
3257
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<section class="container text-center flex flex-column flex-1 my-7 mx-3 p-3 md:p-4">
2+
<h2>{{ 'forbiddenPage.title' | translate }}</h2>
3+
<p class="mt-4">
4+
<span>{{ 'forbiddenPage.message' | translate }}</span>
5+
<a class="ml-1 font-bold" href="mailto:support@osf.io">support&#64;osf.io</a>
6+
</p>
7+
</section>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@use "assets/styles/mixins" as mix;
2+
@use "assets/styles/variables" as var;
3+
4+
:host {
5+
@include mix.flex-center;
6+
flex: 1;
7+
background: var(--gradient-3);
8+
}
9+
10+
.container {
11+
position: relative;
12+
background: var.$white;
13+
border-radius: mix.rem(12px);
14+
box-shadow: 0 2px 4px var.$grey-outline;
15+
color: var.$dark-blue-1;
16+
max-width: mix.rem(448px);
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { ForbiddenPageComponent } from './forbidden-page.component';
4+
5+
describe('ForbiddenPageComponent', () => {
6+
let component: ForbiddenPageComponent;
7+
let fixture: ComponentFixture<ForbiddenPageComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
imports: [ForbiddenPageComponent],
12+
}).compileComponents();
13+
14+
fixture = TestBed.createComponent(ForbiddenPageComponent);
15+
component = fixture.componentInstance;
16+
fixture.detectChanges();
17+
});
18+
19+
it('should create', () => {
20+
expect(component).toBeTruthy();
21+
});
22+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { TranslatePipe } from '@ngx-translate/core';
2+
3+
import { ChangeDetectionStrategy, Component } from '@angular/core';
4+
5+
@Component({
6+
selector: 'osf-forbidden-page',
7+
imports: [TranslatePipe],
8+
templateUrl: './forbidden-page.component.html',
9+
styleUrl: './forbidden-page.component.scss',
10+
changeDetection: ChangeDetectionStrategy.OnPush,
11+
})
12+
export class ForbiddenPageComponent {}

src/app/core/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export { BreadcrumbComponent } from './breadcrumb/breadcrumb.component';
22
export { FooterComponent } from './footer/footer.component';
33
export { HeaderComponent } from './header/header.component';
4+
export { PageNotFoundComponent } from './page-not-found/page-not-found.component';
45
export { RootComponent } from './root/root.component';
56
export { SidenavComponent } from './sidenav/sidenav.component';
67
export { TopnavComponent } from './topnav/topnav.component';
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<section class="container text-center flex flex-column flex-1 my-7 mx-3 p-3 md:p-4">
2+
<h2>{{ 'pageNotFound.title' | translate }}</h2>
3+
<p class="mt-4">
4+
<span>{{ 'pageNotFound.message' | translate }}</span>
5+
<a class="ml-1 font-bold" href="mailto:support@osf.io">support&#64;osf.io</a>
6+
</p>
7+
</section>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@use "assets/styles/mixins" as mix;
2+
@use "assets/styles/variables" as var;
3+
4+
:host {
5+
@include mix.flex-center;
6+
flex: 1;
7+
background: var(--gradient-3);
8+
}
9+
10+
.container {
11+
position: relative;
12+
background: var.$white;
13+
border-radius: mix.rem(12px);
14+
box-shadow: 0 2px 4px var.$grey-outline;
15+
color: var.$dark-blue-1;
16+
max-width: mix.rem(448px);
17+
}

0 commit comments

Comments
 (0)