Skip to content

Widget System Guide

Comprehensive guide to the Barcoding widget system - a dynamic, database-driven dashboard architecture used by all three application instances (Backend, Front, Dashboard).

Overview

The Barcoding widget system provides a powerful, user-customizable dashboard experience where widgets are:

  • Database-Driven: Widget definitions and configurations stored in MySQL database
  • Dynamically Loaded: Widgets loaded on-demand using Angular's dynamic component loading
  • User-Customizable: Users can add, remove, resize, and reposition widgets
  • Multi-Instance: Widgets can be shared across Backend, Front, and Dashboard instances
  • Persistent: Layout and configuration saved per user and synchronized across sessions

Key Concepts

What is a Widget?

A widget is a self-contained, reusable Angular component that can be:

  • Dynamically loaded into a gridster dashboard
  • Configured with custom settings
  • Positioned and sized by users
  • Integrated with the application state and API services

Widget System Architecture

┌─────────────────────────────────────────────────────────────┐
│                    User Dashboard View                       │
├─────────────────────────────────────────────────────────────┤
│  ┌────────────┐  ┌────────────┐  ┌────────────┐            │
│  │  Widget A  │  │  Widget B  │  │  Widget C  │            │
│  │  (Info)    │  │  (Chart)   │  │  (List)    │            │
│  └────────────┘  └────────────┘  └────────────┘            │
└─────────────────────────────────────────────────────────────┘
         │                  │                  │
         ▼                  ▼                  ▼
┌─────────────────────────────────────────────────────────────┐
│              @barcoding/gridster-core                        │
│  - DynamicComponentLoader (lazy loading)                     │
│  - WidgetWrapper (rendering)                                 │
│  - DashboardStore (state management)                         │
└─────────────────────────────────────────────────────────────┘
         │                  │                  │
         ▼                  ▼                  ▼
┌─────────────────────────────────────────────────────────────┐
│                    MySQL Database                            │
│  ┌──────────┐  ┌──────────────┐  ┌───────────────┐         │
│  │  Widget  │  │ WidgetConfig │  │ DashboardView │         │
│  │  (defs)  │  │ (instances)  │  │   (layouts)   │         │
│  └──────────┘  └──────────────┘  └───────────────┘         │
└─────────────────────────────────────────────────────────────┘

Database Schema

The widget system uses three main database tables:

Widget Table

Stores widget definitions (controller names, categories, metadata):

FieldTypeDescription
idintPrimary key
controllervarchar(512)Widget controller name (e.g., "WidgetComments")
general_namevarchar(512)Display name for users
category_idintWidget category for organization
dashboardtinyint(1)Dashboard availability flag
statustinyint(1)Active/inactive status
duplication_optiontinyint(1)Allow multiple instances per dashboard
package_namevarchar(255)Optional package name for shared widgets

WidgetConfig Table

Stores widget instances on dashboards (position, size, configuration):

FieldTypeDescription
idintPrimary key
widget_idintForeign key to Widget table
dashboard_view_idintForeign key to DashboardView (tab)
rowsintWidget height in grid rows
colsintWidget width in grid columns
xintX position on grid
yintY position on grid
configtextJSON configuration for widget

DashboardView Table

Stores dashboard tabs/views that contain widgets:

FieldTypeDescription
idintPrimary key
namevarchar(512)Tab/view name
dashboard_idintForeign key to Dashboard
sortintTab display order

Relationship Flow:

Dashboard (1) ──→ (n) DashboardView (1) ──→ (n) WidgetConfig (n) ──→ (1) Widget

Widget Types

Shared/Package Widgets

Universal widgets packaged as npm packages in @barcoding/widget-* that can be used across all three instances (Backend, Front, Dashboard).

Location: web/projects/packages/@barcoding/widgets/

Characteristics:

  • Published as separate npm packages
  • Can be imported by any instance
  • Follow package dependency hierarchy
  • Must be built before use: ng build @barcoding/widget-example

Example Structure:

web/projects/packages/@barcoding/widget-calendar/
├── src/
│   ├── lib/
│   │   ├── widget-calendar.component.ts
│   │   ├── widget-calendar.component.html
│   │   ├── widget-calendar.component.scss
│   │   └── widget-calendar.module.ts
│   └── public-api.ts
├── package.json
└── ng-package.json

Instance-Specific Widgets

Widgets that exist only in a specific instance and are not shared.

Locations:

  • Backend: web/projects/backend/src/widgets/
  • Front: web/projects/front/src/widgets/
  • Dashboard: web/projects/dashboard/src/widgets/

Characteristics:

  • Scoped to single instance
  • Direct access to instance-specific services
  • Registered in instance's widgets.ts manifest
  • Not published as separate packages

Example Structure:

web/projects/backend/src/widgets/widget-ncr-info/
├── widget-ncr-info/
│   ├── widget-ncr-info.component.ts
│   ├── widget-ncr-info.component.html
│   └── widget-ncr-info.component.scss
├── config/
│   ├── config.component.ts
│   └── modal.html
├── editModal/
│   └── editModal.component.ts
└── widget-ncr-info.module.ts

Widget Categories

Info Widgets

Display information about a specific model/entity being viewed in the application.

Characteristics:

  • Tied to a specific module (NCR, Job, Part, etc.)
  • Display data about the current object in context
  • Usually read-only or minimal interaction
  • Receive state via Observable of current object

Example: widget-ncr-info

typescript
@Component({
  selector: 'widget-ncr-info',
  templateUrl: './widget-ncr-info.component.html'
})
export class WidgetNcrInfoComponent implements WidgetInterface {
  public item: WidgetConfigWithRelations;
  public params: WidgetParams;
  public state: Observable<NcrWithRelations>; // Observes current NCR

  ngOnInit() {
    this.objectSubscription = this.state.subscribe(ncr => {
      this.object = ncr; // Display NCR information
    });
  }
}

Use Cases:

  • Show NCR details (status, description, dates)
  • Display job information (work order, part, timeline)
  • Show employee info (contact, department, schedule)
  • Display document metadata (title, version, owner)

Universal Widgets

Use module_id and object_id to provide a universal data layer that works across multiple modules.

Characteristics:

  • Module-agnostic design
  • Use generic module_id/object_id parameters
  • Can be used on any entity across different modules
  • Typically interact with universal tables (Comments, Documents, History)

Example: widget-comments

typescript
@Component({
  selector: 'widget-comments',
  templateUrl: './widget-comments.component.html'
})
export class WidgetCommentsComponent implements WidgetInterface {
  public item: WidgetConfigWithRelations;
  public params: WidgetParams; // Contains module_id and object_id

  ngOnInit() {
    this.objectSubscription = this.state.subscribe(object => {
      const currentModuleId = this.store.selectSnapshot(ModuleState.module).id;

      // Universal approach: works for any module/object combination
      this.store.dispatch(new FindComments({
        where: {
          module_id: currentModuleId,
          object_id: object.id
        }
      }));
    });
  }
}

Use Cases:

  • Comments system (works on NCR, Jobs, Parts, etc.)
  • Document attachments (works on any entity)
  • Audit history (works on any entity)
  • User favorites (works on any entity)

Chart/Visualization Widgets

Display data visualizations, charts, and analytical dashboards.

Characteristics:

  • Data aggregation and visualization
  • Often use Kendo Charts or custom D3.js
  • May have refresh intervals
  • Configuration for data sources and display options

Use Cases:

  • Production line status charts
  • Time tracking visualizations
  • Sales/revenue dashboards
  • Quality metrics and KPIs

List/Management Widgets

Display lists of data with management capabilities (CRUD operations).

Characteristics:

  • Use Kendo Grid for data display
  • Support filtering, sorting, pagination
  • May include inline editing
  • Action buttons for create/edit/delete

Use Cases:

  • Employee assignment lists
  • Tool usage management
  • Production schedule management
  • Ticket category management

Core Interfaces and Contracts

WidgetInterface

Every widget component must implement the WidgetInterface:

typescript
import { WidgetInterface, WidgetParams } from '@barcoding/gridster-core';
import { WidgetConfigWithRelations } from '@barcoding/sdk';

export interface WidgetInterface {
  item: WidgetConfigWithRelations;  // Widget instance configuration
  params: WidgetParams;              // Runtime parameters
  state?: Observable<any>;           // Optional state observable
}

WidgetParams

Parameters passed to widgets at runtime:

typescript
export interface WidgetParams {
  model?: string;           // Model name (e.g., 'Ncr', 'Job')
  object?: any;             // Current object being viewed
  module_id?: number;       // Current module ID
  object_id?: number;       // Current object ID
  [key: string]: any;       // Additional custom parameters
}

WidgetConfigWithRelations

Widget instance configuration from database:

typescript
export interface WidgetConfigWithRelations {
  id: number;                           // WidgetConfig instance ID
  widget_id: number;                    // Widget definition ID
  dashboard_view_id: number;            // Parent DashboardView ID
  rows: number;                         // Grid height
  cols: number;                         // Grid width
  x: number;                            // X position
  y: number;                            // Y position
  config: any;                          // JSON widget configuration
  widget?: WidgetWithRelations;         // Related Widget definition
}

ConfigInterfaceDashboard

Abstract class for widgets with configurable settings:

typescript
import { ConfigInterfaceDashboard } from '@barcoding/gridster-core';

export class WidgetCommentsComponent
  extends ConfigInterfaceDashboard
  implements WidgetInterface {

  public configChanged$: Subject<any> = new Subject<any>();

  constructor(
    public dialog: MatDialog,
    public store: Store
  ) {
    super(dialog, CommentsConfigDialog, store);
  }

  ngOnDestroy() {
    super.destroy(); // Clean up config subscriptions
  }
}

Syneo/Barcoding Documentation