From de5479cc07e6d9d50cd70ac6c2a4b5b2358187ef Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Date: Mon, 3 Nov 2025 09:06:04 +0530 Subject: [PATCH] chart --- .../allnewdash/allnewdash.component.ts | 1 + .../chart-config-manager.component.html | 630 +++++++++++++++++ .../chart-config-manager.component.scss | 60 ++ .../chart-config-manager.component.ts | 658 ++++++++++++++++++ .../chart-type-manager.component.html | 157 +++++ .../chart-type-manager.component.scss | 60 ++ .../chart-type-manager.component.ts | 144 ++++ .../chart-type-page.component.ts | 16 + .../editnewdash/editnewdash.component.html | 4 +- .../editnewdash/editnewdash.component.ts | 413 +++++------ .../unified-chart.component.html | 6 +- .../unified-chart/unified-chart.component.ts | 16 + 12 files changed, 1954 insertions(+), 211 deletions(-) create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.html create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.scss create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.ts create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.html create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.scss create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.ts create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-page.component.ts diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/allnewdash/allnewdash.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/allnewdash/allnewdash.component.ts index b907dae..b471651 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/allnewdash/allnewdash.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/allnewdash/allnewdash.component.ts @@ -24,6 +24,7 @@ export class AllnewdashComponent implements OnInit { projectname; projectId; error; + chartConfigManagerOpen = false; constructor( private router : Router, private route: ActivatedRoute,private dashboardService : DashboardService, diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.html new file mode 100644 index 0000000..18e5c95 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.html @@ -0,0 +1,630 @@ +
+

Chart Configuration Manager

+ + + + + + +
+
+

Chart Types

+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+ + +
+ + Name + Display Name + Description + Status + Actions + + + {{chartType.name}} + {{chartType.displayName}} + {{chartType.description}} + + + {{chartType.isActive ? 'Active' : 'Inactive'}} + + + + + + + + + + + {{chartTypes.length}} chart types + + +
+ + +
+

Edit Chart Type

+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+
+
+ + + + + +
+
+

UI Components for {{selectedChartType?.name}}

+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+ + +
+ + Component Name + Component Type + Display Label + Placeholder + Required + Sort Order + Actions + + + {{uiComponent.componentName}} + {{uiComponent.componentType}} + {{uiComponent.displayLabel}} + {{uiComponent.placeholder}} + + + {{uiComponent.isRequired ? 'Yes' : 'No'}} + + + {{uiComponent.sortOrder}} + + + + + + + + {{uiComponents.length}} UI components + + +
+ + +
+

Edit UI Component

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+
+
+ + + + + +
+
+

Properties for {{selectedUiComponent?.componentName}}

+ +
+ + +
+
+ + + + + + + + + + + + + + + +
+ + +
+
+
+ + +
+ + Property Name + Property Value + Property Type + Actions + + + {{property.propertyName}} + {{property.propertyValue}} + {{property.propertyType}} + + + + + + + + {{componentProperties.length}} properties + + +
+ + +
+

Edit Component Property

+
+ + + + + + + + + + + + + + + +
+ + +
+
+
+
+
+
+ + + + + +
+
+

Templates for {{selectedChartType?.name}}

+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+ + +
+ + Template Name + Is Default + Actions + + + {{template.templateName}} + + + {{template.isDefault ? 'Yes' : 'No'}} + + + + + + + + + + {{chartTemplates.length}} templates + + +
+ + +
+

Edit Chart Template

+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+
+
+ + + + + +
+
+

Dynamic Fields for {{selectedChartType?.name}}

+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+ + +
+ + Field Name + Field Label + Field Type + Required + Show in UI + Sort Order + Actions + + + {{field.fieldName}} + {{field.fieldLabel}} + {{field.fieldType}} + + + {{field.isRequired ? 'Yes' : 'No'}} + + + + + {{field.showInUi ? 'Yes' : 'No'}} + + + {{field.sortOrder}} + + + + + + + + {{dynamicFields.length}} fields + + +
+ + +
+

Edit Dynamic Field

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+
+
+
+
diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.scss new file mode 100644 index 0000000..8e7895c --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.scss @@ -0,0 +1,60 @@ +.chart-config-manager { + padding: 20px; + + .card { + margin-bottom: 20px; + + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + + h3 { + margin: 0; + } + } + + .card-block { + padding: 15px; + + form { + margin-bottom: 20px; + } + } + } + + .form-actions { + display: flex; + gap: 10px; + margin-top: 15px; + } + + clr-datagrid { + min-height: 200px; + } + + .label { + padding: 4px 8px; + border-radius: 3px; + font-size: 12px; + font-weight: bold; + } + + .label-success { + background-color: #318700; + color: white; + } + + .label-danger { + background-color: #e62200; + color: white; + } + + .required { + color: red; + } + + .alert { + margin-bottom: 20px; + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.ts new file mode 100644 index 0000000..8886d71 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config-manager/chart-config-manager.component.ts @@ -0,0 +1,658 @@ +import { Component, OnInit } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { environment } from 'src/environments/environment'; +import { ClrLoadingState } from '@clr/angular'; + +interface ChartType { + id: number; + name: string; + displayName: string; + description: string; + isActive: boolean; + createdAt: string; + updatedAt: string; +} + +interface UiComponent { + id: number; + chartType: ChartType; + componentName: string; + componentType: string; + displayLabel: string; + placeholder: string; + isRequired: boolean; + sortOrder: number; + createdAt: string; + updatedAt: string; +} + +interface ComponentProperty { + id: number; + component: UiComponent; + propertyName: string; + propertyValue: string; + propertyType: string; + createdAt: string; + updatedAt: string; +} + +interface ChartTemplate { + id: number; + chartType: ChartType; + templateName: string; + templateHtml: string; + templateCss: string; + isDefault: boolean; + createdAt: string; + updatedAt: string; +} + +interface DynamicField { + id: number; + chartType: ChartType; + fieldName: string; + fieldLabel: string; + fieldType: string; + fieldOptions: string; + isRequired: boolean; + showInUi: boolean; + sortOrder: number; + createdAt: string; + updatedAt: string; +} + +@Component({ + selector: 'app-chart-config-manager', + templateUrl: './chart-config-manager.component.html', + styleUrls: ['./chart-config-manager.component.scss'] +}) +export class ChartConfigManagerComponent implements OnInit { + // Chart Types + chartTypes: ChartType[] = []; + selectedChartType: ChartType | null = null; + newChartType: Partial = {}; + showAddChartTypeForm = false; + chartTypeLoadingState: ClrLoadingState = ClrLoadingState.DEFAULT; + + // UI Components + uiComponents: UiComponent[] = []; + selectedUiComponent: UiComponent | null = null; + newUiComponent: Partial = {}; + showAddUiComponentForm = false; + uiComponentLoadingState: ClrLoadingState = ClrLoadingState.DEFAULT; + + // Component Properties + componentProperties: ComponentProperty[] = []; + selectedComponentProperty: ComponentProperty | null = null; + newComponentProperty: Partial = {}; + showAddComponentPropertyForm = false; + componentPropertyLoadingState: ClrLoadingState = ClrLoadingState.DEFAULT; + + // Chart Templates + chartTemplates: ChartTemplate[] = []; + selectedChartTemplate: ChartTemplate | null = null; + newChartTemplate: Partial = {}; + showAddChartTemplateForm = false; + chartTemplateLoadingState: ClrLoadingState = ClrLoadingState.DEFAULT; + + // Dynamic Fields + dynamicFields: DynamicField[] = []; + selectedDynamicField: DynamicField | null = null; + newDynamicField: Partial = {}; + showAddDynamicFieldForm = false; + dynamicFieldLoadingState: ClrLoadingState = ClrLoadingState.DEFAULT; + + // Error handling + errorMessage: string | null = null; + successMessage: string | null = null; + + // API base URL + private apiUrl = environment.apiUrl || 'http://localhost:8080/api'; + + constructor(private http: HttpClient) { } + + ngOnInit(): void { + this.loadChartTypes(); + } + + // Show error message + private showError(message: string): void { + this.errorMessage = message; + setTimeout(() => { + this.errorMessage = null; + }, 5000); + } + + // Show success message + private showSuccess(message: string): void { + this.successMessage = message; + setTimeout(() => { + this.successMessage = null; + }, 3000); + } + + // Chart Type Methods + loadChartTypes(): void { + this.chartTypeLoadingState = ClrLoadingState.LOADING; + this.http.get(`${this.apiUrl}/chart-types`).subscribe({ + next: (data) => { + this.chartTypes = data; + this.chartTypeLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error loading chart types:', error); + this.showError('Error loading chart types: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTypeLoadingState = ClrLoadingState.ERROR; + } + }); + } + + createChartType(): void { + if (!this.newChartType.name) { + this.showError('Chart type name is required'); + return; + } + + this.chartTypeLoadingState = ClrLoadingState.LOADING; + this.http.post(`${this.apiUrl}/chart-types`, this.newChartType).subscribe({ + next: (data) => { + this.chartTypes.push(data); + this.newChartType = {}; + this.showAddChartTypeForm = false; + this.showSuccess('Chart type created successfully'); + this.chartTypeLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error creating chart type:', error); + this.showError('Error creating chart type: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTypeLoadingState = ClrLoadingState.ERROR; + } + }); + } + + updateChartType(): void { + if (!this.selectedChartType || !this.selectedChartType.name) { + this.showError('Chart type name is required'); + return; + } + + this.chartTypeLoadingState = ClrLoadingState.LOADING; + this.http.put(`${this.apiUrl}/chart-types/${this.selectedChartType.id}`, this.selectedChartType).subscribe({ + next: (data) => { + const index = this.chartTypes.findIndex(ct => ct.id === data.id); + if (index !== -1) { + this.chartTypes[index] = data; + } + this.selectedChartType = null; + this.showSuccess('Chart type updated successfully'); + this.chartTypeLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error updating chart type:', error); + this.showError('Error updating chart type: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTypeLoadingState = ClrLoadingState.ERROR; + } + }); + } + + deleteChartType(id: number): void { + if (!confirm('Are you sure you want to delete this chart type?')) { + return; + } + + this.chartTypeLoadingState = ClrLoadingState.LOADING; + this.http.delete(`${this.apiUrl}/chart-types/${id}`).subscribe({ + next: () => { + this.chartTypes = this.chartTypes.filter(ct => ct.id !== id); + // Also clear related data if the deleted chart type was selected + if (this.selectedChartType && this.selectedChartType.id === id) { + this.selectedChartType = null; + this.uiComponents = []; + this.chartTemplates = []; + this.dynamicFields = []; + } + this.showSuccess('Chart type deleted successfully'); + this.chartTypeLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error deleting chart type:', error); + this.showError('Error deleting chart type: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTypeLoadingState = ClrLoadingState.ERROR; + } + }); + } + + selectChartTypeForEdit(chartType: ChartType): void { + this.selectedChartType = { ...chartType }; + } + + // UI Component Methods + loadUiComponents(chartTypeId: number): void { + this.uiComponentLoadingState = ClrLoadingState.LOADING; + this.http.get(`${this.apiUrl}/ui-components/chart-type/${chartTypeId}`).subscribe({ + next: (data) => { + this.uiComponents = data; + this.uiComponentLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error loading UI components:', error); + this.showError('Error loading UI components: ' + (error.error?.message || error.message || 'Unknown error')); + this.uiComponentLoadingState = ClrLoadingState.ERROR; + } + }); + } + + createUiComponent(): void { + if (!this.selectedChartType) { + this.showError('Please select a chart type first'); + return; + } + + if (!this.newUiComponent.componentName) { + this.showError('Component name is required'); + return; + } + + this.uiComponentLoadingState = ClrLoadingState.LOADING; + const uiComponentData = { + ...this.newUiComponent, + chartType: { id: this.selectedChartType.id } + }; + + this.http.post(`${this.apiUrl}/ui-components`, uiComponentData).subscribe({ + next: (data) => { + this.uiComponents.push(data); + this.newUiComponent = {}; + this.showAddUiComponentForm = false; + this.showSuccess('UI component created successfully'); + this.uiComponentLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error creating UI component:', error); + this.showError('Error creating UI component: ' + (error.error?.message || error.message || 'Unknown error')); + this.uiComponentLoadingState = ClrLoadingState.ERROR; + } + }); + } + + updateUiComponent(): void { + if (!this.selectedUiComponent || !this.selectedUiComponent.componentName) { + this.showError('Component name is required'); + return; + } + + this.uiComponentLoadingState = ClrLoadingState.LOADING; + this.http.put(`${this.apiUrl}/ui-components/${this.selectedUiComponent.id}`, this.selectedUiComponent).subscribe({ + next: (data) => { + const index = this.uiComponents.findIndex(uc => uc.id === data.id); + if (index !== -1) { + this.uiComponents[index] = data; + } + this.selectedUiComponent = null; + this.showSuccess('UI component updated successfully'); + this.uiComponentLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error updating UI component:', error); + this.showError('Error updating UI component: ' + (error.error?.message || error.message || 'Unknown error')); + this.uiComponentLoadingState = ClrLoadingState.ERROR; + } + }); + } + + deleteUiComponent(id: number): void { + if (!confirm('Are you sure you want to delete this UI component?')) { + return; + } + + this.uiComponentLoadingState = ClrLoadingState.LOADING; + this.http.delete(`${this.apiUrl}/ui-components/${id}`).subscribe({ + next: () => { + this.uiComponents = this.uiComponents.filter(uc => uc.id !== id); + if (this.selectedUiComponent && this.selectedUiComponent.id === id) { + this.selectedUiComponent = null; + } + this.showSuccess('UI component deleted successfully'); + this.uiComponentLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error deleting UI component:', error); + this.showError('Error deleting UI component: ' + (error.error?.message || error.message || 'Unknown error')); + this.uiComponentLoadingState = ClrLoadingState.ERROR; + } + }); + } + + selectUiComponentForEdit(uiComponent: UiComponent): void { + this.selectedUiComponent = { ...uiComponent }; + } + + // Component Property Methods + loadComponentProperties(componentId: number): void { + this.componentPropertyLoadingState = ClrLoadingState.LOADING; + this.http.get(`${this.apiUrl}/component-properties/component/${componentId}`).subscribe({ + next: (data) => { + this.componentProperties = data; + this.componentPropertyLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error loading component properties:', error); + this.showError('Error loading component properties: ' + (error.error?.message || error.message || 'Unknown error')); + this.componentPropertyLoadingState = ClrLoadingState.ERROR; + } + }); + } + + createComponentProperty(): void { + if (!this.selectedUiComponent) { + this.showError('Please select a UI component first'); + return; + } + + if (!this.newComponentProperty.propertyName) { + this.showError('Property name is required'); + return; + } + + this.componentPropertyLoadingState = ClrLoadingState.LOADING; + const componentPropertyData = { + ...this.newComponentProperty, + component: { id: this.selectedUiComponent.id } + }; + + this.http.post(`${this.apiUrl}/component-properties`, componentPropertyData).subscribe({ + next: (data) => { + this.componentProperties.push(data); + this.newComponentProperty = {}; + this.showAddComponentPropertyForm = false; + this.showSuccess('Component property created successfully'); + this.componentPropertyLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error creating component property:', error); + this.showError('Error creating component property: ' + (error.error?.message || error.message || 'Unknown error')); + this.componentPropertyLoadingState = ClrLoadingState.ERROR; + } + }); + } + + updateComponentProperty(): void { + if (!this.selectedComponentProperty || !this.selectedComponentProperty.propertyName) { + this.showError('Property name is required'); + return; + } + + this.componentPropertyLoadingState = ClrLoadingState.LOADING; + this.http.put(`${this.apiUrl}/component-properties/${this.selectedComponentProperty.id}`, this.selectedComponentProperty).subscribe({ + next: (data) => { + const index = this.componentProperties.findIndex(cp => cp.id === data.id); + if (index !== -1) { + this.componentProperties[index] = data; + } + this.selectedComponentProperty = null; + this.showSuccess('Component property updated successfully'); + this.componentPropertyLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error updating component property:', error); + this.showError('Error updating component property: ' + (error.error?.message || error.message || 'Unknown error')); + this.componentPropertyLoadingState = ClrLoadingState.ERROR; + } + }); + } + + deleteComponentProperty(id: number): void { + if (!confirm('Are you sure you want to delete this component property?')) { + return; + } + + this.componentPropertyLoadingState = ClrLoadingState.LOADING; + this.http.delete(`${this.apiUrl}/component-properties/${id}`).subscribe({ + next: () => { + this.componentProperties = this.componentProperties.filter(cp => cp.id !== id); + if (this.selectedComponentProperty && this.selectedComponentProperty.id === id) { + this.selectedComponentProperty = null; + } + this.showSuccess('Component property deleted successfully'); + this.componentPropertyLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error deleting component property:', error); + this.showError('Error deleting component property: ' + (error.error?.message || error.message || 'Unknown error')); + this.componentPropertyLoadingState = ClrLoadingState.ERROR; + } + }); + } + + selectComponentPropertyForEdit(componentProperty: ComponentProperty): void { + this.selectedComponentProperty = { ...componentProperty }; + } + + // Chart Template Methods + loadChartTemplates(chartTypeId: number): void { + this.chartTemplateLoadingState = ClrLoadingState.LOADING; + this.http.get(`${this.apiUrl}/chart-templates/chart-type/${chartTypeId}`).subscribe({ + next: (data) => { + this.chartTemplates = data; + this.chartTemplateLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error loading chart templates:', error); + this.showError('Error loading chart templates: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTemplateLoadingState = ClrLoadingState.ERROR; + } + }); + } + + createChartTemplate(): void { + if (!this.selectedChartType) { + this.showError('Please select a chart type first'); + return; + } + + if (!this.newChartTemplate.templateName) { + this.showError('Template name is required'); + return; + } + + this.chartTemplateLoadingState = ClrLoadingState.LOADING; + const chartTemplateData = { + ...this.newChartTemplate, + chartType: { id: this.selectedChartType.id } + }; + + this.http.post(`${this.apiUrl}/chart-templates`, chartTemplateData).subscribe({ + next: (data) => { + this.chartTemplates.push(data); + this.newChartTemplate = {}; + this.showAddChartTemplateForm = false; + this.showSuccess('Chart template created successfully'); + this.chartTemplateLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error creating chart template:', error); + this.showError('Error creating chart template: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTemplateLoadingState = ClrLoadingState.ERROR; + } + }); + } + + updateChartTemplate(): void { + if (!this.selectedChartTemplate || !this.selectedChartTemplate.templateName) { + this.showError('Template name is required'); + return; + } + + this.chartTemplateLoadingState = ClrLoadingState.LOADING; + this.http.put(`${this.apiUrl}/chart-templates/${this.selectedChartTemplate.id}`, this.selectedChartTemplate).subscribe({ + next: (data) => { + const index = this.chartTemplates.findIndex(ct => ct.id === data.id); + if (index !== -1) { + this.chartTemplates[index] = data; + } + this.selectedChartTemplate = null; + this.showSuccess('Chart template updated successfully'); + this.chartTemplateLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error updating chart template:', error); + this.showError('Error updating chart template: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTemplateLoadingState = ClrLoadingState.ERROR; + } + }); + } + + deleteChartTemplate(id: number): void { + if (!confirm('Are you sure you want to delete this chart template?')) { + return; + } + + this.chartTemplateLoadingState = ClrLoadingState.LOADING; + this.http.delete(`${this.apiUrl}/chart-templates/${id}`).subscribe({ + next: () => { + this.chartTemplates = this.chartTemplates.filter(ct => ct.id !== id); + if (this.selectedChartTemplate && this.selectedChartTemplate.id === id) { + this.selectedChartTemplate = null; + } + this.showSuccess('Chart template deleted successfully'); + this.chartTemplateLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error deleting chart template:', error); + this.showError('Error deleting chart template: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTemplateLoadingState = ClrLoadingState.ERROR; + } + }); + } + + selectChartTemplateForEdit(chartTemplate: ChartTemplate): void { + this.selectedChartTemplate = { ...chartTemplate }; + } + + // Dynamic Field Methods + loadDynamicFields(chartTypeId: number): void { + this.dynamicFieldLoadingState = ClrLoadingState.LOADING; + this.http.get(`${this.apiUrl}/dynamic-fields/chart-type/${chartTypeId}`).subscribe({ + next: (data) => { + this.dynamicFields = data; + this.dynamicFieldLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error loading dynamic fields:', error); + this.showError('Error loading dynamic fields: ' + (error.error?.message || error.message || 'Unknown error')); + this.dynamicFieldLoadingState = ClrLoadingState.ERROR; + } + }); + } + + createDynamicField(): void { + if (!this.selectedChartType) { + this.showError('Please select a chart type first'); + return; + } + + if (!this.newDynamicField.fieldName) { + this.showError('Field name is required'); + return; + } + + this.dynamicFieldLoadingState = ClrLoadingState.LOADING; + const dynamicFieldData = { + ...this.newDynamicField, + chartType: { id: this.selectedChartType.id } + }; + + this.http.post(`${this.apiUrl}/dynamic-fields`, dynamicFieldData).subscribe({ + next: (data) => { + this.dynamicFields.push(data); + this.newDynamicField = {}; + this.showAddDynamicFieldForm = false; + this.showSuccess('Dynamic field created successfully'); + this.dynamicFieldLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error creating dynamic field:', error); + this.showError('Error creating dynamic field: ' + (error.error?.message || error.message || 'Unknown error')); + this.dynamicFieldLoadingState = ClrLoadingState.ERROR; + } + }); + } + + updateDynamicField(): void { + if (!this.selectedDynamicField || !this.selectedDynamicField.fieldName) { + this.showError('Field name is required'); + return; + } + + this.dynamicFieldLoadingState = ClrLoadingState.LOADING; + this.http.put(`${this.apiUrl}/dynamic-fields/${this.selectedDynamicField.id}`, this.selectedDynamicField).subscribe({ + next: (data) => { + const index = this.dynamicFields.findIndex(df => df.id === data.id); + if (index !== -1) { + this.dynamicFields[index] = data; + } + this.selectedDynamicField = null; + this.showSuccess('Dynamic field updated successfully'); + this.dynamicFieldLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error updating dynamic field:', error); + this.showError('Error updating dynamic field: ' + (error.error?.message || error.message || 'Unknown error')); + this.dynamicFieldLoadingState = ClrLoadingState.ERROR; + } + }); + } + + deleteDynamicField(id: number): void { + if (!confirm('Are you sure you want to delete this dynamic field?')) { + return; + } + + this.dynamicFieldLoadingState = ClrLoadingState.LOADING; + this.http.delete(`${this.apiUrl}/dynamic-fields/${id}`).subscribe({ + next: () => { + this.dynamicFields = this.dynamicFields.filter(df => df.id !== id); + if (this.selectedDynamicField && this.selectedDynamicField.id === id) { + this.selectedDynamicField = null; + } + this.showSuccess('Dynamic field deleted successfully'); + this.dynamicFieldLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error deleting dynamic field:', error); + this.showError('Error deleting dynamic field: ' + (error.error?.message || error.message || 'Unknown error')); + this.dynamicFieldLoadingState = ClrLoadingState.ERROR; + } + }); + } + + selectDynamicFieldForEdit(dynamicField: DynamicField): void { + this.selectedDynamicField = { ...dynamicField }; + } + + // Helper methods + onChartTypeSelect(chartType: ChartType): void { + this.selectedChartType = chartType; + this.loadUiComponents(chartType.id); + this.loadChartTemplates(chartType.id); + this.loadDynamicFields(chartType.id); + } + + resetForms(): void { + this.newChartType = {}; + this.newUiComponent = {}; + this.newComponentProperty = {}; + this.newChartTemplate = {}; + this.newDynamicField = {}; + this.showAddChartTypeForm = false; + this.showAddUiComponentForm = false; + this.showAddComponentPropertyForm = false; + this.showAddChartTemplateForm = false; + this.showAddDynamicFieldForm = false; + this.selectedChartType = null; + this.selectedUiComponent = null; + this.selectedComponentProperty = null; + this.selectedChartTemplate = null; + this.selectedDynamicField = null; + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.html new file mode 100644 index 0000000..5c1ad40 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.html @@ -0,0 +1,157 @@ +
+

Chart Type Management

+ + +
+ +
+ {{ errorMessage }} +
+
+ +
+ +
+ {{ successMessage }} +
+
+ + +
+
+

Add New Chart Type

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ + +
+
+
+
+

Chart Types

+
+
+ +
+
+
+ +
+ + Name + Display Name + Description + Status + Created At + Updated At + Actions + + + {{chartType.name}} + {{chartType.displayName}} + {{chartType.description}} + + + {{chartType.isActive ? 'Active' : 'Inactive'}} + + + {{chartType.createdAt | date:'short'}} + {{chartType.updatedAt | date:'short'}} + + + + + + + + {{chartTypes.length}} chart type(s) + + +
+
+ + +
+
+

Edit Chart Type

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+
\ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.scss new file mode 100644 index 0000000..2e15184 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.scss @@ -0,0 +1,60 @@ +.chart-type-manager { + padding: 20px; + + .card { + margin-bottom: 20px; + + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + + h3 { + margin: 0; + } + } + + .card-block { + padding: 15px; + + form { + margin-bottom: 20px; + } + } + } + + .form-actions { + display: flex; + gap: 10px; + margin-top: 15px; + } + + clr-datagrid { + min-height: 200px; + } + + .label { + padding: 4px 8px; + border-radius: 3px; + font-size: 12px; + font-weight: bold; + } + + .label-success { + background-color: #318700; + color: white; + } + + .label-danger { + background-color: #e62200; + color: white; + } + + .required { + color: red; + } + + .alert { + margin-bottom: 20px; + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.ts new file mode 100644 index 0000000..9f6ef73 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-manager.component.ts @@ -0,0 +1,144 @@ +import { Component, OnInit } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { environment } from 'src/environments/environment'; +import { ClrLoadingState } from '@clr/angular'; + +interface ChartType { + id: number; + name: string; + displayName: string; + description: string; + isActive: boolean; + createdAt: string; + updatedAt: string; +} + +@Component({ + selector: 'app-chart-type-manager', + templateUrl: './chart-type-manager.component.html', + styleUrls: ['./chart-type-manager.component.scss'] +}) +export class ChartTypeManagerComponent implements OnInit { + chartTypes: ChartType[] = []; + selectedChartType: ChartType | null = null; + newChartType: Partial = {}; + showAddChartTypeForm = false; + chartTypeLoadingState: ClrLoadingState = ClrLoadingState.DEFAULT; + + // Error handling + errorMessage: string | null = null; + successMessage: string | null = null; + + // API base URL + private apiUrl = environment.apiUrl || 'http://localhost:8080/api'; + + constructor(private http: HttpClient) { } + + ngOnInit(): void { + this.loadChartTypes(); + } + + // Show error message + private showError(message: string): void { + this.errorMessage = message; + setTimeout(() => { + this.errorMessage = null; + }, 5000); + } + + // Show success message + private showSuccess(message: string): void { + this.successMessage = message; + setTimeout(() => { + this.successMessage = null; + }, 3000); + } + + // Chart Type Methods + loadChartTypes(): void { + this.chartTypeLoadingState = ClrLoadingState.LOADING; + this.http.get(`${this.apiUrl}/chart-types`).subscribe({ + next: (data) => { + this.chartTypes = data; + this.chartTypeLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error loading chart types:', error); + this.showError('Error loading chart types: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTypeLoadingState = ClrLoadingState.ERROR; + } + }); + } + + createChartType(): void { + if (!this.newChartType.name) { + this.showError('Chart type name is required'); + return; + } + + this.chartTypeLoadingState = ClrLoadingState.LOADING; + this.http.post(`${this.apiUrl}/chart-types`, this.newChartType).subscribe({ + next: (data) => { + this.chartTypes.push(data); + this.newChartType = {}; + this.showAddChartTypeForm = false; + this.showSuccess('Chart type created successfully'); + this.chartTypeLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error creating chart type:', error); + this.showError('Error creating chart type: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTypeLoadingState = ClrLoadingState.ERROR; + } + }); + } + + updateChartType(): void { + if (!this.selectedChartType || !this.selectedChartType.name) { + this.showError('Chart type name is required'); + return; + } + + this.chartTypeLoadingState = ClrLoadingState.LOADING; + this.http.put(`${this.apiUrl}/chart-types/${this.selectedChartType.id}`, this.selectedChartType).subscribe({ + next: (data) => { + const index = this.chartTypes.findIndex(ct => ct.id === data.id); + if (index !== -1) { + this.chartTypes[index] = data; + } + this.selectedChartType = null; + this.showSuccess('Chart type updated successfully'); + this.chartTypeLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error updating chart type:', error); + this.showError('Error updating chart type: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTypeLoadingState = ClrLoadingState.ERROR; + } + }); + } + + deleteChartType(id: number): void { + if (!confirm('Are you sure you want to delete this chart type?')) { + return; + } + + this.chartTypeLoadingState = ClrLoadingState.LOADING; + this.http.delete(`${this.apiUrl}/chart-types/${id}`).subscribe({ + next: () => { + this.chartTypes = this.chartTypes.filter(ct => ct.id !== id); + this.showSuccess('Chart type deleted successfully'); + this.chartTypeLoadingState = ClrLoadingState.SUCCESS; + }, + error: (error) => { + console.error('Error deleting chart type:', error); + this.showError('Error deleting chart type: ' + (error.error?.message || error.message || 'Unknown error')); + this.chartTypeLoadingState = ClrLoadingState.ERROR; + } + }); + } + + selectChartTypeForEdit(chartType: ChartType): void { + this.selectedChartType = { ...chartType }; + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-page.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-page.component.ts new file mode 100644 index 0000000..a3385fa --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-type-manager/chart-type-page.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-chart-type-page', + template: ` +
+ +
+ `, + styles: [` + .chart-type-page { + padding: 20px; + } + `] +}) +export class ChartTypePageComponent { } \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.html index 407de1d..e8896ac 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.html +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.html @@ -732,6 +732,7 @@ + @@ -815,4 +816,5 @@ - \ No newline at end of file + + diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.ts index d5e67a2..1664180 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.ts @@ -51,10 +51,10 @@ export class EditnewdashComponent implements OnInit { commonFilterModalOpen: boolean = false; // Add common filter modal state public entryForm: FormGroup; public commonFilterForm: FormGroup; // Add common filter form - + // Add filterOptionsString property for compact filter filterOptionsString: string = ''; - + // Add availableKeys property for compact filter availableKeys: string[] = []; @@ -96,12 +96,12 @@ export class EditnewdashComponent implements OnInit { identifier: 'scatter_chart' }, { - name: 'Dynamic Chart', - identifier: 'dynamic_chart' + name: 'Dynamic Chart', + identifier: 'dynamic_chart' }, { - name: 'Financial Chart', - identifier: 'financial_chart' + name: 'Financial Chart', + identifier: 'financial_chart' }, { name: 'To Do', @@ -156,7 +156,7 @@ export class EditnewdashComponent implements OnInit { apiUrl: '', filters: [] as any[] }; - + // Add common filter column data property commonFilterColumnData: any[] = []; @@ -218,7 +218,7 @@ export class EditnewdashComponent implements OnInit { // Add property to track if coming from dashboard runner fromRunner: boolean = false; - + ngOnInit(): void { // Reset the filter service when the component is initialized this.filterService.resetFilters(); @@ -246,7 +246,7 @@ export class EditnewdashComponent implements OnInit { // Add resize callback to handle chart resizing itemResizeCallback: this.itemResize.bind(this) }; - + // Check if coming from dashboard runner this.route.queryParams.subscribe(params => { if (params['fromRunner'] === 'true') { @@ -292,20 +292,20 @@ export class EditnewdashComponent implements OnInit { drilldownParameter: [null] // Add drilldown parameter to form group // Note: Dynamic drilldown layers and filters will be handled separately since they're complex objects }); - + // Initialize common filter form this.commonFilterForm = this._fb.group({ connection: [''], apiUrl: [''] }); - + // Load sureconnect data first, then load dashboard data this.loadSureconnectData(); - + // Load common filter data if it exists this.loadCommonFilterData(); } - + // Add method to load sureconnect data loadSureconnectData() { this.sureconnectService.getAll().subscribe((data: any[]) => { @@ -319,18 +319,19 @@ export class EditnewdashComponent implements OnInit { this.getData(); }); } - + // Add method to load common filter data loadCommonFilterData() { // In a real implementation, this would fetch common filter data from the server // For now, we'll initialize with empty values console.log('Loading common filter data'); } - + toggleMenu() { this.toggle = !this.toggle; } + onDrag(event, identifier) { console.log("on drag", identifier); console.log("on drag ", event); @@ -342,7 +343,7 @@ export class EditnewdashComponent implements OnInit { getData() { // Reset the filter service when switching between dashboard records this.filterService.resetFilters(); - + // We get the id in get current router dashboard/:id this.route.params.subscribe(params => { // + is used to cast string to int @@ -362,7 +363,7 @@ export class EditnewdashComponent implements OnInit { console.log(this.dashboardCollection); // We parse serialized Json to generate components on the fly this.parseJson(this.dashboardCollection); - + // Set default connections for all gadgets if sureconnect data is available if (this.sureconnectData && this.sureconnectData.length > 0) { this.dashboardCollection.dashboard.forEach(item => { @@ -371,7 +372,7 @@ export class EditnewdashComponent implements OnInit { } }); } - + // We copy array without reference this.dashboardArray = this.dashboardCollection.dashboard.slice(); console.log("this.dashboardArray", this.dashboardArray); @@ -392,7 +393,7 @@ export class EditnewdashComponent implements OnInit { dashboard.component = component.componentInstance; } }); - + // Map chart names to unified chart types const chartTypeMap = { 'Radar Chart': 'radar', @@ -406,14 +407,14 @@ export class EditnewdashComponent implements OnInit { 'Dynamic Chart': 'line', 'Financial Chart': 'line' }; - + // If this is a chart, set the chartType property if (chartTypeMap.hasOwnProperty(dashboard.name)) { dashboard.chartType = chartTypeMap[dashboard.name]; // Keep the original name instead of changing it to "Unified Chart" // dashboard.name = "Unified Chart"; } - + // Ensure compact filter configuration properties are properly initialized if (dashboard.component === 'Compact Filter' || dashboard.name === 'Compact Filter') { // Make sure all compact filter properties exist @@ -437,7 +438,7 @@ export class EditnewdashComponent implements OnInit { dashboard.component = component.name; } }); - + // Map unified chart types back to chart names for serialization const chartNameMap = { 'radar': 'Radar Chart', @@ -449,18 +450,18 @@ export class EditnewdashComponent implements OnInit { 'bubble': 'Bubble Chart', 'scatter': 'Scatter Chart' }; - + // If this is a unified chart, set the name back to the appropriate chart name if (dashboard.name === 'Unified Chart' && dashboard.chartType && chartNameMap.hasOwnProperty(dashboard.chartType)) { dashboard.name = chartNameMap[dashboard.chartType]; } // Also handle the case where the chart already has the correct name - else if (dashboard.chartType && chartNameMap.hasOwnProperty(dashboard.chartType) && - dashboard.name === chartNameMap[dashboard.chartType]) { + else if (dashboard.chartType && chartNameMap.hasOwnProperty(dashboard.chartType) && + dashboard.name === chartNameMap[dashboard.chartType]) { // The name is already correct, no need to change it dashboard.component = "Unified Chart"; } - + // Ensure compact filter configuration properties are preserved if (dashboard.name === 'Compact Filter') { // Make sure all compact filter properties exist @@ -472,22 +473,22 @@ export class EditnewdashComponent implements OnInit { } }); } - + // Add method to get available fields for a filter dropdown (excluding already selected fields) getAvailableFields(filters: any[], currentIndex: number, allFields: string[]): string[] { if (!filters || !allFields) { return allFields || []; } - + // Get all selected fields except the current one const selectedFields = filters .filter((filter, index) => filter.field && index !== currentIndex) .map(filter => filter.field); - + // Return fields that haven't been selected yet return allFields.filter(field => !selectedFields.includes(field)); } - + itemChange() { this.dashboardCollection.dashboard = this.dashboardArray; console.log("itemChange this.dashboardCollection.dashboard ", this.dashboardCollection.dashboard); @@ -512,7 +513,7 @@ export class EditnewdashComponent implements OnInit { const validChartIds = this.dashboardArray .map(item => item.chartid) .filter(chartid => typeof chartid === 'number' && !isNaN(chartid)); - + if (validChartIds.length > 0) { maxChartId = Math.max(...validChartIds); } @@ -752,7 +753,7 @@ export class EditnewdashComponent implements OnInit { console.log('Coming from dashboard runner, skipping config modal'); return; } - + this.modeledit = true; this.modelid = item.chartid; console.log(this.modelid); @@ -762,31 +763,31 @@ export class EditnewdashComponent implements OnInit { if (item.chartcolor === undefined) { item.chartcolor = true; } if (item.chartlegend === undefined) { item.chartlegend = true; } // Initialize common filter property if not present - if (item['commonFilterEnabled'] === undefined) { - this.gadgetsEditdata['commonFilterEnabled'] = false; + if (item['commonFilterEnabled'] === undefined) { + this.gadgetsEditdata['commonFilterEnabled'] = false; } // Initialize drilldown common filter property if not present - if (item['commonFilterEnabledDrilldown'] === undefined) { - this.gadgetsEditdata['commonFilterEnabledDrilldown'] = false; + if (item['commonFilterEnabledDrilldown'] === undefined) { + this.gadgetsEditdata['commonFilterEnabledDrilldown'] = false; } // Initialize compact filter properties if not present - if (item['filterKey'] === undefined) { - this.gadgetsEditdata['filterKey'] = ''; + if (item['filterKey'] === undefined) { + this.gadgetsEditdata['filterKey'] = ''; } - if (item['filterType'] === undefined) { - this.gadgetsEditdata['filterType'] = 'text'; + if (item['filterType'] === undefined) { + this.gadgetsEditdata['filterType'] = 'text'; } - if (item['filterLabel'] === undefined) { - this.gadgetsEditdata['filterLabel'] = ''; + if (item['filterLabel'] === undefined) { + this.gadgetsEditdata['filterLabel'] = ''; } - if (item['filterOptions'] === undefined) { - this.gadgetsEditdata['filterOptions'] = []; + if (item['filterOptions'] === undefined) { + this.gadgetsEditdata['filterOptions'] = []; } // Initialize chartType property if not present (for unified chart) - if (item['chartType'] === undefined) { - this.gadgetsEditdata['chartType'] = 'bar'; + if (item['chartType'] === undefined) { + this.gadgetsEditdata['chartType'] = 'bar'; } - + // Initialize filterOptionsString for compact filter if (item.name === 'Compact Filter') { this.filterOptionsString = this.gadgetsEditdata['filterOptions'].join(', '); @@ -797,10 +798,10 @@ export class EditnewdashComponent implements OnInit { } else { this.filterOptionsString = ''; } - + // Initialize base filters with type and options if not present - if (item['baseFilters'] === undefined) { - this.gadgetsEditdata['baseFilters'] = []; + if (item['baseFilters'] === undefined) { + this.gadgetsEditdata['baseFilters'] = []; } else { // Ensure each base filter has type and options properties this.gadgetsEditdata['baseFilters'] = this.gadgetsEditdata['baseFilters'].map(filter => ({ @@ -811,10 +812,10 @@ export class EditnewdashComponent implements OnInit { availableValues: filter.availableValues || '' })); } - + // Initialize drilldown filters with type and options if not present - if (item['drilldownFilters'] === undefined) { - this.gadgetsEditdata['drilldownFilters'] = []; + if (item['drilldownFilters'] === undefined) { + this.gadgetsEditdata['drilldownFilters'] = []; } else { // Ensure each drilldown filter has type and options properties this.gadgetsEditdata['drilldownFilters'] = this.gadgetsEditdata['drilldownFilters'].map(filter => ({ @@ -825,10 +826,10 @@ export class EditnewdashComponent implements OnInit { availableValues: filter.availableValues || '' })); } - + // Initialize drilldown layers with proper filter structure if not present - if (item['drilldownLayers'] === undefined) { - this.gadgetsEditdata['drilldownLayers'] = []; + if (item['drilldownLayers'] === undefined) { + this.gadgetsEditdata['drilldownLayers'] = []; } else { // Ensure each layer has proper filter structure this.gadgetsEditdata['drilldownLayers'] = this.gadgetsEditdata['drilldownLayers'].map(layer => { @@ -856,58 +857,58 @@ export class EditnewdashComponent implements OnInit { return layer; }); } - + this.getStores(); - + // Set default connection if none is set and we have connections if ((!item['connection'] || item['connection'] === '') && this.sureconnectData && this.sureconnectData.length > 0) { this.gadgetsEditdata['connection'] = this.sureconnectData[0].id; // Also update the form control this.entryForm.patchValue({ connection: this.sureconnectData[0].id }); } - + // Initialize base drilldown properties if not present - if (item['drilldownEnabled'] === undefined) { - this.gadgetsEditdata['drilldownEnabled'] = false; + if (item['drilldownEnabled'] === undefined) { + this.gadgetsEditdata['drilldownEnabled'] = false; } - if (item['drilldownApiUrl'] === undefined) { - this.gadgetsEditdata['drilldownApiUrl'] = ''; + if (item['drilldownApiUrl'] === undefined) { + this.gadgetsEditdata['drilldownApiUrl'] = ''; } // Removed drilldownParameterKey initialization - if (item['drilldownXAxis'] === undefined) { - this.gadgetsEditdata['drilldownXAxis'] = ''; + if (item['drilldownXAxis'] === undefined) { + this.gadgetsEditdata['drilldownXAxis'] = ''; } - if (item['drilldownYAxis'] === undefined) { - this.gadgetsEditdata['drilldownYAxis'] = ''; + if (item['drilldownYAxis'] === undefined) { + this.gadgetsEditdata['drilldownYAxis'] = ''; } - if (item['drilldownParameter'] === undefined) { - this.gadgetsEditdata['drilldownParameter'] = ''; + if (item['drilldownParameter'] === undefined) { + this.gadgetsEditdata['drilldownParameter'] = ''; } - + // Reset drilldown column data this.drilldownColumnData = []; - + // If drilldown is enabled and we have a drilldown API URL, fetch the drilldown column data if (this.gadgetsEditdata.drilldownEnabled && this.gadgetsEditdata.drilldownApiUrl) { this.refreshBaseDrilldownColumns(); } - + // Check if we have either datastore or table to fetch columns - if ((item.datastore !== undefined && item.datastore !== '' && item.datastore !== null) || - (item.table !== undefined && item.table !== '' && item.table !== null)) { + if ((item.datastore !== undefined && item.datastore !== '' && item.datastore !== null) || + (item.table !== undefined && item.table !== '' && item.table !== null)) { const datastore = item.datastore; const table = item.table; - + // Fetch tables if datastore is available if (datastore) { this.getTables(datastore); } - + // Fetch columns if table is available if (table) { this.getColumns(datastore, table); } - + console.log(item.yAxis); // Set selectedyAxis regardless of whether it's an array or string if (item.yAxis !== undefined && item.yAxis !== '' && item.yAxis !== null) { @@ -993,24 +994,24 @@ export class EditnewdashComponent implements OnInit { // Update the onSubmit method to properly save filter data onSubmit(id) { console.log(id); - + // Check if ID is valid, including handling NaN if (id === null || id === undefined || isNaN(id)) { console.warn('Chart ID is null, undefined, or NaN, using modelid instead:', this.modelid); id = this.modelid; } - + // Ensure we have a valid numeric ID const numId = typeof id === 'number' ? id : parseInt(id, 10); if (isNaN(numId)) { console.error('Unable to determine valid chart ID, aborting onSubmit'); return; } - + // Handle both array and string yAxis values - if (this.selectedyAxis !== undefined && this.selectedyAxis !== null && - ((Array.isArray(this.selectedyAxis) && this.selectedyAxis.length > 0) || - (typeof this.selectedyAxis === 'string' && this.selectedyAxis !== ''))) { + if (this.selectedyAxis !== undefined && this.selectedyAxis !== null && + ((Array.isArray(this.selectedyAxis) && this.selectedyAxis.length > 0) || + (typeof this.selectedyAxis === 'string' && this.selectedyAxis !== ''))) { console.log("get y-axis", this.selectedyAxis); this.entryForm.patchValue({ yAxis: this.selectedyAxis }); } @@ -1021,13 +1022,13 @@ export class EditnewdashComponent implements OnInit { if (item.chartid == num) { // Preserve the component reference const componentRef = item.component; - + //item["product_id"] = "thisistest"; const xyz = { ...item, ...formdata } - + // Restore the component reference xyz.component = componentRef; - + // Explicitly ensure drilldown properties are preserved xyz.drilldownEnabled = this.gadgetsEditdata.drilldownEnabled; xyz.drilldownApiUrl = this.gadgetsEditdata.drilldownApiUrl; @@ -1038,7 +1039,7 @@ export class EditnewdashComponent implements OnInit { xyz.drilldownFilters = this.gadgetsEditdata.drilldownFilters; // Add drilldown filters xyz.drilldownLayers = this.gadgetsEditdata.drilldownLayers; xyz.commonFilterEnabled = this.gadgetsEditdata.commonFilterEnabled; // Add common filter property - + // For compact filter, preserve filter configuration properties if (item.name === 'Compact Filter') { xyz.filterKey = this.gadgetsEditdata.filterKey || ''; @@ -1053,24 +1054,24 @@ export class EditnewdashComponent implements OnInit { xyz.table = this.gadgetsEditdata.table || ''; xyz.connection = this.gadgetsEditdata.connection || undefined; } - + // For unified chart, preserve chart configuration properties if (item.name === 'Unified Chart') { xyz.chartType = this.gadgetsEditdata.chartType || 'bar'; } - + console.log(xyz); return xyz; } return item }); console.log('dashboard collection ', this.dashboardCollection.dashboard); - + // Force gridster to refresh by triggering change detection if (this.options && this.options.api) { this.options.api.optionsChanged(); } - + // Trigger change detection manually // This is a workaround to ensure the gridster re-renders the components setTimeout(() => { @@ -1081,7 +1082,7 @@ export class EditnewdashComponent implements OnInit { this.dashboardArray = tempArray; }, 0); }, 0); - + this.modeledit = false; // this.entryForm.reset(); @@ -1103,7 +1104,7 @@ export class EditnewdashComponent implements OnInit { apiUrl: item['table'] || '', // Use table as API URL connectionId: item['connection'] ? parseInt(item['connection'], 10) : undefined }; - + // Preserve configuration in the item itself item['filterKey'] = filterInputs['filterKey']; item['filterType'] = filterInputs['filterType']; @@ -1111,17 +1112,17 @@ export class EditnewdashComponent implements OnInit { item['filterOptions'] = filterInputs['filterOptions']; item['table'] = filterInputs['apiUrl']; item['connection'] = item['connection']; - + // Remove undefined properties to avoid passing unnecessary data Object.keys(filterInputs).forEach(key => { if (filterInputs[key] === undefined) { delete filterInputs[key]; } }); - + return filterInputs; } - + // For CommonFilterComponent, pass only filter-related properties if (item.component && item.component.name === 'CommonFilterComponent') { const commonFilterInputs = { @@ -1131,25 +1132,25 @@ export class EditnewdashComponent implements OnInit { fieldName: item['name'] || '', connection: item['connection'] || undefined }; - + // Remove undefined properties to avoid passing unnecessary data Object.keys(commonFilterInputs).forEach(key => { if (commonFilterInputs[key] === undefined) { delete commonFilterInputs[key]; } }); - + return commonFilterInputs; } - + // For UnifiedChartComponent, pass chart properties with chartType // Check for specific chart names that use UnifiedChartComponent const unifiedChartNames = [ - 'Radar Chart', 'Line Chart', 'Doughnut Chart', 'Bar Chart', + 'Radar Chart', 'Line Chart', 'Doughnut Chart', 'Bar Chart', 'Pie Chart', 'Polar Area Chart', 'Bubble Chart', 'Scatter Chart', 'Dynamic Chart', 'Financial Chart', 'Unified Chart' ]; - + if (unifiedChartNames.includes(item.name)) { const unifiedChartInputs = { chartType: item.chartType || 'bar', @@ -1180,17 +1181,17 @@ export class EditnewdashComponent implements OnInit { // Multi-layer drilldown configurations drilldownLayers: item['drilldownLayers'] || [] }; - + // Remove undefined properties to avoid passing unnecessary data Object.keys(unifiedChartInputs).forEach(key => { if (unifiedChartInputs[key] === undefined) { delete unifiedChartInputs[key]; } }); - + return unifiedChartInputs; } - + // For GridViewComponent, pass chart properties with drilldown support if (item.component && item.component.name === 'GridViewComponent') { const gridInputs = { @@ -1221,17 +1222,17 @@ export class EditnewdashComponent implements OnInit { // Multi-layer drilldown configurations drilldownLayers: item['drilldownLayers'] || [] }; - + // Remove undefined properties to avoid passing unnecessary data Object.keys(gridInputs).forEach(key => { if (gridInputs[key] === undefined) { delete gridInputs[key]; } }); - + return gridInputs; } - + // For all other chart components, pass chart-specific properties const chartInputs = { xAxis: item.xAxis, @@ -1261,60 +1262,60 @@ export class EditnewdashComponent implements OnInit { // Multi-layer drilldown configurations drilldownLayers: item['drilldownLayers'] || [] }; - + // Remove undefined properties to avoid passing unnecessary data Object.keys(chartInputs).forEach(key => { if (chartInputs[key] === undefined) { delete chartInputs[key]; } }); - + return chartInputs; } // Update the applyChanges method to properly save filter data applyChanges(id) { console.log('Apply changes for chart ID:', id); - + // Check if ID is valid, including handling NaN if (id === null || id === undefined || isNaN(id)) { console.warn('Chart ID is null, undefined, or NaN, using modelid instead:', this.modelid); id = this.modelid; } - + // Ensure we have a valid numeric ID const numId = typeof id === 'number' ? id : parseInt(id, 10); if (isNaN(numId)) { console.error('Unable to determine valid chart ID, aborting applyChanges'); return; } - + // Update the form with selected Y-axis values // Handle both array and string yAxis values - if (this.selectedyAxis !== undefined && this.selectedyAxis !== null && - ((Array.isArray(this.selectedyAxis) && this.selectedyAxis.length > 0) || - (typeof this.selectedyAxis === 'string' && this.selectedyAxis !== ''))) { + if (this.selectedyAxis !== undefined && this.selectedyAxis !== null && + ((Array.isArray(this.selectedyAxis) && this.selectedyAxis.length > 0) || + (typeof this.selectedyAxis === 'string' && this.selectedyAxis !== ''))) { console.log("get y-axis", this.selectedyAxis); this.entryForm.patchValue({ yAxis: this.selectedyAxis }); } - + // Get form data let formdata = this.entryForm.value; let num = id; console.log('Form data:', this.entryForm.value); - + // Update the dashboard collection with the new configuration this.dashboardCollection.dashboard = this.dashboardCollection.dashboard.map(item => { if (item.chartid == num) { // Preserve the component reference const componentRef = item.component; - + // Merge the existing item with the new form data const updatedItem = { ...item, ...formdata } - + // Restore the component reference updatedItem.component = componentRef; - + // Explicitly ensure drilldown properties are preserved updatedItem.drilldownEnabled = this.gadgetsEditdata.drilldownEnabled; updatedItem.drilldownApiUrl = this.gadgetsEditdata.drilldownApiUrl; @@ -1326,7 +1327,7 @@ export class EditnewdashComponent implements OnInit { updatedItem.drilldownLayers = this.gadgetsEditdata.drilldownLayers; updatedItem.commonFilterEnabled = this.gadgetsEditdata.commonFilterEnabled; // Add common filter property updatedItem.commonFilterEnabledDrilldown = this.gadgetsEditdata.commonFilterEnabledDrilldown; // Add drilldown common filter property - + // For compact filter, preserve filter configuration properties if (item.name === 'Compact Filter') { updatedItem.filterKey = this.gadgetsEditdata.filterKey || ''; @@ -1340,22 +1341,22 @@ export class EditnewdashComponent implements OnInit { } updatedItem.table = this.gadgetsEditdata.table || ''; // API URL updatedItem.connection = this.gadgetsEditdata.connection || undefined; // Connection ID - + // Also preserve these properties in gadgetsEditdata for consistency this.gadgetsEditdata.filterKey = updatedItem.filterKey; this.gadgetsEditdata.filterType = updatedItem.filterType; this.gadgetsEditdata.filterLabel = updatedItem.filterLabel; this.gadgetsEditdata.filterOptions = updatedItem.filterOptions; } - + console.log('Updated item:', updatedItem); return updatedItem; } return item }); - + console.log('Updated dashboard collection:', this.dashboardCollection.dashboard); - + // Update the dashboardArray to reflect changes immediately // Create a new array with new object references to ensure change detection this.dashboardArray = this.dashboardCollection.dashboard.map(item => { @@ -1366,12 +1367,12 @@ export class EditnewdashComponent implements OnInit { newItem.component = componentRef; return newItem; }); - + // Force gridster to refresh by triggering change detection if (this.options && this.options.api) { this.options.api.optionsChanged(); } - + // Trigger change detection manually // This is a workaround to ensure the gridster re-renders the components setTimeout(() => { @@ -1382,10 +1383,10 @@ export class EditnewdashComponent implements OnInit { this.dashboardArray = tempArray; }, 0); }, 0); - + // Note: We don't close the modal here, allowing the user to make additional changes // The user can click "Save" when they're done with all changes - + // Reset the filter service to ensure clean state this.filterService.resetFilters(); } @@ -1476,7 +1477,7 @@ export class EditnewdashComponent implements OnInit { })); this.drilldownColumnData = []; } - + // Add method to add a new drilldown layer addDrilldownLayer() { const newLayer = { @@ -1489,12 +1490,12 @@ export class EditnewdashComponent implements OnInit { }; this.gadgetsEditdata.drilldownLayers.push(newLayer); } - + // Add method to remove a drilldown layer removeDrilldownLayer(index: number) { this.gadgetsEditdata.drilldownLayers.splice(index, 1); } - + // Add method to refresh drilldown columns for a specific layer refreshDrilldownLayerColumns(layerIndex: number) { const layer = this.gadgetsEditdata.drilldownLayers[layerIndex]; @@ -1516,7 +1517,7 @@ export class EditnewdashComponent implements OnInit { }); } } - + // Add method to refresh base drilldown columns refreshBaseDrilldownColumns() { if (this.gadgetsEditdata.drilldownApiUrl) { @@ -1530,22 +1531,22 @@ export class EditnewdashComponent implements OnInit { }); } } - + // Add method to build drilldown URL with template parameters using angle brackets buildDrilldownUrl(baseUrl: string, parameterValue: string): string { // If no base URL, return empty string if (!baseUrl) { return ''; } - + // If no parameter value, return the base URL as-is if (!parameterValue) { return baseUrl; } - + // Check if the URL contains angle brackets for parameter replacement const hasAngleBrackets = /<[^>]+>/.test(baseUrl); - + if (hasAngleBrackets) { // Replace angle brackets placeholder with actual value // Example: http://localhost:9292/State_ListFilter1/State_ListFilter11/ @@ -1559,32 +1560,32 @@ export class EditnewdashComponent implements OnInit { return baseUrl; } } - + // Add method to get the parameter key from URL template using angle brackets getParameterKeyFromUrl(baseUrl: string): string { if (!baseUrl) { return ''; } - + // Extract parameter key from angle brackets // Example: http://localhost:9292/State_ListFilter1/State_ListFilter11/ // returns: country const match = baseUrl.match(/<([^>]+)>/); return match ? match[1] : ''; } - + // Add method to add a new filter field addFilterField() { // This method is no longer needed with the simplified approach // We're now using addBaseFilter and addLayerFilter methods instead } - + // Add method to remove a filter field removeFilterField(index: number) { // This method is no longer needed with the simplified approach // We're now using removeBaseFilter and removeLayerFilter methods instead } - + // Add method to handle base filter field change onBaseFilterFieldChange(index: number, field: string) { const filter = this.gadgetsEditdata.baseFilters[index]; @@ -1594,14 +1595,14 @@ export class EditnewdashComponent implements OnInit { filter.value = ''; filter.options = ''; filter.availableValues = ''; - + // If we have a field and table URL, load available values if (field && this.gadgetsEditdata.table) { this.loadFilterValuesForField( - this.gadgetsEditdata.table, - this.gadgetsEditdata.connection, - field, - index, + this.gadgetsEditdata.table, + this.gadgetsEditdata.connection, + field, + index, 'base' ); } @@ -1616,10 +1617,10 @@ export class EditnewdashComponent implements OnInit { // If type changes to dropdown/multiselect and we have a field, load available values if ((type === 'dropdown' || type === 'multiselect') && filter.field && this.gadgetsEditdata.table) { this.loadFilterValuesForField( - this.gadgetsEditdata.table, - this.gadgetsEditdata.connection, - filter.field, - index, + this.gadgetsEditdata.table, + this.gadgetsEditdata.connection, + filter.field, + index, 'base' ); } @@ -1635,14 +1636,14 @@ export class EditnewdashComponent implements OnInit { filter.value = ''; filter.options = ''; filter.availableValues = ''; - + // If we have a field and drilldown API URL, load available values if (field && this.gadgetsEditdata.drilldownApiUrl) { this.loadFilterValuesForField( - this.gadgetsEditdata.drilldownApiUrl, - this.gadgetsEditdata.connection, - field, - index, + this.gadgetsEditdata.drilldownApiUrl, + this.gadgetsEditdata.connection, + field, + index, 'drilldown' ); } @@ -1657,10 +1658,10 @@ export class EditnewdashComponent implements OnInit { // If type changes to dropdown/multiselect and we have a field, load available values if ((type === 'dropdown' || type === 'multiselect') && filter.field && this.gadgetsEditdata.drilldownApiUrl) { this.loadFilterValuesForField( - this.gadgetsEditdata.drilldownApiUrl, - this.gadgetsEditdata.connection, - filter.field, - index, + this.gadgetsEditdata.drilldownApiUrl, + this.gadgetsEditdata.connection, + filter.field, + index, 'drilldown' ); } @@ -1678,14 +1679,14 @@ export class EditnewdashComponent implements OnInit { filter.value = ''; filter.options = ''; filter.availableValues = ''; - + // If we have a field and layer API URL, load available values if (field && layer.apiUrl) { this.loadFilterValuesForField( - layer.apiUrl, - this.gadgetsEditdata.connection, - field, - filterIndex, + layer.apiUrl, + this.gadgetsEditdata.connection, + field, + filterIndex, 'layer', layerIndex ); @@ -1704,10 +1705,10 @@ export class EditnewdashComponent implements OnInit { // If type changes to dropdown/multiselect and we have a field, load available values if ((type === 'dropdown' || type === 'multiselect') && filter.field && layer.apiUrl) { this.loadFilterValuesForField( - layer.apiUrl, - this.gadgetsEditdata.connection, - filter.field, - filterIndex, + layer.apiUrl, + this.gadgetsEditdata.connection, + filter.field, + filterIndex, 'layer', layerIndex ); @@ -1718,10 +1719,10 @@ export class EditnewdashComponent implements OnInit { // Add method to load filter values for a specific field loadFilterValuesForField( - apiUrl: string, - connectionId: string | undefined, - field: string, - filterIndex: number, + apiUrl: string, + connectionId: string | undefined, + field: string, + filterIndex: number, filterType: 'base' | 'drilldown' | 'layer', layerIndex?: number ) { @@ -1807,27 +1808,27 @@ export class EditnewdashComponent implements OnInit { } this.gadgetsEditdata.drilldownLayers[layerIndex].filters.push(newFilter); } - + // Add method to remove a base filter removeBaseFilter(index: number) { this.gadgetsEditdata.baseFilters.splice(index, 1); } - + // Add method to remove a drilldown filter removeDrilldownFilter(index: number) { this.gadgetsEditdata.drilldownFilters.splice(index, 1); } - + // Add method to remove a layer filter removeLayerFilter(layerIndex: number, filterIndex: number) { this.gadgetsEditdata.drilldownLayers[layerIndex].filters.splice(filterIndex, 1); } - + // Add method to open common filter modal openCommonFilterModal() { this.commonFilterModalOpen = true; } - + // Add method to add a common filter addCommonFilter() { const newFilter = { @@ -1836,12 +1837,12 @@ export class EditnewdashComponent implements OnInit { }; this.commonFilterData.filters.push(newFilter); } - + // Add method to remove a common filter removeCommonFilter(index: number) { this.commonFilterData.filters.splice(index, 1); } - + // Add method to refresh common filter columns refreshCommonFilterColumns() { if (this.commonFilterData.apiUrl) { @@ -1855,31 +1856,31 @@ export class EditnewdashComponent implements OnInit { }); } } - + // Add method to save common filter saveCommonFilter() { // Here we would typically make an API call to save the common filter // For now, we'll just close the modal console.log('Saving common filter:', this.commonFilterData); - + // Update all charts that have common filter enabled this.updateChartsWithCommonFilter(); - + this.commonFilterModalOpen = false; } - + // Add method to update charts with common filter data updateChartsWithCommonFilter() { // This method will be called when common filter is saved // It will update all charts that have common filter enabled console.log('Updating charts with common filter data'); - + // Update the dashboardArray to reflect changes this.dashboardArray = this.dashboardArray.map(item => { if (item.commonFilterEnabled) { // Preserve the component reference const componentRef = item.component; - + // Update the chart with common filter data const updatedItem = { ...item, @@ -1887,21 +1888,21 @@ export class EditnewdashComponent implements OnInit { connection: this.commonFilterData.connection, baseFilters: [...this.commonFilterData.filters] }; - + // Restore the component reference updatedItem.component = componentRef; - + return updatedItem; } return item; }); - + // Also update the dashboardCollection to persist changes this.dashboardCollection.dashboard = this.dashboardCollection.dashboard.map(item => { if (item.commonFilterEnabled) { // Preserve the component reference const componentRef = item.component; - + // Update the chart with common filter data const updatedItem = { ...item, @@ -1909,20 +1910,20 @@ export class EditnewdashComponent implements OnInit { connection: this.commonFilterData.connection, baseFilters: [...this.commonFilterData.filters] } as DashboardContentModel; - + // Restore the component reference updatedItem.component = componentRef; - + return updatedItem; } return item; }); } - + // Add method to handle common filter toggle onCommonFilterToggle() { console.log('Common filter toggled:', this.gadgetsEditdata.commonFilterEnabled); - + if (this.gadgetsEditdata.commonFilterEnabled) { // When enabling common filter, save current values and apply common filter data this.gadgetsEditdata.table = this.commonFilterData.apiUrl; @@ -1931,24 +1932,24 @@ export class EditnewdashComponent implements OnInit { } // When disabling, the user can edit the filters normally } - + // Add method to handle common filter toggle for base drilldown onCommonFilterToggleDrilldown() { console.log('Common filter drilldown toggled:', this.gadgetsEditdata.commonFilterEnabledDrilldown); - + if (this.gadgetsEditdata.commonFilterEnabledDrilldown) { // When enabling common filter, save current values and apply common filter data this.gadgetsEditdata.drilldownFilters = [...this.commonFilterData.filters]; } // When disabling, the user can edit the filters normally } - + // Add method to handle common filter toggle for drilldown layers onCommonFilterToggleLayer(layerIndex: number) { const layer = this.gadgetsEditdata.drilldownLayers[layerIndex]; if (layer) { console.log(`Common filter layer ${layerIndex} toggled:`, layer.commonFilterEnabled); - + if (layer.commonFilterEnabled) { // When enabling common filter, save current values and apply common filter data layer.filters = [...this.commonFilterData.filters]; @@ -1956,20 +1957,20 @@ export class EditnewdashComponent implements OnInit { // When disabling, the user can edit the filters normally } } - + // Add method to handle item resize events itemResize(item: any, itemComponent: any) { console.log('Item resized:', item); // Trigger a window resize event to notify charts to resize window.dispatchEvent(new Event('resize')); - + // Also try to directly notify the chart component if possible if (itemComponent && itemComponent.item && itemComponent.item.component) { // If the resized item contains a chart, we could try to call its resize method directly // This would require the chart component to have a public resize method } } - + // Add method to load available keys for compact filter loadAvailableKeys(apiUrl: string, connectionId: string | undefined) { if (apiUrl) { @@ -1989,13 +1990,13 @@ export class EditnewdashComponent implements OnInit { // Add method to load available values for a specific key loadAvailableValues(key: string) { if (key && this.gadgetsEditdata['table']) { - const connectionIdNum = this.gadgetsEditdata['connection'] ? + const connectionIdNum = this.gadgetsEditdata['connection'] ? parseInt(this.gadgetsEditdata['connection'], 10) : undefined; this.alertService.getValuesFromUrl(this.gadgetsEditdata['table'], connectionIdNum, key).subscribe( (values: string[]) => { // Update filter options string for dropdown/multiselect - if (this.gadgetsEditdata['filterType'] === 'dropdown' || - this.gadgetsEditdata['filterType'] === 'multiselect') { + if (this.gadgetsEditdata['filterType'] === 'dropdown' || + this.gadgetsEditdata['filterType'] === 'multiselect') { this.filterOptionsString = values.join(', '); // Also update the gadgetsEditdata filterOptions array this.gadgetsEditdata['filterOptions'] = values; @@ -2012,8 +2013,8 @@ export class EditnewdashComponent implements OnInit { onFilterKeyChange(key: string) { this.gadgetsEditdata['filterKey'] = key; // Load available values when filter key changes - if (key && (this.gadgetsEditdata['filterType'] === 'dropdown' || - this.gadgetsEditdata['filterType'] === 'multiselect')) { + if (key && (this.gadgetsEditdata['filterType'] === 'dropdown' || + this.gadgetsEditdata['filterType'] === 'multiselect')) { this.loadAvailableValues(key); } } diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/unified-chart/unified-chart.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/unified-chart/unified-chart.component.html index 3edb352..c416a9f 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/unified-chart/unified-chart.component.html +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/unified-chart/unified-chart.component.html @@ -14,14 +14,12 @@ -
+
- + {{ showFilters ? 'Hide Filters' : 'Show Filters' }}
diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/unified-chart/unified-chart.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/unified-chart/unified-chart.component.ts index cb163f6..f603828 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/unified-chart/unified-chart.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/unified-chart/unified-chart.component.ts @@ -88,6 +88,20 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy { }) ); + // Log initial input values for debugging + console.log('UnifiedChartComponent ngOnInit - initial input values:', { + chartType: this.chartType, + xAxis: this.xAxis, + yAxis: this.yAxis, + table: this.table, + baseFilters: this.baseFilters, + drilldownFilters: this.drilldownFilters, + drilldownLayers: this.drilldownLayers + }); + + // Check if filters are available + console.log('Has filters in ngOnInit:', this.hasFilters()); + // Initialize filter values if they haven't been initialized yet if (!this.filtersInitialized) { this.initializeFilterValues(); @@ -1688,6 +1702,8 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy { return 0; } + + // Clear all filters clearAllFilters(): void { // Clear base filters