Commit 5c675edd by Ooh-Ao

aa

parent 090de8bc
<div *ngIf="errorMessage$ | async as errorMessage" class="alert alert-danger">{{errorMessage}}</div>
<div class="flex h-screen bg-gray-50">
<!-- Widget Sidebar -->
......
......@@ -5,12 +5,10 @@ import { ActivatedRoute, RouterModule } from '@angular/router';
import { CommonModule, TitleCasePipe } from '@angular/common';
import { NgComponentOutlet } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { Observable, of } from 'rxjs';
import { DashboardModel, WidgetModel, DatasetModel } from '../models/widgets.model';
import * as DashboardActions from '../state/dashboard.actions';
import * as DashboardSelectors from '../state/dashboard.selectors';
import { DashboardDataService } from '../services/dashboard-data.service';
// Import all the widget components
import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component';
......@@ -26,7 +24,6 @@ import { SyncfusionDatagridWidgetComponent } from '../widgets/syncfusion-datagri
import { SyncfusionPivotWidgetComponent } from '../widgets/syncfusion-pivot-widget/syncfusion-pivot-widget.component';
import { SyncfusionChartWidgetComponent } from '../widgets/syncfusion-chart-widget/syncfusion-chart-widget.component';
import { DatasetPickerComponent } from './dataset-picker.component';
import { MockDashboardService } from '../services/mock-dashboard.service';
@Component({
selector: 'app-dashboard-management',
......@@ -44,15 +41,11 @@ export class DashboardManagementComponent implements OnInit {
public filteredAvailableWidgets: WidgetModel[] = [];
public widgetSearchTerm: string = '';
public dashboardData: DashboardModel;
public dashboardData: DashboardModel | null = null;
public userDashboards: DashboardModel[] = [];
public selectedDashboardId: string = '';
public userDashboards$: Observable<DashboardModel[]>;
public availableWidgets$: Observable<WidgetModel[]>;
public errorMessage$: Observable<string | null>;
private widgetComponentMap: { [key: string]: Type<any> } = {
'CompanyInfoWidgetComponent': CompanyInfoWidgetComponent,
'HeadcountWidgetComponent': HeadcountWidgetComponent,
......@@ -69,24 +62,24 @@ export class DashboardManagementComponent implements OnInit {
};
constructor(
private store: Store,
private route: ActivatedRoute,
private mockDashboardService: MockDashboardService
private dashboardDataService: DashboardDataService
) { }
ngOnInit(): void {
this.store.dispatch(DashboardActions.loadDashboards());
this.store.dispatch(DashboardActions.loadWidgets());
this.userDashboards$ = this.store.select(DashboardSelectors.selectAllDashboards);
this.availableWidgets$ = this.store.select(DashboardSelectors.selectAllWidgets);
this.errorMessage$ = this.store.select(DashboardSelectors.selectError);
this.mockDashboardService.getDashboards().subscribe(dashboards => {
this.dashboardDataService.getDashboards().subscribe(dashboards => {
this.userDashboards = dashboards;
if (this.userDashboards.length > 0) {
this.selectedDashboardId = this.userDashboards[0].id;
this.loadSelectedDashboard();
}
});
// Assuming availableWidgets are loaded from a separate service or hardcoded for now
// If they come from an API, DashboardDataService should provide a getWidgets() method
// For now, we'll just use the mock service's getWidgets if it exists, or hardcode them.
// Since MockDashboardService doesn't have getWidgets(), we'll leave availableWidgets empty for now
// or you can populate it with static data if needed for testing the widget sidebar.
this.availableWidgets = []; // Or populate with static data if needed
}
......@@ -108,7 +101,7 @@ export class DashboardManagementComponent implements OnInit {
loadSelectedDashboard(): void {
if (this.selectedDashboardId) {
this.store.select(DashboardSelectors.selectDashboardById(this.selectedDashboardId)).subscribe(dashboard => {
this.dashboardDataService.getDashboardById(this.selectedDashboardId).subscribe(dashboard => {
if (dashboard) {
this.dashboardData = dashboard;
this.panels = this.mapWidgetsToPanels(dashboard.widgets || []);
......@@ -126,13 +119,17 @@ export class DashboardManagementComponent implements OnInit {
name: newDashboardName,
widgets: []
});
this.store.dispatch(DashboardActions.addDashboard({ dashboard: newDashboard }));
this.dashboardDataService.addDashboard(newDashboard).subscribe(addedDashboard => {
this.userDashboards.push(addedDashboard);
this.selectedDashboardId = addedDashboard.id;
this.loadSelectedDashboard();
});
}
}
saveDashboardName(): void {
if (this.dashboardData) {
this.store.dispatch(DashboardActions.updateDashboard({ dashboard: this.dashboardData }));
this.dashboardDataService.updateDashboard(this.dashboardData).subscribe();
}
}
......@@ -145,17 +142,18 @@ export class DashboardManagementComponent implements OnInit {
row: widget.y,
col: widget.x,
componentType: this.widgetComponentMap[widget.component],
componentInputs: { ...widget.data, datasetId: this.dashboardData.datasetId }
componentInputs: { ...widget.data, datasetId: this.dashboardData?.datasetId }
}));
}
saveLayout(): void {
if (!this.dashboardData) return;
this.store.dispatch(DashboardActions.updateDashboard({ dashboard: this.dashboardData }));
this.dashboardDataService.updateDashboard(this.dashboardData).subscribe();
}
addWidgetToDashboard(widget: WidgetModel): void {
if (!this.dashboardData) return; // Add null check
if (this.dashboardData.widgets.find(w => w.id === widget.id)) {
alert('Widget already exists in the dashboard.');
return;
......@@ -166,14 +164,31 @@ export class DashboardManagementComponent implements OnInit {
deleteDashboard(): void {
if (this.selectedDashboardId && confirm('Are you sure you want to delete this dashboard?')) {
this.store.dispatch(DashboardActions.deleteDashboard({ id: this.selectedDashboardId }));
this.dashboardDataService.deleteDashboard(this.selectedDashboardId).subscribe(() => {
// After deletion, reload dashboards and select the first one or clear selection
this.dashboardDataService.getDashboards().subscribe(dashboards => {
this.userDashboards = dashboards;
if (this.userDashboards.length > 0) {
this.selectedDashboardId = this.userDashboards[0].id;
this.loadSelectedDashboard();
} else {
this.selectedDashboardId = '';
this.dashboardData = null; // Clear dashboard data if no dashboards left
this.panels = [];
}
});
});
}
}
removeWidgetFromDashboard(panelId: string): void {
if (!this.dashboardData) return; // Add null check
if (confirm('Are you sure you want to remove this widget?')) {
const updatedDashboard = { ...this.dashboardData, widgets: this.dashboardData.widgets.filter(w => w.id !== panelId) };
this.store.dispatch(DashboardActions.updateDashboard({ dashboard: updatedDashboard }));
this.dashboardDataService.updateDashboard(updatedDashboard).subscribe(updated => {
this.dashboardData = updated;
this.panels = this.mapWidgetsToPanels(this.dashboardData.widgets);
});
}
}
......
......@@ -3,12 +3,10 @@ import { Component, OnInit, Type, ChangeDetectionStrategy } from '@angular/core'
import { CommonModule } from '@angular/common';
import { ActivatedRoute, RouterModule } from '@angular/router';
import { DashboardLayoutModule, PanelModel } from '@syncfusion/ej2-angular-layouts';
import { Store } from '@ngrx/store';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { of } from 'rxjs';
import { NgComponentOutlet } from '@angular/common'; // Import NgComponentOutlet
import * as DashboardActions from '../state/dashboard.actions';
import * as DashboardSelectors from '../state/dashboard.selectors';
import { DashboardDataService } from '../services/dashboard-data.service';
import { DashboardModel } from '../models/widgets.model';
// Import all the widget components
......@@ -61,7 +59,7 @@ export class DashboardViewerComponent implements OnInit {
constructor(
private route: ActivatedRoute,
private store: Store
private dashboardDataService: DashboardDataService
) { }
ngOnInit(): void {
......@@ -72,8 +70,7 @@ export class DashboardViewerComponent implements OnInit {
console.error('Dashboard ID is missing from the route.');
return of(null);
}
this.store.dispatch(DashboardActions.loadDashboards());
return this.store.select(DashboardSelectors.selectDashboardById(id));
return this.dashboardDataService.getDashboardById(id);
})
).subscribe({
next: dashboard => {
......
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { DashboardModel, WidgetModel } from '../models/widgets.model';
import { MockDashboardService } from './mock-dashboard.service';
@Injectable({
providedIn: 'root'
})
export class DashboardDataService {
constructor(private mockDashboardService: MockDashboardService) { }
getDashboards(): Observable<DashboardModel[]> {
// In a real application, this would call an API
return this.mockDashboardService.getDashboards();
}
getDashboardById(id: string): Observable<DashboardModel | undefined> {
// In a real application, this would call an API
return this.mockDashboardService.getDashboardById(id);
}
// For now, these methods will operate on the in-memory mock data
// In a real application, these would call API endpoints for CUD operations
addDashboard(dashboard: DashboardModel): Observable<DashboardModel> {
// Simulate adding to mock data (not persistent across app restarts)
const currentDashboards = this.mockDashboardService.getDashboards();
currentDashboards.subscribe(dashboards => {
dashboards.push(dashboard);
});
return of(dashboard);
}
updateDashboard(updatedDashboard: DashboardModel): Observable<DashboardModel> {
// Simulate updating mock data (not persistent across app restarts)
const currentDashboards = this.mockDashboardService.getDashboards();
currentDashboards.subscribe(dashboards => {
const index = dashboards.findIndex(d => d.id === updatedDashboard.id);
if (index > -1) {
dashboards[index] = updatedDashboard;
}
});
return of(updatedDashboard);
}
deleteDashboard(id: string): Observable<void> {
// Simulate deleting from mock data (not persistent across app restarts)
const currentDashboards = this.mockDashboardService.getDashboards();
currentDashboards.subscribe(dashboards => {
const index = dashboards.findIndex(d => d.id === id);
if (index > -1) {
dashboards.splice(index, 1);
}
});
return of(undefined);
}
// Assuming widgets are managed as part of dashboards for now
// If widgets were separate entities, you'd have getWidgets, addWidget, etc.
}
......@@ -20,6 +20,25 @@ export const MOCK_DASHBOARD_DATA: DashboardModel[] = [
{ id: '201', name: 'Website Traffic', component: 'ChartWidgetComponent', cols: 2, rows: 1, x: 0, y: 0, data: { type: 'line', labels: ['Week 1', 'Week 2', 'Week 3'], datasets: [{ data: [120, 150, 130], label: 'Visitors' }] } },
{ id: '202', name: 'Conversion Rate', component: 'KpiWidgetComponent', cols: 1, rows: 1, x: 2, y: 0, data: { value: '2.5%', label: 'Conversion' } }
]
},
{
id: '3',
name: 'All Widgets Test Dashboard',
description: 'Dashboard for testing all available widgets.',
widgets: [
{ id: '301', name: 'Company Info', component: 'CompanyInfoWidgetComponent', cols: 2, rows: 1, x: 0, y: 0, data: { companyName: 'Test Company', address: '123 Test St.' } },
{ id: '302', name: 'Headcount', component: 'HeadcountWidgetComponent', cols: 1, rows: 1, x: 2, y: 0, data: { count: 150 } },
{ id: '303', name: 'Attendance Overview', component: 'AttendanceOverviewWidgetComponent', cols: 2, rows: 1, x: 3, y: 0, data: { present: 140, absent: 10 } },
{ id: '304', name: 'Payroll Summary', component: 'PayrollSummaryWidgetComponent', cols: 2, rows: 1, x: 0, y: 1, data: { totalPayroll: 100000, currency: 'USD' } },
{ id: '305', name: 'Employee Directory', component: 'EmployeeDirectoryWidgetComponent', cols: 2, rows: 2, x: 2, y: 1, data: { employees: [{ name: 'Alice', dept: 'HR' }, { name: 'Bob', dept: 'IT' }] } },
{ id: '306', name: 'KPI Widget', component: 'KpiWidgetComponent', cols: 1, rows: 1, x: 4, y: 1, data: { value: '95%', label: 'Success Rate' } },
{ id: '307', name: 'Welcome Widget', component: 'WelcomeWidgetComponent', cols: 2, rows: 1, x: 0, y: 3, data: { message: 'Welcome to the Dashboard!' } },
{ id: '308', name: 'Chart Widget', component: 'ChartWidgetComponent', cols: 2, rows: 1, x: 2, y: 3, data: { type: 'bar', labels: ['A', 'B', 'C'], datasets: [{ data: [10, 20, 30], label: 'Data' }] } },
{ id: '309', name: 'Quick Links', component: 'QuickLinksWidgetComponent', cols: 1, rows: 1, x: 4, y: 3, data: { links: [{ name: 'Google', url: 'https://google.com' }] } },
{ id: '310', name: 'Syncfusion Datagrid', component: 'SyncfusionDatagridWidgetComponent', cols: 3, rows: 2, x: 0, y: 4, data: { columns: ['ID', 'Name'], data: [{ ID: 1, Name: 'Item 1' }, { ID: 2, Name: 'Item 2' }] } },
{ id: '311', name: 'Syncfusion Pivot', component: 'SyncfusionPivotWidgetComponent', cols: 3, rows: 2, x: 3, y: 4, data: { data: [{ year: '2023', sales: 100 }, { year: '2024', sales: 120 }], rows: [{ name: 'year' }], columns: [{ name: 'sales' }] } },
{ id: '312', name: 'Syncfusion Chart', component: 'SyncfusionChartWidgetComponent', cols: 2, rows: 1, x: 0, y: 6, data: { chartData: [{ x: 'Jan', y: 10 }, { x: 'Feb', y: 20 }], primaryXAxis: { valueType: 'Category' }, series: [{ type: 'Column', xName: 'x', yName: 'y' }] } }
]
}
];
......
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