dashboard
This commit is contained in:
		
							parent
							
								
									f2b6a4d145
								
							
						
					
					
						commit
						8266bfdc01
					
				| @ -23,18 +23,6 @@ | |||||||
|      |      | ||||||
|     <!-- Main Dashboard Content --> |     <!-- Main Dashboard Content --> | ||||||
|     <div class="main-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 --> |       <!-- Deleted Items Section --> | ||||||
|       <div class="deleted-items-section" *ngIf="deletedItems.length > 0"> |       <div class="deleted-items-section" *ngIf="deletedItems.length > 0"> | ||||||
|         <h3>Deleted Items</h3> |         <h3>Deleted Items</h3> | ||||||
| @ -52,9 +40,6 @@ | |||||||
|       </div> |       </div> | ||||||
|        |        | ||||||
|       <!-- Dashboard Grid with Drag and Drop --> |       <!-- 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 [options]="options" (drop)="onDrop($event)" style="background-color: transparent; min-height: 500px;"> | ||||||
|         <gridster-item [item]="item" *ngFor="let item of dashboard"> |         <gridster-item [item]="item" *ngFor="let item of dashboard"> | ||||||
|           <!-- Remove Button --> |           <!-- Remove Button --> | ||||||
| @ -62,6 +47,11 @@ | |||||||
|             <clr-icon shape="trash"></clr-icon> |             <clr-icon shape="trash"></clr-icon> | ||||||
|           </button> |           </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 --> |           <!-- Drag Handle --> | ||||||
|           <button class="btn btn-icon drag-handler" style="margin-left: 10px; margin-top: 10px;"> |           <button class="btn btn-icon drag-handler" style="margin-left: 10px; margin-top: 10px;"> | ||||||
|             <clr-icon shape="drag-handle"></clr-icon> |             <clr-icon shape="drag-handle"></clr-icon> | ||||||
| @ -96,4 +86,361 @@ | |||||||
|       </gridster> |       </gridster> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </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 { Component, OnInit } from '@angular/core'; | ||||||
| import { GridsterConfig, GridsterItem } from 'angular-gridster2'; | 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 { | interface ShieldDashboardItem extends GridsterItem { | ||||||
|   chartType: string; |   chartType: string; | ||||||
|   name: string; |   name: string; | ||||||
|   id: number; |   id: number; | ||||||
|   component?: any; |   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 { | interface WidgetModel { | ||||||
| @ -22,6 +42,12 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|   options: GridsterConfig; |   options: GridsterConfig; | ||||||
|   dashboard: Array<ShieldDashboardItem>; |   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
 |   // Component palette
 | ||||||
|   showComponentPalette = false; |   showComponentPalette = false; | ||||||
|   WidgetsMock: WidgetModel[] = [ |   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
 |   // Keep track of deleted items
 | ||||||
|   deletedItems: Array<ShieldDashboardItem> = []; |   deletedItems: Array<ShieldDashboardItem> = []; | ||||||
| 
 | 
 | ||||||
|   constructor() { } |   constructor( | ||||||
|  |     private _fb: FormBuilder, | ||||||
|  |     private datastoreService: DatastoreService, | ||||||
|  |     private alertService: AlertsService, | ||||||
|  |     private sureconnectService: SureconnectService | ||||||
|  |   ) { } | ||||||
| 
 | 
 | ||||||
|   ngOnInit(): void { |   ngOnInit(): void { | ||||||
|     this.options = { |     this.options = { | ||||||
| @ -81,6 +119,33 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
| 
 | 
 | ||||||
|     // Initialize the dashboard with empty canvas
 |     // Initialize the dashboard with empty canvas
 | ||||||
|     this.dashboard = []; |     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
 |   // Toggle component palette visibility
 | ||||||
| @ -128,7 +193,12 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|           x: 0,  |           x: 0,  | ||||||
|           chartType: 'bar-chart',  |           chartType: 'bar-chart',  | ||||||
|           name: 'Bar Chart',  |           name: 'Bar Chart',  | ||||||
|           id: newId |           id: newId, | ||||||
|  |           chartlegend: true, | ||||||
|  |           showlabel: true, | ||||||
|  |           baseFilters: [], | ||||||
|  |           drilldownEnabled: false, | ||||||
|  |           drilldownLayers: [] | ||||||
|         }; |         }; | ||||||
|         break; |         break; | ||||||
|       case "doughnut_chart": |       case "doughnut_chart": | ||||||
| @ -142,7 +212,12 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|             x: 0,  |             x: 0,  | ||||||
|             chartType: 'donut-chart',  |             chartType: 'donut-chart',  | ||||||
|             name: 'End Customer Donut',  |             name: 'End Customer Donut',  | ||||||
|             id: newId |             id: newId, | ||||||
|  |             chartlegend: true, | ||||||
|  |             showlabel: true, | ||||||
|  |             baseFilters: [], | ||||||
|  |             drilldownEnabled: false, | ||||||
|  |             drilldownLayers: [] | ||||||
|           }; |           }; | ||||||
|         } else { |         } else { | ||||||
|           newItem = {  |           newItem = {  | ||||||
| @ -152,7 +227,12 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|             x: 0,  |             x: 0,  | ||||||
|             chartType: 'donut-chart',  |             chartType: 'donut-chart',  | ||||||
|             name: 'Segment Penetration Donut',  |             name: 'Segment Penetration Donut',  | ||||||
|             id: newId |             id: newId, | ||||||
|  |             chartlegend: true, | ||||||
|  |             showlabel: true, | ||||||
|  |             baseFilters: [], | ||||||
|  |             drilldownEnabled: false, | ||||||
|  |             drilldownLayers: [] | ||||||
|           }; |           }; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
| @ -164,7 +244,12 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|           x: 0,  |           x: 0,  | ||||||
|           chartType: 'map-chart',  |           chartType: 'map-chart',  | ||||||
|           name: 'Map Chart',  |           name: 'Map Chart',  | ||||||
|           id: newId |           id: newId, | ||||||
|  |           chartlegend: true, | ||||||
|  |           showlabel: true, | ||||||
|  |           baseFilters: [], | ||||||
|  |           drilldownEnabled: false, | ||||||
|  |           drilldownLayers: [] | ||||||
|         }; |         }; | ||||||
|         break; |         break; | ||||||
|       case "grid_view": |       case "grid_view": | ||||||
| @ -175,7 +260,12 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|           x: 0,  |           x: 0,  | ||||||
|           chartType: 'data-table',  |           chartType: 'data-table',  | ||||||
|           name: 'Data Table',  |           name: 'Data Table',  | ||||||
|           id: newId |           id: newId, | ||||||
|  |           chartlegend: true, | ||||||
|  |           showlabel: true, | ||||||
|  |           baseFilters: [], | ||||||
|  |           drilldownEnabled: false, | ||||||
|  |           drilldownLayers: [] | ||||||
|         }; |         }; | ||||||
|         break; |         break; | ||||||
|       case "to_do_chart": |       case "to_do_chart": | ||||||
| @ -186,7 +276,12 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|           x: 0,  |           x: 0,  | ||||||
|           chartType: 'deal-details',  |           chartType: 'deal-details',  | ||||||
|           name: 'Deal Details',  |           name: 'Deal Details',  | ||||||
|           id: newId |           id: newId, | ||||||
|  |           chartlegend: true, | ||||||
|  |           showlabel: true, | ||||||
|  |           baseFilters: [], | ||||||
|  |           drilldownEnabled: false, | ||||||
|  |           drilldownLayers: [] | ||||||
|         }; |         }; | ||||||
|         break; |         break; | ||||||
|       case "line_chart": |       case "line_chart": | ||||||
| @ -197,7 +292,12 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|           x: 0,  |           x: 0,  | ||||||
|           chartType: 'quarterwise-flow',  |           chartType: 'quarterwise-flow',  | ||||||
|           name: 'Quarterwise Flow',  |           name: 'Quarterwise Flow',  | ||||||
|           id: newId |           id: newId, | ||||||
|  |           chartlegend: true, | ||||||
|  |           showlabel: true, | ||||||
|  |           baseFilters: [], | ||||||
|  |           drilldownEnabled: false, | ||||||
|  |           drilldownLayers: [] | ||||||
|         }; |         }; | ||||||
|         break; |         break; | ||||||
|       default: |       default: | ||||||
| @ -208,7 +308,12 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|           x: 0,  |           x: 0,  | ||||||
|           chartType: componentType,  |           chartType: componentType,  | ||||||
|           name: 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
 |     // Only pass properties that are relevant to chart components
 | ||||||
|     const chartInputs = { |     const chartInputs = { | ||||||
|       chartType: item.chartType, |       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
 |     // Remove undefined properties to avoid passing unnecessary data
 | ||||||
| @ -268,4 +388,193 @@ export class ShieldDashboardComponent implements OnInit { | |||||||
|      |      | ||||||
|     return chartInputs; |     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 { NgModule, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; | ||||||
| import { CommonModule } from '@angular/common'; | import { CommonModule } from '@angular/common'; | ||||||
| import { FormsModule } from '@angular/forms'; | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; | ||||||
| import { ClarityModule } from '@clr/angular'; | import { ClarityModule } from '@clr/angular'; | ||||||
| import { GridsterModule } from 'angular-gridster2'; | import { GridsterModule } from 'angular-gridster2'; | ||||||
| import { NgChartsModule } from 'ng2-charts'; | import { NgChartsModule } from 'ng2-charts'; | ||||||
| @ -32,6 +32,7 @@ import { LoadingShimmerComponent } from './components/loading-shimmer/loading-sh | |||||||
|   imports: [ |   imports: [ | ||||||
|     CommonModule, |     CommonModule, | ||||||
|     FormsModule, |     FormsModule, | ||||||
|  |     ReactiveFormsModule, | ||||||
|     ClarityModule, |     ClarityModule, | ||||||
|     GridsterModule, |     GridsterModule, | ||||||
|     NgChartsModule, |     NgChartsModule, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user