Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BCMI-419] Fix partial routes and migrate some missing page content #421

Merged
merged 11 commits into from
Oct 11, 2024
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ npm-debug.log
testem.log
/typings

# Secrets
/cms/.env

# e2e
/build

Expand Down
4 changes: 3 additions & 1 deletion bcmi/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { LeafletModule } from '@bluehalo/ngx-leaflet';
import { GraphQLModule } from './graphql.module';
import { PageComponent } from './static-pages/page/page.component';
import { ContentService } from './services/content-service';
import { ContentDirective } from './services/content-directive';

export function initConfig(configService: ConfigService) {
return () => configService.init();
Expand All @@ -57,7 +58,8 @@ export function initConfig(configService: ConfigService) {
WaterQualityComponent,
TailingsManagementComponent,
ReclamationComponent,
NotFoundComponent
NotFoundComponent,
ContentDirective
],
imports: [
TagInputModule,
Expand Down
51 changes: 0 additions & 51 deletions bcmi/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,14 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthorizationsComponent } from './static-pages/authorizations/authorizations.component';
//import { ComplianceOversightComponent } from './static-pages/compliance-oversight/compliance-oversight.component';
import { ContactComponent } from './static-pages/contact/contact.component';
import { HomeComponent } from './home/home.component';
//import { LegislationComponent } from './static-pages/legislation/legislation.component';
//import { LifecycleComponent } from './static-pages/lifecycle/lifecycle.component';
import { ReclamationComponent } from './static-pages/reclamation/reclamation.component';
import { TailingsManagementComponent } from './static-pages/tailings-management/tailings-management.component';
import { TopicsOfInterestComponent } from './static-pages/topics-of-interest/topics-of-interest.component';
import { WaterQualityComponent } from './static-pages/water-quality/water-quality.component';
import { MainMapComponent } from './map/main-map/main-map.component';
import { NotFoundComponent } from './not-found/not-found.component';

export const routes: Routes = [
{
path: 'authorizations',
component: AuthorizationsComponent
},
/* Commenting out for demo
{
path: 'compliance-oversight',
component: ComplianceOversightComponent
},
*/
{
path: '',
component: HomeComponent
},
/* Commenting out for demo
{
path: 'legislation',
component: LegislationComponent
},
*/
/* Commenting out for demo
{
path: 'lifecycle',
component: LifecycleComponent
},
*/
{
path: 'reclamation',
component: ReclamationComponent
},
{
path: 'tailings-management',
component: TailingsManagementComponent
},
{
path: 'topics-of-interest',
component: TopicsOfInterestComponent
},
{
path: 'water-quality',
component: WaterQualityComponent
},
{
path: 'contact',
component: ContactComponent,
},
{
path: 'map',
component: MainMapComponent
Expand Down
4 changes: 4 additions & 0 deletions bcmi/src/app/models/content/header_button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class Header_Button {
Text: string;
Section_id: string;
}
6 changes: 6 additions & 0 deletions bcmi/src/app/models/content/page.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { Header_Button } from "./header_button"

// When adding new properties to this class, edit the query in /src/app/services/content-resolver.ts to include the new property
export class Page {
Title: string
Description: string
Header_button: Header_Button[] // strapi doesn't allow renaming :( I wish I could add an s
Content: string
// If you're adding a new sidecard variable, please add it to the isTwoColumn conditional as well!
Ongoing_card: string
External_card: string
Related_card: string
Enforcement_Actions_card: string
route: string
tooltip: string
}
Expand Down
48 changes: 48 additions & 0 deletions bcmi/src/app/services/content-directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Directive, ElementRef, Input, Renderer2, ViewContainerRef, AfterViewInit } from "@angular/core";
import { DynamicLinkComponent } from "@app/shared/dynamic-link";

@Directive({
selector: "[appContent]",
})

export class ContentDirective implements AfterViewInit {
@Input()
appStyle = true;
constructor(
private ref: ElementRef,
private viewContainerRef: ViewContainerRef,
private renderer: Renderer2,
) {}

ngAfterViewInit() {
const elements = Array.from(this.ref.nativeElement.getElementsByTagName("a"));
if(elements.length){
elements.forEach( (link: HTMLAnchorElement) => {
if(link.hasAttribute("href") && link.getAttribute("href")[0] == '/'){
this.replaceLink(link,link.getAttribute("href"));
}
})
}
}
private replaceLink(anchor: HTMLAnchorElement, href: string) {
let processedHref = href;
// Create a new component dynamically
const componentRef = this.viewContainerRef.createComponent(DynamicLinkComponent);

// Handle fragment if the link has one
const hashtagIndex = href.indexOf('#');
if (hashtagIndex != -1) {
processedHref = href.substring(0, hashtagIndex);
componentRef.instance.fragment = href.substring(hashtagIndex + 1);
}

componentRef.instance.routerLink = processedHref;
componentRef.instance.linkHTML = anchor.innerHTML;
componentRef.instance.linkClass = anchor.className;

// Append the newly created component and destroy the old one
this.renderer.insertBefore(anchor.parentElement, componentRef.location.nativeElement,anchor);
this.renderer.removeChild(this.ref.nativeElement, anchor);
}

}
6 changes: 6 additions & 0 deletions bcmi/src/app/services/content-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,23 @@ export class ContentResolver implements Resolve<Page> {

private getPage = function(route){

// When adding new properties to the Page class, edit this query
return gql`
{
pageByRoute(route: "${route}") {
data{
attributes{
Title,
Description
Header_button{
Text
Section_id
}
Content
Ongoing_card
External_card
Related_card
Enforcement_Actions_card
route
tooltip
}
Expand Down
15 changes: 15 additions & 0 deletions bcmi/src/app/shared/dynamic-link.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Component, Input } from '@angular/core';
import { Router } from '@angular/router';

@Component({
selector: 'app-dynamic-link',
template: `<a [routerLink]="routerLink" [fragment]="fragment" [innerHTML]="linkHTML" [ngClass]="linkClass"></a>`,
})
export class DynamicLinkComponent {
@Input() routerLink: string;
@Input() fragment:string | undefined;
@Input() linkHTML: string;
@Input() linkClass: string;

constructor(private router: Router) {}
}
4 changes: 3 additions & 1 deletion bcmi/src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ProjectStatusFilterPipe } from '@pipes/project-status-filter.pipe';
import { RemoveStringValuePipe } from '@pipes/remove-string-value.pipe';
import { SafeHtmlPipe } from '@pipes/safe-html.pipe';
import { RouterModule } from '@angular/router';
import { DynamicLinkComponent } from './dynamic-link';

@NgModule({
imports: [
Expand All @@ -19,7 +20,8 @@ import { RouterModule } from '@angular/router';
ProjectTypeFilterPipe,
ProjectStatusFilterPipe,
RemoveStringValuePipe,
SafeHtmlPipe
SafeHtmlPipe,
DynamicLinkComponent
],
exports: [
ObjectFilterPipe,
Expand Down
25 changes: 14 additions & 11 deletions bcmi/src/app/static-pages/page/page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,42 @@
<div class="hero-banner__content">
<h1 id="pgTitle">{{pageData.Title}}</h1>
<p>{{pageData.Description}}</p>
<div class="hero-banner__content--cta-btns" *ngIf="pageData.Header_button !== null && pageData.Header_button !== undefined && pageData.Header_button.length > 0">
<ng-container *ngFor="let button of pageData.Header_button">
<a class="btn hero-btn inverted" [routerLink]="routerLink" [fragment]="button.Section_id">
<span>{{button.Text}}</span>
</a>&nbsp;
</ng-container>
</div>
</div>
</div>
</div>
</div>

<div class="container" id="anchor-point">
<div class="row">
<main [ngClass]="{'col-lg-8': isTwoColumn}" [innerHTML]="pageData.Content">
<main id="page-content" [ngClass]="{'col-lg-8': isTwoColumn}" appContent [innerHTML]="pageData.Content | safeHtml">
</main>
<aside *ngIf="isTwoColumn" class="col-lg-4">
<section class="card" *ngIf="!(pageData.Ongoing_card === null || pageData.Ongoing_card === '')">
<h4 class="card-header">Ongoing Lifecycle Activities</h4>
<div [innerHTML]="pageData.Ongoing_card" class="card-body"></div>
<div appContent [innerHTML]="pageData.Ongoing_card" class="card-body"></div>
</section>

<section class="card" *ngIf="!(pageData.Related_card === null || pageData.Related_card === '')">
<h4 class="card-header">Related Documents</h4>
<div [innerHTML]="pageData.Related_card" class="card-list"></div>
<div appContent [innerHTML]="pageData.Related_card" class="card-list"></div>
</section>

<section class="card" *ngIf="!(pageData.External_card === null || pageData.External_card === '')">
<h4 class="card-header">External Links &amp; Resources</h4>
<div [innerHTML]="pageData.External_card"></div>
<div appContent [innerHTML]="pageData.External_card"></div>
</section>

<!----
<section class="card">
<section class="card" *ngIf="!(pageData.Enforcement_Actions_card === null || pageData.Enforcement_Actions_card === '')">
<h4 class="card-header">Enforcement Actions</h4>
<ul class="nv-list">
<<li><a href="/enforcement-actions" target="_blank" rel="noopener"> The Ministry of Energy, Mines, and Low Carbon Innovation </a></li>>
</ul>
</section>
--->
<div appContent [innerHTML]="pageData.Enforcement_Actions_card"></div>
</section>

</aside>
</div>
Expand Down
13 changes: 11 additions & 2 deletions bcmi/src/app/static-pages/page/page.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { SafeHtmlPipe } from '@pipes/safe-html.pipe';

import { PageComponent } from './page.component';
import { ActivatedRoute } from '@angular/router';
Expand All @@ -15,12 +16,20 @@ describe('PageComponent', () => {
const pageData = new Page();
pageData.Title = "Test";

const fakeActivatedRoute = {data: of({pageData: [pageData]}) };
const fakeActivatedRoute = {
data: of({pageData: [pageData]}),
fragment: of(null),
snapshot: {
routeConfig: {
path: '',
},
},
};

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
providers: [{provide: ActivatedRoute, useValue: fakeActivatedRoute}],
declarations: [PageComponent],
declarations: [PageComponent, SafeHtmlPipe],
imports: [CommonModule]
})
.compileComponents();
Expand Down
36 changes: 30 additions & 6 deletions bcmi/src/app/static-pages/page/page.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { afterRender, Component, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Page } from '../../models/content/page';

Expand All @@ -11,18 +11,42 @@ import { Page } from '../../models/content/page';
export class PageComponent implements OnInit {

pageData: Page;
routerLink: string;
initialFragment: string | null;
isTwoColumn: boolean;
handledFragmentFlag: boolean;

constructor(private activatedRoute: ActivatedRoute){};
constructor(private activatedRoute: ActivatedRoute){
this.initialFragment = null;
this.routerLink = "/" + activatedRoute.snapshot.routeConfig.path;

afterRender(() => {
// Only need to do this once after our content loaded
if (this.handledFragmentFlag) { return; }
const contentHasLoaded = document.getElementById('page-content').hasChildNodes();
if (contentHasLoaded && this.initialFragment) {
this.jumpToSection(this.initialFragment);
this.handledFragmentFlag = true;
}
});
};

ngOnInit() {
//window.scrollTo(0, 0);
window.scrollTo(0, 0);
this.activatedRoute.data.subscribe((response: any) => {
this.pageData = response.pageData;
})
});
this.activatedRoute.fragment.subscribe(fragment => {
this.initialFragment = fragment;
});
// This conditional will need to be changed whenever sidecards are added to the template
this.isTwoColumn = !!this.pageData.External_card || !!this.pageData.Ongoing_card || !!this.pageData.Related_card;

this.isTwoColumn = !!this.pageData.External_card || !!this.pageData.Ongoing_card || !!this.pageData.Related_card || !!this.pageData.Enforcement_Actions_card;
}

jumpToSection(section: string | null) {
if (section) {
document.getElementById(section)?.scrollIntoView({ behavior: 'smooth' });
}
}

}
7 changes: 6 additions & 1 deletion cms/src/api/page/content-types/page/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,17 @@
"tooltip": {
"type": "text"
},
"Enforcement_card": {
"Enforcement_Actions_card": {
"type": "customField",
"options": {
"preset": "toolbar"
},
"customField": "plugin::ckeditor5.CKEditor"
},
"Header_button": {
"type": "component",
"repeatable": true,
"component": "page.scroll-button"
}
}
}
16 changes: 16 additions & 0 deletions cms/src/components/page/scroll-button.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"collectionName": "components_page_scroll_buttons",
"info": {
"displayName": "Scroll Button",
"description": ""
},
"options": {},
"attributes": {
"Text": {
"type": "string"
},
"Section_id": {
"type": "string"
}
}
}
Loading
Loading