Commit 7d32073b by Ooh-Ao

ดาต้า source

parent fafd66a2
...@@ -683,44 +683,33 @@ export class DashboardManagementComponent implements OnInit { ...@@ -683,44 +683,33 @@ export class DashboardManagementComponent implements OnInit {
} }
saveLayout(): void { saveLayout(): void {
console.log('saveLayout called. Dashboard data to save:', this.dashboardData);
if (!this.dashboardData) return; if (!this.dashboardData) return;
const dataFetchTasks: Observable<any>[] = this.dashboardData.widgets // Create a deep copy to avoid mutating the component's state
.filter(widget => widget.component === 'NewDataTableWidget' && widget.config?.source?.url) const dashboardToSave = JSON.parse(JSON.stringify(this.dashboardData));
.map(widget =>
this.widgetDataService.fetchDataForWidget(widget.config).pipe(
tap(data => {
// Mutate the config object to include the fetched data
widget.config.data = data;
})
)
);
if (dataFetchTasks.length > 0) { // Stringify all widget configs before saving
forkJoin(dataFetchTasks).subscribe(() => { if (dashboardToSave.widgets) {
console.log('All data fetched, now saving dashboard...'); dashboardToSave.widgets.forEach((widget: WidgetModel) => {
this.dashboardDataService.saveDashboard(this.dashboardData!).pipe( if (widget.config && typeof widget.config === 'object') {
catchError(error => { widget.config = JSON.stringify(widget.config);
this.notificationService.error('Error', 'Failed to save dashboard layout.'); }
return throwError(() => error);
})
).subscribe(() => {
this.notificationService.success('Success', 'Dashboard layout saved successfully!');
});
}); });
} else { }
console.log('No data to fetch, saving dashboard directly...');
this.dashboardDataService.saveDashboard(this.dashboardData).pipe( console.log('Saving dashboard with stringified configs:', dashboardToSave);
this.dashboardDataService.saveDashboard(dashboardToSave).pipe(
catchError(error => { catchError(error => {
this.notificationService.error('Error', 'Failed to save dashboard layout.'); this.notificationService.error('Error', 'Failed to save dashboard layout.');
return throwError(() => error); return throwError(() => error);
}) })
).subscribe(() => { ).subscribe(() => {
this.notificationService.success('Success', 'Dashboard layout saved successfully!'); this.notificationService.success('Success', 'Dashboard layout saved successfully!');
// Optionally, reload the dashboard to ensure UI is consistent with saved state
this.loadSelectedDashboard();
}); });
} }
}
// Kept for compatibility with the sidebar, which is not the focus of this refactor // Kept for compatibility with the sidebar, which is not the focus of this refactor
addWidgetToDashboard(widget: WidgetModel): void { addWidgetToDashboard(widget: WidgetModel): void {
......
...@@ -6,6 +6,8 @@ import { MatFormFieldModule } from '@angular/material/form-field'; ...@@ -6,6 +6,8 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
export interface WidgetConfigDialogData { export interface WidgetConfigDialogData {
...@@ -24,7 +26,9 @@ export interface WidgetConfigDialogData { ...@@ -24,7 +26,9 @@ export interface WidgetConfigDialogData {
MatInputModule, MatInputModule,
MatSelectModule, MatSelectModule,
MatButtonModule, MatButtonModule,
MatDialogModule // Add MatDialogModule MatDialogModule,
MatIconModule,
MatCheckboxModule
], ],
templateUrl: './widget-config.component.html', templateUrl: './widget-config.component.html',
styleUrls: ['./widget-config.component.scss'] styleUrls: ['./widget-config.component.scss']
...@@ -33,6 +37,7 @@ export class WidgetConfigComponent implements OnInit { ...@@ -33,6 +37,7 @@ export class WidgetConfigComponent implements OnInit {
currentConfig: any; currentConfig: any;
availableColumns: string[]; availableColumns: string[];
widgetType: string; widgetType: string;
comboChartTypes: string[] = ['Line', 'Column', 'Area', 'Spline'];
constructor( constructor(
public dialogRef: MatDialogRef<WidgetConfigComponent>, public dialogRef: MatDialogRef<WidgetConfigComponent>,
...@@ -40,140 +45,85 @@ export class WidgetConfigComponent implements OnInit { ...@@ -40,140 +45,85 @@ export class WidgetConfigComponent implements OnInit {
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.currentConfig = { ...this.data.config }; // Create a copy to avoid direct mutation
this.availableColumns = this.data.availableColumns; this.availableColumns = this.data.availableColumns;
this.widgetType = this.data.widgetType; this.widgetType = this.data.widgetType;
// Special handling for ChartWidgetComponent's yFields // Handle config whether it is a string or an object
if (this.widgetType === 'ChartWidgetComponent' && this.currentConfig.yFields) {
this.currentConfig.yFieldsJson = JSON.stringify(this.currentConfig.yFields, null, 2);
}
// Special handling for SyncfusionDatagridWidgetComponent's columns
if (this.widgetType === 'SyncfusionDatagridWidgetComponent' && this.currentConfig.columns) {
this.currentConfig.columnsJson = JSON.stringify(this.currentConfig.columns, null, 2);
}
// Special handling for SyncfusionPivotWidgetComponent's properties
if (this.widgetType === 'SyncfusionPivotWidgetComponent') {
if (this.currentConfig.rows) {
this.currentConfig.rowsJson = JSON.stringify(this.currentConfig.rows, null, 2);
}
if (this.currentConfig.columns) {
this.currentConfig.columnsJson = JSON.stringify(this.currentConfig.columns, null, 2);
}
if (this.currentConfig.values) {
this.currentConfig.valuesJson = JSON.stringify(this.currentConfig.values, null, 2);
}
if (this.currentConfig.filters) {
this.currentConfig.filtersJson = JSON.stringify(this.currentConfig.filters, null, 2);
}
}
// Special handling for NewDataTableWidget's columns
if (this.widgetType === 'NewDataTableWidget' && this.currentConfig.columns) {
this.currentConfig.columnsJson = JSON.stringify(this.currentConfig.columns, null, 2);
}
}
onSave(): void {
// Special handling for ChartWidgetComponent's yFields
if (this.widgetType === 'ChartWidgetComponent' && this.currentConfig.yFieldsJson) {
try { try {
this.currentConfig.yFields = JSON.parse(this.currentConfig.yFieldsJson); if (typeof this.data.config === 'string') {
} catch (e) { this.currentConfig = JSON.parse(this.data.config);
console.error('Invalid JSON for yFields:', e); } else {
alert('Invalid JSON format for Y-Axis Fields. Please correct it.'); // Deep copy config to avoid direct mutation of the original object
return; // Prevent closing dialog with invalid data this.currentConfig = JSON.parse(JSON.stringify(this.data.config || {}));
}
} }
// Special handling for SyncfusionDatagridWidgetComponent's columns
if (this.widgetType === 'SyncfusionDatagridWidgetComponent' && this.currentConfig.columnsJson) {
try {
this.currentConfig.columns = JSON.parse(this.currentConfig.columnsJson);
} catch (e) { } catch (e) {
console.error('Invalid JSON for columns:', e); console.error('Error parsing widget config:', e);
alert('Invalid JSON format for Columns. Please correct it.'); this.currentConfig = {}; // Default to empty object on error
return; // Prevent closing dialog with invalid data
} }
// Initialize arrays if they don't exist
const gridLikeWidgets = ['SyncfusionDatagridWidgetComponent', 'NewDataTableWidget', 'MatrixWidgetComponent'];
if (gridLikeWidgets.includes(this.widgetType) && !this.currentConfig.columns) {
this.currentConfig.columns = [];
} }
// Special handling for SyncfusionPivotWidgetComponent's properties
if (this.widgetType === 'SyncfusionPivotWidgetComponent') { if (this.widgetType === 'SyncfusionPivotWidgetComponent') {
if (this.currentConfig.rowsJson) { if (!this.currentConfig.rows) this.currentConfig.rows = [];
try { if (!this.currentConfig.columns) this.currentConfig.columns = [];
this.currentConfig.rows = JSON.parse(this.currentConfig.rowsJson); if (!this.currentConfig.values) this.currentConfig.values = [];
} catch (e) { if (!this.currentConfig.filters) this.currentConfig.filters = [];
console.error('Invalid JSON for rows:', e);
alert('Invalid JSON format for Rows. Please correct it.');
return;
}
}
if (this.currentConfig.columnsJson) {
try {
this.currentConfig.columns = JSON.parse(this.currentConfig.columnsJson);
} catch (e) {
console.error('Invalid JSON for columns:', e);
alert('Invalid JSON format for Columns. Please correct it.');
return;
}
} }
if (this.currentConfig.valuesJson) { if (this.widgetType === 'ChartWidgetComponent' && !this.currentConfig.yFields) {
try { this.currentConfig.yFields = [];
this.currentConfig.values = JSON.parse(this.currentConfig.valuesJson);
} catch (e) {
console.error('Invalid JSON for values:', e);
alert('Invalid JSON format for Values. Please correct it.');
return;
} }
}
if (this.currentConfig.filtersJson) {
try {
this.currentConfig.filters = JSON.parse(this.currentConfig.filtersJson);
} catch (e) {
console.error('Invalid JSON for filters:', e);
alert('Invalid JSON format for Filters. Please correct it.');
return;
}
}
}
// Special handling for NewDataTableWidget's columns
if (this.widgetType === 'NewDataTableWidget' && this.currentConfig.columnsJson) {
try {
this.currentConfig.columns = JSON.parse(this.currentConfig.columnsJson);
} catch (e) {
console.error('Invalid JSON for columns:', e);
alert('Invalid JSON format for Columns. Please correct it.');
return; // Prevent closing dialog with invalid data
}
}
// Special handling for ComboChartWidgetComponent's yFields and series
if (this.widgetType === 'ComboChartWidgetComponent') { if (this.widgetType === 'ComboChartWidgetComponent') {
if (this.currentConfig.yFieldsJson) { if (!this.currentConfig.yFields) this.currentConfig.yFields = [];
try { if (!this.currentConfig.series) this.currentConfig.series = [];
this.currentConfig.yFields = JSON.parse(this.currentConfig.yFieldsJson);
} catch (e) {
console.error('Invalid JSON for yFields:', e);
alert('Invalid JSON format for Y-Axis Fields. Please correct it.');
return;
} }
} }
if (this.currentConfig.seriesJson) {
try { // Methods for Grid-like Widgets
this.currentConfig.series = JSON.parse(this.currentConfig.seriesJson); addGridColumn() {
} catch (e) { this.currentConfig.columns.push({ field: '', headerText: '', width: 100, isPrimary: false });
console.error('Invalid JSON for series:', e);
alert('Invalid JSON format for Series. Please correct it.');
return;
} }
removeGridColumn(index: number) {
this.currentConfig.columns.splice(index, 1);
} }
// Methods for ChartWidgetComponent & ComboChartWidgetComponent yFields
addChartYField() {
this.currentConfig.yFields.push('');
} }
// Special handling for MatrixWidgetComponent's columns
if (this.widgetType === 'MatrixWidgetComponent' && this.currentConfig.columnsJson) { removeChartYField(index: number) {
try { this.currentConfig.yFields.splice(index, 1);
this.currentConfig.columns = JSON.parse(this.currentConfig.columnsJson);
} catch (e) {
console.error('Invalid JSON for columns:', e);
alert('Invalid JSON format for Columns. Please correct it.');
return; // Prevent closing dialog with invalid data
} }
// Methods for ComboChartWidgetComponent series
addComboSeries() {
this.currentConfig.series.push({ name: '', type: 'Line', xName: '', yName: '' });
} }
removeComboSeries(index: number) {
this.currentConfig.series.splice(index, 1);
}
// Methods for SyncfusionPivotWidgetComponent
addPivotRow() { this.currentConfig.rows.push({ name: '' }); }
removePivotRow(index: number) { this.currentConfig.rows.splice(index, 1); }
addPivotColumn() { this.currentConfig.columns.push({ name: '' }); }
removePivotColumn(index: number) { this.currentConfig.columns.splice(index, 1); }
addPivotValue() { this.currentConfig.values.push({ name: '', caption: '' }); }
removePivotValue(index: number) { this.currentConfig.values.splice(index, 1); }
addPivotFilter() { this.currentConfig.filters.push({ name: '' }); }
removePivotFilter(index: number) { this.currentConfig.filters.splice(index, 1); }
onSave(): void {
// No more JSON parsing needed for the refactored widgets
this.dialogRef.close(this.currentConfig); this.dialogRef.close(this.currentConfig);
} }
......
...@@ -129,18 +129,6 @@ export class DashboardViewerComponent implements OnInit { ...@@ -129,18 +129,6 @@ export class DashboardViewerComponent implements OnInit {
mapWidgetsToPanels(widgets: WidgetModel[]): DashboardPanel[] { mapWidgetsToPanels(widgets: WidgetModel[]): DashboardPanel[] {
return widgets.map(widget => { return widgets.map(widget => {
let widgetConfig: any = {};
if (typeof widget.config === 'string') {
try {
widgetConfig = JSON.parse(widget.config);
} catch (e) {
console.error('Error parsing widget config string:', widget.config, e);
widgetConfig = {}; // Default to empty object on error
}
} else {
widgetConfig = widget.config || {};
}
return { return {
id: widget.widgetId, id: widget.widgetId,
header: widget.thName, header: widget.thName,
...@@ -149,7 +137,7 @@ export class DashboardViewerComponent implements OnInit { ...@@ -149,7 +137,7 @@ export class DashboardViewerComponent implements OnInit {
row: widget.y, row: widget.y,
col: widget.x, col: widget.x,
componentType: this.widgetComponentMap[widget.component], componentType: this.widgetComponentMap[widget.component],
componentInputs: { config: widgetConfig }, componentInputs: { config: widget.config || {} },
}; };
}); });
} }
......
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