Commit 7d32073b by Ooh-Ao

ดาต้า source

parent fafd66a2
......@@ -683,43 +683,32 @@ export class DashboardManagementComponent implements OnInit {
}
saveLayout(): void {
console.log('saveLayout called. Dashboard data to save:', this.dashboardData);
if (!this.dashboardData) return;
const dataFetchTasks: Observable<any>[] = this.dashboardData.widgets
.filter(widget => widget.component === 'NewDataTableWidget' && widget.config?.source?.url)
.map(widget =>
this.widgetDataService.fetchDataForWidget(widget.config).pipe(
tap(data => {
// Mutate the config object to include the fetched data
widget.config.data = data;
})
)
);
// Create a deep copy to avoid mutating the component's state
const dashboardToSave = JSON.parse(JSON.stringify(this.dashboardData));
if (dataFetchTasks.length > 0) {
forkJoin(dataFetchTasks).subscribe(() => {
console.log('All data fetched, now saving dashboard...');
this.dashboardDataService.saveDashboard(this.dashboardData!).pipe(
catchError(error => {
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(
catchError(error => {
this.notificationService.error('Error', 'Failed to save dashboard layout.');
return throwError(() => error);
})
).subscribe(() => {
this.notificationService.success('Success', 'Dashboard layout saved successfully!');
// Stringify all widget configs before saving
if (dashboardToSave.widgets) {
dashboardToSave.widgets.forEach((widget: WidgetModel) => {
if (widget.config && typeof widget.config === 'object') {
widget.config = JSON.stringify(widget.config);
}
});
}
console.log('Saving dashboard with stringified configs:', dashboardToSave);
this.dashboardDataService.saveDashboard(dashboardToSave).pipe(
catchError(error => {
this.notificationService.error('Error', 'Failed to save dashboard layout.');
return throwError(() => error);
})
).subscribe(() => {
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
......
......@@ -6,6 +6,8 @@ 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 { MatIconModule } from '@angular/material/icon';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { FormsModule } from '@angular/forms';
export interface WidgetConfigDialogData {
......@@ -24,7 +26,9 @@ export interface WidgetConfigDialogData {
MatInputModule,
MatSelectModule,
MatButtonModule,
MatDialogModule // Add MatDialogModule
MatDialogModule,
MatIconModule,
MatCheckboxModule
],
templateUrl: './widget-config.component.html',
styleUrls: ['./widget-config.component.scss']
......@@ -33,6 +37,7 @@ export class WidgetConfigComponent implements OnInit {
currentConfig: any;
availableColumns: string[];
widgetType: string;
comboChartTypes: string[] = ['Line', 'Column', 'Area', 'Spline'];
constructor(
public dialogRef: MatDialogRef<WidgetConfigComponent>,
......@@ -40,140 +45,85 @@ export class WidgetConfigComponent implements OnInit {
) { }
ngOnInit(): void {
this.currentConfig = { ...this.data.config }; // Create a copy to avoid direct mutation
this.availableColumns = this.data.availableColumns;
this.widgetType = this.data.widgetType;
// Special handling for ChartWidgetComponent's yFields
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);
// Handle config whether it is a string or an object
try {
if (typeof this.data.config === 'string') {
this.currentConfig = JSON.parse(this.data.config);
} else {
// Deep copy config to avoid direct mutation of the original object
this.currentConfig = JSON.parse(JSON.stringify(this.data.config || {}));
}
} catch (e) {
console.error('Error parsing widget config:', e);
this.currentConfig = {}; // Default to empty object on error
}
// 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 {
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; // 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 SyncfusionDatagridWidgetComponent's columns
if (this.widgetType === 'SyncfusionDatagridWidgetComponent' && 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 SyncfusionPivotWidgetComponent's properties
if (this.widgetType === 'SyncfusionPivotWidgetComponent') {
if (this.currentConfig.rowsJson) {
try {
this.currentConfig.rows = JSON.parse(this.currentConfig.rowsJson);
} catch (e) {
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) {
try {
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;
}
}
if (!this.currentConfig.rows) this.currentConfig.rows = [];
if (!this.currentConfig.columns) this.currentConfig.columns = [];
if (!this.currentConfig.values) this.currentConfig.values = [];
if (!this.currentConfig.filters) this.currentConfig.filters = [];
}
// 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
}
if (this.widgetType === 'ChartWidgetComponent' && !this.currentConfig.yFields) {
this.currentConfig.yFields = [];
}
// Special handling for ComboChartWidgetComponent's yFields and series
if (this.widgetType === 'ComboChartWidgetComponent') {
if (this.currentConfig.yFieldsJson) {
try {
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 {
this.currentConfig.series = JSON.parse(this.currentConfig.seriesJson);
} catch (e) {
console.error('Invalid JSON for series:', e);
alert('Invalid JSON format for Series. Please correct it.');
return;
}
}
}
// Special handling for MatrixWidgetComponent's columns
if (this.widgetType === 'MatrixWidgetComponent' && 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
}
if (!this.currentConfig.yFields) this.currentConfig.yFields = [];
if (!this.currentConfig.series) this.currentConfig.series = [];
}
}
// Methods for Grid-like Widgets
addGridColumn() {
this.currentConfig.columns.push({ field: '', headerText: '', width: 100, isPrimary: false });
}
removeGridColumn(index: number) {
this.currentConfig.columns.splice(index, 1);
}
// Methods for ChartWidgetComponent & ComboChartWidgetComponent yFields
addChartYField() {
this.currentConfig.yFields.push('');
}
removeChartYField(index: number) {
this.currentConfig.yFields.splice(index, 1);
}
// 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);
}
......
......@@ -129,18 +129,6 @@ export class DashboardViewerComponent implements OnInit {
mapWidgetsToPanels(widgets: WidgetModel[]): DashboardPanel[] {
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 {
id: widget.widgetId,
header: widget.thName,
......@@ -149,7 +137,7 @@ export class DashboardViewerComponent implements OnInit {
row: widget.y,
col: widget.x,
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