Commit c9833196 by Ooh-Ao

config

parent 041bbcaf
...@@ -80,8 +80,8 @@ ...@@ -80,8 +80,8 @@
(change)="loadSelectedDashboard()" (change)="loadSelectedDashboard()"
class="p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white" class="p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white"
> >
<option *ngFor="let dash of userDashboards" [value]="dash.id"> <option *ngFor="let dash of userDashboards" [ngValue]="dash">
{{ dash.name }} {{ dash.thName }}
</option> </option>
</select> </select>
<app-dataset-picker <app-dataset-picker
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
<div *ngIf="dashboardData" class="relative flex items-center"> <div *ngIf="dashboardData" class="relative flex items-center">
<input <input
type="text" type="text"
[(ngModel)]="dashboardData.name" [(ngModel)]="dashboardData.thName"
(blur)="saveDashboardName()" (blur)="saveDashboardName()"
class="p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white text-gray-800 font-semibold" class="p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white text-gray-800 font-semibold"
/> />
...@@ -137,7 +137,7 @@ ...@@ -137,7 +137,7 @@
</div> </div>
<div class="dashboard-content"> <div class="dashboard-content">
<ejs-dashboardlayout <ejs-dashboardlayout
[columns]="6" [columns]="6"
#editLayout #editLayout
......
...@@ -111,7 +111,7 @@ export class DashboardManagementComponent implements OnInit { ...@@ -111,7 +111,7 @@ export class DashboardManagementComponent implements OnInit {
public dashboardData: DashboardModel | null = null; public dashboardData: DashboardModel | null = null;
public userDashboards: DashboardModel[] = []; public userDashboards: DashboardModel[] = [];
public selectedDashboardId: string = ''; public selectedDashboardId: DashboardModel
private localWidgets: WidgetModel[] = [ private localWidgets: WidgetModel[] = [
new WidgetModel({ new WidgetModel({
...@@ -212,6 +212,15 @@ export class DashboardManagementComponent implements OnInit { ...@@ -212,6 +212,15 @@ export class DashboardManagementComponent implements OnInit {
component: 'ScatterBubbleChartWidgetComponent', component: 'ScatterBubbleChartWidgetComponent',
cols: 3, cols: 3,
rows: 2, rows: 2,
config: {
title: 'Employee Performance vs. Salary (Scatter)',
source: { type: 'url', url: 'assets/data/employee-data.json' },
xField: 'performanceScore',
yField: 'salary',
xAxisTitle: 'Performance Score',
yAxisTitle: 'Salary',
type: 'Scatter'
}
}), }),
new WidgetModel({ new WidgetModel({
id: 'local-multi-row-card', id: 'local-multi-row-card',
...@@ -377,10 +386,10 @@ export class DashboardManagementComponent implements OnInit { ...@@ -377,10 +386,10 @@ export class DashboardManagementComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
this.dashboardDataService.getDashboards().subscribe(dashboards => { this.dashboardDataService.getDashboards().subscribe(dashboards => {
this.userDashboards = dashboards; this.userDashboards = dashboards;
if (this.userDashboards.length > 0) { // if (this.userDashboards.length > 0) {
this.selectedDashboardId = this.userDashboards[0].id; // this.selectedDashboardId = this.userDashboards[0];
this.loadSelectedDashboard(); // this.loadSelectedDashboard();
} // }
}); });
// Populate availableWidgets from WidgetService // Populate availableWidgets from WidgetService
...@@ -410,8 +419,9 @@ export class DashboardManagementComponent implements OnInit { ...@@ -410,8 +419,9 @@ export class DashboardManagementComponent implements OnInit {
} }
loadSelectedDashboard(): void { loadSelectedDashboard(): void {
console.log(this.selectedDashboardId)
if (this.selectedDashboardId) { if (this.selectedDashboardId) {
this.dashboardDataService.getDashboardById(this.selectedDashboardId).subscribe(dashboard => { this.dashboardDataService.getDashboardById(this.selectedDashboardId.dashboardId).subscribe(dashboard => {
if (dashboard) { if (dashboard) {
this.dashboardData = dashboard; this.dashboardData = dashboard;
this.panels = this.mapWidgetsToPanels(dashboard.widgets || []); this.panels = this.mapWidgetsToPanels(dashboard.widgets || []);
...@@ -427,13 +437,13 @@ export class DashboardManagementComponent implements OnInit { ...@@ -427,13 +437,13 @@ export class DashboardManagementComponent implements OnInit {
const newDashboardName = prompt('Enter a name for the new dashboard:'); const newDashboardName = prompt('Enter a name for the new dashboard:');
if (newDashboardName) { if (newDashboardName) {
const newDashboard = new DashboardModel({ const newDashboard = new DashboardModel({
id: `dash-${Date.now()}`, dashboardId: `dash-${Date.now()}`,
name: newDashboardName, thName: newDashboardName,
widgets: [] widgets: []
}); });
this.dashboardDataService.addDashboard(newDashboard).subscribe(addedDashboard => { this.dashboardDataService.saveDashboard(newDashboard).subscribe(addedDashboard => {
this.userDashboards.push(addedDashboard); this.userDashboards.push(addedDashboard);
this.selectedDashboardId = addedDashboard.id; this.selectedDashboardId = addedDashboard;
this.loadSelectedDashboard(); this.loadSelectedDashboard();
}); });
} }
...@@ -441,7 +451,7 @@ export class DashboardManagementComponent implements OnInit { ...@@ -441,7 +451,7 @@ export class DashboardManagementComponent implements OnInit {
saveDashboardName(): void { saveDashboardName(): void {
if (this.dashboardData) { if (this.dashboardData) {
this.dashboardDataService.updateDashboard(this.dashboardData).subscribe(); this.dashboardDataService.saveDashboard(this.dashboardData).subscribe();
} }
} }
...@@ -451,7 +461,7 @@ export class DashboardManagementComponent implements OnInit { ...@@ -451,7 +461,7 @@ export class DashboardManagementComponent implements OnInit {
// Ensure widget.config exists, initialize if not. // Ensure widget.config exists, initialize if not.
const widgetConfig = widget.config || {}; const widgetConfig = widget.config || {};
return { return {
id: widget.id, id: widget.id,
...@@ -484,11 +494,11 @@ export class DashboardManagementComponent implements OnInit { ...@@ -484,11 +494,11 @@ export class DashboardManagementComponent implements OnInit {
if (dataFetchTasks.length > 0) { if (dataFetchTasks.length > 0) {
forkJoin(dataFetchTasks).subscribe(() => { forkJoin(dataFetchTasks).subscribe(() => {
console.log('All data fetched, now saving dashboard...'); console.log('All data fetched, now saving dashboard...');
this.dashboardDataService.updateDashboard(this.dashboardData!).subscribe(); this.dashboardDataService.saveDashboard(this.dashboardData!).subscribe();
}); });
} else { } else {
console.log('No data to fetch, saving dashboard directly...'); console.log('No data to fetch, saving dashboard directly...');
this.dashboardDataService.updateDashboard(this.dashboardData).subscribe(); this.dashboardDataService.saveDashboard(this.dashboardData).subscribe();
} }
} }
...@@ -538,18 +548,9 @@ export class DashboardManagementComponent implements OnInit { ...@@ -538,18 +548,9 @@ export class DashboardManagementComponent implements OnInit {
deleteDashboard(): void { deleteDashboard(): void {
if (this.selectedDashboardId && confirm('Are you sure you want to delete this dashboard?')) { if (this.selectedDashboardId && confirm('Are you sure you want to delete this dashboard?')) {
this.dashboardDataService.deleteDashboard(this.selectedDashboardId).subscribe(() => { this.dashboardDataService.deleteDashboard(this.selectedDashboardId).subscribe(result => {
this.dashboardDataService.getDashboards().subscribe(dashboards => {
this.userDashboards = dashboards; console.log(result)
if (this.userDashboards.length > 0) {
this.selectedDashboardId = this.userDashboards[0].id;
this.loadSelectedDashboard();
} else {
this.selectedDashboardId = '';
this.dashboardData = null;
this.panels = [];
}
});
}); });
} }
} }
...@@ -558,7 +559,7 @@ export class DashboardManagementComponent implements OnInit { ...@@ -558,7 +559,7 @@ export class DashboardManagementComponent implements OnInit {
if (!this.dashboardData) return; if (!this.dashboardData) return;
if (confirm('Are you sure you want to remove this widget?')) { if (confirm('Are you sure you want to remove this widget?')) {
const updatedDashboard = { ...this.dashboardData, widgets: this.dashboardData.widgets.filter(w => w.id !== panelId) }; const updatedDashboard = { ...this.dashboardData, widgets: this.dashboardData.widgets.filter(w => w.id !== panelId) };
this.dashboardDataService.updateDashboard(updatedDashboard).subscribe(updated => { this.dashboardDataService.saveDashboard(updatedDashboard).subscribe(updated => {
this.dashboardData = updated; this.dashboardData = updated;
this.panels = this.mapWidgetsToPanels(this.dashboardData.widgets); this.panels = this.mapWidgetsToPanels(this.dashboardData.widgets);
}); });
...@@ -597,7 +598,7 @@ export class DashboardManagementComponent implements OnInit { ...@@ -597,7 +598,7 @@ export class DashboardManagementComponent implements OnInit {
// Re-map panels to reflect changes // Re-map panels to reflect changes
this.panels = this.mapWidgetsToPanels(this.dashboardData.widgets); this.panels = this.mapWidgetsToPanels(this.dashboardData.widgets);
// Save the updated dashboard // Save the updated dashboard
this.dashboardDataService.updateDashboard(this.dashboardData).subscribe(); this.dashboardDataService.saveDashboard(this.dashboardData).subscribe();
} }
} }
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<label for="dataset-select">Select Dataset:</label> <label for="dataset-select">Select Dataset:</label>
<select id="dataset-select" (change)="onDatasetChange($event)"> <select id="dataset-select" (change)="onDatasetChange($event)">
<option value="">-- Please choose a dataset --</option> <option value="">-- Please choose a dataset --</option>
<option *ngFor="let dataset of datasets$ | async" [value]="dataset.id"> <option *ngFor="let dataset of datasets$ | async" [value]="dataset">
{{ dataset.name }} {{ dataset.name }}
</option> </option>
</select> </select>
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
margin-bottom: 20px;
} }
label { label {
......
...@@ -147,7 +147,7 @@ export class DashboardViewerComponent implements OnInit { ...@@ -147,7 +147,7 @@ export class DashboardViewerComponent implements OnInit {
} }
loadDashboard(dashboard: DashboardModel): void { loadDashboard(dashboard: DashboardModel): void {
this.dashboardName = dashboard.name; this.dashboardName = dashboard.thName;
if (dashboard.datasetId) { if (dashboard.datasetId) {
this.dashboardStateService.selectDataset(dashboard.datasetId); this.dashboardStateService.selectDataset(dashboard.datasetId);
......
...@@ -57,23 +57,29 @@ export class WidgetModel implements IWidget { ...@@ -57,23 +57,29 @@ export class WidgetModel implements IWidget {
} }
export interface IDashboard { export interface IDashboard {
id: string; dashboardId: string;
name: string; thName: string;
engName: string;
application: string;
description: string; description: string;
datasetId?: string; datasetId?: string;
widgets: IWidget[]; widgets: IWidget[];
} }
export class DashboardModel implements IDashboard { export class DashboardModel implements IDashboard {
id: string; dashboardId: string;
name: string; thName: string;
engName: string;
application: string;
description: string; description: string;
datasetId?: string; datasetId?: string;
widgets: IWidget[]; widgets: IWidget[];
constructor(data: Partial<IDashboard>) { constructor(data: Partial<IDashboard>) {
this.id = data.id ?? ''; this.dashboardId = data.dashboardId ?? '';
this.name = data.name ?? ''; this.thName = data.thName ?? '';
this.engName = data.engName ?? '';
this.application = data.application ?? '';
this.description = data.description ?? ''; this.description = data.description ?? '';
this.datasetId = data.datasetId; this.datasetId = data.datasetId;
this.widgets = data.widgets ? data.widgets.map(w => new WidgetModel(w)) : []; this.widgets = data.widgets ? data.widgets.map(w => new WidgetModel(w)) : [];
......
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { DashboardModel, WidgetModel } from '../models/widgets.model'; import { DashboardModel, WidgetModel } from '../models/widgets.model';
import { MockDashboardService } from './mock-dashboard.service'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { environment } from '../../../environments/environment';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class DashboardDataService { export class DashboardDataService {
apiBaseUrl = environment.url + "dashboard"
constructor(private mockDashboardService: MockDashboardService) { } constructor(private http: HttpClient) { }
getDashboards(): Observable<DashboardModel[]> { getDashboards(queryParams?: any): Observable<DashboardModel[]> {
// In a real application, this would call an API let params = new HttpParams();
return this.mockDashboardService.getDashboards(); if (queryParams) {
Object.keys(queryParams).forEach(key => {
params = params.set(key, queryParams[key]);
});
}
return this.http.get<DashboardModel[]>(`${this.apiBaseUrl}/lists/search`, { params })
} }
getDashboardById(id: string): Observable<DashboardModel | undefined> { getDashboardById(id: string): Observable<DashboardModel | undefined> {
// In a real application, this would call an API return this.http
return this.mockDashboardService.getDashboardById(id); .get<DashboardModel>(this.apiBaseUrl + "/" + id)
} }
// For now, these methods will operate on the in-memory mock data // For now, these methods will operate on the in-memory mock data
// In a real application, these would call API endpoints for CUD operations // In a real application, these would call API endpoints for CUD operations
addDashboard(dashboard: DashboardModel): Observable<DashboardModel> { saveDashboard(dashboard: DashboardModel): Observable<DashboardModel> {
// Simulate adding to mock data (not persistent across app restarts) return this.http.post<any>(this.apiBaseUrl, dashboard);
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> { deleteDashboard(dashboard: DashboardModel): Observable<void> {
// Simulate deleting from mock data (not persistent across app restarts) const options = {
const currentDashboards = this.mockDashboardService.getDashboards(); headers: new HttpHeaders({
currentDashboards.subscribe(dashboards => { "Content-Type": "application/json",
const index = dashboards.findIndex(d => d.id === id); }),
if (index > -1) { body: {}
dashboards.splice(index, 1); };
} return this.http.delete<any>(this.apiBaseUrl, options);
});
return of(undefined);
} }
// Assuming widgets are managed as part of dashboards for now // Assuming widgets are managed as part of dashboards for now
......
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { DashboardModel, WidgetModel } from '../models/widgets.model';
export const MOCK_DASHBOARD_DATA: DashboardModel[] = [
{
id: '1',
name: 'Sales Dashboard',
description: 'Dashboard showing sales performance over time.',
widgets: [
{ id: '101', name: 'Monthly Sales', component: 'ChartWidgetComponent', cols: 2, rows: 1, x: 0, y: 0, data: { type: 'bar', labels: ['Jan', 'Feb', 'Mar'], datasets: [{ data: [65, 59, 80], label: 'Series A' }] }, config: {} },
{ id: '102', name: 'Top Products', component: 'SyncfusionDatagridWidgetComponent', cols: 2, rows: 1, x: 2, y: 0, data: { columns: ['Product', 'Sales'], data: [{ Product: 'A', Sales: 100 }, { Product: 'B', Sales: 150 }] }, config: {} }
]
},
{
id: '2',
name: 'Marketing Overview',
description: 'Overview of marketing campaign performance.',
widgets: [
{ 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' }] }, config: {} },
{ id: '202', name: 'Conversion Rate', component: 'KpiWidgetComponent', cols: 1, rows: 1, x: 2, y: 0, data: { value: '2.5%', label: 'Conversion' }, config: {} }
]
},
{
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.' }, config: {} },
{ id: '302', name: 'Headcount', component: 'HeadcountWidgetComponent', cols: 1, rows: 1, x: 2, y: 0, data: { count: 150 }, config: {} },
{ id: '303', name: 'Attendance Overview', component: 'AttendanceOverviewWidgetComponent', cols: 2, rows: 1, x: 3, y: 0, data: { present: 140, absent: 10 }, config: {} },
{ id: '304', name: 'Payroll Summary', component: 'PayrollSummaryWidgetComponent', cols: 2, rows: 1, x: 0, y: 1, data: { totalPayroll: 100000, currency: 'USD' }, config: {} },
{ 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' }] }, config: {} },
{ id: '306', name: 'KPI Widget', component: 'KpiWidgetComponent', cols: 1, rows: 1, x: 4, y: 1, data: { value: '95%', label: 'Success Rate' }, config: {} },
{ id: '307', name: 'Welcome Widget', component: 'WelcomeWidgetComponent', cols: 2, rows: 1, x: 0, y: 3, data: { message: 'Welcome to the Dashboard!' }, config: {} },
{ 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' }] }, config: {} },
{ id: '309', name: 'Quick Links', component: 'QuickLinksWidgetComponent', cols: 1, rows: 1, x: 4, y: 3, data: { links: [{ name: 'Google', url: 'https://google.com' }] }, config: {} },
{ 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' }] }, config: {} },
{ 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' }] }, config: {} },
{ 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' }] }, config: {} },
{ id: '313', name: 'Employee Data (Pre-configured)', component: 'NewDataTableWidget', cols: 4, rows: 3, x: 0, y: 7, data: {}, config: {
title: 'Employee List (Pre-configured)',
source: {
type: 'url',
url: 'assets/data/sample1.json'
},
data: [], // This will be populated by the service
columns: [
{ field: 'EmployeeID', headerText: 'ID', width: 70 },
{ field: 'FirstName', headerText: 'First Name', width: 120 },
{ field: 'LastName', headerText: 'Last Name', width: 120 },
{ field: 'Position', headerText: 'Position', width: 150 },
{ field: 'Department', headerText: 'Department', width: 150 },
]
} }
]
}
];
@Injectable({
providedIn: 'root'
})
export class MockDashboardService {
constructor() { }
getDashboards(): Observable<DashboardModel[]> {
return of(MOCK_DASHBOARD_DATA);
}
getDashboardById(id: string): Observable<DashboardModel | undefined> {
const dashboard = MOCK_DASHBOARD_DATA.find(d => d.id === id);
return of(dashboard);
}
}
import { createAction, props } from '@ngrx/store';
import { DashboardModel, WidgetModel, DatasetModel } from '../models/widgets.model';
export const loadDashboards = createAction('[Dashboard] Load Dashboards');
export const loadDashboardsSuccess = createAction('[Dashboard] Load Dashboards Success', props<{ dashboards: DashboardModel[] }>());
export const loadDashboardsFailure = createAction('[Dashboard] Load Dashboards Failure', props<{ error: any }>());
export const loadWidgets = createAction('[Dashboard] Load Widgets');
export const loadWidgetsSuccess = createAction('[Dashboard] Load Widgets Success', props<{ widgets: WidgetModel[] }>());
export const loadWidgetsFailure = createAction('[Dashboard] Load Widgets Failure', props<{ error: any }>());
export const loadDatasets = createAction('[Dashboard] Load Datasets');
export const loadDatasetsSuccess = createAction('[Dashboard] Load Datasets Success', props<{ datasets: DatasetModel[] }>());
export const loadDatasetsFailure = createAction('[Dashboard] Load Datasets Failure', props<{ error: any }>());
export const addDashboard = createAction('[Dashboard] Add Dashboard', props<{ dashboard: DashboardModel }>());
export const addDashboardSuccess = createAction('[Dashboard] Add Dashboard Success', props<{ dashboard: DashboardModel }>());
export const addDashboardFailure = createAction('[Dashboard] Add Dashboard Failure', props<{ error: any }>());
export const updateDashboard = createAction('[Dashboard] Update Dashboard', props<{ dashboard: DashboardModel }>());
export const updateDashboardSuccess = createAction('[Dashboard] Update Dashboard Success', props<{ dashboard: DashboardModel }>());
export const updateDashboardFailure = createAction('[Dashboard] Update Dashboard Failure', props<{ error: any }>());
export const deleteDashboard = createAction('[Dashboard] Delete Dashboard', props<{ id: string }>());
export const deleteDashboardSuccess = createAction('[Dashboard] Delete Dashboard Success', props<{ id: string }>());
export const deleteDashboardFailure = createAction('[Dashboard] Delete Dashboard Failure', props<{ error: any }>());
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { DashboardDataService } from '../../shared/services/dashboard-data.service';
import * as DashboardActions from './dashboard.actions';
@Injectable()
export class DashboardEffects {
loadDashboards$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.loadDashboards),
mergeMap(() => this.dashboardDataService.getDashboards()
.pipe(
map(dashboards => DashboardActions.loadDashboardsSuccess({ dashboards })),
catchError(error => of(DashboardActions.loadDashboardsFailure({ error })))
))
));
loadWidgets$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.loadWidgets),
mergeMap(() => this.dashboardDataService.getWidgets()
.pipe(
map(widgets => DashboardActions.loadWidgetsSuccess({ widgets })),
catchError(error => of(DashboardActions.loadWidgetsFailure({ error })))
))
));
loadDatasets$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.loadDatasets),
mergeMap(() => this.dashboardDataService.getDatasets()
.pipe(
map(datasets => DashboardActions.loadDatasetsSuccess({ datasets })),
catchError(error => of(DashboardActions.loadDatasetsFailure({ error })))
))
));
addDashboard$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.addDashboard),
mergeMap(action => this.dashboardDataService.addDashboard(action.dashboard)
.pipe(
map(dashboard => DashboardActions.addDashboardSuccess({ dashboard })),
catchError(error => of(DashboardActions.addDashboardFailure({ error })))
))
));
updateDashboard$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.updateDashboard),
mergeMap(action => this.dashboardDataService.updateDashboard(action.dashboard)
.pipe(
map(dashboard => DashboardActions.updateDashboardSuccess({ dashboard })),
catchError(error => of(DashboardActions.updateDashboardFailure({ error })))
))
));
deleteDashboard$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.deleteDashboard),
mergeMap(action => this.dashboardDataService.deleteDashboard(action.id)
.pipe(
map(() => DashboardActions.deleteDashboardSuccess({ id: action.id })),
catchError(error => of(DashboardActions.deleteDashboardFailure({ error })))
))
));
constructor(
private actions$: Actions,
private dashboardDataService: DashboardDataService
) {}
}
import { createReducer, on } from '@ngrx/store';
import { DashboardModel, WidgetModel, DatasetModel } from '../models/widgets.model';
import * as DashboardActions from './dashboard.actions';
export interface DashboardState {
dashboards: DashboardModel[];
widgets: WidgetModel[];
datasets: DatasetModel[];
error: any;
}
export const initialState: DashboardState = {
dashboards: [],
widgets: [],
datasets: [],
error: null,
};
export const dashboardReducer = createReducer(
initialState,
on(DashboardActions.loadDashboardsSuccess, (state, { dashboards }) => ({ ...state, dashboards })),
on(DashboardActions.loadDashboardsFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.loadWidgetsSuccess, (state, { widgets }) => ({ ...state, widgets })),
on(DashboardActions.loadWidgetsFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.loadDatasetsSuccess, (state, { datasets }) => ({ ...state, datasets })),
on(DashboardActions.loadDatasetsFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.addDashboardSuccess, (state, { dashboard }) => ({ ...state, dashboards: [...state.dashboards, dashboard] })),
on(DashboardActions.addDashboardFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.updateDashboardSuccess, (state, { dashboard }) => ({
...state,
dashboards: state.dashboards.map(d => d.id === dashboard.id ? dashboard : d)
})),
on(DashboardActions.updateDashboardFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.deleteDashboardSuccess, (state, { id }) => ({
...state,
dashboards: state.dashboards.filter(d => d.id !== id)
})),
on(DashboardActions.deleteDashboardFailure, (state, { error }) => ({ ...state, error }))
);
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { DashboardState } from './dashboard.reducer';
import { DashboardModel } from '../models/widgets.model';
export const selectDashboardState = createFeatureSelector<DashboardState>('dashboard');
export const selectAllDashboards = createSelector(
selectDashboardState,
(state: DashboardState) => state.dashboards
);
export const selectAllWidgets = createSelector(
selectDashboardState,
(state: DashboardState) => state.widgets
);
export const selectAllDatasets = createSelector(
selectDashboardState,
(state: DashboardState) => state.datasets
);
export const selectDashboardById = (id: string) => createSelector(
selectAllDashboards,
(dashboards: DashboardModel[]) => dashboards.find(d => d.id === id)
);
export const selectError = createSelector(
selectDashboardState,
(state: DashboardState) => state.error
);
...@@ -5,7 +5,7 @@ import { ActivatedRoute, Router, RouterModule } from '@angular/router'; ...@@ -5,7 +5,7 @@ import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { NgComponentOutlet } from '@angular/common'; import { NgComponentOutlet } from '@angular/common';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import * as DashboardActions from '../state/dashboard.actions'; // import * as DashboardActions from '../state/dashboard.actions';
import { WidgetModel } from '../models/widgets.model'; import { WidgetModel } from '../models/widgets.model';
// Import all the widget components // Import all the widget components
...@@ -75,7 +75,7 @@ export class WidgetFormComponent implements OnInit { ...@@ -75,7 +75,7 @@ export class WidgetFormComponent implements OnInit {
if (this.widgetId && this.widgetId !== 'new') { if (this.widgetId && this.widgetId !== 'new') {
this.isNew = false; this.isNew = false;
this.store.dispatch(DashboardActions.loadWidgets()); // this.store.dispatch(DashboardActions.loadWidgets());
// this.store.select(DashboardSelectors.selectWidgetById(this.widgetId)).subscribe(widget => { // this.store.select(DashboardSelectors.selectWidgetById(this.widgetId)).subscribe(widget => {
// if (widget) { // if (widget) {
// this.widgetForm.patchValue(widget); // this.widgetForm.patchValue(widget);
......
...@@ -5,8 +5,6 @@ import { Observable } from 'rxjs'; ...@@ -5,8 +5,6 @@ import { Observable } from 'rxjs';
import { CommonModule, TitleCasePipe } from '@angular/common'; import { CommonModule, TitleCasePipe } from '@angular/common';
import { NgComponentOutlet } from '@angular/common'; import { NgComponentOutlet } from '@angular/common';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import * as DashboardActions from '../state/dashboard.actions';
import * as DashboardSelectors from '../state/dashboard.selectors';
import { WidgetModel } from '../models/widgets.model'; import { WidgetModel } from '../models/widgets.model';
// Import all the widget components // Import all the widget components
...@@ -56,8 +54,8 @@ export class WidgetListComponent implements OnInit { ...@@ -56,8 +54,8 @@ export class WidgetListComponent implements OnInit {
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.store.dispatch(DashboardActions.loadWidgets()); // this.store.dispatch(DashboardActions.loadWidgets());
this.widgets$ = this.store.select(DashboardSelectors.selectAllWidgets); // this.widgets$ = this.store.select(DashboardSelectors.selectAllWidgets);
} }
getComponentType(componentName: string): Type<any> | null { getComponentType(componentName: string): Type<any> | null {
......
...@@ -25,8 +25,6 @@ import { DashboardDataService } from './shared/services/dashboard-data.service'; ...@@ -25,8 +25,6 @@ import { DashboardDataService } from './shared/services/dashboard-data.service';
import { provideStore, provideState } from '@ngrx/store'; import { provideStore, provideState } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects'; import { provideEffects } from '@ngrx/effects';
import { provideStoreDevtools } from '@ngrx/store-devtools'; import { provideStoreDevtools } from '@ngrx/store-devtools';
import { dashboardReducer } from './DPU/state/dashboard.reducer';
import { DashboardEffects } from './DPU/state/dashboard.effects';
export function HttpLoaderFactory(http: HttpClient) { export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, "./assets/i18n/", ".json"); return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
...@@ -84,8 +82,6 @@ export const appConfig: ApplicationConfig = { ...@@ -84,8 +82,6 @@ export const appConfig: ApplicationConfig = {
httpInterceptorProviders, httpInterceptorProviders,
DashboardDataService, DashboardDataService,
provideStore(), provideStore(),
provideState({ name: 'dashboard', reducer: dashboardReducer }),
provideEffects([DashboardEffects]),
provideStoreDevtools({ maxAge: 25, logOnly: environment.production }) provideStoreDevtools({ maxAge: 25, logOnly: environment.production })
] ]
}; };
......
...@@ -8,93 +8,32 @@ import { DashboardModel, WidgetModel, DatasetModel } from '../../DPU/models/widg ...@@ -8,93 +8,32 @@ import { DashboardModel, WidgetModel, DatasetModel } from '../../DPU/models/widg
}) })
export class DashboardDataService { export class DashboardDataService {
private mockDatasets: DatasetModel[] = [
new DatasetModel({ id: 'ds-1', name: 'Sales Data', url: '/api/data/sales' }),
new DatasetModel({ id: 'ds-2', name: 'HR Data', url: '/api/data/hr' }),
new DatasetModel({ id: 'ds-3', name: 'Marketing Data', url: '/api/data/marketing' })
];
private mockData: { [key: string]: any[] } = {
'ds-1': [
{ OrderID: 10248, CustomerID: 'VINET', EmployeeID: 5, OrderDate: new Date(8364186e5), ShipName: 'Vins et alcools Chevalier' },
{ OrderID: 10249, CustomerID: 'TOMSP', EmployeeID: 6, OrderDate: new Date(836505e6), ShipName: 'Toms Spezialitäten' },
{ OrderID: 10250, CustomerID: 'HANAR', EmployeeID: 4, OrderDate: new Date(8367642e5), ShipName: 'Hanari Carnes' },
],
'ds-2': [
{ Name: 'John Doe', Title: 'CEO', Country: 'USA' },
{ Name: 'Jane Smith', Title: 'CFO', Country: 'USA' },
{ Name: 'Peter Jones', Title: 'CTO', Country: 'UK' },
]
};
private mockDashboards: DashboardModel[] = [
new DashboardModel({
id: 'dash-1',
name: 'Sales Dashboard',
datasetId: 'ds-1',
widgets: [
new WidgetModel({ id: 'widget-1', name: 'Welcome Message', component: 'WelcomeWidgetComponent', cols: 2, rows: 1, y: 0, x: 0, data: { userName: 'Jane Doe' } }),
new WidgetModel({ id: 'widget-2', name: 'Sales Data Grid', component: 'SyncfusionDatagridWidgetComponent', cols: 4, rows: 3, y: 0, x: 2, data: {} })
]
}),
new DashboardModel({
id: 'dash-2',
name: 'HR Dashboard',
datasetId: 'ds-2',
widgets: [
new WidgetModel({ id: 'widget-1', name: 'Welcome Message', component: 'WelcomeWidgetComponent', cols: 2, rows: 1, y: 0, x: 0, data: { userName: 'John Smith' } })
]
})
];
private mockWidgets: WidgetModel[] = [
new WidgetModel({ id: 'widget-1', name: 'Welcome Message', component: 'WelcomeWidgetComponent', cols: 2, rows: 1, y: 0, x: 0, data: { userName: 'Default User' } }),
new WidgetModel({ id: 'widget-2', name: 'Sales Data Grid', component: 'SyncfusionDatagridWidgetComponent', cols: 4, rows: 3, y: 0, x: 2, data: {} }),
new WidgetModel({ id: 'widget-3', name: 'Chart Widget', component: 'ChartWidgetComponent', cols: 3, rows: 2, y: 0, x: 0, data: {} })
];
constructor() { } constructor() { }
// Dashboard methods // // Dashboard methods
getDashboards(): Observable<DashboardModel[]> { // getDashboards(): Observable<DashboardModel[]> {
return of(this.mockDashboards).pipe(catchError(this.handleError)); // return of(this.mockDashboards).pipe(catchError(this.handleError));
} // }
getDashboardById(id: string): Observable<DashboardModel | undefined> {
return of(this.mockDashboards.find(d => d.id === id)).pipe(catchError(this.handleError));
}
addDashboard(dashboard: DashboardModel): Observable<DashboardModel> {
this.mockDashboards.push(dashboard);
return of(dashboard).pipe(catchError(this.handleError));
}
updateDashboard(dashboard: DashboardModel): Observable<DashboardModel> { // addDashboard(dashboard: DashboardModel): Observable<DashboardModel> {
const index = this.mockDashboards.findIndex(d => d.id === dashboard.id); // this.mockDashboards.push(dashboard);
if (index !== -1) { // return of(dashboard).pipe(catchError(this.handleError));
this.mockDashboards[index] = dashboard; // }
}
return of(dashboard).pipe(catchError(this.handleError));
}
deleteDashboard(id: string): Observable<void> {
this.mockDashboards = this.mockDashboards.filter(d => d.id !== id);
return of(undefined).pipe(catchError(this.handleError));
}
// Widget methods // Widget methods
getWidgets(): Observable<WidgetModel[]> { // getWidgets(): Observable<WidgetModel[]> {
return of(this.mockWidgets).pipe(catchError(this.handleError)); // return of(this.mockWidgets).pipe(catchError(this.handleError));
} // }
// Dataset methods // // Dataset methods
getDatasets(): Observable<DatasetModel[]> { // getDatasets(): Observable<DatasetModel[]> {
return of(this.mockDatasets).pipe(catchError(this.handleError)); // return of(this.mockDatasets).pipe(catchError(this.handleError));
} // }
getDatasetById(id: string): Observable<DatasetModel | undefined> { // getDatasetById(id: string): Observable<DatasetModel | undefined> {
return of(this.mockDatasets.find(ds => ds.id === id)).pipe(catchError(this.handleError)); // return of(this.mockDatasets.find(ds => ds.id === id)).pipe(catchError(this.handleError));
} // }
private handleError(error: any) { private handleError(error: any) {
console.error(error); console.error(error);
......
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