Commit 0a0f3edf by Ooh-Ao

parent a769dd08
......@@ -157,12 +157,20 @@
class="p-2 bg-white border-b border-gray-200 text-gray-700 font-semibold flex justify-between items-center"
>
<span>{{ panel.header }}</span>
<button
(click)="removeWidgetFromDashboard(panel.id!)"
class="text-red-500 hover:text-red-700"
>
<i class="bi bi-trash"></i>
</button>
<div class="flex items-center space-x-2">
<button
(click)="openWidgetConfigDialog(panel)"
class="text-blue-500 hover:text-blue-700"
>
<i class="bi bi-gear"></i>
</button>
<button
(click)="removeWidgetFromDashboard(panel.id!)"
class="text-red-500 hover:text-red-700"
>
<i class="bi bi-trash"></i>
</button>
</div>
</div>
</ng-template>
<ng-template #content>
......
......@@ -13,6 +13,7 @@ import { DashboardModel, WidgetModel, DatasetModel } from '../models/widgets.mod
import { DashboardDataService } from '../services/dashboard-data.service';
import { WidgetDataService } from '../services/widget-data.service'; // Import new service
import { WidgetService } from '../services/widgets.service'; // Import WidgetService
import { DashboardStateService } from '../services/dashboard-state.service';
// Import all the widget components
import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component';
......@@ -359,7 +360,8 @@ export class DashboardManagementComponent implements OnInit {
private route: ActivatedRoute,
private dashboardDataService: DashboardDataService,
private widgetDataService: WidgetDataService, // Inject new service
private widgetService: WidgetService // Inject WidgetService
private widgetService: WidgetService, // Inject WidgetService
private dashboardStateService: DashboardStateService
) { }
ngOnInit(): void {
......@@ -436,10 +438,7 @@ export class DashboardManagementComponent implements OnInit {
// Ensure widget.config exists, initialize if not.
const widgetConfig = widget.config || {};
// Add datasetId to the config if it exists in the dashboardData
if (this.dashboardData?.datasetId) {
widgetConfig.datasetId = this.dashboardData.datasetId;
}
return {
id: widget.id,
......@@ -555,7 +554,40 @@ export class DashboardManagementComponent implements OnInit {
onDatasetSelected(datasetId: string): void {
if (this.dashboardData) {
this.dashboardData.datasetId = datasetId;
this.panels = this.mapWidgetsToPanels(this.dashboardData.widgets);
this.dashboardStateService.selectDataset(datasetId);
}
}
openWidgetConfigDialog(panel: PanelModel & { originalWidget: WidgetModel }): void {
const widget = panel.originalWidget;
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
const availableColumns = selectedDataset ? selectedDataset.columns : [];
const dialogRef = this.dialog.open(WidgetConfigComponent, {
width: '400px',
data: {
config: widget.config,
availableColumns: availableColumns,
widgetType: widget.component
}
});
dialogRef.afterClosed().subscribe((result: any) => {
if (result) {
// Update the widget's config with the new values
const updatedWidget = { ...widget, config: result };
if (this.dashboardData) {
const widgetIndex = this.dashboardData.widgets.findIndex(w => w.id === updatedWidget.id);
if (widgetIndex > -1) {
this.dashboardData.widgets[widgetIndex] = updatedWidget;
// Re-map panels to reflect changes
this.panels = this.mapWidgetsToPanels(this.dashboardData.widgets);
// Save the updated dashboard
this.dashboardDataService.updateDashboard(this.dashboardData).subscribe();
}
}
}
});
});
}
}
<h2 mat-dialog-title>Configure Widget: {{ widgetType }}</h2>
<mat-dialog-content>
<form>
<div *ngIf="widgetType === 'SimpleKpiWidgetComponent'">
<mat-form-field appearance="fill">
<mat-label>Value Field</mat-label>
<mat-select [(ngModel)]="currentConfig.valueField" name="valueField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Aggregation</mat-label>
<mat-select [(ngModel)]="currentConfig.aggregation" name="aggregation">
<mat-option value="count">Count</mat-option>
<mat-option value="sum">Sum</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Unit</mat-label>
<input matInput [(ngModel)]="currentConfig.unit" name="unit">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Title</mat-label>
<input matInput [(ngModel)]="currentConfig.title" name="title">
</mat-form-field>
</div>
<div *ngIf="widgetType === 'PieChartWidgetComponent' || widgetType === 'BarChartWidgetComponent' || widgetType === 'AreaChartWidgetComponent' || widgetType === 'DoughnutChartWidgetComponent' || widgetType === 'FunnelChartWidgetComponent'">
<mat-form-field appearance="fill">
<mat-label>X-Axis Field</mat-label>
<mat-select [(ngModel)]="currentConfig.xField" name="xField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Y-Axis Field</mat-label>
<mat-select [(ngModel)]="currentConfig.yField" name="yField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Aggregation (for Pie/Doughnut/Funnel)</mat-label>
<mat-select [(ngModel)]="currentConfig.aggregation" name="aggregation">
<mat-option value="none">None</mat-option>
<mat-option value="count">Count</mat-option>
<mat-option value="sum">Sum</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Title</mat-label>
<input matInput [(ngModel)]="currentConfig.title" name="title">
</mat-form-field>
</div>
<div *ngIf="widgetType === 'GaugeChartWidgetComponent'">
<mat-form-field appearance="fill">
<mat-label>Value Field</mat-label>
<mat-select [(ngModel)]="currentConfig.valueField" name="valueField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Title</mat-label>
<input matInput [(ngModel)]="currentConfig.title" name="title">
</mat-form-field>
</div>
<div *ngIf="widgetType === 'SimpleTableWidgetComponent'">
<mat-form-field appearance="fill">
<mat-label>Title</mat-label>
<input matInput [(ngModel)]="currentConfig.title" name="title">
</mat-form-field>
<!-- For table columns, a more complex UI might be needed, but for now, we'll assume the columns are derived from the dataset -->
<p>Table columns will be derived from the selected dataset.</p>
</div>
<div *ngIf="widgetType === 'TreemapWidgetComponent'">
<mat-form-field appearance="fill">
<mat-label>Group Field</mat-label>
<mat-select [(ngModel)]="currentConfig.groupField" name="groupField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Value Field</mat-label>
<mat-select [(ngModel)]="currentConfig.valueField" name="valueField">
<mat-option *ngFor="let col of availableColumns" [value]="col">{{ col }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Title</mat-label>
<input matInput [(ngModel)]="currentConfig.title" name="title">
</mat-form-field>
</div>
</form>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button (click)="onCancel()">Cancel</button>
<button mat-raised-button color="primary" (click)="onSave()">Save</button>
</mat-dialog-actions>
mat-form-field {
width: 100%;
margin-bottom: 15px;
}
import { Component, Inject, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { FormsModule } from '@angular/forms';
export interface WidgetConfigDialogData {
config: any;
availableColumns: string[];
widgetType: string;
}
@Component({
selector: 'app-widget-config',
standalone: true,
imports: [
CommonModule,
FormsModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
MatButtonModule
],
templateUrl: './widget-config.component.html',
styleUrls: ['./widget-config.component.scss']
})
export class WidgetConfigComponent implements OnInit {
currentConfig: any;
availableColumns: string[];
widgetType: string;
constructor(
public dialogRef: MatDialogRef<WidgetConfigComponent>,
@Inject(MAT_DIALOG_DATA) public data: WidgetConfigDialogData
) { }
ngOnInit(): void {
this.currentConfig = { ...this.data.config }; // Create a copy to avoid direct mutation
this.availableColumns = this.data.availableColumns;
this.widgetType = this.data.widgetType;
}
onSave(): void {
this.dialogRef.close(this.currentConfig);
}
onCancel(): void {
this.dialogRef.close();
}
}
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { switchMap, map } from 'rxjs/operators';
import { DatasetService } from './dataset.service';
import { HttpClient } from '@angular/common/http';
import { DatasetModel } from '../models/widgets.model';
export interface SelectedDataset {
data: any[];
columns: string[];
}
@Injectable({
providedIn: 'root'
})
export class DashboardStateService {
private selectedDatasetId = new BehaviorSubject<string | null>(null);
public selectedDataset$: Observable<SelectedDataset | null>;
constructor(private datasetService: DatasetService, private http: HttpClient) {
this.selectedDataset$ = this.selectedDatasetId.pipe(
switchMap(id => {
if (id) {
return this.datasetService.getDatasetById(id).pipe(
switchMap((dataset: DatasetModel | undefined) => {
if (dataset && dataset.url) {
return this.http.get<any[]>(dataset.url).pipe(
map(data => {
if (data && data.length > 0) {
const columns = Object.keys(data[0]);
return { data, columns };
} else {
return { data: [], columns: [] };
}
})
);
}
return of(null);
})
);
}
return of(null);
})
);
}
selectDataset(datasetId: string): void {
this.selectedDatasetId.next(datasetId);
}
}
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ChartModule, AreaSeriesService, CategoryService, LegendService, TooltipService, DataLabelService } from '@syncfusion/ej2-angular-charts';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { DatasetService } from '../../services/dataset.service';
import { DatasetModel } from '../../models/widgets.model';
import { DashboardStateService, SelectedDataset } from '../../services/dashboard-state.service';
@Component({
selector: 'app-area-chart-widget',
standalone: true,
imports: [CommonModule, ChartModule, HttpClientModule],
providers: [AreaSeriesService, CategoryService, LegendService, TooltipService, DataLabelService, DatasetService, HttpClient],
imports: [CommonModule, ChartModule],
providers: [AreaSeriesService, CategoryService, LegendService, TooltipService, DataLabelService],
templateUrl: './area-chart-widget.component.html',
})
export class AreaChartWidgetComponent implements OnInit, OnChanges {
export class AreaChartWidgetComponent implements OnInit {
@Input() config: any;
public chartData: Object[];
......@@ -21,54 +19,38 @@ export class AreaChartWidgetComponent implements OnInit, OnChanges {
public primaryXAxis: Object;
public primaryYAxis: Object;
constructor(private datasetService: DatasetService, private http: HttpClient) { }
constructor(private dashboardStateService: DashboardStateService) { }
ngOnInit(): void {
this.primaryXAxis = { valueType: 'Category', title: 'Month' };
this.primaryYAxis = { title: 'Sales' };
// Default data if no config is provided
if (!this.config || !this.config.datasetId) {
this.chartData = [
{ month: 'Jan', sales: 35 }, { month: 'Feb', sales: 28 },
{ month: 'Mar', sales: 34 }, { month: 'Apr', sales: 32 },
{ month: 'May', sales: 40 }, { month: 'Jun', sales: 30 },
];
}
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
if (selectedDataset && selectedDataset.data && this.config && this.config.xField && this.config.yField) {
this.updateChart(selectedDataset.data);
} else {
this.resetChart();
}
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['config'] && this.config && this.config.datasetId) {
this.loadData();
} else if (changes['config'] && (!this.config || !this.config.datasetId)) {
// Reset to default data if config or datasetId is removed
this.chartData = [
{ month: 'Jan', sales: 35 }, { month: 'Feb', sales: 28 },
{ month: 'Mar', sales: 34 }, { month: 'Apr', sales: 32 },
{ month: 'May', sales: 40 }, { month: 'Jun', sales: 30 },
];
updateChart(data: any[]): void {
this.chartData = data.map(item => ({ x: item[this.config.xField], y: item[this.config.yField] }));
if (this.config.title) {
this.title = this.config.title;
}
if (this.config.xAxisTitle) {
this.primaryXAxis = { ...this.primaryXAxis, title: this.config.xAxisTitle, valueType: 'Category' };
}
if (this.config.yAxisTitle) {
this.primaryYAxis = { ...this.primaryYAxis, title: this.config.yAxisTitle };
}
}
loadData(): void {
if (this.config.datasetId) {
this.datasetService.getDatasetById(this.config.datasetId).subscribe((dataset: DatasetModel | undefined) => {
if (dataset && dataset.url) {
this.http.get<any[]>(dataset.url).subscribe(data => {
// Assuming the data fetched is directly usable by the chart
// You might need to transform the data based on config.xField, config.yField
this.chartData = data.map(item => ({ x: item[this.config.xField], y: item[this.config.yField] }));
if (this.config.title) {
this.title = this.config.title;
}
if (this.config.xAxisTitle) {
this.primaryXAxis = { ...this.primaryXAxis, title: this.config.xAxisTitle, valueType: 'Category' };
}
if (this.config.yAxisTitle) {
this.primaryYAxis = { ...this.primaryYAxis, title: this.config.yAxisTitle };
}
});
}
});
}
resetChart(): void {
this.chartData = [
{ month: 'Jan', sales: 35 }, { month: 'Feb', sales: 28 },
{ month: 'Mar', sales: 34 }, { month: 'Apr', sales: 32 },
{ month: 'May', sales: 40 }, { month: 'Jun', sales: 30 },
];
}
}
import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ChartModule, BarSeriesService, ColumnSeriesService, CategoryService, LegendService, TooltipService, DataLabelService } from '@syncfusion/ej2-angular-charts';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { DatasetService } from '../../services/dataset.service';
import { DatasetModel } from '../../models/widgets.model';
import { DashboardStateService, SelectedDataset } from '../../services/dashboard-state.service';
@Component({
selector: 'app-bar-chart-widget',
standalone: true,
imports: [CommonModule, ChartModule, HttpClientModule],
providers: [BarSeriesService, ColumnSeriesService, CategoryService, LegendService, TooltipService, DataLabelService, DatasetService, HttpClient],
imports: [CommonModule, ChartModule],
providers: [BarSeriesService, ColumnSeriesService, CategoryService, LegendService, TooltipService, DataLabelService],
templateUrl: './bar-chart-widget.component.html',
})
export class BarChartWidgetComponent implements OnInit {
......@@ -21,55 +19,42 @@ export class BarChartWidgetComponent implements OnInit {
public primaryXAxis: Object;
public primaryYAxis: Object;
constructor(private datasetService: DatasetService, private http: HttpClient) { }
constructor(private dashboardStateService: DashboardStateService) { }
ngOnInit(): void {
this.primaryXAxis = { valueType: 'Category', title: 'Country' };
this.primaryYAxis = { title: 'Sales' };
if (!this.config || !this.config.datasetId) {
this.chartData = [
{ country: 'USA', sales: 20 },
{ country: 'China', sales: 25 },
{ country: 'Japan', sales: 18 },
{ country: 'Germany', sales: 15 },
];
}
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
if (selectedDataset && selectedDataset.data && this.config && this.config.xField && this.config.yField) {
this.updateChart(selectedDataset.data);
} else {
this.resetChart();
}
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['config'] && this.config && this.config.datasetId) {
this.loadData();
} else if (changes['config'] && (!this.config || !this.config.datasetId)) {
this.chartData = [
{ country: 'USA', sales: 20 },
{ country: 'China', sales: 25 },
{ country: 'Japan', sales: 18 },
{ country: 'Germany', sales: 15 },
];
updateChart(data: any[]): void {
this.chartData = data.map(item => ({ x: item[this.config.xField], y: item[this.config.yField] }));
if (this.config.title) {
this.title = this.config.title;
}
if (this.config.xAxisTitle) {
this.primaryXAxis = { ...this.primaryXAxis, title: this.config.xAxisTitle };
}
if (this.config.yAxisTitle) {
this.primaryYAxis = { ...this.primaryYAxis, title: this.config.yAxisTitle };
}
if (this.config.type) {
this.type = this.config.type;
}
}
loadData(): void {
if (this.config.datasetId) {
this.datasetService.getDatasetById(this.config.datasetId).subscribe((dataset: DatasetModel | undefined) => {
if (dataset && dataset.url) {
this.http.get<any[]>(dataset.url).subscribe(data => {
this.chartData = data.map(item => ({ x: item[this.config.xField], y: item[this.config.yField] }));
if (this.config.title) {
this.title = this.config.title;
}
if (this.config.xAxisTitle) {
this.primaryXAxis = { ...this.primaryXAxis, title: this.config.xAxisTitle };
}
if (this.config.yAxisTitle) {
this.primaryYAxis = { ...this.primaryYAxis, title: this.config.yAxisTitle };
}
if (this.config.type) {
this.type = this.config.type;
}
});
}
});
}
resetChart(): void {
this.chartData = [
{ country: 'USA', sales: 20 },
{ country: 'China', sales: 25 },
{ country: 'Japan', sales: 18 },
{ country: 'Germany', sales: 15 },
];
}
}
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AccumulationChartModule, AccumulationDataLabelService, AccumulationLegendService, AccumulationTooltipService } from '@syncfusion/ej2-angular-charts';
import { DatasetService } from '../../services/dataset.service';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { DashboardStateService, SelectedDataset } from '../../services/dashboard-state.service';
@Component({
selector: 'app-doughnut-chart-widget',
standalone: true,
imports: [CommonModule, AccumulationChartModule, HttpClientModule],
providers: [AccumulationDataLabelService, AccumulationLegendService, AccumulationTooltipService, DatasetService, HttpClient],
imports: [CommonModule, AccumulationChartModule],
providers: [AccumulationDataLabelService, AccumulationLegendService, AccumulationTooltipService],
templateUrl: './doughnut-chart-widget.component.html',
})
export class DoughnutChartWidgetComponent implements OnInit {
......@@ -17,19 +16,45 @@ export class DoughnutChartWidgetComponent implements OnInit {
@Input() legendSettings: Object;
@Input() config: any;
constructor(private datasetService: DatasetService, private http: HttpClient) { }
constructor(private dashboardStateService: DashboardStateService) { }
ngOnInit(): void {
if (!this.chartData) {
this.chartData = [
{ browser: 'Chrome', users: 37 },
{ browser: 'Firefox', users: 17 },
{ browser: 'Internet Explorer', users: 19 },
{ browser: 'Edge', users: 4 },
{ browser: 'Safari', users: 11 },
{ browser: 'Other', users: 12 },
];
}
this.legendSettings = { visible: true };
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
if (selectedDataset && selectedDataset.data && this.config && this.config.xField && this.config.yField) {
this.updateChart(selectedDataset.data);
} else {
this.resetChart();
}
});
}
updateChart(data: any[]): void {
let transformedData = data;
if (this.config.aggregation === 'count') {
const counts = transformedData.reduce((acc, item) => {
const key = item[this.config.xField];
acc[key] = (acc[key] || 0) + 1;
return acc;
}, {});
transformedData = Object.keys(counts).map(key => ({ x: key, y: counts[key] }));
} else {
transformedData = transformedData.map(item => ({ x: item[this.config.xField], y: item[this.config.yField] }));
}
this.chartData = transformedData;
if (this.config.title) {
this.title = this.config.title;
}
}
resetChart(): void {
this.chartData = [
{ browser: 'Chrome', users: 37 },
{ browser: 'Firefox', users: 17 },
{ browser: 'Internet Explorer', users: 19 },
{ browser: 'Edge', users: 4 },
{ browser: 'Safari', users: 11 },
{ browser: 'Other', users: 12 },
];
}
}
import { Component, Input, OnInit, SimpleChanges } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AccumulationChartModule, FunnelSeriesService, AccumulationDataLabelService, AccumulationLegendService, AccumulationTooltipService } from '@syncfusion/ej2-angular-charts';
import { DatasetService } from '../../services/dataset.service';
import { HttpClient } from '@angular/common/http';
import { DatasetModel } from '../../models/widgets.model';
import { DashboardStateService, SelectedDataset } from '../../services/dashboard-state.service';
@Component({
selector: 'app-funnel-chart-widget',
......@@ -17,44 +15,31 @@ export class FunnelChartWidgetComponent implements OnInit {
@Input() chartData: Object[];
@Input() title: string = 'Funnel Chart';
@Input() legendSettings: Object;
constructor(private datasetService: DatasetService, private http: HttpClient) { }
constructor(private dashboardStateService: DashboardStateService) { }
ngOnInit(): void {
if (!this.config || !this.config.datasetId) {
this.chartData = [
{ x: 'Website Visitors', y: 10000 },
{ x: 'Leads', y: 8000 },
{ x: 'Opportunities', y: 6000 },
{ x: 'Converted', y: 4000 },
];
}
this.legendSettings = { visible: true };
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
if (selectedDataset && selectedDataset.data && this.config && this.config.xField && this.config.yField) {
this.updateChart(selectedDataset.data);
} else {
this.resetChart();
}
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['config'] && this.config && this.config.datasetId) {
this.loadData();
} else if (changes['config'] && (!this.config || !this.config.datasetId)) {
this.chartData = [
{ x: 'Website Visitors', y: 10000 },
{ x: 'Leads', y: 8000 },
{ x: 'Opportunities', y: 6000 },
{ x: 'Converted', y: 4000 },
];
updateChart(data: any[]): void {
this.chartData = data.map(item => ({ x: item[this.config.xField], y: item[this.config.yField] }));
if (this.config.title) {
this.title = this.config.title;
}
}
loadData(): void {
if (this.config.datasetId) {
this.datasetService.getDatasetById(this.config.datasetId).subscribe((dataset: DatasetModel | undefined) => {
if (dataset && dataset.url) {
this.http.get<any[]>(dataset.url).subscribe(data => {
this.chartData = data.map(item => ({ x: item[this.config.xField], y: item[this.config.yField] }));
if (this.config.title) {
this.title = this.config.title;
}
});
}
});
}
resetChart(): void {
this.chartData = [
{ x: 'Website Visitors', y: 10000 },
{ x: 'Leads', y: 8000 },
{ x: 'Opportunities', y: 6000 },
{ x: 'Converted', y: 4000 },
];
}
}
import { Component, Input, OnInit, SimpleChanges } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CircularGaugeModule, GaugeTooltipService, AnnotationsService } from '@syncfusion/ej2-angular-circulargauge';
import { DatasetModel } from '../../models/widgets.model';
import { DatasetService } from '../../services/dataset.service';
import { HttpClient } from '@angular/common/http';
import { DashboardStateService, SelectedDataset } from '../../services/dashboard-state.service';
@Component({
selector: 'app-gauge-chart-widget',
......@@ -19,9 +17,35 @@ export class GaugeChartWidgetComponent implements OnInit {
public axes: Object[];
constructor(private datasetService: DatasetService, private http: HttpClient) { }
constructor(private dashboardStateService: DashboardStateService) { }
ngOnInit(): void {
this.resetChart(); // Set initial state
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
if (selectedDataset && selectedDataset.data && this.config && this.config.valueField) {
this.updateChart(selectedDataset.data);
} else {
this.resetChart();
}
});
}
updateChart(data: any[]): void {
if (data.length > 0) {
this.value = data[0][this.config.valueField]; // Assuming single value for gauge
}
if (this.config.title) {
this.title = this.config.title;
}
this.setAxes();
}
resetChart(): void {
this.value = 70;
this.setAxes();
}
setAxes(): void {
this.axes = [{
line: { width: 0 },
labelStyle: { font: { size: '0px' } },
......@@ -40,51 +64,5 @@ export class GaugeChartWidgetComponent implements OnInit {
{ start: 75, end: 100, color: '#B9EAB9' }
]
}];
if (!this.config || !this.config.datasetId) {
this.value = 70;
}
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['config'] && this.config && this.config.datasetId) {
this.loadData();
} else if (changes['config'] && (!this.config || !this.config.datasetId)) {
this.value = 70;
}
}
loadData(): void {
if (this.config.datasetId) {
this.datasetService.getDatasetById(this.config.datasetId).subscribe((dataset: DatasetModel | undefined) => {
if (dataset && dataset.url) {
this.http.get<any[]>(dataset.url).subscribe(data => {
if (this.config.valueField && data.length > 0) {
this.value = data[0][this.config.valueField]; // Assuming single value for gauge
}
if (this.config.title) {
this.title = this.config.title;
}
this.axes = [{
line: { width: 0 },
labelStyle: { font: { size: '0px' } },
majorTicks: { height: 0 },
minorTicks: { height: 0 },
pointers: [{
value: this.value,
radius: '80%',
pointerWidth: 8,
cap: { radius: 7 },
needleTail: { length: '18%' }
}],
ranges: [
{ start: 0, end: 50, color: '#E0B9B9' },
{ start: 50, end: 75, color: '#B9D7EA' },
{ start: 75, end: 100, color: '#B9EAB9' }
]
}];
});
}
});
}
}
}
import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AccumulationChartModule, PieSeriesService, AccumulationDataLabelService, AccumulationLegendService, AccumulationTooltipService } from '@syncfusion/ej2-angular-charts';
import { DatasetService } from '../../services/dataset.service';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { DatasetModel } from '../../models/widgets.model';
import { DashboardStateService, SelectedDataset } from '../../services/dashboard-state.service';
@Component({
selector: 'app-pie-chart-widget',
standalone: true,
imports: [CommonModule, AccumulationChartModule, HttpClientModule],
providers: [PieSeriesService, AccumulationDataLabelService, AccumulationLegendService, AccumulationTooltipService, DatasetService, HttpClient],
imports: [CommonModule, AccumulationChartModule],
providers: [PieSeriesService, AccumulationDataLabelService, AccumulationLegendService, AccumulationTooltipService],
templateUrl: './pie-chart-widget.component.html',
})
export class PieChartWidgetComponent implements OnInit, OnChanges {
export class PieChartWidgetComponent implements OnInit {
@Input() chartData: Object[];
@Input() title: string = 'Pie Chart';
@Input() legendSettings: Object;
@Input() config: any;
constructor(private datasetService: DatasetService, private http: HttpClient) { }
constructor(private dashboardStateService: DashboardStateService) { }
ngOnInit(): void {
if (!this.config || !this.config.datasetId) {
this.chartData = [
{ browser: 'Chrome', users: 37 },
{ browser: 'Firefox', users: 17 },
{ browser: 'Internet Explorer', users: 19 },
{ browser: 'Edge', users: 4 },
{ browser: 'Safari', users: 11 },
{ browser: 'Other', users: 12 },
];
}
this.legendSettings = { visible: true };
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
if (selectedDataset && selectedDataset.data && this.config && this.config.xField && this.config.yField) {
this.updateChart(selectedDataset.data);
} else {
this.resetChart();
}
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['config'] && this.config && this.config.datasetId) {
this.loadData();
} else if (changes['config'] && (!this.config || !this.config.datasetId)) {
this.chartData = [
{ browser: 'Chrome', users: 37 },
{ browser: 'Firefox', users: 17 },
{ browser: 'Internet Explorer', users: 19 },
{ browser: 'Edge', users: 4 },
{ browser: 'Safari', users: 11 },
{ browser: 'Other', users: 12 },
];
updateChart(data: any[]): void {
let transformedData = data;
if (this.config.aggregation === 'count') {
const counts = transformedData.reduce((acc, item) => {
const key = item[this.config.xField];
acc[key] = (acc[key] || 0) + 1;
return acc;
}, {});
transformedData = Object.keys(counts).map(key => ({ x: key, y: counts[key] }));
} else {
transformedData = transformedData.map(item => ({ x: item[this.config.xField], y: item[this.config.yField] }));
}
this.chartData = transformedData;
if (this.config.title) {
this.title = this.config.title;
}
}
loadData(): void {
if (this.config.datasetId) {
this.datasetService.getDatasetById(this.config.datasetId).subscribe((dataset: DatasetModel | undefined) => {
if (dataset && dataset.url) {
this.http.get<any[]>(dataset.url).subscribe(data => {
let transformedData = data;
if (this.config.xField && this.config.yField) {
if (this.config.aggregation === 'count') {
const counts = transformedData.reduce((acc, item) => {
const key = item[this.config.xField];
acc[key] = (acc[key] || 0) + 1;
return acc;
}, {});
transformedData = Object.keys(counts).map(key => ({ x: key, y: counts[key] }));
} else {
transformedData = transformedData.map(item => ({ x: item[this.config.xField], y: item[this.config.yField] }));
}
}
this.chartData = transformedData;
if (this.config.title) {
this.title = this.config.title;
}
});
}
});
}
resetChart(): void {
this.chartData = [
{ browser: 'Chrome', users: 37 },
{ browser: 'Firefox', users: 17 },
{ browser: 'Internet Explorer', users: 19 },
{ browser: 'Edge', users: 4 },
{ browser: 'Safari', users: 11 },
{ browser: 'Other', users: 12 },
];
}
}
import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DatasetService } from '../../services/dataset.service';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { DatasetModel } from '../../models/widgets.model';
import { DashboardStateService } from '../../services/dashboard-state.service';
@Component({
selector: 'app-simple-kpi-widget',
standalone: true,
imports: [CommonModule, HttpClientModule],
providers: [DatasetService, HttpClient],
imports: [CommonModule],
providers: [],
templateUrl: './simple-kpi-widget.component.html',
styleUrls: ['./simple-kpi-widget.component.scss']
})
export class SimpleKpiWidgetComponent implements OnInit, OnChanges {
export class SimpleKpiWidgetComponent implements OnInit {
@Input() title: string = 'Key Performance Indicator';
@Input() value: string = '123,456';
@Input() unit: string = '';
......@@ -20,51 +18,40 @@ export class SimpleKpiWidgetComponent implements OnInit, OnChanges {
@Input() trendValue: string = '';
@Input() config: any;
constructor(private datasetService: DatasetService, private http: HttpClient) { }
constructor(private dashboardStateService: DashboardStateService) { }
ngOnInit(): void {
if (!this.config || !this.config.datasetId) {
this.value = '123,456';
this.unit = '';
this.trend = 'neutral';
this.trendValue = '';
}
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
if (selectedDataset && selectedDataset.data && this.config && this.config.valueField) {
this.updateWidget(selectedDataset.data);
} else {
this.resetWidget();
}
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['config'] && this.config && this.config.datasetId) {
this.loadData();
} else if (changes['config'] && (!this.config || !this.config.datasetId)) {
this.value = '123,456';
this.unit = '';
this.trend = 'neutral';
this.trendValue = '';
updateWidget(data: any[]): void {
if (data.length > 0) {
let kpiValue = data[0][this.config.valueField];
if (this.config.aggregation === 'count') {
kpiValue = data.length;
} else if (this.config.aggregation === 'sum') {
kpiValue = data.reduce((sum, item) => sum + (item[this.config.valueField] || 0), 0);
}
this.value = kpiValue.toLocaleString();
this.unit = this.config.unit || '';
this.trend = this.config.trend || 'neutral';
this.trendValue = this.config.trendValue || '';
}
if (this.config.title) {
this.title = this.config.title;
}
}
loadData(): void {
if (this.config.datasetId) {
this.datasetService.getDatasetById(this.config.datasetId).subscribe((dataset: DatasetModel | undefined) => {
if (dataset && dataset.url) {
this.http.get<any[]>(dataset.url).subscribe(data => {
if (data.length > 0) {
let kpiValue = data[0][this.config.valueField];
if (this.config.aggregation === 'count') {
kpiValue = data.length;
} else if (this.config.aggregation === 'sum') {
kpiValue = data.reduce((sum, item) => sum + (item[this.config.valueField] || 0), 0);
}
this.value = kpiValue.toLocaleString();
this.unit = this.config.unit || '';
this.trend = this.config.trend || 'neutral';
this.trendValue = this.config.trendValue || '';
}
if (this.config.title) {
this.title = this.config.title;
}
});
}
});
}
resetWidget(): void {
this.value = '123,456';
this.unit = '';
this.trend = 'neutral';
this.trendValue = '';
}
}
import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DatasetModel } from '../../models/widgets.model';
import { DatasetService } from '../../services/dataset.service';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { DashboardStateService, SelectedDataset } from '../../services/dashboard-state.service';
@Component({
selector: 'app-simple-table-widget',
standalone: true,
imports: [CommonModule, HttpClientModule],
providers: [DatasetService, HttpClient],
imports: [CommonModule],
providers: [],
templateUrl: './simple-table-widget.component.html',
styleUrls: ['./simple-table-widget.component.scss']
})
export class SimpleTableWidgetComponent implements OnInit, OnChanges {
export class SimpleTableWidgetComponent implements OnInit {
@Input() config: any;
@Input() title: string = 'Table';
@Input() headers: string[] = [];
@Input() data: any[][] = [];
constructor(private datasetService: DatasetService, private http: HttpClient) { }
constructor(private dashboardStateService: DashboardStateService) { }
ngOnInit(): void {
if (!this.config || !this.config.datasetId) {
this.headers = ['ID', 'Name', 'Status'];
this.data = [
[1, 'Item A', 'Active'],
[2, 'Item B', 'Inactive'],
[3, 'Item C', 'Active'],
];
}
this.resetTable();
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
if (selectedDataset && selectedDataset.data && this.config && this.config.columns) {
this.updateTable(selectedDataset.data);
} else {
this.resetTable();
}
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['config'] && this.config && this.config.datasetId) {
this.loadData();
} else if (changes['config'] && (!this.config || !this.config.datasetId)) {
this.headers = ['ID', 'Name', 'Status'];
this.data = [
[1, 'Item A', 'Active'],
[2, 'Item B', 'Inactive'],
[3, 'Item C', 'Active'],
];
updateTable(data: any[]): void {
if (data.length > 0) {
this.headers = this.config.columns.map((col: any) => col.headerText);
this.data = data.map(row => this.config.columns.map((col: any) => row[col.field]));
}
if (this.config.title) {
this.title = this.config.title;
}
}
loadData(): void {
if (this.config.datasetId) {
this.datasetService.getDatasetById(this.config.datasetId).subscribe((dataset: DatasetModel | undefined) => {
if (dataset && dataset.url) {
this.http.get<any[]>(dataset.url).subscribe(data => {
if (this.config.columns && data.length > 0) {
this.headers = this.config.columns.map((col: any) => col.headerText);
this.data = data.map(row => this.config.columns.map((col: any) => row[col.field]));
}
if (this.config.title) {
this.title = this.config.title;
}
});
}
});
}
resetTable(): void {
this.headers = ['ID', 'Name', 'Status'];
this.data = [
[1, 'Item A', 'Active'],
[2, 'Item B', 'Inactive'],
[3, 'Item C', 'Active'],
];
}
}
import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TreeMapModule, TreeMapTooltipService, TreeMapLegendService, TreeMapHighlightService, TreeMapSelectionService } from '@syncfusion/ej2-angular-treemap';
import { DatasetModel } from '../../models/widgets.model';
import { DatasetService } from '../../services/dataset.service';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { DashboardStateService, SelectedDataset } from '../../services/dashboard-state.service';
@Component({
selector: 'app-treemap-widget',
standalone: true,
imports: [CommonModule, TreeMapModule, HttpClientModule],
providers: [TreeMapTooltipService, TreeMapLegendService, TreeMapHighlightService, TreeMapSelectionService, DatasetService, HttpClient],
imports: [CommonModule, TreeMapModule],
providers: [TreeMapTooltipService, TreeMapLegendService, TreeMapHighlightService, TreeMapSelectionService],
templateUrl: './treemap-widget.component.html',
})
export class TreemapWidgetComponent implements OnInit, OnChanges {
export class TreemapWidgetComponent implements OnInit {
@Input() config: any;
@Input() title: string = 'Treemap';
@Input() treemapData: Object[];
public dataSource: Object[];
public weightValuePath: string;
public leafItemSettings: Object;
constructor(private datasetService: DatasetService, private http: HttpClient) { }
constructor(private dashboardStateService: DashboardStateService) { }
ngOnInit(): void {
if (!this.config || !this.config.datasetId) {
this.treemapData = [
{ Continent: 'Asia', Countries: 'China', population: 1400 },
{ Continent: 'Asia', Countries: 'India', population: 1350 },
{ Continent: 'Europe', Countries: 'Germany', population: 83 },
{ Continent: 'Europe', Countries: 'France', population: 67 },
{ Continent: 'North America', Countries: 'USA', population: 330 },
{ Continent: 'North America', Countries: 'Canada', population: 38 },
];
}
this.dataSource = this.treemapData;
this.weightValuePath = 'population';
this.leafItemSettings = { labelPath: 'Countries' };
this.resetChart();
this.dashboardStateService.selectedDataset$.subscribe((selectedDataset: SelectedDataset | null) => {
if (selectedDataset && selectedDataset.data && this.config && this.config.valueField) {
this.updateChart(selectedDataset.data);
} else {
this.resetChart();
}
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['config'] && this.config && this.config.datasetId) {
this.loadData();
} else if (changes['config'] && (!this.config || !this.config.datasetId)) {
this.treemapData = [
{ Continent: 'Asia', Countries: 'China', population: 1400 },
{ Continent: 'Asia', Countries: 'India', population: 1350 },
{ Continent: 'Europe', Countries: 'Germany', population: 83 },
{ Continent: 'Europe', Countries: 'France', population: 67 },
{ Continent: 'North America', Countries: 'USA', population: 330 },
{ Continent: 'North America', Countries: 'Canada', population: 38 },
];
this.dataSource = this.treemapData;
updateChart(data: any[]): void {
this.dataSource = data;
if (this.config.title) {
this.title = this.config.title;
}
if (this.config.groupField) {
this.leafItemSettings = { labelPath: this.config.groupField };
}
if (this.config.valueField) {
this.weightValuePath = this.config.valueField;
}
}
loadData(): void {
if (this.config.datasetId) {
this.datasetService.getDatasetById(this.config.datasetId).subscribe((dataset: DatasetModel | undefined) => {
if (dataset && dataset.url) {
this.http.get<any[]>(dataset.url).subscribe(data => {
// Transform data for treemap
// Assuming config.groupField, config.subGroupField, config.valueField
const transformedData = data.map(item => ({
group: item[this.config.groupField],
subGroup: item[this.config.subGroupField],
value: item[this.config.valueField]
}));
this.treemapData = transformedData;
this.dataSource = this.treemapData;
if (this.config.title) {
this.title = this.config.title;
}
if (this.config.groupField) {
this.leafItemSettings = { labelPath: this.config.groupField };
}
if (this.config.valueField) {
this.weightValuePath = this.config.valueField;
}
});
}
});
}
resetChart(): void {
this.dataSource = [
{ Continent: 'Asia', Countries: 'China', population: 1400 },
{ Continent: 'Asia', Countries: 'India', population: 1350 },
{ Continent: 'Europe', Countries: 'Germany', population: 83 },
{ Continent: 'Europe', Countries: 'France', population: 67 },
{ Continent: 'North America', Countries: 'USA', population: 330 },
{ Continent: 'North America', Countries: 'Canada', population: 38 },
];
this.weightValuePath = 'population';
this.leafItemSettings = { labelPath: 'Countries' };
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment