dashboard
This commit is contained in:
		
							parent
							
								
									f2b6a4d145
								
							
						
					
					
						commit
						8266bfdc01
					
				| @ -23,18 +23,6 @@ | ||||
|      | ||||
|     <!-- Main Dashboard Content --> | ||||
|     <div class="main-content"> | ||||
|       <!-- KPI Metrics --> | ||||
|       <!-- <div class="kpi-section"> | ||||
|         <div class="kpi-card total-leads"> | ||||
|           <div class="kpi-title">Total Leads</div> | ||||
|           <div class="kpi-value">1,248</div> | ||||
|         </div> | ||||
|         <div class="kpi-card total-deals"> | ||||
|           <div class="kpi-title">Total Deals</div> | ||||
|           <div class="kpi-value">842</div> | ||||
|         </div> | ||||
|       </div> --> | ||||
|        | ||||
|       <!-- Deleted Items Section --> | ||||
|       <div class="deleted-items-section" *ngIf="deletedItems.length > 0"> | ||||
|         <h3>Deleted Items</h3> | ||||
| @ -52,9 +40,6 @@ | ||||
|       </div> | ||||
|        | ||||
|       <!-- Dashboard Grid with Drag and Drop --> | ||||
|       <!-- <div class="drop-zone-indicator" *ngIf="dashboard.length === 0"> | ||||
|         <p>Drag components here from the sidebar</p> | ||||
|       </div> --> | ||||
|       <gridster [options]="options" (drop)="onDrop($event)" style="background-color: transparent; min-height: 500px;"> | ||||
|         <gridster-item [item]="item" *ngFor="let item of dashboard"> | ||||
|           <!-- Remove Button --> | ||||
| @ -62,6 +47,11 @@ | ||||
|             <clr-icon shape="trash"></clr-icon> | ||||
|           </button> | ||||
|            | ||||
|           <!-- Edit Button --> | ||||
|           <button class="btn btn-icon" style="margin-top: 10px; float: right;" (click)="editGadget(item)"> | ||||
|             <clr-icon shape="pencil"></clr-icon> | ||||
|           </button> | ||||
|            | ||||
|           <!-- Drag Handle --> | ||||
|           <button class="btn btn-icon drag-handler" style="margin-left: 10px; margin-top: 10px;"> | ||||
|             <clr-icon shape="drag-handle"></clr-icon> | ||||
| @ -97,3 +87,360 @@ | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
| 
 | ||||
| <!-- Configuration Modal --> | ||||
| <clr-modal [(clrModalOpen)]="modeledit" [clrModalStaticBackdrop]="true" clrModalSize="lg"> | ||||
|   <h3 class="modal-title">Configure Chart</h3> | ||||
|   <div class="modal-body" *ngIf="selectedItem"> | ||||
|     <form [formGroup]="configForm" class="clr-form-horizontal"> | ||||
|       <div class="clr-row"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <label for="charttitle">Chart Title</label> | ||||
|           <input id="charttitle" type="text" formControlName="charttitle" class="clr-input"> | ||||
|         </div> | ||||
|       </div> | ||||
|        | ||||
|       <!-- Connection Selection Field --> | ||||
|       <div class="clr-row"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <label for="connection">Connection</label> | ||||
|           <select id="connection" formControlName="connection" class="clr-select"> | ||||
|             <option value="">Select Connection</option> | ||||
|             <option *ngFor="let conn of sureconnectData" [value]="conn.id"> | ||||
|               {{conn.connection_name || conn.id}} | ||||
|             </option> | ||||
|           </select> | ||||
|           <div class="clr-subtext">Select a SureConnect connection to use for this chart</div> | ||||
|         </div> | ||||
|       </div> | ||||
|        | ||||
|       <div class="clr-row" *ngIf="selectedItem?.name !== 'Data Table' && selectedItem?.name !== 'Deal Details'"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <div class="clr-form-control" style="margin-top: 5px;margin-bottom: 10px;"> | ||||
|             <div class="clr-control-container"> | ||||
|               <div class="clr-checkbox-wrapper"> | ||||
|                 <input type="checkbox" id="chartlegend" formControlName="chartlegend" class="clr-checkbox" /> | ||||
|                 <label for="chartlegend" class="clr-control-label">Show Chart Legend</label> | ||||
|               </div> | ||||
|               <div class="clr-checkbox-wrapper"> | ||||
|                 <input type="checkbox" id="showlabel" formControlName="showlabel" class="clr-checkbox" /> | ||||
|                 <label for="showlabel" class="clr-control-label">Show Chart Label</label> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|        | ||||
|       <div class="clr-row"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <label for="table">Api Url</label> | ||||
|           <div> | ||||
|             <input type="text" id="table" formControlName="table" class="clr-input" style="width:90%">  | ||||
|             <span> | ||||
|               <button class="btn btn-icon btn-primary" style="margin: 0px;" (click)="getColumns(configForm.value.connection, configForm.value.table)"> | ||||
|                 <clr-icon shape="redo"></clr-icon> | ||||
|               </button> | ||||
|             </span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|        | ||||
|       <div class="clr-row" *ngIf="selectedItem?.name !== 'Data Table' && selectedItem?.name !== 'Deal Details'"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <label for="xAxis">X-Axis</label> | ||||
|           <select id="xAxis" formControlName="xAxis"> | ||||
|             <option value="null">choose Column</option> | ||||
|             <option *ngFor="let data of columnData" [value]="data">{{data}}</option> | ||||
|           </select> | ||||
|         </div> | ||||
|       </div> | ||||
|        | ||||
|       <div class="clr-row" *ngIf="selectedItem?.name !== 'Data Table' && selectedItem?.name !== 'Deal Details'"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <label for="yAxis">Y-Axis (Numeric)</label> | ||||
|           <clr-combobox-container style="margin-top: 10px !important;"> | ||||
|             <clr-combobox id="yAxis" formControlName="yAxis" clrMulti="true" required> | ||||
|               <ng-container *clrOptionSelected="let selected"> | ||||
|                 {{selected}} | ||||
|               </ng-container> | ||||
|               <clr-options> | ||||
|                 <clr-option *clrOptionItems="let state of columnData" [clrValue]="state"> | ||||
|                   {{state}} | ||||
|                 </clr-option> | ||||
|               </clr-options> | ||||
|             </clr-combobox> | ||||
|           </clr-combobox-container> | ||||
|         </div> | ||||
|       </div> | ||||
|        | ||||
|       <!-- Base API Filters --> | ||||
|       <div class="clr-row" style="margin-top: 15px;"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <h5>Base API Filters</h5> | ||||
|            | ||||
|           <!-- Add Base Filter Button --> | ||||
|           <button class="btn btn-sm btn-primary" (click)="addBaseFilter()" style="margin-top: 10px; margin-bottom: 10px;"> | ||||
|             <clr-icon shape="plus"></clr-icon> Add Filter | ||||
|           </button> | ||||
|            | ||||
|           <!-- Base Filter Fields List --> | ||||
|           <div *ngFor="let filter of selectedItem?.baseFilters; let i = index"  | ||||
|                style="margin-bottom: 10px; padding: 8px; border: 1px solid #eee; border-radius: 4px; background-color: #f9f9f9;"> | ||||
|             <div style="display: flex; justify-content: space-between; align-items: center;"> | ||||
|               <span>Filter {{i + 1}}</span> | ||||
|               <button class="btn btn-icon btn-danger btn-sm" (click)="removeBaseFilter(i)"> | ||||
|                 <clr-icon shape="trash"></clr-icon> | ||||
|               </button> | ||||
|             </div> | ||||
|              | ||||
|             <div class="clr-row" style="margin-top: 8px;"> | ||||
|               <div class="clr-col-sm-5"> | ||||
|                 <input type="text" [(ngModel)]="filter.field" [ngModelOptions]="{standalone: true}"  | ||||
|                        class="clr-input" placeholder="Field Name" /> | ||||
|               </div> | ||||
|                | ||||
|               <div class="clr-col-sm-5"> | ||||
|                 <input type="text" [(ngModel)]="filter.value" [ngModelOptions]="{standalone: true}"  | ||||
|                        class="clr-input" placeholder="Filter Value" /> | ||||
|               </div> | ||||
|                | ||||
|               <div class="clr-col-sm-2"> | ||||
|                 <button class="btn btn-icon btn-danger btn-sm" (click)="removeBaseFilter(i)"> | ||||
|                   <clr-icon shape="trash"></clr-icon> | ||||
|                 </button> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|        | ||||
|       <!-- Base Drilldown Configuration Section --> | ||||
|       <div class="clr-row" style="margin-top: 20px; padding-top: 15px; border-top: 1px solid #ddd;"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <h4>Base Drilldown Configuration</h4> | ||||
|           <div class="clr-form-control"> | ||||
|             <div class="clr-control-container"> | ||||
|               <div class="clr-checkbox-wrapper"> | ||||
|                 <input type="checkbox" id="drilldownEnabled" [(ngModel)]="selectedItem.drilldownEnabled"  | ||||
|                        [ngModelOptions]="{standalone: true}" class="clr-checkbox" /> | ||||
|                 <label for="drilldownEnabled" class="clr-control-label">Enable Base Drilldown</label> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="clr-row" *ngIf="selectedItem?.drilldownEnabled"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <label for="drilldownApiUrl">Base Drilldown API URL</label> | ||||
|           <div> | ||||
|             <input type="text" id="drilldownApiUrl" [(ngModel)]="selectedItem.drilldownApiUrl"  | ||||
|                    [ngModelOptions]="{standalone: true}" class="clr-input" style="width:90%">  | ||||
|             <span> | ||||
|               <button class="btn btn-icon btn-primary" style="margin: 0px;"  | ||||
|                 (click)="refreshDrilldownColumns()" [disabled]="!selectedItem.drilldownApiUrl"> | ||||
|                 <clr-icon shape="redo"></clr-icon> | ||||
|               </button> | ||||
|             </span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="clr-row" *ngIf="selectedItem?.drilldownEnabled"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <label for="drilldownXAxis">Base Drilldown X-Axis</label> | ||||
|           <select id="drilldownXAxis" [(ngModel)]="selectedItem.drilldownXAxis" [ngModelOptions]="{standalone: true}"> | ||||
|             <option value="">Select X-Axis Column</option> | ||||
|             <option *ngFor="let column of drilldownColumnData" [value]="column">{{column}}</option> | ||||
|           </select> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="clr-row" *ngIf="selectedItem?.drilldownEnabled && selectedItem?.name !== 'Deal Details'"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <label for="drilldownYAxis">Base Drilldown Y-Axis</label> | ||||
|           <select id="drilldownYAxis" [(ngModel)]="selectedItem.drilldownYAxis" [ngModelOptions]="{standalone: true}"> | ||||
|             <option value="">Select Y-Axis Column</option> | ||||
|             <option *ngFor="let column of drilldownColumnData" [value]="column">{{column}}</option> | ||||
|           </select> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <!-- Base Drilldown Parameter Configuration --> | ||||
|       <div class="clr-row" *ngIf="selectedItem?.drilldownEnabled"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <label for="drilldownParameter">Base Drilldown Parameter</label> | ||||
|           <select id="drilldownParameter" [(ngModel)]="selectedItem.drilldownParameter" [ngModelOptions]="{standalone: true}"> | ||||
|             <option value="">Select Parameter Column</option> | ||||
|             <option *ngFor="let column of drilldownColumnData" [value]="column">{{column}}</option> | ||||
|           </select> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <!-- Base Drilldown Filter Configuration --> | ||||
|       <div class="clr-row" *ngIf="selectedItem?.drilldownEnabled" style="margin-top: 15px;"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <h5>Base Drilldown Filters</h5> | ||||
|            | ||||
|           <!-- Add Drilldown Filter Button --> | ||||
|           <button class="btn btn-sm btn-primary" (click)="addDrilldownFilter()" style="margin-top: 10px; margin-bottom: 10px;"> | ||||
|             <clr-icon shape="plus"></clr-icon> Add Filter | ||||
|           </button> | ||||
|            | ||||
|           <!-- Drilldown Filter Fields List --> | ||||
|           <div *ngFor="let filter of selectedItem?.drilldownFilters; let i = index"  | ||||
|                style="margin-bottom: 10px; padding: 8px; border: 1px solid #eee; border-radius: 4px; background-color: #f9f9f9;"> | ||||
|             <div style="display: flex; justify-content: space-between; align-items: center;"> | ||||
|               <span>Filter {{i + 1}}</span> | ||||
|               <button class="btn btn-icon btn-danger btn-sm" (click)="removeDrilldownFilter(i)"> | ||||
|                 <clr-icon shape="trash"></clr-icon> | ||||
|               </button> | ||||
|             </div> | ||||
|              | ||||
|             <div class="clr-row" style="margin-top: 8px;"> | ||||
|               <div class="clr-col-sm-5"> | ||||
|                 <input type="text" [(ngModel)]="filter.field" [ngModelOptions]="{standalone: true}"  | ||||
|                        class="clr-input" placeholder="Field Name" /> | ||||
|               </div> | ||||
|                | ||||
|               <div class="clr-col-sm-5"> | ||||
|                 <input type="text" [(ngModel)]="filter.value" [ngModelOptions]="{standalone: true}"  | ||||
|                        class="clr-input" placeholder="Filter Value" /> | ||||
|               </div> | ||||
|                | ||||
|               <div class="clr-col-sm-2"> | ||||
|                 <button class="btn btn-icon btn-danger btn-sm" (click)="removeDrilldownFilter(i)"> | ||||
|                   <clr-icon shape="trash"></clr-icon> | ||||
|                 </button> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <!-- Multi-Layer Drilldown Configurations --> | ||||
|       <div class="clr-row" *ngIf="selectedItem?.drilldownEnabled" style="margin-top: 20px; padding-top: 15px; border-top: 1px solid #ddd;"> | ||||
|         <div class="clr-col-sm-12"> | ||||
|           <h4>Multi-Layer Drilldown Configurations</h4> | ||||
|           <button class="btn btn-sm btn-primary" (click)="addDrilldownLayer()"> | ||||
|             <clr-icon shape="plus"></clr-icon> Add Drilldown Layer | ||||
|           </button> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <!-- Dynamic Drilldown Layers --> | ||||
|       <div class="clr-row" *ngFor="let layer of selectedItem?.drilldownLayers; let i = index"> | ||||
|         <div class="clr-col-sm-12" style="margin-top: 15px; padding: 10px; border: 1px solid #eee; border-radius: 4px;"> | ||||
|           <div style="display: flex; justify-content: space-between; align-items: center;"> | ||||
|             <h5>Drilldown Layer {{i + 1}}</h5> | ||||
|             <button class="btn btn-icon btn-danger btn-sm" (click)="removeDrilldownLayer(i)"> | ||||
|               <clr-icon shape="trash"></clr-icon> | ||||
|             </button> | ||||
|           </div> | ||||
|            | ||||
|           <div class="clr-form-control"> | ||||
|             <div class="clr-control-container"> | ||||
|               <div class="clr-checkbox-wrapper"> | ||||
|                 <input type="checkbox" [id]="'layerEnabled' + i" [(ngModel)]="layer.enabled"  | ||||
|                        [ngModelOptions]="{standalone: true}" class="clr-checkbox" /> | ||||
|                 <label [for]="'layerEnabled' + i" class="clr-control-label">Enable Layer {{i + 1}} Drilldown</label> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|            | ||||
|           <div class="clr-row"> | ||||
|             <div class="clr-col-sm-12"> | ||||
|               <label [for]="'layerApiUrl' + i">Layer {{i + 1}} API URL</label> | ||||
|               <div> | ||||
|                 <input type="text" [id]="'layerApiUrl' + i" class="clr-input" | ||||
|                   [(ngModel)]="layer.apiUrl" style="width:90%" [ngModelOptions]="{standalone: true}">  | ||||
|                 <span> | ||||
|                   <button class="btn btn-icon btn-primary" style="margin: 0px;"  | ||||
|                     (click)="refreshDrilldownLayerColumns(i)" [disabled]="!layer.apiUrl"> | ||||
|                     <clr-icon shape="redo"></clr-icon> | ||||
|                   </button> | ||||
|                 </span> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|            | ||||
|           <div class="clr-row"> | ||||
|             <div class="clr-col-sm-12"> | ||||
|               <label [for]="'layerXAxis' + i">Layer {{i + 1}} X-Axis</label> | ||||
|               <select [id]="'layerXAxis' + i" [(ngModel)]="layer.xAxis" [ngModelOptions]="{standalone: true}"> | ||||
|                 <option value="">Select X-Axis Column</option> | ||||
|                 <option *ngFor="let column of layerColumnData[i] || []" [value]="column">{{column}}</option> | ||||
|               </select> | ||||
|             </div> | ||||
|           </div> | ||||
|            | ||||
|           <div class="clr-row" *ngIf="selectedItem?.name !== 'Deal Details'"> | ||||
|             <div class="clr-col-sm-12"> | ||||
|               <label [for]="'layerYAxis' + i">Layer {{i + 1}} Y-Axis</label> | ||||
|               <select [id]="'layerYAxis' + i" [(ngModel)]="layer.yAxis" [ngModelOptions]="{standalone: true}"> | ||||
|                 <option value="">Select Y-Axis Column</option> | ||||
|                 <option *ngFor="let column of layerColumnData[i] || []" [value]="column">{{column}}</option> | ||||
|               </select> | ||||
|             </div> | ||||
|           </div> | ||||
| 
 | ||||
|           <!-- Parameter Selection for Drilldown Layer --> | ||||
|           <div class="clr-row"> | ||||
|             <div class="clr-col-sm-12"> | ||||
|               <label [for]="'layerParameter' + i">Layer {{i + 1}} Parameter</label> | ||||
|               <select [id]="'layerParameter' + i" [(ngModel)]="layer.parameter" [ngModelOptions]="{standalone: true}"> | ||||
|                 <option value="">Select Parameter Column</option> | ||||
|                 <option *ngFor="let column of layerColumnData[i] || []" [value]="column">{{column}}</option> | ||||
|               </select> | ||||
|             </div> | ||||
|           </div> | ||||
| 
 | ||||
|           <!-- Layer Filter Configuration --> | ||||
|           <div class="clr-row" style="margin-top: 15px;"> | ||||
|             <div class="clr-col-sm-12"> | ||||
|               <h5>Layer {{i + 1}} Filters</h5> | ||||
|                | ||||
|               <!-- Add Layer Filter Button --> | ||||
|               <button class="btn btn-sm btn-primary" (click)="addLayerFilter(i)" style="margin-top: 10px; margin-bottom: 10px;"> | ||||
|                 <clr-icon shape="plus"></clr-icon> Add Filter | ||||
|               </button> | ||||
|                | ||||
|               <!-- Layer Filter Fields List --> | ||||
|               <div *ngFor="let filter of layer.filters; let j = index"  | ||||
|                    style="margin-bottom: 10px; padding: 8px; border: 1px solid #eee; border-radius: 4px; background-color: #f9f9f9;"> | ||||
|                 <div style="display: flex; justify-content: space-between; align-items: center;"> | ||||
|                   <span>Filter {{j + 1}}</span> | ||||
|                   <button class="btn btn-icon btn-danger btn-sm" (click)="removeLayerFilter(i, j)"> | ||||
|                     <clr-icon shape="trash"></clr-icon> | ||||
|                   </button> | ||||
|                 </div> | ||||
|                  | ||||
|                 <div class="clr-row" style="margin-top: 8px;"> | ||||
|                   <div class="clr-col-sm-5"> | ||||
|                     <input type="text" [(ngModel)]="filter.field" [ngModelOptions]="{standalone: true}"  | ||||
|                            class="clr-input" placeholder="Field Name" /> | ||||
|                   </div> | ||||
|                    | ||||
|                   <div class="clr-col-sm-5"> | ||||
|                     <input type="text" [(ngModel)]="filter.value" [ngModelOptions]="{standalone: true}"  | ||||
|                            class="clr-input" placeholder="Filter Value" /> | ||||
|                   </div> | ||||
|                    | ||||
|                   <div class="clr-col-sm-2"> | ||||
|                     <button class="btn btn-icon btn-danger btn-sm" (click)="removeLayerFilter(i, j)"> | ||||
|                       <clr-icon shape="trash"></clr-icon> | ||||
|                     </button> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </form> | ||||
|   </div> | ||||
|   <div class="modal-footer"> | ||||
|     <button type="button" class="btn btn-outline" (click)="cancelConfiguration()">Cancel</button> | ||||
|     <button type="button" class="btn btn-primary" (click)="saveConfiguration()">Save</button> | ||||
|   </div> | ||||
| </clr-modal> | ||||
| @ -1,11 +1,31 @@ | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| import { GridsterConfig, GridsterItem } from 'angular-gridster2'; | ||||
| import { FormBuilder, FormGroup } from '@angular/forms'; | ||||
| import { DatastoreService } from 'src/app/services/fnd/datastore.service'; | ||||
| import { AlertsService } from 'src/app/services/fnd/alerts.service'; | ||||
| import { SureconnectService } from '../../sureconnect/sureconnect.service'; | ||||
| 
 | ||||
| interface ShieldDashboardItem extends GridsterItem { | ||||
|   chartType: string; | ||||
|   name: string; | ||||
|   id: number; | ||||
|   component?: any; | ||||
|   // Configuration properties
 | ||||
|   charttitle?: string; | ||||
|   connection?: string; | ||||
|   table?: string; | ||||
|   xAxis?: string; | ||||
|   yAxis?: string[]; | ||||
|   chartlegend?: boolean; | ||||
|   showlabel?: boolean; | ||||
|   baseFilters?: any[]; | ||||
|   drilldownEnabled?: boolean; | ||||
|   drilldownApiUrl?: string; | ||||
|   drilldownXAxis?: string; | ||||
|   drilldownYAxis?: string; | ||||
|   drilldownParameter?: string; | ||||
|   drilldownFilters?: any[]; | ||||
|   drilldownLayers?: any[]; | ||||
| } | ||||
| 
 | ||||
| interface WidgetModel { | ||||
| @ -22,6 +42,12 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|   options: GridsterConfig; | ||||
|   dashboard: Array<ShieldDashboardItem>; | ||||
|    | ||||
|   // Configuration modal
 | ||||
|   configModalOpen = false; | ||||
|   modeledit = false; // Add this to match the main dashboard pattern
 | ||||
|   configForm: FormGroup; | ||||
|   selectedItem: ShieldDashboardItem | null = null; | ||||
|    | ||||
|   // Component palette
 | ||||
|   showComponentPalette = false; | ||||
|   WidgetsMock: WidgetModel[] = [ | ||||
| @ -51,10 +77,22 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|     } | ||||
|   ]; | ||||
|    | ||||
|   // Services data
 | ||||
|   storedata: any[] = []; | ||||
|   columnData: any[] = []; | ||||
|   sureconnectData: any[] = []; | ||||
|   drilldownColumnData: any[] = []; | ||||
|   layerColumnData: { [key: number]: any[] } = {}; | ||||
|    | ||||
|   // Keep track of deleted items
 | ||||
|   deletedItems: Array<ShieldDashboardItem> = []; | ||||
| 
 | ||||
|   constructor() { } | ||||
|   constructor( | ||||
|     private _fb: FormBuilder, | ||||
|     private datastoreService: DatastoreService, | ||||
|     private alertService: AlertsService, | ||||
|     private sureconnectService: SureconnectService | ||||
|   ) { } | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|     this.options = { | ||||
| @ -81,6 +119,33 @@ export class ShieldDashboardComponent implements OnInit { | ||||
| 
 | ||||
|     // Initialize the dashboard with empty canvas
 | ||||
|     this.dashboard = []; | ||||
|      | ||||
|     // Initialize form
 | ||||
|     this.configForm = this._fb.group({ | ||||
|       charttitle: [''], | ||||
|       connection: [''], | ||||
|       table: [''], | ||||
|       xAxis: [''], | ||||
|       yAxis: [''], | ||||
|       chartlegend: [true], | ||||
|       showlabel: [true] | ||||
|     }); | ||||
|      | ||||
|     // Load service data
 | ||||
|     this.loadServicesData(); | ||||
|   } | ||||
|    | ||||
|   // Load initial data from services
 | ||||
|   loadServicesData() { | ||||
|     // Load sureconnect data
 | ||||
|     this.sureconnectService.getAll().subscribe((data: any[]) => { | ||||
|       this.sureconnectData = data; | ||||
|     }); | ||||
|      | ||||
|     // Load datastore data
 | ||||
|     this.datastoreService.getAll().subscribe((data) => { | ||||
|       this.storedata = data as any[]; | ||||
|     }); | ||||
|   } | ||||
|    | ||||
|   // Toggle component palette visibility
 | ||||
| @ -128,7 +193,12 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|           x: 0,  | ||||
|           chartType: 'bar-chart',  | ||||
|           name: 'Bar Chart',  | ||||
|           id: newId | ||||
|           id: newId, | ||||
|           chartlegend: true, | ||||
|           showlabel: true, | ||||
|           baseFilters: [], | ||||
|           drilldownEnabled: false, | ||||
|           drilldownLayers: [] | ||||
|         }; | ||||
|         break; | ||||
|       case "doughnut_chart": | ||||
| @ -142,7 +212,12 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|             x: 0,  | ||||
|             chartType: 'donut-chart',  | ||||
|             name: 'End Customer Donut',  | ||||
|             id: newId | ||||
|             id: newId, | ||||
|             chartlegend: true, | ||||
|             showlabel: true, | ||||
|             baseFilters: [], | ||||
|             drilldownEnabled: false, | ||||
|             drilldownLayers: [] | ||||
|           }; | ||||
|         } else { | ||||
|           newItem = {  | ||||
| @ -152,7 +227,12 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|             x: 0,  | ||||
|             chartType: 'donut-chart',  | ||||
|             name: 'Segment Penetration Donut',  | ||||
|             id: newId | ||||
|             id: newId, | ||||
|             chartlegend: true, | ||||
|             showlabel: true, | ||||
|             baseFilters: [], | ||||
|             drilldownEnabled: false, | ||||
|             drilldownLayers: [] | ||||
|           }; | ||||
|         } | ||||
|         break; | ||||
| @ -164,7 +244,12 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|           x: 0,  | ||||
|           chartType: 'map-chart',  | ||||
|           name: 'Map Chart',  | ||||
|           id: newId | ||||
|           id: newId, | ||||
|           chartlegend: true, | ||||
|           showlabel: true, | ||||
|           baseFilters: [], | ||||
|           drilldownEnabled: false, | ||||
|           drilldownLayers: [] | ||||
|         }; | ||||
|         break; | ||||
|       case "grid_view": | ||||
| @ -175,7 +260,12 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|           x: 0,  | ||||
|           chartType: 'data-table',  | ||||
|           name: 'Data Table',  | ||||
|           id: newId | ||||
|           id: newId, | ||||
|           chartlegend: true, | ||||
|           showlabel: true, | ||||
|           baseFilters: [], | ||||
|           drilldownEnabled: false, | ||||
|           drilldownLayers: [] | ||||
|         }; | ||||
|         break; | ||||
|       case "to_do_chart": | ||||
| @ -186,7 +276,12 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|           x: 0,  | ||||
|           chartType: 'deal-details',  | ||||
|           name: 'Deal Details',  | ||||
|           id: newId | ||||
|           id: newId, | ||||
|           chartlegend: true, | ||||
|           showlabel: true, | ||||
|           baseFilters: [], | ||||
|           drilldownEnabled: false, | ||||
|           drilldownLayers: [] | ||||
|         }; | ||||
|         break; | ||||
|       case "line_chart": | ||||
| @ -197,7 +292,12 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|           x: 0,  | ||||
|           chartType: 'quarterwise-flow',  | ||||
|           name: 'Quarterwise Flow',  | ||||
|           id: newId | ||||
|           id: newId, | ||||
|           chartlegend: true, | ||||
|           showlabel: true, | ||||
|           baseFilters: [], | ||||
|           drilldownEnabled: false, | ||||
|           drilldownLayers: [] | ||||
|         }; | ||||
|         break; | ||||
|       default: | ||||
| @ -208,7 +308,12 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|           x: 0,  | ||||
|           chartType: componentType,  | ||||
|           name: componentType,  | ||||
|           id: newId | ||||
|           id: newId, | ||||
|           chartlegend: true, | ||||
|           showlabel: true, | ||||
|           baseFilters: [], | ||||
|           drilldownEnabled: false, | ||||
|           drilldownLayers: [] | ||||
|         }; | ||||
|     } | ||||
|      | ||||
| @ -256,7 +361,22 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|     // Only pass properties that are relevant to chart components
 | ||||
|     const chartInputs = { | ||||
|       chartType: item.chartType, | ||||
|       name: item.name | ||||
|       name: item.name, | ||||
|       charttitle: item.charttitle, | ||||
|       connection: item.connection, | ||||
|       table: item.table, | ||||
|       xAxis: item.xAxis, | ||||
|       yAxis: item.yAxis, | ||||
|       chartlegend: item.chartlegend, | ||||
|       showlabel: item.showlabel, | ||||
|       baseFilters: item.baseFilters || [], | ||||
|       drilldownEnabled: item.drilldownEnabled, | ||||
|       drilldownApiUrl: item.drilldownApiUrl, | ||||
|       drilldownXAxis: item.drilldownXAxis, | ||||
|       drilldownYAxis: item.drilldownYAxis, | ||||
|       drilldownParameter: item.drilldownParameter, | ||||
|       drilldownFilters: item.drilldownFilters || [], | ||||
|       drilldownLayers: item.drilldownLayers || [] | ||||
|     }; | ||||
|      | ||||
|     // Remove undefined properties to avoid passing unnecessary data
 | ||||
| @ -268,4 +388,193 @@ export class ShieldDashboardComponent implements OnInit { | ||||
|      | ||||
|     return chartInputs; | ||||
|   } | ||||
|    | ||||
|   // Open configuration modal for a chart
 | ||||
|   editGadget(item: ShieldDashboardItem) { | ||||
|     console.log('Opening configuration modal for item:', item); | ||||
|     this.selectedItem = item; | ||||
|     this.modeledit = true; // Use modeledit instead of configModalOpen
 | ||||
|      | ||||
|     // Initialize form with item data
 | ||||
|     this.configForm.patchValue({ | ||||
|       charttitle: item.charttitle || '', | ||||
|       connection: item.connection || '', | ||||
|       table: item.table || '', | ||||
|       xAxis: item.xAxis || '', | ||||
|       yAxis: item.yAxis || [], | ||||
|       chartlegend: item.chartlegend !== undefined ? item.chartlegend : true, | ||||
|       showlabel: item.showlabel !== undefined ? item.showlabel : true | ||||
|     }); | ||||
|      | ||||
|     console.log('Form values after patch:', this.configForm.value); | ||||
|      | ||||
|     // Load columns if table is set
 | ||||
|     if (item.table) { | ||||
|       this.getColumns(item.connection, item.table); | ||||
|     } | ||||
|      | ||||
|     // Load drilldown columns if drilldown API URL is set
 | ||||
|     if (item.drilldownApiUrl) { | ||||
|       this.refreshDrilldownColumns(); | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Save configuration changes
 | ||||
|   saveConfiguration() { | ||||
|     if (this.selectedItem) { | ||||
|       const formData = this.configForm.value; | ||||
|       console.log('Saving configuration:', formData); | ||||
|        | ||||
|       // Update the selected item with form data
 | ||||
|       Object.assign(this.selectedItem, formData); | ||||
|        | ||||
|       // Close the modal
 | ||||
|       this.modeledit = false; // Use modeledit instead of configModalOpen
 | ||||
|       this.selectedItem = null; | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Cancel configuration changes
 | ||||
|   cancelConfiguration() { | ||||
|     console.log('Canceling configuration'); | ||||
|     this.modeledit = false; // Use modeledit instead of configModalOpen
 | ||||
|     this.selectedItem = null; | ||||
|   } | ||||
|    | ||||
|   // Get tables from datastore
 | ||||
|   getTables(id: string) { | ||||
|     this.alertService.getTablefromstore(parseInt(id, 10)).subscribe(gateway => { | ||||
|       console.log(gateway); | ||||
|       // Handle table data
 | ||||
|     }, (error) => { | ||||
|       console.log(error); | ||||
|     }); | ||||
|   } | ||||
|    | ||||
|   // Get columns from API
 | ||||
|   getColumns(connectionId: string, table: string) { | ||||
|     const connId = connectionId ? parseInt(connectionId, 10) : undefined; | ||||
|     this.alertService.getColumnfromurl(table, connId).subscribe(data => { | ||||
|       console.log('Column data:', data); | ||||
|       this.columnData = data; | ||||
|     }, (error) => { | ||||
|       console.log(error); | ||||
|       this.columnData = []; | ||||
|     }); | ||||
|   } | ||||
|    | ||||
|   // Refresh drilldown columns
 | ||||
|   refreshDrilldownColumns() { | ||||
|     if (this.selectedItem && this.selectedItem.drilldownApiUrl) { | ||||
|       const connId = this.selectedItem.connection ? parseInt(this.selectedItem.connection, 10) : undefined; | ||||
|       this.alertService.getColumnfromurl(this.selectedItem.drilldownApiUrl, connId).subscribe(data => { | ||||
|         console.log('Drilldown column data:', data); | ||||
|         this.drilldownColumnData = data; | ||||
|       }, (error) => { | ||||
|         console.log('Error fetching drilldown columns:', error); | ||||
|         this.drilldownColumnData = []; | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|    | ||||
| 
 | ||||
|    | ||||
|   // Add base filter
 | ||||
|   addBaseFilter() { | ||||
|     if (this.selectedItem) { | ||||
|       if (!this.selectedItem.baseFilters) { | ||||
|         this.selectedItem.baseFilters = []; | ||||
|       } | ||||
|       this.selectedItem.baseFilters.push({ field: '', value: '' }); | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Remove base filter
 | ||||
|   removeBaseFilter(index: number) { | ||||
|     if (this.selectedItem && this.selectedItem.baseFilters) { | ||||
|       this.selectedItem.baseFilters.splice(index, 1); | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Add drilldown filter
 | ||||
|   addDrilldownFilter() { | ||||
|     if (this.selectedItem) { | ||||
|       if (!this.selectedItem.drilldownFilters) { | ||||
|         this.selectedItem.drilldownFilters = []; | ||||
|       } | ||||
|       this.selectedItem.drilldownFilters.push({ field: '', value: '' }); | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Remove drilldown filter
 | ||||
|   removeDrilldownFilter(index: number) { | ||||
|     if (this.selectedItem && this.selectedItem.drilldownFilters) { | ||||
|       this.selectedItem.drilldownFilters.splice(index, 1); | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Add drilldown layer
 | ||||
|   addDrilldownLayer() { | ||||
|     if (this.selectedItem) { | ||||
|       if (!this.selectedItem.drilldownLayers) { | ||||
|         this.selectedItem.drilldownLayers = []; | ||||
|       } | ||||
|       this.selectedItem.drilldownLayers.push({ | ||||
|         enabled: false, | ||||
|         apiUrl: '', | ||||
|         xAxis: '', | ||||
|         yAxis: '', | ||||
|         parameter: '', | ||||
|         filters: [] | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Remove drilldown layer
 | ||||
|   removeDrilldownLayer(index: number) { | ||||
|     if (this.selectedItem && this.selectedItem.drilldownLayers) { | ||||
|       this.selectedItem.drilldownLayers.splice(index, 1); | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Add layer filter
 | ||||
|   addLayerFilter(layerIndex: number) { | ||||
|     if (this.selectedItem && this.selectedItem.drilldownLayers) { | ||||
|       const layer = this.selectedItem.drilldownLayers[layerIndex]; | ||||
|       if (layer) { | ||||
|         if (!layer.filters) { | ||||
|           layer.filters = []; | ||||
|         } | ||||
|         layer.filters.push({ field: '', value: '' }); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Refresh drilldown columns for a specific layer
 | ||||
|   refreshDrilldownLayerColumns(layerIndex: number) { | ||||
|     if (this.selectedItem && this.selectedItem.drilldownLayers && this.selectedItem.drilldownLayers[layerIndex]) { | ||||
|       const layer = this.selectedItem.drilldownLayers[layerIndex]; | ||||
|       if (layer && layer.apiUrl) { | ||||
|         const connId = this.selectedItem.connection ? parseInt(this.selectedItem.connection, 10) : undefined; | ||||
|         this.alertService.getColumnfromurl(layer.apiUrl, connId).subscribe(data => { | ||||
|           console.log(`Drilldown layer ${layerIndex} column data:`, data); | ||||
|           // Store layer column data in the layerColumnData property
 | ||||
|           this.layerColumnData[layerIndex] = data; | ||||
|         }, (error) => { | ||||
|           console.log(`Error fetching drilldown layer ${layerIndex} columns:`, error); | ||||
|           this.layerColumnData[layerIndex] = []; | ||||
|         }); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Remove layer filter
 | ||||
|   removeLayerFilter(layerIndex: number, filterIndex: number) { | ||||
|     if (this.selectedItem && this.selectedItem.drilldownLayers) { | ||||
|       const layer = this.selectedItem.drilldownLayers[layerIndex]; | ||||
|       if (layer && layer.filters) { | ||||
|         layer.filters.splice(filterIndex, 1); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| import { NgModule, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; | ||||
| import { CommonModule } from '@angular/common'; | ||||
| import { FormsModule } from '@angular/forms'; | ||||
| import { FormsModule, ReactiveFormsModule } from '@angular/forms'; | ||||
| import { ClarityModule } from '@clr/angular'; | ||||
| import { GridsterModule } from 'angular-gridster2'; | ||||
| import { NgChartsModule } from 'ng2-charts'; | ||||
| @ -32,6 +32,7 @@ import { LoadingShimmerComponent } from './components/loading-shimmer/loading-sh | ||||
|   imports: [ | ||||
|     CommonModule, | ||||
|     FormsModule, | ||||
|     ReactiveFormsModule, | ||||
|     ClarityModule, | ||||
|     GridsterModule, | ||||
|     NgChartsModule, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user