-
Notifications
You must be signed in to change notification settings - Fork 31
feat: Reusable charts #454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 69 commits
Commits
Show all changes
92 commits
Select commit
Hold shift + click to select a range
5d7a881
add initial plan(s) and tasks
DaveSkender 9c9f530
add initial smoke test (task 1)
DaveSkender a8e3dfa
add claude config
DaveSkender 623cde3
add tmpclaude-* to .gitignore (Claude bug)
DaveSkender e847d68
Extract financial charting library and integrate into Angular app
DaveSkender 37b88d9
initial implementation
DaveSkender 9924fd8
Update README and VitePress guide for improved clarity
DaveSkender 9676ea1
fix tests
DaveSkender 75d1129
Fix markdown linting for VitePress Vue components (#455)
Copilot 257a8ba
Update pnpm version to 10.30.0 across the project
DaveSkender 45d4d69
Add Zsh and Oh My Zsh to devcontainer features
DaveSkender 26014ae
Merge branch 'reusable-charts' of https://github.com/facioquo/stock-c…
DaveSkender 74e3d8b
Refactor API client fetch calls and update documentation
DaveSkender 7c854ef
Enhance setup script to support Debian alongside Ubuntu
DaveSkender 955d86e
fix: Resolve test failures and VitePress build errors (#456)
Copilot b01fa5c
Update client/src/chartjs/financial/api/client.ts
DaveSkender 52d5509
Update libs/indy-charts/charts/chart-manager.ts
DaveSkender 5adf744
refactor: Encapsulate ChartManager properties with private access
DaveSkender 0512c3e
Remove platform-specific setup scripts and add linting script
DaveSkender 416a532
review fixes for non-code aspects
DaveSkender a4ebbd1
add vitepress skill
DaveSkender 6d45d5c
add chartjs, vite skills
DaveSkender 774ac92
general code cleanup
DaveSkender 512bd56
remove claude settings
DaveSkender 5923ef3
Update .agents/skills/chartjs/SKILL.md
DaveSkender 2e64e9f
fix: prevent chart creation errors in test environment
DaveSkender a489b52
Merge branch 'reusable-charts' of https://github.com/facioquo/stock-c…
DaveSkender 31b1246
fix: improve error handling for nvm and CodeRabbit CLI installs
DaveSkender da1425b
update eslint configuration, misc
DaveSkender 8554af8
feat: add Playwright E2E tests for VitePress documentation site
DaveSkender 0cce1b6
Potential fix for pull request finding 'Unneeded defensive code'
DaveSkender 2f25c4c
fix: update date-fns version to 3.0.0 and improve setup scripts for .…
DaveSkender 4f0fdcf
fix: enhance error handling for manual path validation in Playwright …
DaveSkender 0edbfe8
feat: add Vite configuration for resolving workspace package aliases
DaveSkender 4cabe20
feat(tests): enhance Playwright configuration with web server setup a…
DaveSkender 2b685b6
feat: update reusable components and improve API client handling
DaveSkender cdf43e8
feat: render live indicator charts in VitePress example site
DaveSkender 808cf40
add Claude configuration
DaveSkender 299ef3e
fix: update markdownlint ignores and clean up pnpm-lock
DaveSkender 71bf554
fix: auto-create local.settings.json before func start
DaveSkender 0e54033
Refactor code structure for improved readability and maintainability
DaveSkender dc93629
fix: include playwright-report directory in .gitignore
DaveSkender 1d42465
fix: move vitepress dev host/port into package.json script
DaveSkender e21b27f
fix(tests): update seed test URL to match VitePress dev server port 5173
DaveSkender 13bc5b6
fix(vitepress): default dark mode and contain chart overflow
DaveSkender 7345618
fix(vitepress): use position: absolute on canvas for proper Chart.js …
DaveSkender 98a484e
docs: mark task-12 and plan complete with checkbox status
DaveSkender e5f6b82
fix: remove non-idiomatic ResizeObserver and position:absolute from c…
DaveSkender f9fce50
fix: address review feedback - settings encapsulation, type deduplica…
DaveSkender 6cfaa11
docs: update plan and task-12 for responsive canvas correction and re…
DaveSkender cd14a69
add Angular package update tasks
DaveSkender 3a54fe3
review feedback fixes
DaveSkender 3d7d50a
fix: address unresolved CodeRabbit review comments (#457)
Copilot eb7589b
remove timestamp element from backup quotes
DaveSkender a884b61
fixes for code review feedback
DaveSkender 0d9eadd
Update scripts/setup-linux.sh
DaveSkender b61c4ec
chore: update pnpm version in configuration files
DaveSkender 0456532
code review fixes
DaveSkender e8a49d0
update plan
DaveSkender 111130b
Add CSS linting checks to website-lint script
DaveSkender 9fc0987
use node 24 types
DaveSkender 12f4771
update angular packages
DaveSkender 4299280
Enhance quote update function and update dependencies in tests
DaveSkender bf15ae8
Update task details and adjust ports for VitePress and Azure Functions
DaveSkender 4ea686f
fix missing annotations on main site
DaveSkender cdac340
update plan
DaveSkender 5315f40
fix main website
DaveSkender 1713335
Refactor chart services to use IndyCharts library functions
DaveSkender 1d59310
Implement Phase 2 of plan
DaveSkender 6bc4739
Task 3.2 complete
DaveSkender 81f7f18
Update test coverage and add unit tests for data transformers
DaveSkender ad57881
Add GitHub Actions workflow for package publishing and update configs
DaveSkender 40f02fb
Enhance localStorage handling and improve chart selection tests
DaveSkender a3842fa
Refactor tests and improve code formatting across multiple files
DaveSkender cf8982d
Add Phase 5 tasks for external VitePress site integration
DaveSkender 3207602
Merge remote-tracking branch 'origin/main' into reusable-charts
DaveSkender 327971f
fix: resolve 3 Codacy issues blocking PR #454 quality gate (#461)
Copilot 551c6ce
fix: remove unused variable assignments in bench-chart-config.js (#462)
Copilot 69f5e6f
fix: update selector-class-pattern and add scss/function disallowed list
DaveSkender 00d3980
fix: update coverage exclusions and improve Node.js setup script
DaveSkender 317d285
fix: address open CodeRabbit review feedback on #454 (#463)
DaveSkender a9d6356
update packages
DaveSkender e457957
update packages
DaveSkender a999ab9
fix: migrate to xunit.v3, address review feedback, fix Codacy issues
DaveSkender be66226
feat: enhance VitePress integration with indy-charts
DaveSkender 7d405a8
fix: address reusable chart review feedback
DaveSkender c4062d3
fix: address remaining PR review feedback
DaveSkender 349c0bd
fix: apply CodeRabbit auto-fixes
coderabbitai[bot] 4f576df
Remove unused global variable 'console'
DaveSkender e7807f4
Remove global process declaration from script
DaveSkender af96962
Update client/tsconfig.json
DaveSkender f562073
address review feedback
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| // inherits from root config | ||
| "config": { | ||
| "MD033": false // allows <any-placeholder> | ||
| }, | ||
| "ignores": ["find-skills/**", "vite/**", "vitest/**", "vitepress/**"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,388 @@ | ||
| --- | ||
| name: chartjs | ||
| description: Build data visualizations using Chart.js with TypeScript | ||
| --- | ||
|
|
||
| # Chart.js data visualization development | ||
|
|
||
| Build production-quality data visualizations using Chart.js with TypeScript for interactive charts, graphs, and dashboards across React, Angular, and other frameworks. | ||
|
|
||
| ## When to use this skill | ||
|
|
||
| - Building interactive charts and graphs (line, bar, pie, doughnut, radar, etc.) | ||
| - Creating data dashboards with standard chart types | ||
| - Simple to moderately complex data visualizations | ||
| - Projects requiring responsive, accessible charts | ||
| - Applications needing animation and interactivity | ||
| - Complex financial analytics and indicator charts | ||
|
|
||
| ## Required tools | ||
|
|
||
| - #tool:execute - Run npm/pnpm commands (build, test, dev) | ||
| - #tool:edit - Modify source files | ||
| - #tool:search - Find patterns in codebase | ||
| - #tool:read - Read existing code and configurations | ||
| - #tool:web - Fetching official documentation | ||
| - #tool:github/search_repositories - To retrieve information about a GitHub repository | ||
| - #tool:github/web_search - Find answers to specific questions not covered in documentation | ||
|
|
||
| ## Workflow | ||
|
|
||
| ### Step 1: Query authoritative sources | ||
|
|
||
| Use Chart.js documentation for current best practices: | ||
|
|
||
| - Check Chart.js documentation at <https://chartjs.org/docs> | ||
| - Review Chart.js GitHub repository at <https://github.com/chartjs/Chart.js> | ||
| - Verify TypeScript type definitions from the `chart.js` package | ||
|
|
||
| ### Step 2: Review existing patterns | ||
|
|
||
| Search codebase for similar implementations: | ||
|
|
||
| - Look for existing Chart.js components or services | ||
| - Identify repository structure and naming conventions | ||
| - Check for existing chart configurations and themes | ||
| - Review data transformation patterns | ||
|
|
||
| ### Step 3: Implement code | ||
|
|
||
| Follow these core principles: | ||
|
|
||
| **Type safety**: | ||
|
|
||
| - Use TypeScript with Chart.js type definitions (`chart.js`) | ||
| - Define explicit types for chart data and options | ||
| - Avoid `any` type for chart configurations | ||
| - Use proper typing for plugins and custom elements | ||
|
|
||
| **Framework integration**: | ||
|
|
||
| - Use `chart.js` directly via canvas refs in all frameworks | ||
| - Ensure proper component lifecycle management (create on mount, destroy on unmount) | ||
| - Handle chart updates and rerendering efficiently | ||
|
|
||
| **Chart configuration**: | ||
|
|
||
| - Use responsive options for mobile support | ||
| - Configure proper accessibility labels and ARIA attributes | ||
| - Implement consistent color schemes using design tokens | ||
| - Configure animations appropriately for UX | ||
|
|
||
| **Data handling**: | ||
|
|
||
| - Transform API data to Chart.js format | ||
| - Handle loading and error states | ||
| - Implement real-time updates when needed | ||
| - Optimize large datasets with sampling/decimation | ||
|
|
||
| **Best practices**: | ||
|
|
||
| ```typescript | ||
| // ✅ Good - Typed Chart.js configuration | ||
| import { Chart, ChartConfiguration, ChartData } from "chart.js"; | ||
|
|
||
| interface SalesData { | ||
| month: string; | ||
| revenue: number; | ||
| } | ||
|
|
||
| function createChartData(data: SalesData[]): ChartData<"line"> { | ||
| return { | ||
| labels: data.map(d => d.month), | ||
| datasets: [{ | ||
| label: "Revenue", | ||
| data: data.map(d => d.revenue), | ||
| borderColor: "rgb(75, 192, 192)", | ||
| tension: 0.1 | ||
| }] | ||
| }; | ||
| } | ||
|
|
||
| const config: ChartConfiguration<"line"> = { | ||
| type: "line", | ||
| data: createChartData(salesData), | ||
| options: { | ||
| responsive: true, | ||
| maintainAspectRatio: false, | ||
| plugins: { | ||
| legend: { | ||
| display: true, | ||
| position: "top" | ||
| }, | ||
| tooltip: { | ||
| enabled: true, | ||
| mode: "index", | ||
| intersect: false | ||
| } | ||
| }, | ||
| scales: { | ||
| y: { | ||
| beginAtZero: true | ||
| } | ||
| } | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| **React integration example**: | ||
|
|
||
| ```typescript | ||
| // ✅ Good - React Chart.js component with TypeScript | ||
| import { useEffect, useRef } from "react"; | ||
| import { | ||
| Chart, | ||
| CategoryScale, | ||
| LinearScale, | ||
| PointElement, | ||
| LineElement, | ||
| Title, | ||
| Tooltip, | ||
| Legend, | ||
| ChartData, | ||
| ChartOptions | ||
| } from "chart.js"; | ||
|
|
||
| // Register required Chart.js components once at module level | ||
| Chart.register( | ||
| CategoryScale, | ||
| LinearScale, | ||
| PointElement, | ||
| LineElement, | ||
| Title, | ||
| Tooltip, | ||
| Legend | ||
| ); | ||
|
|
||
| interface SalesChartProps { | ||
| data: SalesData[]; | ||
| loading?: boolean; | ||
| } | ||
|
|
||
| export function SalesChart({ data, loading }: SalesChartProps) { | ||
| const canvasRef = useRef<HTMLCanvasElement>(null); | ||
| const chartRef = useRef<Chart<"line"> | null>(null); | ||
|
|
||
| useEffect(() => { | ||
| if (!canvasRef.current || loading) return; | ||
|
|
||
| const chartData: ChartData<"line"> = { | ||
| labels: data.map(d => d.month), | ||
| datasets: [{ | ||
| label: "Monthly Revenue", | ||
| data: data.map(d => d.revenue), | ||
| borderColor: "rgb(75, 192, 192)", | ||
| backgroundColor: "rgba(75, 192, 192, 0.2)", | ||
| tension: 0.1 | ||
| }] | ||
| }; | ||
|
|
||
| const options: ChartOptions<"line"> = { | ||
| responsive: true, | ||
| maintainAspectRatio: false, | ||
| plugins: { | ||
| legend: { position: "top" }, | ||
| title: { display: true, text: "Sales Performance" } | ||
| } | ||
| }; | ||
|
|
||
| chartRef.current = new Chart(canvasRef.current, { | ||
| type: "line", | ||
| data: chartData, | ||
| options | ||
| }); | ||
|
|
||
| return () => { | ||
| chartRef.current?.destroy(); | ||
| chartRef.current = null; | ||
| }; | ||
| }, [data, loading]); | ||
|
|
||
| if (loading) { | ||
| return <div>Loading chart...</div>; | ||
| } | ||
|
|
||
| return ( | ||
| <div style={{ height: "400px", position: "relative" }}> | ||
| <canvas ref={canvasRef} /> | ||
| </div> | ||
| ); | ||
| } | ||
| ``` | ||
|
|
||
| **Angular integration example**: | ||
|
|
||
| ```typescript | ||
| // ✅ Good - Angular Chart.js component with TypeScript | ||
| import { Component, Input, ViewChild, ElementRef, AfterViewInit, OnDestroy } from "@angular/core"; | ||
| import { Chart, ChartConfiguration, ChartData } from "chart.js"; | ||
|
|
||
| @Component({ | ||
| selector: "app-sales-chart", | ||
| template: ` | ||
| <div class="chart-container"> | ||
| <canvas #chartCanvas></canvas> | ||
| </div> | ||
| `, | ||
| styles: [` | ||
| .chart-container { | ||
| position: relative; | ||
| height: 400px; | ||
| width: 100%; | ||
| } | ||
| `] | ||
| }) | ||
| export class SalesChartComponent implements AfterViewInit, OnDestroy { | ||
| @Input() data: SalesData[] = []; | ||
| @ViewChild("chartCanvas") chartCanvas!: ElementRef<HTMLCanvasElement>; | ||
| private chart?: Chart; | ||
|
|
||
| ngAfterViewInit(): void { | ||
| this.createChart(); | ||
| } | ||
|
|
||
| ngOnDestroy(): void { | ||
| this.chart?.destroy(); | ||
| } | ||
|
|
||
| private createChart(): void { | ||
| const config: ChartConfiguration<"line"> = { | ||
| type: "line", | ||
| data: this.getChartData(), | ||
| options: { | ||
| responsive: true, | ||
| maintainAspectRatio: false, | ||
| plugins: { | ||
| legend: { | ||
| position: "top" | ||
| } | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| this.chart = new Chart(this.chartCanvas.nativeElement, config); | ||
| } | ||
|
|
||
| private getChartData(): ChartData<"line"> { | ||
| return { | ||
| labels: this.data.map(d => d.month), | ||
| datasets: [{ | ||
| label: "Revenue", | ||
| data: this.data.map(d => d.revenue), | ||
| borderColor: "rgb(75, 192, 192)" | ||
| }] | ||
| }; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Step 4: Format and validate | ||
|
|
||
| pnpm run lint --fix # Fix ESLint errors | ||
| pnpm run format # Format code (uses project-configured prettier) | ||
| pnpm run build # Verify compilation | ||
| pnpm test # Run tests | ||
|
|
||
| ### Step 5: Check for errors | ||
|
|
||
| Review the Problems panel for compilation errors and warnings. | ||
|
|
||
| ## Completion criteria/quality standards | ||
|
|
||
| - Code compiles without errors or warnings | ||
| - Prettier and linter pass | ||
| - Build succeeds | ||
| - Charts render correctly and are responsive | ||
| - TypeScript strict mode satisfied (no `any` types) | ||
| - Proper accessibility labels configured | ||
| - Loading and error states handled | ||
| - Chart updates efficiently on data changes | ||
|
|
||
| --- | ||
|
|
||
| ## Common chart types and configurations | ||
|
|
||
| ### Line charts | ||
|
|
||
| Best for: Time series data, trends over time | ||
|
|
||
| ```typescript | ||
| const config: ChartConfiguration<"line"> = { | ||
| type: "line", | ||
| data: chartData, | ||
| options: { | ||
| responsive: true, | ||
| plugins: { | ||
| legend: { position: "top" } | ||
| }, | ||
| scales: { | ||
| y: { beginAtZero: true } | ||
| } | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| ### Bar charts | ||
|
|
||
| Best for: Comparing categories, discrete data points | ||
|
|
||
| ```typescript | ||
| const config: ChartConfiguration<"bar"> = { | ||
| type: "bar", | ||
| data: chartData, | ||
| options: { | ||
| responsive: true, | ||
| plugins: { | ||
| legend: { display: false } | ||
| }, | ||
| scales: { | ||
| y: { beginAtZero: true } | ||
| } | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| ### Pie/Doughnut charts | ||
|
|
||
| Best for: Part-to-whole relationships, proportions | ||
|
|
||
| ```typescript | ||
| const config: ChartConfiguration<"doughnut"> = { | ||
| type: "doughnut", | ||
| data: chartData, | ||
| options: { | ||
| responsive: true, | ||
| plugins: { | ||
| legend: { position: "right" } | ||
| } | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| ## Customizations and advanced features | ||
|
|
||
| See [official docs](https://chartjs.org/docs) for additional information on: | ||
|
|
||
| - [Chart.js types reference](https://www.chartjs.org/docs/latest/api/) for exports, enumerations, classes, and interfaces | ||
| - [Developer API reference](https://www.chartjs.org/docs/latest/developers/api.html) | ||
| - [Extending chart types](https://www.chartjs.org/docs/latest/developers/charts.html#extending-existing-chart-types) and [derived chart types](https://www.chartjs.org/docs/latest/samples/advanced/derived-chart-type.html) | ||
| - [Customizing with Plugins](https://www.chartjs.org/docs/latest/developers/plugins.html) | ||
| - [Updating charts](https://www.chartjs.org/docs/latest/developers/updates.html) | ||
| - adding or removing data | ||
| - updating chart options | ||
| - [Animations](https://www.chartjs.org/docs/latest/configuration/animations.html) | ||
| - [Building extensions](https://www.chartjs.org/docs/latest/developers/publishing.html) with ESM and Rollup | ||
|
|
||
| ## Performance optimization | ||
|
|
||
| - Use `decimation` plugin for large datasets | ||
| - Implement virtual scrolling for real-time data | ||
| - Disable animations for frequently updating charts | ||
| - Use `parsing: false` for pre-formatted data | ||
| - Consider chart pooling for dashboard with many charts | ||
|
|
||
| ## Additional references | ||
|
|
||
| - Chart.js documentation: <https://chartjs.org/docs> | ||
| - Chart.js GitHub: <https://github.com/chartjs/Chart.js> | ||
| - Indy Charts GitHub: <https://github.com/facioquo/stock-charts> (this repository) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.