...
Code Block | ||
---|---|---|
| ||
interface IChart extends IBase {
readonly reportType: IReportType = "chart"
readonly _defaultConfig: IChartConfig; // default config for tooltips colors legend etc.
config: IChartConfig;
chartClick: EventEmitter<any>;
chartHover: EventEmitter<any>;
chartBuilder(config); // (prepares / converts) input chart config as per the underlying chart library used.
refreshChart(); // refreshes and updates the chart either at specific interval or explicitly triggerd
addData({ label, data, config }); //appends the label and data at the end;
removeData(); //pops the last data and label
removeData(label: string) // removes a specific label
getTelemetry();
// mergeData(data1, data2, ...dataN): any[];
getCurrentSelection();
getDatasetAtIndex(index: number);
}
/*
##########################################################################
*
*. depenedent interfaces are as follows:-
*
##########################################################################
*/
interface IChartConfig {
type: IChartType;
options?: IChartOptions;
[key: string]: any;
}
type IChartType = "bar" | "line" | "pie" | "etc";
type IChartOptions = {
labels? : string[], // if labels are passed explicitely
labelExpr ? : string; // column name to use as x-axis labels;
datasets: IDataset[]; // datasets - y axis data
tooltip?: object;
legend?: object
animation?: object;
colors?: object;
title?: string;
description: string;
subtitle?: string;
caption?: object;
filters?: IFilterConfig;
scales?: {
axes: any;
[key: string]: any;
};
[key: string]: any;
};
type IDataset = {
label: string;
dataExpr?: string;
data: any[];
} |
...
Code Block | ||
---|---|---|
| ||
interface ITable extends IBase { readonly reportType: IReportType = "table" readonly _defaultConfiguration: ITableConfig; config: ITableConfigurationITableConfig[]; getRowsCount(); // rows count getRowAtIndex(index: number); //get row at index number rowSelector(selectors); //fetch first row matching the config rowSelectorAll(selectors); // fetch rows matching a config addRow(data: object); // add a new row to the table by passing row configuration removeRow(index?: string); //removes row from the end or at specific index; addColumn(config: ITableConfiguration); // adds a new column at the end removeColumn(columnName: string); // removes a column rowClick: EventEmitter<any>; // row click event emitter rowHover: EventEmitter<any>; // mouse over event emitter exportTable(exportType: string); // exports the table into a type sortTable(sortByColumnName: string, orderBy: "asc" | "desc"); } /* ########################################################################## * *. depenedent interfaces are as follows:- * ########################################################################## */ interface ITableConfig { title?: string; // header name for the column searchable?: boolean; // if the column is searchable or not - will be used by the search bar at the top orderable?: boolean; // if the column can be ordered or sorted in asecending or descending fashion data?: string; // key in the input JSON to be used as column visible?: boolean; // hides or shows a column within a table render?: () => any; // method to override the view and customise it like showing a button or chip instead of normal text autoWidth?: boolean; widthSize?: string; // customised width either in percentage or fixed width [key: string]: any; //any other metadata } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
abstract class Filter<T> { data: T[]; config: IFilterConfig[]; filteredDataEventEmitter: EventEmitter<T[]> abstract init(config: IFilterConfig); //Get the initialisation options to render the filters; abstract filterData(data: T, config): object[]; } interface IFilterConfig { reference: string; label: string; placeholder: string; controlType: "single-select" | "multi-select" | "date"; searchable?: boolean; filters: IFilterConfig[]; default?: string; } /* Questions Nested Filter Capability.. */ |
🧐 Implemenation Approach
...
Dashlet Main Component Proposed Structure
(**Please refer to the next sections for more detailed info about each component)
Code Block | ||||
---|---|---|---|---|
| ||||
<sb-dashlet [type]="string" [config]="config" [data]="data | IDataLocation" , [id]="string | uuid" [height]="string"
[width]="string" (...anyOtherEvent)="eventListener($event)">
<some-title-element>
<div>{{title}}</div>
<div>{{subTitle}}</div>
<div>{{description}}</div>
</some-title-element>
<some-action-buttons-component> </some-action-buttons-component>
<dashlet-filter [data]="data" , [config]="IFilterConfig[]" , (filteredData)="..."> </dashlet-filter>
<container-element [ngSwitch]="reportType">
<chart-element switchCase="chart" (chartClick)="eventListener($event)" (chartHover)="eventListener($event)"
(afterChartLoaded)="eventListener($event)">
<container-element [ngSwitch]="libraryType" default="chartjs">
<chartJs-element switchCase="chartjs" [options]="options" [chartType]="chartType" (events)="">
</chartJs-element>
<highCharts-element switchCase="highCharts" [options]="options" [chartType]="chartType" (events)="">
</highCharts-element>
<d3-element switchCase="d3" [options]="options" [chartType]="chartType" (events)=""> </d3-element>
<custom-chartTypes switchCase="custom">
<container-element [ngSwitch]="reportSubType">
<map-element switchCase="map" [options]="options" [chartType]="chartType" (events)="">
</map-element>
<bigNumber switchCase="bigNumber" [options]="chartOptions"></bigNumber>
<other switchCase="others" [options]="chartOptions"></other>
</container-element>
</custom-chartTypes>
</container-element>
</chart-element>
<table-element switchCase="table" (rowClicked)="eventListener($event)">
<container-element [ngSwitch]="libraryType" default="datatables">
<dataTable-component switchCase="datatables" [...options]="tableOptions"> </dataTable-component>
<custom-table switchCase="custom">
<container-element [ngSwitch]="reportSubType">
<stripped-table switchCase="stripped-table" [...options]="tableOptions"></stripped-table>
</container-element>
</custom-table>
</container-element>
</table-element>
<dataset-element switchCase="dataset" (events)="eventListener($event)"> </dataset-element>
<new-reportType-element switchCase="newReportType">
<container-element [ngSwitch]="libraryType" default="datatables">
<custom-table switchCase="custom">
<container-element [ngSwitch]="reportSubType">
<custom-element switchCase="type1" [...options]="customOptions"></custom-element>
</container-element>
</custom-table>
</container-element>
</new-reportType-element>
</container-element>
</sb-dashlet> |
...
Selector - sb-dashlet
Description - This is the main component will exposes certain Input properties and events Handlers to the end user to render a. certain chart or table.
Attributes -
Property | Description |
---|---|
type | chartType like bar, line, pie etc |
config | config JSON as per the interfaces mentioned in the previous sections |
data | data or API details as per the IDataLocation interface mentioned in the previous sections. |
id <optional> | unique id. If not passed a uuid is assigned by the component |
height or Width <optional> | If not passed 100% is assumed |
events | certain event listeners exposed by the component |
Code Block | ||||
---|---|---|---|---|
| ||||
<chartJs<sb-elementdashlet [datasetstype]="datasetsstring" [labelsconfig]="labelsconfig" [chartTypedata]="chartType"data | IDataLocation" , [colorsid]="colorsstring | uuid" [optionsheight]="optionsstring" [legendswidth]="legends" [plugins]="pluginsstring" (...anyOtherEvent)="eventListener($event)"> </sb-dashlet> |
...
Example of a Pie Chart using the Component
...
Code Block | ||||
---|---|---|---|---|
| ||||
<sb-dashlet [config]="config" (chartClick)=" |
...
chartClickHandler($event)" (chartHover)=" |
...
chartHoverHandler($event)"></sb-dashlet> |
Code Block | ||
---|---|---|
| ||
let config: IChartConfig = { |
...
|
...
|
...
|
...
|
...
|
...
type: "pie", |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
options: { datasets: [ { data: [65, 59, 80, 81, 56, 55, 40], label: 'Series A' }, { data: [28, 48, 40, 19, 86, 27, 90], label: 'Series B' }, { data: [180, 480, 770, 90, 1000, 270, 400], label: 'Series C', yAxisID: 'y-axis-1' } ], labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], options: { responsive: true, scales: { xAxes: [{}], yAxes: [ { id: 'y-axis-0', position: 'left', } ] } }, colors: [ { backgroundColor: 'rgba(148,159,177,0.2)', borderColor: 'rgba(148,159,177,1)', pointBackgroundColor: 'rgba(148,159,177,1)', pointBorderColor: '#fff', pointHoverBackgroundColor: '#fff', pointHoverBorderColor: 'rgba(148,159,177,0.8)' |
...
|
...
} |
...
], |
...
|
...
legends: |
...
true |
...
} } |
...
Component specs:-
Properties
Note: For more information about possible options please refer to the original chart.js documentation
data (SingleOrMultiDataSet) - set of points of the chart, it should be MultiDataSet only for line, bar, radar and doughnut, otherwise SingleDataSettype: string - indicates the type of charts, it can be: line, bar, radar, pie, polar area, doughnut
datasets ({data: SingleDataSet, label: string}[]) - data see about, the label for the dataset which appears in the legend and tooltips
labels (Label[]) - x-axis labels. It's necessary for charts: line, bar, and radar. And just labels (on hover) for charts: polar area, pie, and a doughnut. The label is either a single string, or it may be a string[] representing a multi-line label where each array element is on a new line.
chartType (ChartType) - indicates the type of charts, it can be: line, bar, radar, pie, polar area, doughnut
options (ChartOptions) - chart options (as from Chart.js documentation) with some custom options.as per the IChartConfig for title, legend, tooltips configuration.
colors (Color[]) - data colors, will use the default and|or random colors if not specified (see below)
legend: (boolean = false) - if true show legend below the chart, otherwise not be shown
...
chartClick: fires, when click on a chart, has occurred, returns information regarding active points and labels
chartHover: fires when mousemove (hover) on a chart has occurred, returns information regarding active points and labels
...
Map Using Dashlet Component
Code Block | ||||
---|---|---|---|---|
| ||||
<map<sb-dashlet [optionsconfig]="options" [mapData]="mapData" (featureClicked)="eventListener($event)"> </map>sb-dashlet> <script> let mapData = { state: 'Karnataka', districts: ['Bengaluru', 'Mysuru'], reportData: [{}, {}], reportLoc: 'url', metrics: [''], // country: 'India', // Optional - to show india map with states // states: ['Karnataka'], // Optional - list of states to show on the map } // default config and can be overridden with new configurations let options = { initialCoordinate: [20, 78], latBounds: [6.4626999, 68.1097], lonBounds: [35.513327, 97.39535869999999], initialZoomLevel: 5, controlTitle: 'India Heat Map', tileLayer: { urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', options: { attributions: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' } }, rootStyle: { fillColor: '#007cbe' }, otherOptions: any }; </script> |
...
Table Example using Dashlet Component
...
Code Block | ||||
---|---|---|---|---|
| ||||
<table<sb-elementdashlet [data]="[{}]" [columnsConfigurationconfig]="columnsConfiguration" (rowClickHandler)="eventListener($click)"> </tablesb-element>dashlet> <script> let columnsConfiguration = [{ title: string, searchable: boolean, orderable: boolean, data: 'key', visible: boolean, render: () => {}, paging: boolean, info: boolean, autoWidth: boolean, others: any }] </script> |
...