app/dxa/dxa-entity/views/related-info-views/related-info-main/related-info-main.component.ts
changeDetection | ChangeDetectionStrategy.OnPush |
selector | div[related-info-main] |
styleUrls | ./related-info-main.component.scss |
templateUrl | ./related-info-main.component.html |
Properties |
|
Methods |
|
Inputs |
HostBindings |
constructor(util: UtilService, linkService: ComponentLinkService, idGenerator: IdGeneratorService, resizer: ResizeContentService, constants: ConstantsService, changeDetector: ChangeDetectorRef, doc)
|
||||||||||||||||||||||||
Parameters :
|
entity | |
class |
actOnResize |
actOnResize()
|
Returns :
void
|
inDesktopView | ||||||
inDesktopView(width: number)
|
||||||
Parameters :
Returns :
boolean
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
Public resolveColumn | ||||||||
resolveColumn(column, CtaTitle, CtaLinkTarget)
|
||||||||
Resolves a column to a uniform format
Parameters :
Returns :
{ videojson: any; Icon: any; Title: any; Description: any; links: any; CtaButtonTitle: any; CtaBu...
|
Public resolveDescription | ||||||
resolveDescription(description: string)
|
||||||
Parameters :
Returns :
boolean
|
Public setUpFields |
setUpFields()
|
Returns :
void
|
Public videoLoad | ||||||
videoLoad(e, index)
|
||||||
Parameters :
Returns :
void
|
Public accordionId |
Default value : this.idGenerator.getId()
|
Public columns |
Type : []
|
Default value : []
|
Private componentId |
Default value : this.idGenerator.getId()
|
Public desktopView |
Type : boolean
|
isLoading |
Default value : false
|
Public title |
Type : string
|
windowWidth |
Type : any
|
import { Component, OnDestroy, Input, ChangeDetectionStrategy, Inject, ChangeDetectorRef, HostBinding, OnInit } from '@angular/core';
import { UtilService } from 'src/app/core/services/util-service/util.service';
import { ComponentLinkService } from 'src/app/core/services/component-link-service/component-link.service';
import { DOCUMENT } from '@angular/common';
import { IdGeneratorService } from 'src/app/core/services/id-generator.service';
import { ResizeContentService } from 'src/app/core/services/resize-service/resize-content.service';
import { ConstantsService } from 'src/app/shared/constants/constants.service';
@Component({
selector: 'div[related-info-main]',
templateUrl: './related-info-main.component.html',
styleUrls: ['./related-info-main.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class RelatedInfoMainComponent implements OnInit, OnDestroy {
@Input() entity;
isLoading = false;
public columns = [];
public title: string;
public desktopView: boolean;
public accordionId = this.idGenerator.getId();
windowWidth: any;
private componentId = this.idGenerator.getId();
@HostBinding('class') get class() {
const template = this.util.extract(this.entity, 'MvcData', 'ViewName');
if (template === 'RelatedInfoLightGreyMain') {
return 'col-md-12 space-between bg-off-white';
} else {
return 'col-md-12 space-between';
}
}
constructor(
private util: UtilService,
private linkService: ComponentLinkService,
private idGenerator: IdGeneratorService,
private resizer: ResizeContentService,
private constants: ConstantsService,
private changeDetector: ChangeDetectorRef,
@Inject(DOCUMENT) private doc) { }
public videoLoad(e, index) {
const v = e.srcElement.duration;
// Assuming that title has loaded since that the video tag has loaded
const a = new Date(null);
a.setSeconds(v);
const time = a.toISOString().substr(11, 8).replace(/^0+/, '').replace(/^:+/, '');
this.columns[index].linkToVideo.linkTitle += ' (' + time + ')';
}
ngOnInit(): void {
const width = (window.innerWidth || this.doc.documentElement.clientWidth);
this.desktopView = this.inDesktopView(width);
this.resizer.registerCallback(this.componentId, () => this.actOnResize());
this.setUpFields();
}
ngOnDestroy(): void {
this.resizer.destroyCallback(this.componentId);
}
actOnResize(): void {
const width = (window.innerWidth || this.doc.documentElement.clientWidth);
this.desktopView = this.inDesktopView(width);
this.changeDetector.detectChanges();
}
public setUpFields() {
const id = this.util.extract(this.entity, 'Id');
this.title = this.util.extract(this.entity, 'Title') || '';
const columnOne = this.util.extract(this.entity, 'ColumnOne') || '';
const columnOneCtaTitle = this.util.extract(this.entity, 'ColumnOneCtaTitle') || '';
const columnOneCtaLinkTarget = this.util.extract(this.entity, 'ColumnOneCtaLinkTarget') || {};
const columnTwo = this.util.extract(this.entity, 'ColumnTwo') || '';
const columnTwoCtaTitle = this.util.extract(this.entity, 'ColumnTwoCtaTitle') || '';
const columnTwoCtaLinkTarget = this.util.extract(this.entity, 'ColumnTwoCtaLinkTarget') || {};
const columnThree = this.util.extract(this.entity, 'ColumnThree') || '';
const columnThreeCtaTitle = this.util.extract(this.entity, 'ColumnThreeCtaTitle') || '';
const columnThreeCtaLinkTarget = this.util.extract(this.entity, 'ColumnThreeCtaLinkTarget') || {};
const content = this.resolveColumn(columnOne, columnOneCtaTitle, columnOneCtaLinkTarget);
const content2 = this.resolveColumn(columnTwo, columnTwoCtaTitle, columnTwoCtaLinkTarget);
const content3 = this.resolveColumn(columnThree, columnThreeCtaTitle, columnThreeCtaLinkTarget);
// Need these for the mobile view, add box at the start since ids need to start with a letter
content['boxId'] = `box-${this.idGenerator.getId()}`;
content2['boxId'] = `box-${this.idGenerator.getId()}`;
content3['boxId'] = `box-${this.idGenerator.getId()}`;
this.columns = [content, content2, content3];
this.changeDetector.detectChanges();
}
/** Resolves a column to a uniform format */
public resolveColumn(column, CtaTitle, CtaLinkTarget) {
const links = column.LinkTarget || [];
const videojson = this.util.extract(column, 'Video');
const resolved = {
videojson: videojson,
Icon: this.util.extract(column, 'Icon'),
Title: this.util.extract(column, 'Title'),
Description: this.util.extract(column, 'Description'),
links: links.map(link => this.linkService.parseLink(link)),
CtaButtonTitle: CtaTitle,
CtaButtonLinkTarget: CtaLinkTarget,
hasVideo: !!this.util.extract(column, 'Video')
};
return resolved;
}
public resolveDescription(description: string): boolean {
return description === 'With description';
}
inDesktopView(width: number): boolean {
return width > this.constants.BOOTSTRAP_BREAKPOINTS.LG;
}
}
<div class="container">
<h2 *ngIf="title" class="title">{{title}}</h2>
<div class="accordion" [id]="'accordion-' + accordionId" *ngIf="!desktopView">
<div class="card" [id]="'card-' + col.boxId + '-' + accordionId" *ngFor="let col of columns; let i = index;">
<div class="card-header" [id]="'heading-' + accordionId">
<h5 class="mb-0">
<a class="toggler" data-toggle="collapse" [href]="'#' + col.boxId + '-' + accordionId"
[attr.aria-expanded]="i === 0" [attr.aria-controls]="col.boxId + '-' + accordionId">
<i class="card-header-icon" [ngClass]="col.Icon"></i>
<span *ngIf="!col.hasVideo">{{col.Title}}</span>
<span *ngIf="col.hasVideo">{{col.Icon}}</span>
<i class="card-header-chevron icon-chevronDown"></i>
<i class="card-header-chevron icon-chevronUp"></i>
</a>
</h5>
</div>
<div [id]="col.boxId + '-' + accordionId" [ngClass]="{'collapse': true, 'show': i === 0}"
[attr.aria-labelledby]="'heading-' + accordionId" [attr.data-parent]="'#accordion-' + accordionId">
<div class="card-body">
<div class="card-text">
<div *ngIf="col.hasVideo" video-player [videoJSON]="col.videojson">
</div>
</div>
<ng-container *ngIf="!col.hasVideo">
<div class="list-group list-group-flush" *ngIf="col.links && !col.Description">
<a class="comp-link" component-link [linkObject]="link.linkObject"
class="list-group-item list-group-item-action" *ngFor="let link of col.links">
<div class="link-group-title">
<i *ngIf="link.linkObject?.LinkModelTarget?.MimeType === 'application/pdf' " class="icon-related-pdf"></i>
<i *ngIf="link.linkObject?.LinkModelTarget?.MimeType === 'application/zip' " class="icon-link-download"></i>
{{link.title}}
<span *ngIf="link.linkObject?.LinkModelTarget?.MimeType === 'application/pdf'">{{link.fileSize}} </span>
<i *ngIf="link.newWindow" class="icon-link-openNewWindow"></i>
</div>
<p class="mb-0" *ngIf="link.useDescription">
{{link.description}}
</p>
</a>
</div>
<p *ngIf="col.Description">
{{col.Description}}
</p>
</ng-container>
</div>
<div class="card-footer" *ngIf="col.CtaButtonTitle">
<a component-link [linkObject]="col.CtaButtonLinkTarget" class="btn btn-cool-grey button-link">
{{col.CtaButtonTitle}}
</a>
</div>
</div>
</div>
</div>
<div class="card-group" [id]="accordionId" *ngIf="desktopView">
<ng-container *ngFor="let col of columns; let i = index;">
<div class="card">
<div class="card-header">
<h5 class="mb-0 d-inline-flex">
<i class="card-header-icon" [ngClass]="col.Icon"></i>
<span *ngIf="col.Title">{{col.Title}}</span>
</h5>
</div>
<div class="card-body">
<div class="card-text">
<div *ngIf="col.hasVideo" video-player [videoJSON]="col.videojson" [videoDescription]="col.Description"></div>
<ng-container *ngIf="!col.hasVideo">
<div class="list-group list-group-flush" *ngIf="col.links && !col.Description">
<a class="comp-link" component-link [linkObject]="c.linkObject"
class="list-group-item list-group-item-action" *ngFor="let c of col.links">
<div class="link-group-title">
<i *ngIf="c.linkObject?.LinkModelTarget?.MimeType === 'application/pdf' " class="icon-related-pdf"></i>
<i *ngIf="c.linkObject?.LinkModelTarget?.MimeType === 'application/zip' " class="icon-link-download"></i>
{{c.title}}
<span *ngIf="c.linkObject?.LinkModelTarget?.MimeType === 'application/pdf'"> {{c.fileSize}} </span>
<i *ngIf="c.openInNewWindow" class="icon-link-openNewWindow"></i>
</div>
<p class="mb-0" *ngIf="c.useDescription">{{c.description}}</p>
</a>
</div>
<p *ngIf="col.Description">{{col.Description}}</p>
</ng-container>
</div>
</div>
<div class="card-footer" *ngIf="col.CtaButtonTitle">
<a component-link [linkObject]="col.CtaButtonLinkTarget" class="btn btn-cool-grey button-link">
{{col.CtaButtonTitle}}
</a>
</div>
</div>
</ng-container>
</div>
./related-info-main.component.scss
@import "src/app/styles/helpers";
//@import "~bootstrap/scss/card";
//@import "~bootstrap/scss/list-group";
.title {
padding-left: calc-rem(40);
padding-bottom: calc-rem(35);
}
.accordion {
border: 2px solid $slate;
}
.card-group {
border: 2px solid $slate;
padding-bottom: 0;
}
.card {
:host-context(.bg-off-white) {
background-color: $off-white;
}
&-header,
&-body,
&-footer {
background-color: $white;
::ng-deep .bg-off-white & {
background-color: $off-white;
}
}
&-body {
.video-description-text {
color: $blue;
@include font-scale(16, medium);
}
.list-group {
&-item {
border-bottom: 1px solid $slate !important;
padding: calc-rem(10) 0;
color: $blue;
background-color: transparent;
&:after {
content: none;
}
p {
color: $cool-grey;
@include font-size(16);
}
&:hover {
background-color: $blue;
padding-left: calc-rem(8);
color: $white;
&:hover {
text-decoration: none;
}
p {
color: $white;
}
}
}
.comp-link:last-child {
.list-group-item {
border-bottom: none !important;
}
}
}
}
&-footer {
.button-link {
width: 100%;
}
}
.accordion & {
margin-left: calc-rem(30);
margin-right: calc-rem(30);
border: none;
&:first-of-type,
&:not(:first-of-type):not(:last-of-type) {
border-bottom: 2px solid $slate;
}
&-header {
position: relative;
padding: calc-rem(30) 0;
border-bottom: none;
&-icon {
padding-right: calc-rem(25);
}
&-chevron {
text-align: right;
position: absolute;
top: 45%;
right: calc-rem(12);
@include font-size(12);
color: $blue;
font-style: normal;
}
.toggler {
color: $cool-grey;
display: block;
text-decoration: none;
&[aria-expanded=true] .icon-chevronDown {
display: none;
}
&[aria-expanded=false] .icon-chevronUp {
display: none;
}
}
}
&-body {
padding-left: 0;
padding-right: 0;
}
&-footer {
border: none;
text-align: center;
padding-bottom: calc-rem(60);
}
}
.card-group & {
border-bottom: none;
border-right: 2px solid $slate;
&:last-child {
border-right: none;
}
&-header {
padding: calc-rem(40) calc-rem(40) calc-rem(20) calc-rem(70);
border: none;
@include font-scale(20, bold);
&-icon {
position: absolute;
font-size: calc-rem(30);
transform: translate(-45px, -7px);
}
}
&-body {
padding-left: calc-rem(70);
padding-right: calc-rem(50);
}
&-footer {
border: none;
text-align: center;
padding-bottom: calc-rem(60);
padding-left: calc-rem(70);
padding-right: calc-rem(50);
}
}
}