diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-config-manager.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-config-manager.component.html new file mode 100644 index 0000000..bb36ba8 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-config-manager.component.html @@ -0,0 +1,481 @@ +
+

Chart Configuration Manager

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

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

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

UI Components for {{selectedChartType?.name}}

+ +
+ + +
+ + +
+ + +
+ + Component Name + Component Type + Display Label + Placeholder + Required + Sort Order + Created At + Updated At + Actions + + + {{uiComponent.componentName}} + {{uiComponent.componentType}} + {{uiComponent.displayLabel}} + {{uiComponent.placeholder}} + + + {{uiComponent.isRequired ? 'Yes' : 'No'}} + + + {{uiComponent.sortOrder}} + {{uiComponent.createdAt | date:'short'}} + {{uiComponent.updatedAt | date:'short'}} + + + + + + + + {{uiComponents.length}} UI component(s) + + +
+ + +
+

Edit UI Component

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

Properties for {{selectedUiComponent?.componentName}}

+ +
+ + +
+ + +
+ + +
+ + Property Name + Property Value + Property Type + Created At + Updated At + Actions + + + {{property.propertyName}} + {{property.propertyValue}} + {{property.propertyType}} + {{property.createdAt | date:'short'}} + {{property.updatedAt | date:'short'}} + + + + + + + + {{componentProperties.length}} propertie(s) + + +
+ + +
+

Edit Component Property

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

Templates for {{selectedChartType?.name}}

+ +
+ + +
+ + +
+ + +
+ + Template Name + Is Default + Created At + Updated At + Actions + + + {{template.templateName}} + + + {{template.isDefault ? 'Yes' : 'No'}} + + + {{template.createdAt | date:'short'}} + {{template.updatedAt | date:'short'}} + + + + + + + + {{chartTemplates.length}} template(s) + + +
+ + +
+

Edit Chart Template

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

Dynamic Fields for {{selectedChartType?.name}}

+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+ + +
+ + Field Name + Field Label + Field Type + Required + Show in UI + Sort Order + Created At + Updated At + Actions + + + {{field.fieldName}} + {{field.fieldLabel}} + {{field.fieldType}} + + + {{field.isRequired ? 'Yes' : 'No'}} + + + + + {{field.showInUi ? 'Yes' : 'No'}} + + + {{field.sortOrder}} + {{field.createdAt | date:'short'}} + {{field.updatedAt | date:'short'}} + + + + + + + + {{dynamicFields.length}} field(s) + + +
+ + +
+

Edit Dynamic Field

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+
+
+
\ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-config-manager.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-config-manager.component.scss new file mode 100644 index 0000000..29f401d --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-config-manager.component.scss @@ -0,0 +1,64 @@ +.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; + } + + clr-tab-content { + padding: 15px 0; + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-config-manager.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-config-manager.component.ts new file mode 100644 index 0000000..e506df4 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-config-manager.component.ts @@ -0,0 +1,726 @@ +import { Component, OnInit } from '@angular/core'; +import { ClrLoadingState } from '@clr/angular'; +import { ChartTypeService } from '../chart-type-manager/chart-type.service'; +import { UiComponentService } from './ui-component.service'; +import { ComponentPropertyService } from './component-property.service'; +import { ChartTemplateService } from './chart-template.service'; +import { DynamicFieldService } from './dynamic-field.service'; + +export interface ChartType { + id: number; + name: string; + displayName: string; + description: string; + isActive: boolean; + createdAt: string; + updatedAt: string; +} + +export interface UiComponent { + id: number; + chartType: ChartType; + componentName: string; + componentType: string; + displayLabel: string; + placeholder: string; + isRequired: boolean; + sortOrder: number; + createdAt: string; + updatedAt: string; +} + +export interface ComponentProperty { + id: number; + component: UiComponent; + propertyName: string; + propertyValue: string; + propertyType: string; + createdAt: string; + updatedAt: string; +} + +export interface ChartTemplate { + id: number; + chartType: ChartType; + templateName: string; + templateHtml: string; + templateCss: string; + isDefault: boolean; + createdAt: string; + updatedAt: string; +} + +export 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; + + // Make ClrLoadingState available to template + readonly ClrLoadingState = ClrLoadingState; + + // Error handling + errorMessage: string | null = null; + successMessage: string | null = null; + + constructor( + private chartTypeService: ChartTypeService, + private uiComponentService: UiComponentService, + private componentPropertyService: ComponentPropertyService, + private chartTemplateService: ChartTemplateService, + private dynamicFieldService: DynamicFieldService + ) { } + + 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.chartTypeService.getAllChartTypes().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.chartTypeService.createChartType(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.chartTypeService.updateChartType(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? This will also delete all related UI components, templates, and fields.')) { + return; + } + + this.chartTypeLoadingState = ClrLoadingState.LOADING; + this.chartTypeService.deleteChartType(id).subscribe({ + next: () => { + this.chartTypes = this.chartTypes.filter(ct => ct.id !== id); + // 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 { + if (!chartTypeId) { + this.uiComponents = []; + return; + } + + this.uiComponentLoadingState = ClrLoadingState.LOADING; + this.uiComponentService.getUiComponentsByChartType(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; + + // Create a complete chartType object with only the ID + const chartTypeWithId = { + id: this.selectedChartType.id, + name: '', + displayName: '', + description: '', + isActive: true, + createdAt: '', + updatedAt: '' + }; + + const uiComponentData = { + ...this.newUiComponent, + chartType: chartTypeWithId + }; + + this.uiComponentService.createUiComponent(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.uiComponentService.updateUiComponent(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.uiComponentService.deleteUiComponent(id).subscribe({ + next: () => { + this.uiComponents = this.uiComponents.filter(uc => uc.id !== id); + 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 { + if (!componentId) { + this.componentProperties = []; + return; + } + + this.componentPropertyLoadingState = ClrLoadingState.LOADING; + this.componentPropertyService.getComponentPropertiesByComponent(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; + + // Create a complete component object with only the ID + const componentWithId = { + id: this.selectedUiComponent.id, + chartType: { id: 0, name: '', displayName: '', description: '', isActive: true, createdAt: '', updatedAt: '' }, + componentName: '', + componentType: '', + displayLabel: '', + placeholder: '', + isRequired: false, + sortOrder: 0, + createdAt: '', + updatedAt: '' + }; + + const componentPropertyData = { + ...this.newComponentProperty, + component: componentWithId + }; + + this.componentPropertyService.createComponentProperty(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.componentPropertyService.updateComponentProperty(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.componentPropertyService.deleteComponentProperty(id).subscribe({ + next: () => { + this.componentProperties = this.componentProperties.filter(cp => cp.id !== id); + 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 { + if (!chartTypeId) { + this.chartTemplates = []; + return; + } + + this.chartTemplateLoadingState = ClrLoadingState.LOADING; + this.chartTemplateService.getChartTemplatesByChartType(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; + + // Create a complete chartType object with only the ID + const chartTypeWithId = { + id: this.selectedChartType.id, + name: '', + displayName: '', + description: '', + isActive: true, + createdAt: '', + updatedAt: '' + }; + + const chartTemplateData = { + ...this.newChartTemplate, + chartType: chartTypeWithId + }; + + this.chartTemplateService.createChartTemplate(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.chartTemplateService.updateChartTemplate(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.chartTemplateService.deleteChartTemplate(id).subscribe({ + next: () => { + this.chartTemplates = this.chartTemplates.filter(ct => ct.id !== id); + 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 { + if (!chartTypeId) { + this.dynamicFields = []; + return; + } + + this.dynamicFieldLoadingState = ClrLoadingState.LOADING; + this.dynamicFieldService.getDynamicFieldsByChartType(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; + + // Create a complete chartType object with only the ID + const chartTypeWithId = { + id: this.selectedChartType.id, + name: '', + displayName: '', + description: '', + isActive: true, + createdAt: '', + updatedAt: '' + }; + + const dynamicFieldData = { + ...this.newDynamicField, + chartType: chartTypeWithId + }; + + this.dynamicFieldService.createDynamicField(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.dynamicFieldService.updateDynamicField(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.dynamicFieldService.deleteDynamicField(id).subscribe({ + next: () => { + this.dynamicFields = this.dynamicFields.filter(df => df.id !== id); + 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-config/chart-template.service.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-template.service.ts new file mode 100644 index 0000000..2ffc12c --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/chart-template.service.ts @@ -0,0 +1,43 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ApiRequestService } from 'src/app/services/api/api-request.service'; +import { ChartTemplate } from './chart-config-manager.component'; + +@Injectable({ + providedIn: 'root' +} +) +export class ChartTemplateService { + private chartTemplatesUrl = 'chart-templates'; + + constructor(private apiRequest: ApiRequestService) { } + + // Get all chart templates for a chart type + getChartTemplatesByChartType(chartTypeId: number): Observable { + const url = `${this.chartTemplatesUrl}/chart-type/${chartTypeId}`; + return this.apiRequest.get(url); + } + + // Get chart template by ID + getChartTemplateById(id: number): Observable { + const url = `${this.chartTemplatesUrl}/${id}`; + return this.apiRequest.get(url); + } + + // Create new chart template + createChartTemplate(chartTemplate: Partial): Observable { + return this.apiRequest.post(this.chartTemplatesUrl, chartTemplate); + } + + // Update chart template + updateChartTemplate(id: number, chartTemplate: ChartTemplate): Observable { + const url = `${this.chartTemplatesUrl}/${id}`; + return this.apiRequest.put(url, chartTemplate); + } + + // Delete chart template + deleteChartTemplate(id: number): Observable { + const url = `${this.chartTemplatesUrl}/${id}`; + return this.apiRequest.delete(url); + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/component-property.service.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/component-property.service.ts new file mode 100644 index 0000000..5904618 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/component-property.service.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ApiRequestService } from 'src/app/services/api/api-request.service'; +import { ComponentProperty } from './chart-config-manager.component'; + +@Injectable({ + providedIn: 'root' +}) +export class ComponentPropertyService { + private componentPropertiesUrl = 'component-properties'; + + constructor(private apiRequest: ApiRequestService) { } + + // Get all component properties for a component + getComponentPropertiesByComponent(componentId: number): Observable { + const url = `${this.componentPropertiesUrl}/component/${componentId}`; + return this.apiRequest.get(url); + } + + // Get component property by ID + getComponentPropertyById(id: number): Observable { + const url = `${this.componentPropertiesUrl}/${id}`; + return this.apiRequest.get(url); + } + + // Create new component property + createComponentProperty(componentProperty: Partial): Observable { + return this.apiRequest.post(this.componentPropertiesUrl, componentProperty); + } + + // Update component property + updateComponentProperty(id: number, componentProperty: ComponentProperty): Observable { + const url = `${this.componentPropertiesUrl}/${id}`; + return this.apiRequest.put(url, componentProperty); + } + + // Delete component property + deleteComponentProperty(id: number): Observable { + const url = `${this.componentPropertiesUrl}/${id}`; + return this.apiRequest.delete(url); + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/dynamic-field.service.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/dynamic-field.service.ts new file mode 100644 index 0000000..ae6cbfe --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/dynamic-field.service.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ApiRequestService } from 'src/app/services/api/api-request.service'; +import { DynamicField } from './chart-config-manager.component'; + +@Injectable({ + providedIn: 'root' +}) +export class DynamicFieldService { + private dynamicFieldsUrl = 'dynamic-fields'; + + constructor(private apiRequest: ApiRequestService) { } + + // Get all dynamic fields for a chart type + getDynamicFieldsByChartType(chartTypeId: number): Observable { + const url = `${this.dynamicFieldsUrl}/chart-type/${chartTypeId}`; + return this.apiRequest.get(url); + } + + // Get dynamic field by ID + getDynamicFieldById(id: number): Observable { + const url = `${this.dynamicFieldsUrl}/${id}`; + return this.apiRequest.get(url); + } + + // Create new dynamic field + createDynamicField(dynamicField: Partial): Observable { + return this.apiRequest.post(this.dynamicFieldsUrl, dynamicField); + } + + // Update dynamic field + updateDynamicField(id: number, dynamicField: DynamicField): Observable { + const url = `${this.dynamicFieldsUrl}/${id}`; + return this.apiRequest.put(url, dynamicField); + } + + // Delete dynamic field + deleteDynamicField(id: number): Observable { + const url = `${this.dynamicFieldsUrl}/${id}`; + return this.apiRequest.delete(url); + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-template-form.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-template-form.component.html new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-template-form.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-template-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-template-form.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-template-form.component.ts new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-type-form.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-type-form.component.html new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-type-form.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-type-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-type-form.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/chart-type-form.component.ts new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/component-property-form.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/component-property-form.component.html new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/component-property-form.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/component-property-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/component-property-form.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/component-property-form.component.ts new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/dynamic-field-form.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/dynamic-field-form.component.html new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/dynamic-field-form.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/dynamic-field-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/dynamic-field-form.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/dynamic-field-form.component.ts new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/ui-component-form.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/ui-component-form.component.html new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/ui-component-form.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/ui-component-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/ui-component-form.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/forms/ui-component-form.component.ts new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/ui-component.service.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/ui-component.service.ts new file mode 100644 index 0000000..c804c14 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/chart-config/ui-component.service.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ApiRequestService } from 'src/app/services/api/api-request.service'; +import { UiComponent } from './chart-config-manager.component'; + +@Injectable({ + providedIn: 'root' +}) +export class UiComponentService { + private uiComponentsUrl = 'ui-components'; + + constructor(private apiRequest: ApiRequestService) { } + + // Get all UI components for a chart type + getUiComponentsByChartType(chartTypeId: number): Observable { + const url = `${this.uiComponentsUrl}/chart-type/${chartTypeId}`; + return this.apiRequest.get(url); + } + + // Get UI component by ID + getUiComponentById(id: number): Observable { + const url = `${this.uiComponentsUrl}/${id}`; + return this.apiRequest.get(url); + } + + // Create new UI component + createUiComponent(uiComponent: Partial): Observable { + return this.apiRequest.post(this.uiComponentsUrl, uiComponent); + } + + // Update UI component + updateUiComponent(id: number, uiComponent: UiComponent): Observable { + const url = `${this.uiComponentsUrl}/${id}`; + return this.apiRequest.put(url, uiComponent); + } + + // Delete UI component + deleteUiComponent(id: number): Observable { + const url = `${this.uiComponentsUrl}/${id}`; + return this.apiRequest.delete(url); + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/chart-config-modal.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/chart-config-modal.component.html new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/chart-config-modal.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/chart-config-modal.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/chart-config-modal.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/chart-config-modal.component.ts new file mode 100644 index 0000000..e69de29 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 1664180..3d0ac44 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 @@ -30,6 +30,8 @@ import { CompactFilterComponent } from '../common-filter'; import { FilterService } from '../common-filter/filter.service'; // Add the UnifiedChartComponent import import { UnifiedChartComponent } from '../gadgets/unified-chart'; +// Add the ChartConfigModalComponent import +import { ChartConfigModalComponent } from './chart-config-modal.component'; function isNullArray(arr) { return !Array.isArray(arr) || arr.length === 0;