File

C:/GoDev/src/TCSTK-Angular/projects/tibco-tcstk/tc-liveapps-lib/src/lib/components/live-apps-active-cases-for-type-report/live-apps-active-cases-for-type-report.component.ts

Description

Home page active cases widget sub component

Extends

LiveAppsComponent

Implements

OnInit OnChanges AfterViewChecked

Example

<tcla-live-apps-active-cases-for-type-report></tcla-live-apps-active-cases-for-type-report>

Metadata

selector tcla-live-apps-active-cases-for-type-report
styleUrls ./live-apps-active-cases-for-type-report.component.css
templateUrl ./live-apps-active-cases-for-type-report.component.html

Index

Properties
Methods
Inputs
Outputs
HostListeners
Accessors

Constructor

constructor(reportingService: TcLiveAppsReportingService)
Parameters :
Name Type Optional
reportingService TcLiveAppsReportingService No

Inputs

appId
Type : string

The LA Application Id

maxLegendItems
Type : number
sandboxId
Type : number

sandboxId - this comes from claims resolver

showPercentages
Type : boolean
typeId
Type : string

The LA Application Type Id (generally 1)

uiAppId
Type : string

The Application ID of the UI (should ideally be unique as it is shared state key)

Outputs

selectedCaseTypeState
Type : EventEmitter<CaseTypeStateReportStateInfo>

~event selectedCaseTypeState : Case Type state selected in vizualization ~payload CaseTypeStateReportStateInfo : CaseTypeStateReportStateInfo object selected from component (to drive caller to display something different (drill down))

HostListeners

window:resize
Arguments : '$event'
window:resize(event)
Inherited from LiveAppsComponent

Methods

Public chartClicked
chartClicked(undefined: literal type)
Parameters :
Name Type Optional
literal type No
Returns : void
Public chartHovered
chartHovered(undefined: literal type)
Parameters :
Name Type Optional
literal type No
Returns : void
ngAfterViewChecked
ngAfterViewChecked()
Returns : void
ngOnChanges
ngOnChanges(changes: SimpleChanges)
Parameters :
Name Type Optional
changes SimpleChanges No
Returns : void
ngOnInit
ngOnInit()
Returns : void
ngAfterViewInit
ngAfterViewInit()
Inherited from LiveAppsComponent
Returns : void
ngOnDestroy
ngOnDestroy()
Inherited from LiveAppsComponent
Returns : void
ngOnInit
ngOnInit()
Inherited from LiveAppsComponent
Returns : void
setupWidthObserver
setupWidthObserver()
Inherited from LiveAppsComponent
Returns : void

Properties

Public caseTypeStateReport
Type : CaseTypeStateReport
caseTypeStateReportChart
Type : BaseChartDirective
Decorators :
@ViewChild(BaseChartDirective, {static: false})
Public chartColors
Type : any[]
Default value : []
componentDiv
Type : ElementRef
Decorators :
@ViewChild('componentDiv', {static: false})
Public defaultColors
Type : string[]
Default value : DEFAULT_COLORS.slice().reverse()
Public doughnutChartData
Public doughnutChartOptions
Type : ChartOptions<doughnut>
Default value : { responsive: true, maintainAspectRatio: false, layout: { padding: { left: 0, right: 0, top: 10, bottom: 10 } }, plugins: { legend: { position: 'left' }, datalabels: { anchor: 'end', backgroundColor: function(context): string { return context?.dataset?.backgroundColor[context.dataIndex]; }, borderColor: 'white', borderRadius: 25, borderWidth: 2, color: 'white', display: function(context) { const dataset = context.dataset; const value = dataset.data[context.dataIndex]; return value > 0; }, font: { weight: 'bold' }, formatter: (value, ctx) => { const datasets = ctx.chart.data.datasets; if (datasets.indexOf(ctx.dataset) === datasets.length - 1) { if (this.showPercentages) { //@ts-ignore const sum = datasets[0].data.reduce((a, b) => a + b, 0); const percentage = Math.round((value / sum) * 100) + '%'; return percentage; } else { return value; } } else { return 0; } } } } }
Public doughnutChartType
Type : ChartType
Default value : 'doughnut'
Public errorMessage
Type : string
Private getCaseCount
Default value : () => {...}
Private initReportDataToChart
Default value : () => {...}
Public legendData
Type : any
Public maxLegendItems
Type : number
Default value : 8

Maximum rows to show in legend before it is hidden (otherwise would take whole widget)

Public refresh
Default value : () => {...}
Public renderChart
Default value : false
Public showPercentages
Type : boolean
Default value : false

Whether to show percentages or raw case numbers on the doughnut chart

Public totalActiveCaseCount
Type : number
Public widgetHeight
Type : number
Public widgetWidth
Type : number
Protected _destroyed$
Default value : new Subject()
Inherited from LiveAppsComponent
componentChildDivs
Type : LiveAppsComponent[]
Decorators :
@ViewChildren('componentChildDiv')
Inherited from LiveAppsComponent
componentDiv
Type : ElementRef
Decorators :
@ViewChild('componentDiv', {static: false})
Inherited from LiveAppsComponent
Protected containerChanges$
Type : Observable<TcComponent>
Inherited from LiveAppsComponent
Private observer
Inherited from LiveAppsComponent
Public resize
Default value : () => {...}
Inherited from LiveAppsComponent
Public widget
Type : TcComponent
Inherited from LiveAppsComponent

Accessors

MaxLegendItems
setMaxLegendItems(maxLegendItems: number)
Parameters :
Name Type Optional
maxLegendItems number No
Returns : void
ShowPercentages
setShowPercentages(showPercentages: boolean)
Parameters :
Name Type Optional
showPercentages boolean No
Returns : void
import {
  AfterViewChecked,
  Component,
  ElementRef,
  EventEmitter,
  Input,
  OnChanges,
  OnInit,
  Output,
  SimpleChanges,
  ViewChild
} from '@angular/core';
import {Chart, ChartConfiguration, ChartOptions, ChartType} from 'chart.js';
import {BaseChartDirective} from 'ng2-charts';
import {LiveAppsComponent} from '../live-apps-component/live-apps-component.component';
import {TcLiveAppsReportingService} from '../../services/tc-live-apps-reporting.service';
import {CaseTypeStateReport, CaseTypeStateReportStateInfo} from '../../models/tc-live-apps-reporting';
import {take, takeUntil} from 'rxjs/operators';
import {DEFAULT_COLORS, DEFAULT_TYPE_COLOR} from '../../services/tc-case-card-config.service';


/**
 * Home page active cases widget sub component
 *
 *@example <tcla-live-apps-active-cases-for-type-report></tcla-live-apps-active-cases-for-type-report>
 */
@Component({
  selector: 'tcla-live-apps-active-cases-for-type-report',
  templateUrl: './live-apps-active-cases-for-type-report.component.html',
  styleUrls: ['./live-apps-active-cases-for-type-report.component.css']
})
export class LiveAppsActiveCasesForTypeReportComponent extends LiveAppsComponent implements OnInit, OnChanges, AfterViewChecked {



  /**
   * sandboxId - this comes from claims resolver
   */
  @Input() sandboxId: number;

  /**
   * The LA Application Id
   */
  @Input() appId: string;

  /**
   * The LA Application Type Id (generally 1)
   */
  @Input() typeId: string;

  /**
   * The Application ID of the UI (should ideally be unique as it is shared state key)
   */
  @Input() uiAppId: string;

  /**
   * Maximum rows to show in legend before it is hidden (otherwise would take whole widget)
   */
  public maxLegendItems: number = 8;
  @Input('maxLegendItems') set MaxLegendItems(maxLegendItems: number) {
    if (maxLegendItems){
      this.maxLegendItems = maxLegendItems;
    }
  }

  /**
   * Whether to show percentages or raw case numbers on the doughnut chart
   */
  public showPercentages: boolean = false;
  @Input('showPercentages') set ShowPercentages(showPercentages: boolean) {
    if (showPercentages){
      this.showPercentages = showPercentages;
    }
  }

  /**
   * ~event selectedCaseTypeState : Case Type state selected in vizualization
   * ~payload CaseTypeStateReportStateInfo : CaseTypeStateReportStateInfo object selected from component (to drive caller to display something different (drill down))
   */
  @Output() selectedCaseTypeState: EventEmitter<CaseTypeStateReportStateInfo> = new EventEmitter<CaseTypeStateReportStateInfo>();

  @ViewChild(BaseChartDirective, {static: false}) caseTypeStateReportChart: BaseChartDirective;
  @ViewChild('componentDiv', {static: false}) componentDiv: ElementRef;

  public errorMessage: string;
  public caseTypeStateReport: CaseTypeStateReport;
  public renderChart = false;

  public doughnutChartData: ChartConfiguration<'doughnut'>['data'];
  public doughnutChartType: ChartType = 'doughnut';
  public chartColors: any[] = [];
  public defaultColors: string[] = DEFAULT_COLORS.slice().reverse();
  public widgetWidth: number;
  public widgetHeight: number;

  public legendData: any;
  public totalActiveCaseCount: number;

  private getCaseCount = () => {
    return this.totalActiveCaseCount;
  }

  public doughnutChartOptions: ChartOptions<'doughnut'> = {
    responsive: true,
    maintainAspectRatio: false,
    layout: {
      padding: {
        left: 0,
        right: 0,
        top: 10,
        bottom: 10
      }
    },
    plugins: {
      legend: {
        position: 'left'
      },
      datalabels: {
        anchor: 'end',
        backgroundColor: function(context): string {
          return context?.dataset?.backgroundColor[context.dataIndex];
        },
        borderColor: 'white',
        borderRadius: 25,
        borderWidth: 2,
        color: 'white',
        display: function(context) {
          const dataset = context.dataset;
          const value = dataset.data[context.dataIndex];
          return value > 0;
        },
        font: {
          weight: 'bold'
        },
        formatter: (value, ctx) => {

          const datasets = ctx.chart.data.datasets;

          if (datasets.indexOf(ctx.dataset) === datasets.length - 1) {
            if (this.showPercentages) {
              //@ts-ignore
              const sum = datasets[0].data.reduce((a, b) => a + b, 0);
              const percentage = Math.round((value / sum) * 100) + '%';
              return percentage;
            } else {
              return value;
            }
          } else {
            return 0;
          }
        }
      }

    }
  };

  constructor(protected reportingService: TcLiveAppsReportingService) {
    super();
  }

  private initReportDataToChart = (reportData: CaseTypeStateReport, status: string) => {
    this.doughnutChartData = {
      labels: [],
      datasets: []
    };
    this.totalActiveCaseCount = 0;
    const casesByStateArray: number[] = [];
    const labels: string[] = [];
    const colorArray: string[] = [];
    // remove any taken colors from the defaultColors
    // we have to do this before parsing the record to avoid getting same colors
    reportData.caseStates.forEach(cs => {
      // remove color from defaults
      if (cs.stateInfo.color) {
        this.defaultColors = this.defaultColors.filter(item => item !== cs.stateInfo.color);
      }
    });
    // parse record
    reportData.caseStates.forEach(caseState => {
        this.totalActiveCaseCount = this.totalActiveCaseCount + caseState.caseCount;
        casesByStateArray.push(caseState.caseCount);
        labels.push(caseState.stateInfo.label);
      // we will re-color anything that has the default color
      let col: string;
      if (caseState.stateInfo.color && caseState.stateInfo.color !== DEFAULT_TYPE_COLOR) {
        // use the set color
        col = caseState.stateInfo.color;
      } else {
        // try and get a color from the palette
        const palCol = this.defaultColors.pop();
        if (palCol) {
          col = palCol;
        } else {
          // if no more in palette use a random color!
          const i = Math.random() * 0xffffff;
          const p = parseInt(i.toString(), 0);
          col = '#' + p.toString(16);
        }
      }
      colorArray.push(col);
    });
    this.doughnutChartData.datasets.push({ data: casesByStateArray, backgroundColor: colorArray });
    this.doughnutChartData.labels = labels;
    this.chartColors.push( { backgroundColor: colorArray});
    // showing more than 8 in the legend will take up too much space
    this.doughnutChartOptions.plugins.legend.display = labels.length <= 8;
    this.renderChart = true;
  }

  public refresh = () => {
    this.reportingService.getCaseTypeStateReport(this.sandboxId, this.appId, this.typeId, false, this.uiAppId).pipe(
      take(1),
      takeUntil(this._destroyed$)
    )
      .subscribe(
        report => {
          this.caseTypeStateReport = report;
          this.initReportDataToChart(report, status);
          return report;
        }, error => { this.errorMessage = 'Error retrieving case types report: ' + error.error.errorMsg; }
      );
  }

  // events
  public chartClicked({ event, active }: { event: { chart: Chart, native: MouseEvent }, active: any }): void {
    if (active.length > 0) {
        this.selectedCaseTypeState.emit(this.caseTypeStateReport.caseStates[active[0].element.$context.dataIndex].stateInfo);
    }
  }

  public chartHovered({ event, active }: { event: MouseEvent, active: {}[] }): void {
    // console.log(event, active);
  }

  ngAfterViewChecked() {
    if (this.componentDiv && this.caseTypeStateReport && this.componentDiv.nativeElement.offsetWidth) {
      if (this.widgetWidth !== this.componentDiv.nativeElement.offsetWidth || this.widgetHeight !== this.componentDiv.nativeElement.offsetHeight) {
        this.widgetWidth = this.componentDiv.nativeElement.offsetWidth;
        this.widgetHeight = this.componentDiv.nativeElement.offsetHeight;
        this.caseTypeStateReportChart.chart.resize();
      }
    }
  }

  ngOnInit() {
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes.appId && (changes.firstChange || (changes.appId.currentValue !== changes.appId.previousValue))) {
      this.refresh();
    }
  }

}
<div #componentDiv fxLayout="column" fxFlex style="overflow: auto">
  <div *ngIf="renderChart" style="height:100%; width:100%; padding: 20px" class="relative">
    <canvas #caseReportChart baseChart
            [data]="doughnutChartData"
            [options]="doughnutChartOptions"
            [type]="doughnutChartType"
            (chartHover)="chartHovered($event)"
            (chartClick)="chartClicked($event)"
    >
    </canvas>
  </div>
</div>

./live-apps-active-cases-for-type-report.component.css

:host {
  height: 100%;
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""