shield
This commit is contained in:
parent
f24138cfbd
commit
02f37a1bc5
@ -17,42 +17,46 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Charts and Components Grid -->
|
<!-- Dashboard Grid with Drag and Drop -->
|
||||||
<div class="dashboard-grid">
|
<gridster [options]="options" style="background-color: transparent;">
|
||||||
<!-- Bar Chart -->
|
<gridster-item [item]="item" *ngFor="let item of dashboard">
|
||||||
<div class="grid-item">
|
<!-- 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>
|
<app-shield-bar-chart></app-shield-bar-chart>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="item.chartType === 'donut-chart' && item.name === 'End Customer'">
|
||||||
<!-- Donut Charts -->
|
|
||||||
<div class="grid-item">
|
|
||||||
<app-shield-donut-chart chartType="endCustomer"></app-shield-donut-chart>
|
<app-shield-donut-chart chartType="endCustomer"></app-shield-donut-chart>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="item.chartType === 'donut-chart' && item.name === 'Segment Penetration'">
|
||||||
<div class="grid-item">
|
|
||||||
<app-shield-donut-chart chartType="segmentPenetration"></app-shield-donut-chart>
|
<app-shield-donut-chart chartType="segmentPenetration"></app-shield-donut-chart>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="item.chartType === 'map-chart'">
|
||||||
<!-- Map Section -->
|
|
||||||
<div class="grid-item map-container">
|
|
||||||
<app-shield-map-chart></app-shield-map-chart>
|
<app-shield-map-chart></app-shield-map-chart>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="item.chartType === 'data-table'">
|
||||||
<!-- Data Table -->
|
|
||||||
<div class="grid-item table-container">
|
|
||||||
<app-shield-data-table></app-shield-data-table>
|
<app-shield-data-table></app-shield-data-table>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="item.chartType === 'deal-details'">
|
||||||
<!-- Deal Details Card -->
|
|
||||||
<div class="grid-item">
|
|
||||||
<app-shield-deal-details-card></app-shield-deal-details-card>
|
<app-shield-deal-details-card></app-shield-deal-details-card>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="item.chartType === 'quarterwise-flow'">
|
||||||
<!-- Quarterwise Flow -->
|
|
||||||
<div class="grid-item">
|
|
||||||
<app-shield-quarterwise-flow></app-shield-quarterwise-flow>
|
<app-shield-quarterwise-flow></app-shield-quarterwise-flow>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</gridster-item>
|
||||||
|
</gridster>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1,134 +1,109 @@
|
|||||||
.shield-dashboard {
|
.shield-dashboard {
|
||||||
height: 100%;
|
padding: 20px;
|
||||||
width: 100%;
|
background-color: #f5f5f5;
|
||||||
background-color: #f5f7fa;
|
min-height: 100vh;
|
||||||
font-family: 'Inter', sans-serif;
|
}
|
||||||
|
|
||||||
.dashboard-container {
|
.dashboard-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
gap: 20px;
|
||||||
width: 100%;
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 300px;
|
flex: 0 0 250px;
|
||||||
background: linear-gradient(135deg, #0a192f 0%, #172a45 100%);
|
background: white;
|
||||||
color: white;
|
border-radius: 4px;
|
||||||
padding: 20px;
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
box-shadow: 3px 0 10px rgba(0, 0, 0, 0.1);
|
padding: 15px;
|
||||||
z-index: 10;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 20px;
|
display: flex;
|
||||||
overflow-y: auto;
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.kpi-section {
|
.kpi-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.kpi-card {
|
.kpi-card {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.kpi-title {
|
.kpi-title {
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
color: #64748b;
|
color: #666;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kpi-value {
|
.kpi-value {
|
||||||
font-size: 32px;
|
font-size: 24px;
|
||||||
font-weight: 700;
|
font-weight: bold;
|
||||||
}
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.total-leads {
|
.total-leads {
|
||||||
border-top: 4px solid #ff6b35;
|
border-top: 4px solid #4285f4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.total-deals {
|
.total-deals {
|
||||||
border-top: 4px solid #0a192f;
|
border-top: 4px solid #0f9d58;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-grid {
|
.dashboard-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.grid-item {
|
.grid-item {
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
padding: 20px;
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
padding: 15px;
|
||||||
|
position: relative;
|
||||||
&.map-container {
|
|
||||||
grid-column: span 2;
|
|
||||||
min-height: 400px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.table-container {
|
.grid-item-content {
|
||||||
grid-column: span 2;
|
margin-top: 30px;
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Responsive design
|
.drag-handler {
|
||||||
@media (max-width: 1200px) {
|
cursor: move;
|
||||||
.shield-dashboard {
|
|
||||||
.dashboard-container {
|
|
||||||
.sidebar {
|
|
||||||
width: 250px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
/* Gridster specific styles */
|
||||||
.dashboard-grid {
|
gridster {
|
||||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
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) {
|
@media (max-width: 768px) {
|
||||||
.shield-dashboard {
|
|
||||||
.dashboard-container {
|
.dashboard-container {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 100%;
|
|
||||||
padding: 15px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.sidebar {
|
||||||
padding: 15px;
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.kpi-section {
|
.kpi-section {
|
||||||
flex-direction: column;
|
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 { Component, OnInit } from '@angular/core';
|
||||||
|
import { GridsterConfig, GridsterItem } from 'angular-gridster2';
|
||||||
|
|
||||||
|
interface ShieldDashboardItem extends GridsterItem {
|
||||||
|
chartType: string;
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-shield-dashboard',
|
selector: 'app-shield-dashboard',
|
||||||
@ -6,10 +13,62 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
styleUrls: ['./shield-dashboard.component.scss']
|
styleUrls: ['./shield-dashboard.component.scss']
|
||||||
})
|
})
|
||||||
export class ShieldDashboardComponent implements OnInit {
|
export class ShieldDashboardComponent implements OnInit {
|
||||||
|
options: GridsterConfig;
|
||||||
|
dashboard: Array<ShieldDashboardItem>;
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
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