// SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2018 Georgi Marinov // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import { Injectable } from '@angular/core'; import { ChartConfiguration, ChartData, ChartType, ChartTypeRegistry, ScaleOptionsByType, Tick } from 'chart.js'; import { DeepPartial } from '../../types/chart-js-hacks'; import { Indexable } from '../../interfaces/indexable'; import { GanttChartEntry } from '../../classes/gantt-chart-entry/gantt-chart-entry'; import { StringExService } from '../string-ex/string-ex.service'; import { ChartService } from '../chart/chart.service'; import { ChartColorService } from '../../services/chart-color/chart-color.service'; import { ChartModel } from '../../model/chart/chart.model'; import { UiService } from '../../services/ui/ui.service'; /** * A gantt chart diagram service. * ~extends {@link ChartService} */ @Injectable({ providedIn: 'root' }) export class GanttChartService extends ChartService { /** All background items shown. */ protected items = []; /** The current context-relevant items. */ protected filteredItems = []; /** The X-axis range. */ public optionsScalesXAxes0Ticks = { min: 34700, max: 43831 + Math.floor(5 * 365.25) }; /** * Constructs the Gantt chart service. * ~constructor * * @param chartColorService The chart color service injected dependency. * @param chartModel The chart model injected dependency. * @param uiService The ui service injected dependency. */ constructor( protected override readonly chartColorService: ChartColorService, public override readonly chartModel: ChartModel, public override readonly uiService: UiService, ) { super(chartColorService, chartModel, uiService); } /** * The current context data. * * @returns A Data object. */ public get data(): ChartData { return { datasets: [{ ...this.backgroundColor(), ...this.borderColor('#00000000'), fill: false, borderWidth: 0, pointRadius: 0, barPercentage: 1.2, data: this.items.map((_: any) => _.From) }, { backgroundColor: this.items.map((_: any) => this.filteredItems.filter((__: GanttChartEntry) => __.Id === _.Id).length > 0 ? _.Color : '#00000020'), hoverBackgroundColor: this.items.map((_: any) => _.Color), ...this.borderColor(), fill: false, borderWidth: 1, pointRadius: 0, barPercentage: 1.2, data: this.items.map((_: any) => _.To - _.From) }], labels: this.items.map((_: any) => _['Project name']) }; } /** * The chart configuration. * * @returns A ChartConfiguration object. */ protected override get chartConfiguration(): DeepPartial { const ttype: ChartType = 'bar'; const chartConfiguration: ChartConfiguration = { type: ttype, options: { indexAxis: 'y', responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: this.tooltip() as any, }, scales: this.scales, }, data: this.data, }; // tslint:disable-next-line: no-non-null-assertion chartConfiguration.options!.plugins!.tooltip!.callbacks!.title = (_) => ''; // tslint:disable-next-line: no-non-null-assertion chartConfiguration.options!.plugins!.tooltip!.callbacks!.label = (tooltipItem) => StringExService.splitLine(tooltipItem.label); return chartConfiguration; } /** * The scales. * * @returns A scales object. */ private get scales(): DeepPartial>> { return { x: { type: 'linear', position: 'bottom', beginAtZero: false, min: this.optionsScalesXAxes0Ticks.min, max: this.optionsScalesXAxes0Ticks.max, ticks: { stepSize: 365.24 / 4, callback: this.ticks, font: { size: 12 } }, grid: {}, stacked: true }, y: { title: { display: true }, ticks: { mirror: true, font: { lineHeight: 1, size: 12 } }, grid: { display: false }, stacked: true } }; } /** * The ticks. * * @returns A ticks object. */ // tslint:disable-next-line: variable-name private ticks(tickValue: number | string, index: number, _ticks: Tick[]) { if (index % 4 === 0) { const dateValueFromExcel = (tickValue as number - (25567 + 1)) * 86400 * 1000; const dateFromExcel = new Date(dateValueFromExcel); return dateFromExcel.getFullYear(); } else { return ''; } } /** * Adds a gantt chart. * * @param items The background items shown. * @param filteredItems The current context-relevant items. * * @returns A ChartConfiguration object. */ public override addChart(items: any, filteredItems: any): DeepPartial { this.items = items; this.filteredItems = filteredItems; return this.chartConfiguration; } }