1430 lines
32 KiB
TypeScript
1430 lines
32 KiB
TypeScript
import {
|
|
Component,
|
|
ViewChild,
|
|
ElementRef,
|
|
HostListener,
|
|
ChangeDetectionStrategy,
|
|
} from '@angular/core';
|
|
import {
|
|
nameof,
|
|
XMimeType,
|
|
downloadFile,
|
|
generateUuid,
|
|
downloadFileByUrl,
|
|
isNullOrUndefined,
|
|
isNullOrEmptyString,
|
|
downloadArrayBufferedFile,
|
|
} from 'x-framework-core';
|
|
import {
|
|
isChartType,
|
|
XChartAction,
|
|
XChartOptions,
|
|
XChartSeriesType,
|
|
XChartActionBarItem,
|
|
XChartContainerComponent,
|
|
} from './x-chart.typings';
|
|
import { Subscription } from 'rxjs';
|
|
import ApexCharts from 'apexcharts';
|
|
import {
|
|
XActionBarItem,
|
|
XActionBarItemSlot,
|
|
XActionBarActionFiredModel,
|
|
} from '../x-action-bar/x-action-bar.typings';
|
|
import { XIconNames } from '../x-icon/x-icon.typings';
|
|
|
|
@Component({
|
|
selector: 'x-chart',
|
|
templateUrl: './x-chart.component.html',
|
|
styleUrls: ['./x-chart.component.scss'],
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
})
|
|
export class XChartComponent extends XChartContainerComponent {
|
|
//
|
|
//#region Props ...
|
|
//
|
|
private CHART_CONTAINER: ElementRef | undefined;
|
|
|
|
@ViewChild('chartContainer', { static: false })
|
|
set chartContainer(el: ElementRef | undefined) {
|
|
//
|
|
if (isNullOrUndefined(el)) {
|
|
//
|
|
this.destroyComponent();
|
|
return;
|
|
}
|
|
|
|
//
|
|
this.CHART_CONTAINER = el;
|
|
this.initializeComponent();
|
|
}
|
|
|
|
get chartContainer() {
|
|
return this.CHART_CONTAINER;
|
|
}
|
|
|
|
//
|
|
@HostListener('resize', ['$event'])
|
|
onResize(event: any) {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
// this.chartInstance.updateOptions();
|
|
}
|
|
|
|
//
|
|
private CHART_OPTIONS: XChartOptions = null;
|
|
|
|
//
|
|
private chartInstance: ApexCharts = null;
|
|
|
|
//
|
|
private ACTION_PROVIDER_SUBSCRIPTION: Subscription;
|
|
|
|
//
|
|
readonly IconNames = Object.assign({}, XIconNames);
|
|
readonly ActionBarItems = Object.assign({}, XChartActionBarItem);
|
|
readonly ActionBarItemSlots = Object.assign({}, XActionBarItemSlot);
|
|
//#endregion
|
|
|
|
//
|
|
//#region LifeCycles ...
|
|
async afterViewInit() {
|
|
super.afterViewInit();
|
|
|
|
//
|
|
await this.initializeComponent();
|
|
}
|
|
|
|
async onChange(changeKeys: string[]) {
|
|
super.onChange(changeKeys);
|
|
|
|
//
|
|
// Auto Update ...
|
|
const isAutoUpdateChanged = changeKeys.includes(
|
|
nameof<XChartComponent>('autoUpdate'),
|
|
);
|
|
if (isAutoUpdateChanged) {
|
|
//
|
|
if (isNullOrUndefined(this.autoUpdate)) {
|
|
this.autoUpdate = this.propertyProvider.autoUpdate;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Action Provider Changed ...
|
|
const isActionProviderChanged = changeKeys.includes(
|
|
nameof<XChartComponent>('actionProvider'),
|
|
);
|
|
if (isActionProviderChanged) {
|
|
this.registerActionProvider();
|
|
}
|
|
|
|
//
|
|
// Available Action Bar Items Changed ...
|
|
const isAvailableActionBarItemsChanged = changeKeys.includes(
|
|
nameof<XChartComponent>('availableActionBarItems')
|
|
);
|
|
if (isAvailableActionBarItemsChanged) {
|
|
//
|
|
if (isNullOrUndefined(this.availableActionBarItems)) {
|
|
this.availableActionBarItems = this.propertyProvider.availableActionBarItems;
|
|
}
|
|
|
|
//
|
|
await this.prepareActionBar();
|
|
}
|
|
|
|
//
|
|
// Zoom Step ...
|
|
const isZoomStepChanged = changeKeys.includes(
|
|
nameof<XChartComponent>('zoomStep')
|
|
);
|
|
if (isZoomStepChanged) {
|
|
//
|
|
let zoomStep = await this.getValueAsync(this.zoomStep);
|
|
if (isNullOrUndefined(zoomStep) ||
|
|
zoomStep < 0 ||
|
|
zoomStep > 1
|
|
) {
|
|
this.zoomStep = 0.125;
|
|
}
|
|
|
|
//
|
|
zoomStep = await this.getValueAsync(this.zoomStep);
|
|
}
|
|
|
|
//
|
|
// Check Auto Update ...
|
|
var autoUpdate = await this.getValueAsync(this.autoUpdate);
|
|
if (
|
|
autoUpdate &&
|
|
!isNullOrUndefined(this.chartInstance) &&
|
|
!isNullOrUndefined(this.chartContainer) &&
|
|
!isNullOrUndefined(this.chartContainer.nativeElement)
|
|
) {
|
|
//
|
|
// Options Changed ...
|
|
const isOptionsChanged = changeKeys.includes(
|
|
nameof<XChartComponent>('options'),
|
|
);
|
|
if (isOptionsChanged) {
|
|
//
|
|
if (isNullOrUndefined(this.options)) {
|
|
this.options = this.propertyProvider.options;
|
|
}
|
|
|
|
//
|
|
await this.handleChartUpdate();
|
|
}
|
|
|
|
//
|
|
// Chart Type ...
|
|
const isTypeChanged = changeKeys.includes(
|
|
nameof<XChartComponent>('type'),
|
|
);
|
|
if (isTypeChanged) {
|
|
//
|
|
if (isNullOrUndefined(this.type)) {
|
|
this.type = this.propertyProvider.type;
|
|
}
|
|
|
|
//
|
|
var type = await this.getValueAsync(this.type);
|
|
if (!isChartType(type)) {
|
|
//
|
|
type = await this.getValueAsync(this.propertyProvider.type);
|
|
this.type = type;
|
|
}
|
|
|
|
//
|
|
await this.handleChartUpdate();
|
|
}
|
|
|
|
//
|
|
// Series Changed ...
|
|
const isSeriesChanged = changeKeys.includes(
|
|
nameof<XChartComponent>('series'),
|
|
);
|
|
if (isSeriesChanged) {
|
|
//
|
|
if (isNullOrUndefined(this.series)) {
|
|
this.series = this.propertyProvider.series;
|
|
}
|
|
|
|
//
|
|
await this.handleChartUpdate();
|
|
}
|
|
}
|
|
|
|
//
|
|
this.detectChanges();
|
|
}
|
|
|
|
onDestroy() {
|
|
super.onDestroy();
|
|
|
|
//
|
|
this.destroyComponent();
|
|
this.unregisterActionProvider();
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region UI Handler ...
|
|
async handleActionBarActionFired(model: XActionBarActionFiredModel) {
|
|
//
|
|
if (isNullOrUndefined(model) || isNullOrEmptyString(model.action)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
switch (model.action) {
|
|
//
|
|
// Print ...
|
|
case XChartActionBarItem.Print:
|
|
await this.handlePrint();
|
|
break;
|
|
|
|
//
|
|
// Export As CSV ...
|
|
case XChartActionBarItem.ExportAsCSV:
|
|
await this.handleExportAsCSV();
|
|
break;
|
|
|
|
//
|
|
// Export As PNG ...
|
|
case XChartActionBarItem.ExportAsPNG:
|
|
await this.handleExportAsPng();
|
|
break;
|
|
|
|
//
|
|
// Export As SVG ...
|
|
case XChartActionBarItem.ExportAsSVG:
|
|
await this.handleExportAsSVG();
|
|
break;
|
|
|
|
//
|
|
// Zoom In ...
|
|
case XChartActionBarItem.ZoomIn:
|
|
await this.handleZoomIn();
|
|
break;
|
|
|
|
//
|
|
// Zoom Out ...
|
|
case XChartActionBarItem.ZoomOut:
|
|
await this.handleZoomOut();
|
|
break;
|
|
|
|
//
|
|
// Zoom Selection ...
|
|
case XChartActionBarItem.ZoomSelection:
|
|
break;
|
|
|
|
//
|
|
// X Selection ...
|
|
case XChartActionBarItem.XSelection:
|
|
break;
|
|
|
|
//
|
|
// Y Selection ...
|
|
case XChartActionBarItem.YSelection:
|
|
break;
|
|
|
|
//
|
|
// XY Selection ...
|
|
case XChartActionBarItem.XYSelection:
|
|
break;
|
|
|
|
//
|
|
// Pan ...
|
|
case XChartActionBarItem.Pan:
|
|
await this.handlePan();
|
|
break;
|
|
|
|
//
|
|
// ResetChart ...
|
|
case XChartActionBarItem.ResetChart:
|
|
await this.handleResetChart();
|
|
break;
|
|
|
|
//
|
|
// ToggleFullScreen ...
|
|
case XChartActionBarItem.ToggleFullScreen:
|
|
await this.handleToggleFullscreen();
|
|
break;
|
|
|
|
//
|
|
}
|
|
|
|
//
|
|
this.actionBarActionFired.emit(model);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Actions ...
|
|
/**
|
|
* Export Chart Data in Specified Format ...
|
|
*
|
|
* @param format Export Format ...
|
|
* @param fileName Provided File Name without Extension ...
|
|
*/
|
|
async export(format: 'png' | 'svg' | 'csv' = 'png', fileName: string = '') {
|
|
//
|
|
// Normalize File Name ...
|
|
if (isNullOrEmptyString(fileName)) {
|
|
fileName = generateUuid('XChart');
|
|
}
|
|
|
|
//
|
|
fileName += '.' + format;
|
|
|
|
//
|
|
switch (format) {
|
|
//
|
|
case 'png':
|
|
//
|
|
const dataObject = await this.chartInstance.dataURI();
|
|
|
|
//
|
|
if ('imgURI' in dataObject) {
|
|
downloadFileByUrl(dataObject.imgURI, fileName);
|
|
} else if ('blob' in dataObject) {
|
|
downloadArrayBufferedFile(fileName, dataObject.blob);
|
|
}
|
|
break;
|
|
|
|
//
|
|
case 'svg':
|
|
//
|
|
const svgString = this.chartInstance.exports.exportToSVG();
|
|
downloadFile(svgString, XMimeType.ImageSVG, fileName);
|
|
break;
|
|
|
|
//
|
|
case 'csv':
|
|
//
|
|
this.chartInstance.exports.exportToCSV({
|
|
fileName: fileName,
|
|
columnDelimiter: ',',
|
|
lineDelimiter: '\n',
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Toolbar Actions ...
|
|
async handleExportAsPng() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
await this.export('png');
|
|
}
|
|
|
|
async handleExportAsSVG() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
await this.export('svg');
|
|
}
|
|
|
|
async handleExportAsCSV() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
await this.export('csv');
|
|
}
|
|
|
|
async handleZoomIn() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
var zoomStep = await this.getValueAsync(this.zoomStep);
|
|
|
|
//
|
|
const state = this.chartInstance.getState();
|
|
const minX = state.minX;
|
|
const maxX = state.maxX;
|
|
const rangeIn = maxX - minX;
|
|
|
|
//
|
|
await this.chartInstance.zoomX(minX + rangeIn * zoomStep, maxX - rangeIn * zoomStep);
|
|
}
|
|
|
|
async handleZoomOut() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
var zoomStep = await this.getValueAsync(this.zoomStep);
|
|
|
|
//
|
|
const state = this.chartInstance.getState();
|
|
const minX = state.minX;
|
|
const maxX = state.maxX;
|
|
const rangeIn = maxX - minX;
|
|
|
|
//
|
|
await this.chartInstance.zoomX(minX - rangeIn * zoomStep, maxX + rangeIn * zoomStep);
|
|
}
|
|
|
|
async handlePan() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
await this.chartInstance.updateOptions({
|
|
chart: {
|
|
zoom: {
|
|
enabled: false
|
|
},
|
|
selection: {
|
|
type: 'x',
|
|
enabled: true,
|
|
},
|
|
}
|
|
});
|
|
}
|
|
|
|
async handleResetChart() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
this.chartInstance.resetSeries(true, true);
|
|
}
|
|
|
|
async handlePrint() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
try {
|
|
//
|
|
const result = await this.chartInstance.dataURI();
|
|
if ('imgURI' in result) {
|
|
//
|
|
const imgURI = result.imgURI;
|
|
const printWindow = window.open('', '_blank');
|
|
if (printWindow) {
|
|
//
|
|
// Write Data Uri on a Page for Printing ...
|
|
printWindow.document.write(`
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Print Chart</title>
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
padding: 20px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
min-height: 100vh;
|
|
}
|
|
img {
|
|
max-width: 100%;
|
|
height: auto;
|
|
}
|
|
@media print {
|
|
body {
|
|
margin: 0;
|
|
}
|
|
img {
|
|
max-width: 100%;
|
|
page-break-inside: avoid;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<img src="${imgURI}" alt="Chart" />
|
|
<script>
|
|
window.onload = function() {
|
|
window.print();
|
|
window.onafterprint = function() {
|
|
window.close();
|
|
};
|
|
};
|
|
</script>
|
|
</body>
|
|
</html>
|
|
`);
|
|
|
|
//
|
|
printWindow.document.close();
|
|
}
|
|
}
|
|
} catch (error) {
|
|
}
|
|
}
|
|
|
|
async handleToggleFullscreen() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance) ||
|
|
isNullOrUndefined(this.chartContainer) ||
|
|
isNullOrUndefined(this.chartContainer.nativeElement)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
const chartWrapper =
|
|
this.chartContainer.nativeElement;
|
|
const doc = document as any;
|
|
|
|
//
|
|
// Check if the chart wrapper is currently in fullscreen mode
|
|
const isFullscreen =
|
|
doc.fullscreenElement === chartWrapper ||
|
|
doc.msFullscreenElement === chartWrapper ||
|
|
doc.mozFullScreenElement === chartWrapper ||
|
|
doc.webkitFullscreenElement === chartWrapper;
|
|
if (!isFullscreen) {
|
|
//
|
|
// Enter Fullscreen
|
|
if (chartWrapper.requestFullscreen) {
|
|
await chartWrapper.requestFullscreen();
|
|
} else if (chartWrapper.webkitRequestFullscreen) {
|
|
await chartWrapper.webkitRequestFullscreen();
|
|
} else if (chartWrapper.mozRequestFullScreen) {
|
|
await chartWrapper.mozRequestFullScreen();
|
|
} else if (chartWrapper.msRequestFullscreen) {
|
|
await chartWrapper.msRequestFullscreen();
|
|
}
|
|
} else {
|
|
//
|
|
// Exit Fullscreen
|
|
if (doc.exitFullscreen) {
|
|
await doc.exitFullscreen();
|
|
} else if (doc.webkitExitFullscreen) {
|
|
await doc.webkitExitFullscreen();
|
|
} else if (doc.mozCancelFullScreen) {
|
|
await doc.mozCancelFullScreen();
|
|
} else if (doc.msExitFullscreen) {
|
|
await doc.msExitFullscreen();
|
|
}
|
|
}
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Private ...
|
|
private async initializeComponent() {
|
|
//
|
|
if (isNullOrUndefined(this.CHART_CONTAINER)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Reading Requirement Properties ...
|
|
const type = await this.getValueAsync(this.type);
|
|
const chartId = await this.getValueAsync(this.uuid);
|
|
const series = await this.getValueAsync(this.series);
|
|
const options = await this.getValueAsync(this.options);
|
|
|
|
//
|
|
const computedStyle = getComputedStyle(document.documentElement);
|
|
const primaryColor =
|
|
computedStyle.getPropertyValue('--x-color-primary').trim() || '#008ffb';
|
|
const textColor =
|
|
computedStyle.getPropertyValue('--x-color-dark-contrast').trim() ||
|
|
'#373d3f';
|
|
const gridColor =
|
|
computedStyle.getPropertyValue('--x-color-light-shade').trim() ||
|
|
'#e0e0e0';
|
|
|
|
//
|
|
this.CHART_OPTIONS = {
|
|
...options,
|
|
series: series || options.series,
|
|
chart: {
|
|
...options.chart,
|
|
id: chartId,
|
|
type: type as any,
|
|
foreColor: textColor,
|
|
toolbar: {
|
|
show: false,
|
|
autoSelected: 'pan',
|
|
},
|
|
events: {
|
|
...options.chart?.events,
|
|
mounted: (chartContext, config) => {
|
|
this.chartRendered.emit();
|
|
options.chart?.events?.mounted?.(chartContext, config);
|
|
},
|
|
dataPointSelection: (event, chartContext, config) => {
|
|
this.dataPointSelected.emit({ event, chartContext, config });
|
|
options.chart?.events?.dataPointSelection?.(
|
|
event,
|
|
chartContext,
|
|
config,
|
|
);
|
|
},
|
|
zoomed: (chartContext, { xaxis, yaxis }) => {
|
|
this.zoomed.emit({ xaxis, yaxis });
|
|
options.chart?.events?.zoomed?.(chartContext, { xaxis, yaxis });
|
|
},
|
|
},
|
|
},
|
|
theme: {
|
|
...options.theme,
|
|
palette: options.theme?.palette || 'palette1',
|
|
},
|
|
colors: options.colors || [primaryColor],
|
|
grid: {
|
|
...options.grid,
|
|
borderColor: gridColor,
|
|
},
|
|
};
|
|
|
|
//
|
|
this.chartInstance = new ApexCharts(
|
|
this.chartContainer.nativeElement,
|
|
this.CHART_OPTIONS,
|
|
);
|
|
|
|
//
|
|
await this.prepareActionBar();
|
|
|
|
//
|
|
await this.chartInstance.render();
|
|
}
|
|
|
|
private async prepareActionBar() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
const showActionBar = await this.getValueAsync(this.showActionBar);
|
|
if (!showActionBar) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
//#region DefaultActionBarActions ...
|
|
//
|
|
// Reset ...
|
|
const defaultResetItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
icon: this.IconNames.refresh,
|
|
title: this.ResourceIDs.reset,
|
|
slot: this.ActionBarItemSlots.END,
|
|
id: this.ActionBarItems.ResetChart,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Print ...
|
|
const defaultPrintItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
icon: this.IconNames.print,
|
|
title: this.ResourceIDs.print,
|
|
id: this.ActionBarItems.Print,
|
|
slot: this.ActionBarItemSlots.END,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Export As PNG ...
|
|
const defaultExportPNGItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
icon: this.IconNames.png,
|
|
disabled: this.uiDisabled,
|
|
slot: this.ActionBarItemSlots.END,
|
|
title: this.ResourceIDs.export_png,
|
|
id: this.ActionBarItems.ExportAsPNG,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Export as SVG ...
|
|
const defaultExportSVGItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
icon: this.IconNames.image,
|
|
disabled: this.uiDisabled,
|
|
slot: this.ActionBarItemSlots.END,
|
|
title: this.ResourceIDs.export_svg,
|
|
id: this.ActionBarItems.ExportAsSVG,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Export as CSV ...
|
|
const defaultExportCSVItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
icon: this.IconNames.csv,
|
|
disabled: this.uiDisabled,
|
|
slot: this.ActionBarItemSlots.END,
|
|
title: this.ResourceIDs.export_csv,
|
|
id: this.ActionBarItems.ExportAsCSV,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Zoom In ...
|
|
const defaultZoomInItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
icon: this.IconNames.zoom_in,
|
|
id: this.ActionBarItems.ZoomIn,
|
|
title: this.ResourceIDs.zoom_in,
|
|
slot: this.ActionBarItemSlots.START,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Zoom Out ...
|
|
const defaultZoomOutItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
icon: this.IconNames.zoom_out,
|
|
id: this.ActionBarItems.ZoomOut,
|
|
title: this.ResourceIDs.zoom_out,
|
|
slot: this.ActionBarItemSlots.START,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Zoom Selection ...
|
|
const defaultZoomSelectionItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
slot: this.ActionBarItemSlots.START,
|
|
icon: this.IconNames.range_selection,
|
|
id: this.ActionBarItems.ZoomSelection,
|
|
title: this.ResourceIDs.zoom_selection,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// X Axis Selection ...
|
|
const defaultXAxisSelectionItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
icon: this.IconNames.x_axis,
|
|
title: this.ResourceIDs.x_axis,
|
|
id: this.ActionBarItems.XSelection,
|
|
slot: this.ActionBarItemSlots.START,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Y Axis Selection ...
|
|
const defaultYAxisSelectionItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
icon: this.IconNames.y_axis,
|
|
title: this.ResourceIDs.y_axis,
|
|
id: this.ActionBarItems.YSelection,
|
|
slot: this.ActionBarItemSlots.START,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// XY Axis Selection ...
|
|
const defaultXYAxisSelectionItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
icon: this.IconNames.xy_axis,
|
|
title: this.ResourceIDs.xy_axis,
|
|
id: this.ActionBarItems.XYSelection,
|
|
slot: this.ActionBarItemSlots.START,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Pan ...
|
|
const defaultPanItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
icon: this.IconNames.touch,
|
|
title: this.ResourceIDs.pan,
|
|
id: this.ActionBarItems.Pan,
|
|
slot: this.ActionBarItemSlots.START,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
|
|
//
|
|
// Toggle Full Screen ...
|
|
const defaultFullscreenItem: XActionBarItem = {
|
|
onlyIcon: true,
|
|
disabled: this.uiDisabled,
|
|
icon: this.IconNames.fullscreen,
|
|
title: this.ResourceIDs.full_screen,
|
|
slot: this.ActionBarItemSlots.START,
|
|
id: this.ActionBarItems.ToggleFullScreen,
|
|
iconColor: this.defaultActionBarItemColor,
|
|
};
|
|
//#endregion
|
|
|
|
//
|
|
this.actionBarActions = [];
|
|
this.detectChanges();
|
|
|
|
//
|
|
const availableItems = await this.getArrayValueAsync(
|
|
this.availableActionBarItems,
|
|
);
|
|
if (!this.hasChild(availableItems)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
let hasItem = false;
|
|
const actionBarItems: XActionBarItem[] = [];
|
|
|
|
//
|
|
//#region Print ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.Print);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.Print,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultPrintItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region ExportAsPNG ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.ExportAsPNG);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.ExportAsPNG,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultExportPNGItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region ExportAsSVG ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.ExportAsSVG);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.ExportAsSVG,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultExportSVGItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region ExportAsCSV ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.ExportAsCSV);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.ExportAsCSV,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultExportCSVItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region ZoomIn ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.ZoomIn);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.ZoomIn,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultZoomInItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region ZoomOut ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.ZoomOut);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.ZoomOut,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultZoomOutItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region ZoomSelection ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.ZoomSelection);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.ZoomSelection,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultZoomSelectionItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region XSelection ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.XSelection);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.XSelection,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultXAxisSelectionItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region YSelection ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.YSelection);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.YSelection,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultYAxisSelectionItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region XYSelection ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.XYSelection);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.XYSelection,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultXYAxisSelectionItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Pan ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.Pan);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.Pan,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultPanItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Reset ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.ResetChart);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.ResetChart,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultResetItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region FullScreen ...
|
|
hasItem = availableItems
|
|
.map((ai) => ai.actionId)
|
|
.includes(this.ActionBarItems.ToggleFullScreen);
|
|
|
|
//
|
|
if (hasItem) {
|
|
//
|
|
const selectedItem = availableItems.find(
|
|
(ai) => ai.actionId === this.ActionBarItems.ToggleFullScreen,
|
|
);
|
|
const providedItem = selectedItem.descriptor;
|
|
let item = {
|
|
...defaultFullscreenItem,
|
|
};
|
|
if (!isNullOrUndefined(providedItem)) {
|
|
item = {
|
|
...item,
|
|
...providedItem,
|
|
};
|
|
}
|
|
|
|
//
|
|
item = {
|
|
...item,
|
|
disabled: this.uiDisabled,
|
|
};
|
|
|
|
//
|
|
actionBarItems.push(item);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
this.actionBarActions = [...actionBarItems];
|
|
this.detectChanges();
|
|
}
|
|
|
|
private async handleChartUpdate() {
|
|
//
|
|
if (
|
|
isNullOrUndefined(this.chartInstance) ||
|
|
isNullOrUndefined(this.CHART_OPTIONS) ||
|
|
isNullOrUndefined(this.chartContainer) ||
|
|
isNullOrUndefined(this.chartContainer.nativeElement)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Reading Requirement Properties ...
|
|
const type = await this.getValueAsync(this.type);
|
|
const series = await this.getValueAsync(this.series);
|
|
|
|
//
|
|
const options = await this.getValueAsync(this.options);
|
|
this.CHART_OPTIONS = {
|
|
...options,
|
|
...this.CHART_OPTIONS,
|
|
chart: {
|
|
...this.CHART_OPTIONS.chart,
|
|
type: type as any,
|
|
},
|
|
};
|
|
|
|
//
|
|
await this.chartInstance.updateOptions(this.CHART_OPTIONS);
|
|
await this.chartInstance.updateSeries(series);
|
|
}
|
|
|
|
private destroyComponent() {
|
|
//
|
|
if (isNullOrUndefined(this.chartInstance)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
this.chartInstance.destroy();
|
|
this.chartInstance = null;
|
|
}
|
|
|
|
private registerActionProvider() {
|
|
//
|
|
this.unregisterActionProvider();
|
|
|
|
//
|
|
if (!this.actionProvider) {
|
|
this.actionProvider = this.propertyProvider.actionProvider;
|
|
}
|
|
|
|
//
|
|
this.ACTION_PROVIDER_SUBSCRIPTION = this.actionProvider
|
|
.asObservable()
|
|
.subscribe(async (model) => {
|
|
//
|
|
switch (model.action) {
|
|
//
|
|
case XChartAction.Refresh:
|
|
this.detectChanges();
|
|
break;
|
|
|
|
//
|
|
case XChartAction.Destroy:
|
|
this.onDestroy();
|
|
break;
|
|
|
|
//
|
|
case XChartAction.UpdateSeries:
|
|
//
|
|
if (
|
|
!isNullOrUndefined(model.payload) ||
|
|
!isNullOrUndefined(this.chartInstance)
|
|
) {
|
|
//
|
|
this.series = await this.getValueAsync(
|
|
model.payload as XChartSeriesType,
|
|
);
|
|
await this.chartInstance.updateSeries(this.series);
|
|
this.detectChanges();
|
|
}
|
|
break;
|
|
|
|
//
|
|
case XChartAction.UpdateOptions:
|
|
//
|
|
if (
|
|
!isNullOrUndefined(model.payload) ||
|
|
!isNullOrUndefined(this.chartInstance)
|
|
) {
|
|
//
|
|
this.options = await this.getValueAsync(
|
|
model.payload as XChartOptions,
|
|
);
|
|
await this.chartInstance.updateOptions(this.options);
|
|
this.detectChanges();
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
private unregisterActionProvider() {
|
|
//
|
|
if (!this.ACTION_PROVIDER_SUBSCRIPTION) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
this.ACTION_PROVIDER_SUBSCRIPTION.unsubscribe();
|
|
this.ACTION_PROVIDER_SUBSCRIPTION = null;
|
|
}
|
|
//#endregion
|
|
}
|