Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { Document, Schema as MongooseSchema } from 'mongoose'; @Schema({ timestamps: true, collection: 'widget_definitions' }) export class WidgetDefinition extends Document { @Prop({ required: true, unique: true, index: true }) key: string; // e.g. 'kpi.totalRevenue', 'chart.salesTrend' @Prop({ required: true }) name: string; @Prop({ required: true }) type: string; // 'KPI' | 'CHART' | 'TABLE' | 'ACTIVITY' | 'TASK' | 'CALENDAR' | 'PROGRESS' | 'REPORT' | 'QUICK_ACTION' | 'ANNOUNCEMENT' @Prop({ default: null }) moduleKey: string; // Widget belongs to this module @Prop({ type: MongooseSchema.Types.Mixed, default: {} }) defaultConfig: any; @Prop({ default: null }) description: string; @Prop({ default: 'medium' }) defaultSize: string; // 'small' | 'medium' | 'large' @Prop({ default: true }) isActive: boolean; } export const WidgetDefinitionSchema = SchemaFactory.createForClass(WidgetDefinition); @Schema({ timestamps: true, collection: 'dashboard_definitions' }) export class DashboardDefinition extends Document { @Prop({ required: true, index: true }) tenantId: string; @Prop({ default: null, index: true }) userId: string; // null means shared/default dashboard @Prop({ default: null }) role: string; @Prop({ required: true }) name: string; @Prop({ required: true, default: 'TENANT' }) scope: string; // 'PLATFORM' | 'TENANT' | 'ROLE' | 'USER' | 'BRANCH' | 'DEPARTMENT' @Prop({ default: false }) isDefault: boolean; } export const DashboardDefinitionSchema = SchemaFactory.createForClass(DashboardDefinition); DashboardDefinitionSchema.index({ tenantId: 1, scope: 1, userId: 1 }); @Schema({ timestamps: true, collection: 'dashboard_layouts' }) export class DashboardLayout extends Document { @Prop({ required: true, unique: true, index: true }) dashboardId: string; @Prop({ type: MongooseSchema.Types.Mixed, default: { desktop: [], tablet: [], mobile: [] }, }) gridPositions: any; // { desktop: [{widgetKey, x, y, w, h}], tablet: [...], mobile: [...] } } export const DashboardLayoutSchema = SchemaFactory.createForClass(DashboardLayout); @Schema({ timestamps: true, collection: 'dashboard_widget_instances' }) export class DashboardWidgetInstance extends Document { @Prop({ required: true, index: true }) dashboardId: string; @Prop({ required: true }) widgetKey: string; @Prop({ type: MongooseSchema.Types.Mixed, default: {} }) config: any; // User-specific override config for this widget instance @Prop({ default: 300 }) refreshIntervalSeconds: number; @Prop({ type: MongooseSchema.Types.Mixed, default: null }) savedFilters: any; } export const DashboardWidgetInstanceSchema = SchemaFactory.createForClass( DashboardWidgetInstance, ); @Schema({ timestamps: true, collection: 'widget_data_cache' }) export class WidgetDataCache extends Document { @Prop({ required: true, index: true }) tenantId: string; @Prop({ required: true }) widgetKey: string; @Prop({ type: MongooseSchema.Types.Mixed, default: null }) data: any; @Prop({ required: true }) expiresAt: Date; } export const WidgetDataCacheSchema = SchemaFactory.createForClass(WidgetDataCache); WidgetDataCacheSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 }); // TTL index |