{"id":24836948,"url":"https://github.com/schlessera/dashboard-abstraction-poc","last_synced_at":"2025-03-26T03:43:30.312Z","repository":{"id":274673563,"uuid":"923685980","full_name":"schlessera/dashboard-abstraction-poc","owner":"schlessera","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-29T00:59:53.000Z","size":3875,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-25T00:12:25.999Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://schlessera.github.io/dashboard-abstraction-poc/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/schlessera.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-28T17:24:47.000Z","updated_at":"2025-01-29T00:59:56.000Z","dependencies_parsed_at":"2025-01-28T18:41:39.518Z","dependency_job_id":null,"html_url":"https://github.com/schlessera/dashboard-abstraction-poc","commit_stats":null,"previous_names":["schlessera/dashboard-abstraction-poc"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schlessera%2Fdashboard-abstraction-poc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schlessera%2Fdashboard-abstraction-poc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schlessera%2Fdashboard-abstraction-poc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schlessera%2Fdashboard-abstraction-poc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schlessera","download_url":"https://codeload.github.com/schlessera/dashboard-abstraction-poc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245585798,"owners_count":20639671,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-31T05:48:39.064Z","updated_at":"2025-03-26T03:43:30.287Z","avatar_url":"https://github.com/schlessera.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dashboard Widget Architecture POC\n\nThis project demonstrates a flexible and extensible dashboard architecture using React and TypeScript. It showcases several design patterns and architectural approaches for building modular, maintainable widget-based dashboards.\n\n## Core Concepts\n\n### Architecture Overview\n\n```mermaid\ngraph TD\n    Dashboard[Dashboard] --\u003e |Creates| WF[Widget Factory]\n    Dashboard --\u003e |Manages State| WS[Widget State]\n    WF --\u003e |Creates| W1[Widget Instance]\n    W1 --\u003e |Uses| DP[Data Provider]\n    W1 --\u003e |Uses| CS[Cache Service]\n    \n    subgraph Data Sources\n        DP --\u003e |Fetches| API[Remote API]\n        DP --\u003e |Loads| Files[JSON Files]\n        DP --\u003e |Uses| Mock[Mock Data]\n    end\n```\n\n### Widget Creation Flow\n\n```mermaid\nsequenceDiagram\n    participant D as Dashboard\n    participant WF as Widget Factory\n    participant W as Widget\n    participant DP as Data Provider\n    participant CS as Cache Service\n    \n    D-\u003e\u003eWF: createWidget(id, type)\n    WF-\u003e\u003eW: create(props)\n    W-\u003e\u003eCS: check cache\n    alt Cache Hit\n        CS--\u003e\u003eW: return cached data\n    else Cache Miss\n        W-\u003e\u003eDP: fetch data\n        DP--\u003e\u003eW: return data\n        W-\u003e\u003eCS: store in cache\n    end\n    W--\u003e\u003eD: render widget\n```\n\n## Features\n\n### Data-Driven Widgets\n- Remote data fetching with caching\n- Multiple data source support (APIs, JSON files)\n- Automatic error handling\n- Loading states\n- Type-safe data handling\n\n### Table Widget System\n- Dynamic column configuration\n- Automatic title adaptation\n- Data caching\n\n### Widget Factory\n- Central registry of available widgets\n- Type-safe widget creation\n- Widget metadata management\n- Automatic widget discovery in UI\n\n### Dashboard Features\n- Dynamic widget layout\n- Add/remove widgets\n- Widget state persistence\n- Empty state handling\n- Responsive grid system\n\n## Architecture Benefits\n\n1. **Extensibility**\n   - New widgets can be added without modifying dashboard code\n   - Support for different data sources\n   - Pluggable caching mechanisms\n\n2. **Maintainability**\n   - Clear separation of concerns\n   - Isolated widget logic\n   - Centralized widget management\n\n3. **Reusability**\n   - Shared components and patterns\n   - Abstract data handling\n   - Common widget features\n\n## Getting Started\n\n1. Install dependencies:\n```bash\nnpm install\n```\n\n2. Run Storybook:\n```bash\nnpm run storybook\n```\n\n3. Build for production:\n```bash\nnpm run build\n```\n\n## Development\n\n### Adding a New Widget\n\n1. Create widget component\n\n```typescript\nexport const MyWidget: React.FC\u003cMyWidgetProps\u003e = ({ id, title, onRemove }) =\u003e {\n  return (\n    \u003cWidget id={id} title={title} onRemove={onRemove}\u003e\n      {/* Widget content */}\n    \u003c/Widget\u003e\n  );\n};\n```\n\n2. Add to WidgetFactory\n\n```typescript\nexport class WidgetFactory {\n  private static readonly widgetTypes: WidgetTypeInfo[] = [\n    {\n      type: 'my-widget',\n      label: 'My Widget',\n      description: 'My Widget description'\n    },\n    //...\n  ];\n\n  createWidget(widgetId: string, type: WidgetInstance['type'], onRemove?: (id: string) =\u003e void): React.ReactElement {\n    switch (type) {\n      case 'my-widget':\n        return \u003cMyWidget key={widgetId} id={widgetId} onRemove={onRemove} /\u003e;\n      //...\n    }\n  }\n}\n```\n\n## Project Structure\n\n```\nsrc/\n  components/\n    Dashboard/      # Dashboard component and layout\n    Widget/         # Widget components and base classes\n  services/\n    DataProvider.ts # Data fetching abstraction\n    WidgetFactory.ts # Widget creation and management\n  storybook/\n    stories/        # Component stories\npublic/\n  fixtures/         # JSON data files\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschlessera%2Fdashboard-abstraction-poc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschlessera%2Fdashboard-abstraction-poc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschlessera%2Fdashboard-abstraction-poc/lists"}