shield
This commit is contained in:
parent
f24138cfbd
commit
02f37a1bc5
@ -17,42 +17,46 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Charts and Components Grid -->
|
||||
<div class="dashboard-grid">
|
||||
<!-- Bar Chart -->
|
||||
<div class="grid-item">
|
||||
<!-- Dashboard Grid with Drag and Drop -->
|
||||
<gridster [options]="options" style="background-color: transparent;">
|
||||
<gridster-item [item]="item" *ngFor="let item of dashboard">
|
||||
<!-- Remove Button -->
|
||||
<button class="btn btn-icon btn-danger" style="margin-left: 10px; margin-top: 10px;" (click)="removeItem(item)">
|
||||
<clr-icon shape="trash"></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>
|
||||
</button>
|
||||
|
||||
<!-- Chart Components -->
|
||||
<div class="grid-item-content">
|
||||
<h4 style="margin-top: 0px; margin-left: 10px;">{{item.name}}</h4>
|
||||
<div *ngIf="item.chartType === 'bar-chart'">
|
||||
<app-shield-bar-chart></app-shield-bar-chart>
|
||||
</div>
|
||||
|
||||
<!-- Donut Charts -->
|
||||
<div class="grid-item">
|
||||
<div *ngIf="item.chartType === 'donut-chart' && item.name === 'End Customer'">
|
||||
<app-shield-donut-chart chartType="endCustomer"></app-shield-donut-chart>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<div *ngIf="item.chartType === 'donut-chart' && item.name === 'Segment Penetration'">
|
||||
<app-shield-donut-chart chartType="segmentPenetration"></app-shield-donut-chart>
|
||||
</div>
|
||||
|
||||
<!-- Map Section -->
|
||||
<div class="grid-item map-container">
|
||||
<div *ngIf="item.chartType === 'map-chart'">
|
||||
<app-shield-map-chart></app-shield-map-chart>
|
||||
</div>
|
||||
|
||||
<!-- Data Table -->
|
||||
<div class="grid-item table-container">
|
||||
<div *ngIf="item.chartType === 'data-table'">
|
||||
<app-shield-data-table></app-shield-data-table>
|
||||
</div>
|
||||
|
||||
<!-- Deal Details Card -->
|
||||
<div class="grid-item">
|
||||
<div *ngIf="item.chartType === 'deal-details'">
|
||||
<app-shield-deal-details-card></app-shield-deal-details-card>
|
||||
</div>
|
||||
|
||||
<!-- Quarterwise Flow -->
|
||||
<div class="grid-item">
|
||||
<div *ngIf="item.chartType === 'quarterwise-flow'">
|
||||
<app-shield-quarterwise-flow></app-shield-quarterwise-flow>
|
||||
</div>
|
||||
</div>
|
||||
</gridster-item>
|
||||
</gridster>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,134 +1,109 @@
|
||||
.shield-dashboard {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #f5f7fa;
|
||||
font-family: 'Inter', sans-serif;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.dashboard-container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 300px;
|
||||
background: linear-gradient(135deg, #0a192f 0%, #172a45 100%);
|
||||
color: white;
|
||||
padding: 20px;
|
||||
box-shadow: 3px 0 10px rgba(0, 0, 0, 0.1);
|
||||
z-index: 10;
|
||||
flex-shrink: 0;
|
||||
flex: 0 0 250px;
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.kpi-section {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.kpi-card {
|
||||
flex: 1;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.kpi-title {
|
||||
font-size: 16px;
|
||||
color: #64748b;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.kpi-value {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
}
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.total-leads {
|
||||
border-top: 4px solid #ff6b35;
|
||||
border-top: 4px solid #4285f4;
|
||||
}
|
||||
|
||||
.total-deals {
|
||||
border-top: 4px solid #0a192f;
|
||||
}
|
||||
border-top: 4px solid #0f9d58;
|
||||
}
|
||||
|
||||
.dashboard-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
|
||||
&.map-container {
|
||||
grid-column: span 2;
|
||||
min-height: 400px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
padding: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&.table-container {
|
||||
grid-column: span 2;
|
||||
min-height: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.grid-item-content {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
// Responsive design
|
||||
@media (max-width: 1200px) {
|
||||
.shield-dashboard {
|
||||
.dashboard-container {
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
.drag-handler {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
.dashboard-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Gridster specific styles */
|
||||
gridster {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
gridster-item {
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 768px) {
|
||||
.shield-dashboard {
|
||||
.dashboard-container {
|
||||
flex-direction: column;
|
||||
|
||||
.sidebar {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 15px;
|
||||
.sidebar {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.kpi-section {
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.dashboard-grid {
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
.grid-item {
|
||||
&.map-container, &.table-container {
|
||||
grid-column: span 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,11 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { GridsterConfig, GridsterItem } from 'angular-gridster2';
|
||||
|
||||
interface ShieldDashboardItem extends GridsterItem {
|
||||
chartType: string;
|
||||
name: string;
|
||||
id: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-shield-dashboard',
|
||||
@ -6,10 +13,62 @@ import { Component, OnInit } from '@angular/core';
|
||||
styleUrls: ['./shield-dashboard.component.scss']
|
||||
})
|
||||
export class ShieldDashboardComponent implements OnInit {
|
||||
options: GridsterConfig;
|
||||
dashboard: Array<ShieldDashboardItem>;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.options = {
|
||||
gridType: 'fit',
|
||||
enableEmptyCellDrop: true,
|
||||
emptyCellDropCallback: this.onDrop.bind(this),
|
||||
pushItems: true,
|
||||
swap: true,
|
||||
pushDirections: { north: true, east: true, south: true, west: true },
|
||||
resizable: { enabled: true },
|
||||
itemChangeCallback: this.itemChange.bind(this),
|
||||
draggable: {
|
||||
enabled: true,
|
||||
ignoreContent: true,
|
||||
dropOverItems: true,
|
||||
dragHandleClass: 'drag-handler',
|
||||
ignoreContentClass: 'no-drag',
|
||||
},
|
||||
displayGrid: 'always',
|
||||
minCols: 10,
|
||||
minRows: 10,
|
||||
itemResizeCallback: this.itemResize.bind(this)
|
||||
};
|
||||
|
||||
// Initialize the dashboard with default components
|
||||
this.dashboard = [
|
||||
{ cols: 5, rows: 6, y: 0, x: 0, chartType: 'bar-chart', name: 'Bar Chart', id: 1 },
|
||||
{ cols: 5, rows: 6, y: 0, x: 5, chartType: 'donut-chart', name: 'End Customer', id: 2 },
|
||||
{ cols: 5, rows: 6, y: 6, x: 0, chartType: 'donut-chart', name: 'Segment Penetration', id: 3 },
|
||||
{ cols: 5, rows: 6, y: 6, x: 5, chartType: 'map-chart', name: 'Map Chart', id: 4 },
|
||||
{ cols: 10, rows: 6, y: 12, x: 0, chartType: 'data-table', name: 'Data Table', id: 5 },
|
||||
{ cols: 5, rows: 6, y: 18, x: 0, chartType: 'deal-details', name: 'Deal Details', id: 6 },
|
||||
{ cols: 5, rows: 6, y: 18, x: 5, chartType: 'quarterwise-flow', name: 'Quarterwise Flow', id: 7 }
|
||||
];
|
||||
}
|
||||
|
||||
onDrop(event: any) {
|
||||
// Handle dropping new components onto the dashboard
|
||||
console.log('Item dropped:', event);
|
||||
}
|
||||
|
||||
removeItem(item: ShieldDashboardItem) {
|
||||
this.dashboard.splice(this.dashboard.indexOf(item), 1);
|
||||
}
|
||||
|
||||
itemChange() {
|
||||
console.log('Item changed:', this.dashboard);
|
||||
}
|
||||
|
||||
itemResize(item: any, itemComponent: any) {
|
||||
console.log('Item resized:', item);
|
||||
// Trigger a window resize event to notify charts to resize
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { ClarityModule } from '@clr/angular';
|
||||
import { GridsterModule } from 'angular-gridster2';
|
||||
import { NgChartsModule } from 'ng2-charts';
|
||||
import { DynamicModule } from 'ng-dynamic-component';
|
||||
|
||||
import { ShieldDashboardRoutingModule } from './shield-dashboard-routing.module';
|
||||
import { ShieldDashboardComponent } from './shield-dashboard.component';
|
||||
import { SidebarFiltersComponent } from './components/sidebar-filters/sidebar-filters.component';
|
||||
import { BarChartComponent } from './components/bar-chart/bar-chart.component';
|
||||
import { DonutChartComponent } from './components/donut-chart/donut-chart.component';
|
||||
import { MapChartComponent } from './components/map-chart/map-chart.component';
|
||||
import { DataTableComponent } from './components/data-table/data-table.component';
|
||||
import { DealDetailsCardComponent } from './components/deal-details-card/deal-details-card.component';
|
||||
import { QuarterwiseFlowComponent } from './components/quarterwise-flow/quarterwise-flow.component';
|
||||
import { LoadingShimmerComponent } from './components/loading-shimmer/loading-shimmer.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ShieldDashboardComponent,
|
||||
SidebarFiltersComponent,
|
||||
BarChartComponent,
|
||||
DonutChartComponent,
|
||||
MapChartComponent,
|
||||
DataTableComponent,
|
||||
DealDetailsCardComponent,
|
||||
QuarterwiseFlowComponent,
|
||||
LoadingShimmerComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ClarityModule,
|
||||
GridsterModule,
|
||||
NgChartsModule,
|
||||
DynamicModule,
|
||||
ShieldDashboardRoutingModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA]
|
||||
})
|
||||
export class ShieldDashboardModule { }
|
||||
Loading…
x
Reference in New Issue
Block a user