Skip to content

Commit 8d0ef8a

Browse files
authored
Merge pull request #5 from objectql/copilot/add-chart-type-metadata
2 parents 8dff858 + efe682e commit 8d0ef8a

File tree

9 files changed

+255
-1
lines changed

9 files changed

+255
-1
lines changed

docs/spec/metadata-format.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,116 @@ actions:
261261
result:
262262
type: currency
263263
```
264+
265+
## 7. Chart Definition
266+
267+
Chart files define data visualizations based on object data. They use the naming convention `*.chart.yml` or `*.chart.yaml`.
268+
269+
### 7.1 Root Properties
270+
271+
| Property | Type | Description |
272+
| :--- | :--- | :--- |
273+
| `name` | `string` | **Required.** Unique API name of the chart. |
274+
| `label` | `string` | Human-readable label for the chart. |
275+
| `description` | `string` | Description of what the chart visualizes. |
276+
| `type` | `string` | **Required.** Chart type: `bar`, `line`, `pie`, or `area`. |
277+
| `object` | `string` | **Required.** The object/entity to visualize data from. |
278+
| `xAxisKey` | `string` | **Required.** Field name for X-axis data. |
279+
| `yAxisKeys` | `string[]` | **Required.** Array of field names for Y-axis data series. |
280+
| `height` | `number` | Chart height in pixels. Default: `300`. |
281+
| `colors` | `string[]` | Custom color palette for chart series. |
282+
| `showGrid` | `boolean` | Whether to display grid lines. Default: `true`. |
283+
| `showLegend` | `boolean` | Whether to display the legend. Default: `true`. |
284+
| `showTooltip` | `boolean` | Whether to show tooltips on hover. Default: `true`. |
285+
| `filters` | `array` | Optional filters to apply to the data query. |
286+
| `sort` | `array` | Sort criteria as `[field, direction]` pairs. |
287+
288+
### 7.2 Chart Types
289+
290+
**Bar Chart**: Best for comparing values across categories.
291+
292+
**Line Chart**: Ideal for showing trends over time.
293+
294+
**Area Chart**: Similar to line charts but with filled areas, great for cumulative data.
295+
296+
**Pie Chart**: Best for showing proportions and distributions (limit to 5-7 categories).
297+
298+
### 7.3 Example Chart Definitions
299+
300+
#### Pie Chart Example
301+
302+
```yaml
303+
name: projects_by_status
304+
label: Projects by Status
305+
description: Distribution of projects across different statuses
306+
type: pie
307+
object: projects
308+
xAxisKey: status
309+
yAxisKeys:
310+
- count
311+
height: 350
312+
showLegend: true
313+
showTooltip: true
314+
```
315+
316+
#### Bar Chart with Custom Colors
317+
318+
```yaml
319+
name: projects_by_priority
320+
label: Projects by Priority
321+
description: Bar chart showing project distribution by priority level
322+
type: bar
323+
object: projects
324+
xAxisKey: priority
325+
yAxisKeys:
326+
- count
327+
height: 300
328+
showGrid: true
329+
showLegend: true
330+
showTooltip: true
331+
colors:
332+
- '#FF6F2C' # High priority (Orange)
333+
- '#FFC940' # Normal priority (Yellow)
334+
- '#20C933' # Low priority (Green)
335+
```
336+
337+
#### Multi-Series Area Chart
338+
339+
```yaml
340+
name: tasks_completion
341+
label: Task Completion Trend
342+
description: Track task completion progress over time
343+
type: area
344+
object: tasks
345+
xAxisKey: due_date
346+
yAxisKeys:
347+
- completed_count
348+
- total_count
349+
height: 350
350+
showGrid: true
351+
showLegend: true
352+
showTooltip: true
353+
colors:
354+
- '#20C933'
355+
- '#2D7FF9'
356+
```
357+
358+
#### Bar Chart with Sorting
359+
360+
```yaml
361+
name: project_budget
362+
label: Project Budget Overview
363+
description: Visualize total budget allocated for each project
364+
type: bar
365+
object: projects
366+
xAxisKey: name
367+
yAxisKeys:
368+
- budget
369+
height: 400
370+
showGrid: true
371+
showLegend: true
372+
showTooltip: true
373+
sort:
374+
- - budget
375+
- desc
376+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: project_budget
2+
label: Project Budget Overview
3+
description: Visualize total budget allocated for each project
4+
type: bar
5+
object: projects
6+
xAxisKey: name
7+
yAxisKeys:
8+
- budget
9+
height: 400
10+
showGrid: true
11+
showLegend: true
12+
showTooltip: true
13+
sort:
14+
- - budget
15+
- desc
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: projects_by_priority
2+
label: Projects by Priority
3+
description: Bar chart showing project distribution by priority level
4+
type: bar
5+
object: projects
6+
xAxisKey: priority
7+
yAxisKeys:
8+
- count
9+
height: 300
10+
showGrid: true
11+
showLegend: true
12+
showTooltip: true
13+
colors:
14+
- '#FF6F2C'
15+
- '#FFC940'
16+
- '#20C933'
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name: projects_by_status
2+
label: Projects by Status
3+
description: Distribution of projects across different statuses
4+
type: pie
5+
object: projects
6+
xAxisKey: status
7+
yAxisKeys:
8+
- count
9+
height: 350
10+
showLegend: true
11+
showTooltip: true
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: tasks_completion
2+
label: Task Completion Trend
3+
description: Track task completion progress over time
4+
type: area
5+
object: tasks
6+
xAxisKey: due_date
7+
yAxisKeys:
8+
- completed_count
9+
- total_count
10+
height: 350
11+
showGrid: true
12+
showLegend: true
13+
showTooltip: true
14+
colors:
15+
- '#20C933'
16+
- '#2D7FF9'

packages/metadata/src/plugins/objectql.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as yaml from 'js-yaml';
22
import * as path from 'path';
33
import { MetadataLoader } from '../loader';
4-
import { ObjectConfig } from '../types';
4+
import { ObjectConfig, ChartConfig } from '../types';
55

66
export function registerObjectQLPlugins(loader: MetadataLoader) {
77
// Objects
@@ -166,6 +166,32 @@ export function registerObjectQLPlugins(loader: MetadataLoader) {
166166
}
167167
}
168168
});
169+
170+
// Charts
171+
loader.use({
172+
name: 'chart',
173+
glob: ['**/*.chart.yml', '**/*.chart.yaml'],
174+
handler: (ctx) => {
175+
try {
176+
const doc = yaml.load(ctx.content) as any;
177+
if (!doc) return;
178+
179+
if (doc.name && doc.type && doc.object) {
180+
registerChart(ctx.registry, doc, ctx.file, ctx.packageName);
181+
} else {
182+
for (const [key, value] of Object.entries(doc)) {
183+
if (typeof value === 'object' && (value as any).type && (value as any).object) {
184+
const chart = value as any;
185+
if (!chart.name) chart.name = key;
186+
registerChart(ctx.registry, chart, ctx.file, ctx.packageName);
187+
}
188+
}
189+
}
190+
} catch (e) {
191+
console.error(`Error loading chart from ${ctx.file}:`, e);
192+
}
193+
}
194+
});
169195
}
170196

171197
function registerObject(registry: any, obj: any, file: string, packageName?: string) {
@@ -188,3 +214,13 @@ function registerObject(registry: any, obj: any, file: string, packageName?: str
188214
});
189215
}
190216

217+
function registerChart(registry: any, chart: any, file: string, packageName?: string) {
218+
registry.register('chart', {
219+
type: 'chart',
220+
id: chart.name,
221+
path: file,
222+
package: packageName,
223+
content: chart
224+
});
225+
}
226+

packages/metadata/src/types.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,22 @@ export interface ObjectConfig {
9595
actions?: Record<string, ActionConfig>;
9696
data?: any[];
9797
}
98+
99+
export type ChartType = 'bar' | 'line' | 'pie' | 'area';
100+
101+
export interface ChartConfig {
102+
name: string;
103+
label?: string;
104+
description?: string;
105+
type: ChartType;
106+
object: string;
107+
xAxisKey: string;
108+
yAxisKeys: string[];
109+
height?: number;
110+
colors?: string[];
111+
showGrid?: boolean;
112+
showLegend?: boolean;
113+
showTooltip?: boolean;
114+
filters?: any[];
115+
sort?: [string, 'asc' | 'desc'][];
116+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
name: test_chart
2+
label: Test Chart
3+
type: bar
4+
object: test_object
5+
xAxisKey: category
6+
yAxisKeys:
7+
- value
8+
height: 300

packages/metadata/test/index.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { MetadataRegistry } from '../src/registry';
22
import { MetadataLoader } from '../src/loader';
3+
import { registerObjectQLPlugins } from '../src/plugins/objectql';
34
import * as path from 'path';
45
import * as yaml from 'js-yaml';
56

@@ -82,3 +83,22 @@ describe('MetadataLoader', () => {
8283
expect(item.value).toBe(123);
8384
});
8485
});
86+
87+
describe('Chart Metadata Loader', () => {
88+
it('should load chart metadata from .chart.yml files', () => {
89+
const registry = new MetadataRegistry();
90+
const loader = new MetadataLoader(registry);
91+
92+
registerObjectQLPlugins(loader);
93+
94+
const fixturesDir = path.join(__dirname, 'fixtures');
95+
loader.load(fixturesDir);
96+
97+
const chart = registry.get('chart', 'test_chart');
98+
expect(chart).toBeDefined();
99+
expect(chart.type).toBe('bar');
100+
expect(chart.object).toBe('test_object');
101+
expect(chart.xAxisKey).toBe('category');
102+
expect(chart.yAxisKeys).toEqual(['value']);
103+
});
104+
});

0 commit comments

Comments
 (0)