import { Component, OnInit, Input, ChangeDetectorRef, forwardRef, OnDestroy } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormGroup } from '@angular/forms'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatButtonModule } from '@angular/material/button'; import { MatMenuModule } from '@angular/material/menu'; import { interval } from 'rxjs'; import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components'; import { Utils } from '@pega/angular-sdk-components'; import { ComponentMapperComponent } from '@pega/angular-sdk-components'; interface CaseViewProps { // If any, enter additional props that only exist on this component icon: string; subheader: string; header: string; } @Component({ selector: 'app-case-view', templateUrl: './case-view.component.html', styleUrls: ['./case-view.component.scss'], providers: [Utils], imports: [CommonModule, MatToolbarModule, MatButtonModule, MatMenuModule, forwardRef(() => ComponentMapperComponent)] }) export class CaseViewComponent implements OnInit, OnDestroy { @Input() pConn$: typeof PConnect; @Input() formGroup$: FormGroup; // Used with AngularPConnect angularPConnectData: AngularPConnectData = {}; configProps$: CaseViewProps; arChildren$: any[]; heading$ = ''; id$ = ''; status$ = ''; caseTabs$: any[] = []; svgCase$: string; tabData$: any; mainTabs: any; mainTabData: any; arAvailableActions$: any[] = []; arAvailabeProcesses$: any[] = []; caseSummaryPConn$: any; currentCaseID = ''; editAction: boolean; localizedVal: any; localeCategory = 'CaseView'; localeKey: string; constructor( private cdRef: ChangeDetectorRef, private angularPConnect: AngularPConnectService, private utils: Utils ) {} ngOnInit(): void { // First thing in initialization is registering and subscribing to the AngularPConnect service this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange); // this.updateSelf(); this.checkAndUpdate(); this.localizedVal = PCore.getLocaleUtils().getLocaleValue; } ngOnDestroy(): void { if (this.angularPConnectData.unsubscribeFn) { this.angularPConnectData.unsubscribeFn(); } } // Callback passed when subscribing to store change onStateChange() { this.checkAndUpdate(); } checkAndUpdate() { // Should always check the bridge to see if the component should update itself (re-render) const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this); // ONLY call updateSelf when the component should update // AND removing the "gate" that was put there since shouldComponentUpdate // should be the real "gate" if (bUpdateSelf) { // generally, don't want to refresh everything when data changes in caseView, it is usually the // case summary. But check if the case ID changes, this means a different case and we should // update all. if (this.hasCaseIDChanged()) { this.fullUpdate(); // update okToInitFlowContainer, because case view was drawn, flow container will need to be init // to match Nebula/Constellation sessionStorage.setItem('okToInitFlowContainer', 'true'); } else { this.updateHeaderAndSummary(); } } } hasCaseIDChanged(): boolean { if (this.currentCaseID !== this.pConn$.getDataObject().caseInfo.ID) { this.currentCaseID = this.pConn$.getDataObject().caseInfo.ID; return true; } return false; } updateHeaderAndSummary() { this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as CaseViewProps; const kids = this.pConn$.getChildren() as any[]; for (const kid of kids) { const meta = kid.getPConnect().getRawMetadata(); if (meta.type.toLowerCase() == 'region' && meta.name.toLowerCase() == 'summary') { this.caseSummaryPConn$ = kid.getPConnect().getChildren()[0].getPConnect(); } } // have to put in a timeout, otherwise get an angular change event error const timer = interval(100).subscribe(() => { timer.unsubscribe(); this.heading$ = this.pConn$.getLocalizationService().getLocalizedText(this.configProps$.header); this.id$ = this.configProps$.subheader; this.status$ = this.pConn$.getValue('.pyStatusWork'); }); } fullUpdate() { this.caseTabs$ = []; this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as CaseViewProps; // let caseTypeID = this.configProps$.ruleClass; // let caseTypeName = this.configProps$.header; // this.localeKey = `${caseTypeID}!CASE!${caseTypeName}`.toUpperCase(); this.localeKey = `${this.pConn$.getCaseInfo().getClassName()}!CASE!${this.pConn$.getCaseInfo().getName()}`.toUpperCase(); this.updateHeaderAndSummary(); this.arChildren$ = this.pConn$.getChildren() as any[]; const caseInfo = this.pConn$.getDataObject().caseInfo; this.currentCaseID = caseInfo.ID; this.arAvailableActions$ = caseInfo?.availableActions ? caseInfo.availableActions : []; this.editAction = this.arAvailableActions$.find(action => action.ID === 'pyUpdateCaseDetails'); this.arAvailabeProcesses$ = caseInfo?.availableProcesses ? caseInfo.availableProcesses : []; this.svgCase$ = this.utils.getImageSrc(this.configProps$.icon, this.utils.getSDKStaticContentUrl()); for (const kid of this.arChildren$) { const kidPConn = kid.getPConnect(); if (kidPConn.getRawMetadata().name == 'Tabs') { this.mainTabs = kid; this.mainTabData = this.mainTabs.getPConnect().getChildren(); } } this.generateTabsData(); } generateTabsData() { this.mainTabs .getPConnect() .getChildren() ?.forEach((child, i) => { const config = child.getPConnect().resolveConfigProps(child.getPConnect().getRawMetadata()).config; let { label } = config; const { inheritedProps, visibility } = config; // For some tabs, "label" property is not avaialable in theTabCompConfig, so will get them from inheritedProps if (!label) { inheritedProps.forEach((inheritedProp: any) => { if (inheritedProp.prop === 'label') { label = inheritedProp.value; } }); } // We'll display the tabs when either visibility property doesn't exist or is true(if exists) if (visibility === undefined || visibility === true) { this.caseTabs$.push({ name: label, id: i }); // To make first visible tab display at the beginning if (!this.tabData$) { this.tabData$ = { type: 'DeferLoad', config: child.getPConnect().getRawMetadata().config }; } } }); } updateSelf() { this.fullUpdate(); } onTabClick(tab: any) { this.tabData$ = this.mainTabData[tab].getPConnect().getRawMetadata(); this.cdRef.detectChanges(); } _editClick() { const editAction = this.arAvailableActions$.find(action => action.ID === 'pyUpdateCaseDetails'); const actionsAPI = this.pConn$.getActionsApi(); const openLocalAction = actionsAPI.openLocalAction.bind(actionsAPI); openLocalAction(editAction.ID, { ...editAction, containerName: 'modal', type: 'express' }); } _menuActionClick(data) { const actionsAPI = this.pConn$.getActionsApi(); const openLocalAction = actionsAPI.openLocalAction.bind(actionsAPI); openLocalAction(data.ID, { ...data, containerName: 'modal', type: 'express' }); } _menuProcessClick(data) { const actionsAPI = this.pConn$.getActionsApi(); const openProcessAction = actionsAPI.openProcessAction.bind(actionsAPI); openProcessAction(data.ID, { ...data }); } }