Commit e1eb60f1 by Ooh-Ao

manage widget

parent b2633955
......@@ -42,6 +42,7 @@
"@syncfusion/ej2-angular-inputs": "^29.2.4",
"@syncfusion/ej2-angular-layouts": "^29.2.4",
"@syncfusion/ej2-angular-maps": "^29.1.33",
"@syncfusion/ej2-angular-navigations": "^29.2.4",
"@syncfusion/ej2-angular-pivotview": "^29.2.4",
"@syncfusion/ej2-angular-popups": "^29.2.8",
"@syncfusion/ej2-angular-treemap": "^29.2.4",
......@@ -6316,6 +6317,31 @@
"@syncfusion/ej2-maps": "29.2.11"
}
},
"node_modules/@syncfusion/ej2-angular-navigations": {
"version": "29.2.4",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-angular-navigations/-/ej2-angular-navigations-29.2.4.tgz",
"integrity": "sha512-+tT4w4NigZGK7/+m9zpku2lgcmiZIb6DORWwxyQ19pWFs/tqST5cryeJojWxp8UUTSaWu/OEpTbfH8jhJ+VUnw==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-angular-base": "~29.2.4",
"@syncfusion/ej2-base": "~29.2.4",
"@syncfusion/ej2-navigations": "29.2.4"
}
},
"node_modules/@syncfusion/ej2-angular-navigations/node_modules/@syncfusion/ej2-navigations": {
"version": "29.2.4",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-navigations/-/ej2-navigations-29.2.4.tgz",
"integrity": "sha512-7uP3giD2VyegHH8h2mfo8QGMxC903JLZg/3EDY5PUOqG1IqlnVjBRoQrj5nclxANGyq/R8v3cYpn42+x+ZzcAQ==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-base": "~29.2.4",
"@syncfusion/ej2-buttons": "~29.2.4",
"@syncfusion/ej2-data": "~29.2.4",
"@syncfusion/ej2-inputs": "~29.2.4",
"@syncfusion/ej2-lists": "~29.2.4",
"@syncfusion/ej2-popups": "~29.2.4"
}
},
"node_modules/@syncfusion/ej2-angular-pivotview": {
"version": "29.2.10",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-angular-pivotview/-/ej2-angular-pivotview-29.2.10.tgz",
......
......@@ -27,7 +27,7 @@ export class WidgetService {
downloadFile(logId: string): Observable<any> {
return this.http.get(this.url + "widget-registry/files/download/" + logId, { responseType: 'blob' })
}
createWidget(model: WidgetModel): Observable<any> {
saveWidget(model: WidgetModel): Observable<any> {
let body: any = model
return this.http.post(this.url + 'widget-registry', body)
}
......
<div class="container mx-auto p-6 bg-gray-50">
<h1 class="text-3xl font-extrabold mb-6 text-gray-800">{{ isNew ? 'Add New Widget' : 'Edit Widget' }}</h1>
<form [formGroup]="widgetForm" (ngSubmit)="onSubmit()" class="bg-white shadow-xl rounded-xl px-8 pt-8 pb-8 mb-4">
<h1 class="text-3xl font-extrabold mb-6 text-gray-800">
{{ isNew ? 'Add New Widget' : 'Edit Widget' }}
</h1>
<form
[formGroup]="widgetForm"
(ngSubmit)="onSubmit()"
class="bg-white shadow-xl rounded-xl px-8 pt-8 pb-8 mb-4"
>
<!-- Widget Name (Thai) -->
<div class="mb-6">
<label class="block text-gray-700 text-sm font-bold mb-2" for="thName">
Widget Name (Thai)
</label>
<input formControlName="thName" id="thName" type="text" placeholder="เช่น ข่าวสารบริษัท"
class="shadow-sm border border-gray-200 rounded-lg w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent">
<ejs-textbox
formControlName="thName"
id="thName"
placeholder="เช่น ข่าวสารบริษัท"
cssClass="e-outline"
floatLabelType="Auto"
></ejs-textbox>
</div>
<!-- Widget Name (English) -->
......@@ -19,8 +29,13 @@
<label class="block text-gray-700 text-sm font-bold mb-2" for="engName">
Widget Name (English)
</label>
<input formControlName="engName" id="engName" type="text" placeholder="e.g., Company News"
class="shadow-sm border border-gray-200 rounded-lg w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent">
<ejs-textbox
formControlName="engName"
id="engName"
placeholder="e.g., Company News"
cssClass="e-outline"
floatLabelType="Auto"
></ejs-textbox>
</div>
<!-- Component Name -->
......@@ -28,8 +43,15 @@
<label class="block text-gray-700 text-sm font-bold mb-2" for="component">
Angular Component Name
</label>
<input formControlName="component" id="component" type="text" placeholder="e.g., CompanyNewsComponent"
class="shadow-sm border border-gray-200 rounded-lg w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent">
<ejs-dropdownlist
formControlName="component"
id="component"
[dataSource]="componentData"
[fields]="componentFields"
placeholder="e.g., CompanyNewsComponent"
cssClass="e-outline"
floatLabelType="Auto"
></ejs-dropdownlist>
</div>
<!-- Sizing -->
......@@ -38,37 +60,58 @@
<label class="block text-gray-700 text-sm font-bold mb-2" for="cols">
Default Columns
</label>
<input formControlName="cols" id="cols" type="number" min="1"
class="shadow-sm border border-gray-200 rounded-lg w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent">
<ejs-numerictextbox
formControlName="cols"
id="cols"
[min]="1"
cssClass="e-outline"
floatLabelType="Auto"
></ejs-numerictextbox>
</div>
<div class="w-full md:w-1/2 px-3">
<label class="block text-gray-700 text-sm font-bold mb-2" for="rows">
Default Rows
</label>
<input formControlName="rows" id="rows" type="number" min="1"
class="shadow-sm border border-gray-200 rounded-lg w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent">
<ejs-numerictextbox
formControlName="rows"
id="rows"
[min]="1"
cssClass="e-outline"
floatLabelType="Auto"
></ejs-numerictextbox>
</div>
</div>
<!-- Preview Section -->
<div class="mb-6 p-6 border border-gray-200 rounded-lg bg-gray-50">
<h3 class="text-xl font-bold mb-4 text-gray-800">Widget Preview</h3>
<div class="w-full h-48 border border-gray-300 rounded-lg overflow-hidden shadow-inner flex items-center justify-center bg-white">
<div
class="w-full h-48 border border-gray-300 rounded-lg overflow-hidden shadow-inner flex items-center justify-center bg-white"
>
<ng-container *ngComponentOutlet="previewComponentType"></ng-container>
<p *ngIf="!previewComponentType" class="text-gray-500">Enter a valid component name to see a preview.</p>
<p *ngIf="!previewComponentType" class="text-gray-500">
Enter a valid component name to see a preview.
</p>
</div>
</div>
<!-- Action Buttons -->
<div class="flex items-center justify-end mt-8">
<button (click)="cancel()" type="button" class="bg-gray-200 hover:bg-gray-300 text-gray-700 font-bold py-2 px-4 rounded-lg focus:outline-none focus:shadow-outline mr-3 transition duration-150 ease-in-out">
<button
(click)="cancel()"
type="button"
class="bg-gray-200 hover:bg-gray-300 text-gray-700 font-bold py-2 px-4 rounded-lg focus:outline-none focus:shadow-outline mr-3 transition duration-150 ease-in-out"
>
Cancel
</button>
<button type="submit" [disabled]="widgetForm.invalid" class="bg-primary hover:bg-primary-dark text-white font-bold py-2 px-4 rounded-lg focus:outline-none focus:shadow-outline disabled:bg-gray-400 disabled:cursor-not-allowed transition duration-150 ease-in-out">
<button
type="submit"
[disabled]="widgetForm.invalid"
class="bg-primary hover:bg-primary-dark text-white font-bold py-2 px-4 rounded-lg focus:outline-none focus:shadow-outline disabled:bg-gray-400 disabled:cursor-not-allowed transition duration-150 ease-in-out"
>
Save Widget
</button>
</div>
</form>
</div>
import { Component, OnInit, Type, Inject } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import {
FormBuilder,
FormGroup,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { CommonModule } from '@angular/common';
import { NgComponentOutlet } from '@angular/common';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { TextBoxModule } from '@syncfusion/ej2-angular-inputs';
import { NumericTextBoxModule } from '@syncfusion/ej2-angular-inputs';
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns';
// import * as DashboardActions from '../state/dashboard.actions';
import { WidgetModel } from '../models/widgets.model';
......@@ -25,7 +33,26 @@ import { SyncfusionChartWidgetComponent } from '../widgets/syncfusion-chart-widg
@Component({
selector: 'app-widget-form',
standalone: true,
imports: [CommonModule, ReactiveFormsModule, NgComponentOutlet, CompanyInfoWidgetComponent, HeadcountWidgetComponent, AttendanceOverviewWidgetComponent, PayrollSummaryWidgetComponent, EmployeeDirectoryWidgetComponent, KpiWidgetComponent, WelcomeWidgetComponent, ChartWidgetComponent, QuickLinksWidgetComponent, SyncfusionDatagridWidgetComponent, SyncfusionPivotWidgetComponent, SyncfusionChartWidgetComponent],
imports: [
CommonModule,
ReactiveFormsModule,
NgComponentOutlet,
TextBoxModule,
NumericTextBoxModule,
DropDownListModule,
CompanyInfoWidgetComponent,
HeadcountWidgetComponent,
AttendanceOverviewWidgetComponent,
PayrollSummaryWidgetComponent,
EmployeeDirectoryWidgetComponent,
KpiWidgetComponent,
WelcomeWidgetComponent,
ChartWidgetComponent,
QuickLinksWidgetComponent,
SyncfusionDatagridWidgetComponent,
SyncfusionPivotWidgetComponent,
SyncfusionChartWidgetComponent,
],
templateUrl: './widget-form.component.html',
})
export class WidgetFormComponent implements OnInit {
......@@ -34,34 +61,41 @@ export class WidgetFormComponent implements OnInit {
appName: string = '';
previewComponentType: Type<any> | null = null; // For dynamic preview
public componentData: { [key: string]: string }[] = [];
public componentFields: object = { text: 'name', value: 'id' };
// Map string names to actual component classes
private widgetComponentMap: { [key: string]: Type<any> } = {
'CompanyInfoWidgetComponent': CompanyInfoWidgetComponent,
'HeadcountWidgetComponent': HeadcountWidgetComponent,
'AttendanceOverviewWidgetComponent': AttendanceOverviewWidgetComponent,
'PayrollSummaryWidgetComponent': PayrollSummaryWidgetComponent,
'EmployeeDirectoryWidgetComponent': EmployeeDirectoryWidgetComponent,
'KpiWidgetComponent': KpiWidgetComponent,
'WelcomeWidgetComponent': WelcomeWidgetComponent,
'ChartWidgetComponent': ChartWidgetComponent,
'QuickLinksWidgetComponent': QuickLinksWidgetComponent,
'SyncfusionDatagridWidgetComponent': SyncfusionDatagridWidgetComponent,
'SyncfusionPivotWidgetComponent': SyncfusionPivotWidgetComponent,
'SyncfusionChartWidgetComponent': SyncfusionChartWidgetComponent
CompanyInfoWidgetComponent: CompanyInfoWidgetComponent,
HeadcountWidgetComponent: HeadcountWidgetComponent,
AttendanceOverviewWidgetComponent: AttendanceOverviewWidgetComponent,
PayrollSummaryWidgetComponent: PayrollSummaryWidgetComponent,
EmployeeDirectoryWidgetComponent: EmployeeDirectoryWidgetComponent,
KpiWidgetComponent: KpiWidgetComponent,
WelcomeWidgetComponent: WelcomeWidgetComponent,
ChartWidgetComponent: ChartWidgetComponent,
QuickLinksWidgetComponent: QuickLinksWidgetComponent,
SyncfusionDatagridWidgetComponent: SyncfusionDatagridWidgetComponent,
SyncfusionPivotWidgetComponent: SyncfusionPivotWidgetComponent,
SyncfusionChartWidgetComponent: SyncfusionChartWidgetComponent,
};
constructor(
private fb: FormBuilder,
public dialogRef: MatDialogRef<WidgetFormComponent>,
@Inject(MAT_DIALOG_DATA) public data: { widget: WidgetModel, isNew: boolean }
) { }
@Inject(MAT_DIALOG_DATA) public data: { widget: WidgetModel; isNew: boolean }
) {}
ngOnInit(): void {
this.isNew = this.data.isNew;
this.componentData = Object.keys(this.widgetComponentMap).map((key) => ({
id: key,
name: key,
}));
this.widgetForm = this.fb.group({
id: [null],
widgetId: [this.data.widget?.widgetId || new Date().getTime()],
thName: ['', Validators.required],
engName: ['', Validators.required],
component: ['', Validators.required],
......@@ -69,7 +103,7 @@ export class WidgetFormComponent implements OnInit {
rows: [1, [Validators.required, Validators.min(1)]],
x: [0],
y: [0],
data: [null]
data: [null],
});
if (!this.isNew && this.data.widget) {
......@@ -78,7 +112,7 @@ export class WidgetFormComponent implements OnInit {
}
// Subscribe to component name changes for live preview
this.widgetForm.get('component')?.valueChanges.subscribe(componentName => {
this.widgetForm.get('component')?.valueChanges.subscribe((componentName) => {
this.updatePreview(componentName);
});
}
......
<div class="p-4 sm:p-6 lg:p-8">
<div class="sm:flex sm:items-center justify-between">
<div class="sm:flex sm:items-center justify-between mb-6">
<div class="sm:flex-auto">
<h1 class="text-xl font-semibold text-gray-900">Widget Registry</h1>
<p class="mt-2 text-sm text-gray-700">
......@@ -7,123 +7,60 @@
central API.
</p>
</div>
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none flex space-x-2">
<button
(click)="openAddWidgetDialog()"
type="button"
class="btn btn-green sm:w-auto"
>
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
<button (click)="openAddWidgetDialog()" type="button" class="inline-flex items-center justify-center rounded-md border border-transparent bg-indigo px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo/70 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:w-auto">
Add New Widget
</button>
<button
routerLink="/portal-manage/widget-management/linker"
type="button"
class="btn btn-indigo sm:w-auto"
>
Manage Dataset Widgets
</button>
</div>
</div>
<!-- Search/Filter Input -->
<div class="mt-6 relative rounded-md shadow-sm">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<!-- Assuming Boxicons or RemixIcons are available. Using a generic search icon class. -->
<i class="bx bx-search text-gray-400"></i>
</div>
<input
type="text"
[(ngModel)]="searchTerm"
(input)="applyFilter()"
placeholder="Search widgets..."
class="block w-full rounded-md border-gray-300 pl-10 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm p-2"
/>
</div>
<!-- Registered Widgets List -->
<div class="mt-8 bg-white shadow-lg rounded-lg p-6">
<div class="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="inline-block min-w-full py-2 align-middle md:px-6 lg:px-8">
<div
class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 md:rounded-lg"
>
<table class="min-w-full divide-y divide-gray-300">
<thead class="bg-gray-50">
<tr>
<th
scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6"
>
Name
</th>
<th
scope="col"
class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900"
<ejs-grid
#grid
[dataSource]="registeredWidgets"
[allowPaging]="true"
[allowSorting]="true"
[pageSettings]="pageSettings"
[toolbar]="toolbarOptions"
(toolbarClick)="toolbarClickHandler($event)"
(commandClick)="commandClickHandler($event)"
[filterSettings]="filterSettings"
[allowFiltering]="true"
height="600"
>
Component
</th>
<th
scope="col"
class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900"
>
Default Size
</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6">
<span class="sr-only">Edit</span>
<span class="sr-only">Delete</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tr *ngFor="let widget of filteredWidgets" class="hover:bg-gray-50">
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<e-columns>
<e-column headerText="Name" width="250">
<ng-template #template let-data>
<div class="flex items-center">
<div class="ml-4">
<div class="font-medium text-gray-900">
{{ widget.thName }}
{{ data.thName }}
</div>
<div class="text-gray-500">{{ widget.engName }}</div>
<div class="text-gray-500">{{ data.engName }}</div>
</div>
</div>
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
<span
class="inline-flex rounded-full bg-blue/50 px-2 text-xs font-semibold leading-5 text-white"
>{{ widget.component }}</span
>
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
{{ widget.cols }}x{{ widget.rows }}
</td>
<td
class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6"
</ng-template>
</e-column>
<e-column
field="component"
headerText="Component"
width="250"
></e-column>
<e-column
field="cols"
headerText="Default Size"
width="150"
textAlign="Center"
>
<button
(click)="openEditWidgetDialog(widget)"
class="btn-text-indigo mr-4"
>
Edit
</button>
<button
(click)="confirmDeleteWidget(widget)"
class="btn btn-text-red"
>
Delete
</button>
</td>
</tr>
<tr *ngIf="filteredWidgets.length === 0">
<td
colspan="5"
class="whitespace-nowrap px-3 py-4 text-lg font-semibold text-center text-gray-500"
>
No widgets found.
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<ng-template #template let-data>
<span>{{ data.cols }}x{{ data.rows }}</span>
</ng-template>
</e-column>
<e-column
headerText="Actions"
width="120"
[commands]="commands"
textAlign="Right"
></e-column>
</e-columns>
</ejs-grid>
</div>
import { Component, OnInit, Type } from '@angular/core';
import { Component, OnInit, Type, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import {
GridModule,
GridComponent,
ToolbarService,
PageService,
SortService,
FilterService,
CommandColumnService,
EditService,
CommandModel,
ToolbarItems,
CommandClickEventArgs,
} from '@syncfusion/ej2-angular-grids';
import { NgComponentOutlet } from '@angular/common';
import { Dialog, DialogUtility } from '@syncfusion/ej2-angular-popups';
// Import all widget components for preview
import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component';
......@@ -21,7 +34,7 @@ import { WidgetModel } from '../models/widgets.model';
import { WidgetService } from '../services/widgets.service';
import { SimpleKpiWidgetComponent } from '../widgets/simple-kpi-widget/simple-kpi-widget.component';
import { WidgetFormComponent } from './widget-form.component';
import { ConfirmModalComponent } from '../../confirm-modal/confirm-modal.component';
import { ClickEventArgs } from '@syncfusion/ej2-angular-navigations';
@Component({
selector: 'app-widget-list',
......@@ -30,21 +43,9 @@ import { ConfirmModalComponent } from '../../confirm-modal/confirm-modal.compone
CommonModule,
FormsModule,
MatDialogModule,
GridModule,
NgComponentOutlet,
// Import widgets to be available for NgComponentOutlet
CompanyInfoWidgetComponent, HeadcountWidgetComponent, AttendanceOverviewWidgetComponent, PayrollSummaryWidgetComponent, EmployeeDirectoryWidgetComponent, WelcomeWidgetComponent, QuickLinksWidgetComponent, SyncfusionDatagridWidgetComponent, SyncfusionPivotWidgetComponent, SyncfusionChartWidgetComponent, SimpleKpiWidgetComponent
],
templateUrl: './widget-list.component.html',
styleUrls: ['./widget-list.component.scss']
})
export class WidgetListComponent implements OnInit {
public registeredWidgets: WidgetModel[] = [];
public filteredWidgets: WidgetModel[] = [];
public searchTerm: string = '';
// This map is crucial for mapping component string names to actual component types for previewing.
private widgetComponentMap: { [key: string]: Type<any> } = {
CompanyInfoWidgetComponent,
HeadcountWidgetComponent,
AttendanceOverviewWidgetComponent,
......@@ -56,59 +57,102 @@ export class WidgetListComponent implements OnInit {
SyncfusionPivotWidgetComponent,
SyncfusionChartWidgetComponent,
SimpleKpiWidgetComponent,
};
],
providers: [
ToolbarService,
PageService,
SortService,
FilterService,
CommandColumnService,
EditService,
],
templateUrl: './widget-list.component.html',
styleUrls: ['./widget-list.component.scss'],
})
export class WidgetListComponent implements OnInit {
@ViewChild('grid') public grid?: GridComponent;
public registeredWidgets: WidgetModel[] = [];
public pageSettings: object;
public toolbarOptions: ToolbarItems[] | object;
public commands: CommandModel[];
public filterSettings: object;
constructor(
private widgetService: WidgetService,
private notificationService: NotificationService,
private dialog: MatDialog
) { }
) {
this.pageSettings = { pageSize: 10 };
this.toolbarOptions = [
'Search',
{
text: 'Manage Dataset Widgets',
tooltipText: 'Manage Dataset Widgets',
prefixIcon: 'e-icons e-link',
id: 'link_widget',
},
];
this.commands = [
{
type: 'Edit',
buttonOption: { iconCss: 'e-icons e-edit', cssClass: 'e-flat' },
},
{
type: 'Delete',
buttonOption: { iconCss: 'e-icons e-delete', cssClass: 'e-flat' },
},
];
this.filterSettings = { type: 'Excel' };
}
ngOnInit(): void {
this.loadRegisteredWidgets();
}
loadRegisteredWidgets(): void {
this.widgetService.getListWidgets().subscribe(widgets => {
this.widgetService.getListWidgets().subscribe((widgets) => {
this.registeredWidgets = widgets;
this.applyFilter(); // Apply filter after loading widgets
});
}
applyFilter(): void {
if (!this.searchTerm) {
this.filteredWidgets = [...this.registeredWidgets];
return;
toolbarClickHandler(args: ClickEventArgs): void {
if (args.item.id === 'Grid_add') {
this.openAddWidgetDialog();
}
const lowerCaseSearchTerm = this.searchTerm.toLowerCase();
this.filteredWidgets = this.registeredWidgets.filter(widget =>
(widget.thName && widget.thName.toLowerCase().includes(lowerCaseSearchTerm)) ||
(widget.engName && widget.engName.toLowerCase().includes(lowerCaseSearchTerm)) ||
(widget.component && widget.component.toLowerCase().includes(lowerCaseSearchTerm))
);
}
getComponentType(componentName: string): Type<any> {
return this.widgetComponentMap[componentName];
commandClickHandler(args: CommandClickEventArgs): void {
if (args.commandColumn?.type === 'Edit' && args.rowData) {
this.openEditWidgetDialog(args.rowData as WidgetModel);
} else if (args.commandColumn?.type === 'Delete' && args.rowData) {
this.confirmDeleteWidget(args.rowData as WidgetModel);
}
}
openAddWidgetDialog(): void {
const dialogRef = this.dialog.open(WidgetFormComponent, {
width: '800px',
height: 'auto',
data: { isNew: true } // Indicate that it's a new widget
data: { isNew: true }, // Indicate that it's a new widget
});
dialogRef.afterClosed().subscribe(result => {
dialogRef.afterClosed().subscribe((result) => {
if (result) {
// Assuming result is the new widget data
this.widgetService.createWidget(result).subscribe(() => {
this.notificationService.success('Success','Widget added successfully!');
this.widgetService.saveWidget(result).subscribe(
() => {
this.notificationService.success(
'Success',
'Widget added successfully!'
);
this.loadRegisteredWidgets(); // Reload the list
}, error => {
this.notificationService.error('Error','Failed to add widget.');
},
(error) => {
this.notificationService.error('Error', 'Failed to add widget.');
console.error('Add widget error:', error);
});
}
);
}
});
}
......@@ -116,44 +160,73 @@ export class WidgetListComponent implements OnInit {
openEditWidgetDialog(widget: WidgetModel): void {
const dialogRef = this.dialog.open(WidgetFormComponent, {
width: '800px',
data: { widget: { ...widget }, isNew: false } // Pass a copy of the widget data and indicate it's an edit
data: { widget: { ...widget }, isNew: false }, // Pass a copy of the widget data and indicate it's an edit
});
dialogRef.afterClosed().subscribe(result => {
dialogRef.afterClosed().subscribe((result) => {
if (result) {
// Assuming result is the updated widget data
this.widgetService.createWidget(result).subscribe(() => {
this.notificationService.success('Success','Widget updated successfully!');
this.widgetService.saveWidget(result).subscribe(
() => {
this.notificationService.success(
'Success',
'Widget updated successfully!'
);
this.loadRegisteredWidgets(); // Reload the list
}, error => {
this.notificationService.error('Error','Failed to update widget.');
},
(error) => {
this.notificationService.error(
'Error',
'Failed to update widget.'
);
console.error('Update widget error:', error);
});
}
);
}
});
}
confirmDeleteWidget(widget: WidgetModel): void {
const dialogRef = this.dialog.open(ConfirmModalComponent, {
width: '400px',
data: { title: 'Confirm Deletion', message: `Are you sure you want to delete the widget \'${widget.thName || widget.engName}\'?` }
});
dialogRef.afterClosed().subscribe(result => {
if (result) {
// User confirmed deletion
let dialog: Dialog;
const okClick = () => {
if (widget.widgetId) {
this.widgetService.deleteWidget(widget).subscribe(() => {
this.notificationService.success('Success','Widget deleted successfully!');
this.loadRegisteredWidgets(); // Reload the list
}, error => {
this.notificationService.error('Error','Failed to delete widget.');
this.widgetService.deleteWidget(widget).subscribe({
next: () => {
this.notificationService.success(
'Success',
'Widget deleted successfully!'
);
this.loadRegisteredWidgets();
dialog.hide();
},
error: (error) => {
this.notificationService.error(
'Error',
'Failed to delete widget.'
);
console.error('Delete widget error:', error);
dialog.hide();
},
});
} else {
this.notificationService.error('Error', 'Widget ID is missing. Cannot delete.');
}
this.notificationService.error(
'Error',
'Widget ID is missing. Cannot delete.'
);
dialog.hide();
}
};
dialog = DialogUtility.confirm({
title: 'Confirm Deletion',
content: `Are you sure you want to delete the widget '${
widget.thName || widget.engName
}'?`,
okButton: { text: 'Delete', click: okClick },
cancelButton: { text: 'Cancel' },
showCloseIcon: true,
closeOnEscape: true,
animationSettings: { effect: 'Zoom' },
});
}
}
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