Skip to content

Commit 1ea4ba2

Browse files
authored
Merge pull request #180 from n-side-dev/SOFA-310-gantt-chart-clean-structure
Sofa 310 gantt chart clean structure
2 parents 5470e86 + 6569ead commit 1ea4ba2

26 files changed

Lines changed: 2217 additions & 10 deletions

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
- **Component discovery**: inspect `src/components`, exported barrels (`src/components/**/index.ts`), and `@nside/wefa` type definitions before crafting new UI. Use `npm info @nside/wefa` or the local `dist/lib.d.ts` for quick lookup.
2222
- **PrimeVue composition**: when WeFa lacks a widget, compose PrimeVue primitives with Tailwind classes. Imports follow `import Component from 'primevue/component'` and styling sticks to utility classes or theme tokens (`bg-primary-500`, `text-surface-900`, etc.).
2323
- **State & data utilities**: rely on provided composables (`src/composables`), Pinia stores (`src/stores`), and network helpers (`src/network`). Prefer enhancing these layers rather than re-implementing ad-hoc logic inside components.
24+
- **Props definition**: use `const { prop1 = prop1Default, ... } = defineProps<YourPropsType>()` with explicit interfaces/types. Avoid the usage of `withDefault()`.
2425
- **Stories & docs**: every component lives with `.stories.ts`, `.mdx`, and spec files under its folder. Keep stories authoritative and update MDX docs when props/state change.
2526
- **Quality gates**: run `npm run lint-check`, `npm run format-check`, `npm run test:unit`, `npm run test:e2e` (when flows/routing change), `npm run build`, and regenerate Storybook (`npm run storybook` or `npm run build-storybook`) before handing work off.
2627

vue/eslint.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ export default defineConfigWithVueTs(
4646
"order": [ "template", "script", "style" ] // Enforce this precise order in component definition!
4747
}],
4848
"vitest/prefer-called-exactly-once-with": "off", // Exactly once is not always possible
49-
'sonarjs/todo-tag': 'warn' // TODOs can refer to issues that are not yet fixed
49+
"sonarjs/todo-tag": "warn", // TODOs can refer to issues that are not yet fixed
50+
"security/detect-object-injection": "off" // False positives are common with this rule in TS projects
5051
}
5152
},
5253
{

vue/knip.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,9 @@
88
"ignoreDependencies": ["@tailwindcss/cli", "@vee-validate/zod"],
99
"tags": [
1010
"-lintignore"
11-
]
11+
],
12+
"storybook": {
13+
"config": [".storybook/main.ts"],
14+
"entry": [".storybook/preview.ts", "src/**/*.stories.@(js|jsx|ts|tsx)"]
15+
}
1216
}

vue/package-lock.json

Lines changed: 63 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vue/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@
7272
"@tailwindcss/vite": "^4.1.18",
7373
"@tanstack/vue-query": "^5.92.8",
7474
"@vee-validate/zod": "^4.15.1",
75+
"@vueuse/core": "^14.1.0",
7576
"axios": "^1.13.2",
77+
"luxon": "^3.7.2",
7678
"marked": "^17.0.1",
7779
"pinia": "^3.0.4",
7880
"plotly.js-dist-min": "^3.3.1",
@@ -96,6 +98,7 @@
9698
"@tsconfig/node22": "^22.0.5",
9799
"@types/eslint-plugin-security": "^3.0.0",
98100
"@types/jsdom": "^27.0.0",
101+
"@types/luxon": "^3.7.1",
99102
"@types/node": "^25.0.9",
100103
"@types/plotly.js-dist-min": "^2.3.4",
101104
"@vitejs/plugin-vue": "^6.0.3",
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import { Meta, Canvas, ArgTypes } from '@storybook/addon-docs/blocks'
2+
import * as GanttChartStories from './GanttChartComponent.stories'
3+
4+
<Meta of={GanttChartStories} />
5+
6+
# Gantt Chart
7+
8+
A flexible, virtualized Gantt chart that supports daily and weekly views, layered activity types, and translation-ready labels.
9+
10+
## Overview
11+
12+
The GanttChart component renders a calendar grid with month and week headers, and a virtualized list of rows. Activities can be rendered as stripes, primary bars, or compact stacked minis. Weekly view collapses the grid to week columns and expands month headers across overlapping weeks.
13+
14+
### Key Features
15+
16+
- **Daily & Weekly Views**: Toggle with `viewMode`.
17+
- **Layered Activities**: Stripe, bar, and mini styles with overlap rules.
18+
- **Stacked Minis**: Overlapping minis grow row height automatically.
19+
- **Virtualized Rows**: Smooth scrolling for large datasets.
20+
- **Translation Ready**: All user-facing labels are passed through `t()`.
21+
- **Configurable Sidebar**: Adjust the label column width via `leftHeaderWidthPx`.
22+
23+
## Basic Usage
24+
25+
<Canvas of={GanttChartStories.Default} />
26+
27+
```vue
28+
<template>
29+
<GanttChartComponent
30+
:start-date="startDate"
31+
:end-date="endDate"
32+
:rows="rows"
33+
:links="links"
34+
header-label="gantt_chart.header"
35+
/>
36+
</template>
37+
38+
<script setup lang="ts">
39+
import { ref } from 'vue'
40+
import GanttChartComponent from '@/components/GanttChartComponent/GanttChartComponent.vue'
41+
42+
const startDate = ref(new Date(2026, 0, 1))
43+
const endDate = ref(new Date(2026, 0, 2))
44+
const rows = ref([
45+
{
46+
id: 1,
47+
header: 'gantt_chart.row',
48+
activities: [
49+
{
50+
id: 'planned',
51+
label: 'gantt_chart.activity',
52+
startDate: new Date(2026, 0, 1),
53+
endDate: new Date(2026, 0, 4),
54+
visualType: 'stripe',
55+
color: 'rgba(59, 130, 246, 0.2)',
56+
},
57+
{
58+
id: 'optimized',
59+
label: 'gantt_chart.activity',
60+
startDate: new Date(2026, 0, 2),
61+
endDate: new Date(2026, 0, 8),
62+
visualType: 'bar',
63+
colorClass: 'bg-emerald-400/80',
64+
},
65+
],
66+
},
67+
])
68+
const links = ref([{ fromId: 'planned', toId: 'optimized' }])
69+
</script>
70+
```
71+
72+
## Weekly View
73+
74+
```vue
75+
<GanttChartComponent
76+
:start-date="startDate"
77+
:end-date="endDate"
78+
:rows="rows"
79+
view-mode="week"
80+
:show-weekend-shading="false"
81+
/>
82+
```
83+
84+
- Weekly view renders a single week cell per column.
85+
- Activities fill any week they overlap (inclusive by week).
86+
- Month headers can span overlapping weeks.
87+
88+
## Activity Types
89+
90+
Activities support a `visualType`:
91+
92+
- `stripe`: diagonal background context
93+
- `bar`: primary rounded bar
94+
- `mini`: compact bar, stacked into lanes when overlapping
95+
96+
## Tooltips and Clicks
97+
98+
```vue
99+
<GanttChartComponent
100+
:start-date="startDate"
101+
:end-date="endDate"
102+
:rows="rows"
103+
:links="links"
104+
:activity-tooltip="(activity, row) => `${row?.id}: ${activity.label}`"
105+
:activity-click="(activity, row) => console.log(activity, row)"
106+
/>
107+
```
108+
109+
## API Reference
110+
111+
<ArgTypes of={GanttChartStories} />
112+
113+
```ts
114+
export type GanttChartActivityData = {
115+
id?: string | number
116+
label?: string
117+
startDate: Date
118+
endDate: Date
119+
visualType?: 'stripe' | 'bar' | 'mini'
120+
color?: string
121+
colorClass?: string
122+
}
123+
124+
export type GanttChartRowData = {
125+
id?: string | number
126+
label?: string
127+
header?: string
128+
activities: GanttChartActivityData[]
129+
}
130+
131+
export type GanttChartLinkData = {
132+
id?: string | number
133+
fromId: string | number
134+
toId: string | number
135+
type?: 'finish-start' | 'start-start'
136+
color?: string
137+
}
138+
```
139+
140+
## Translation Notes
141+
142+
- `headerLabel`, `row.header`, `row.label`, and `activity.label` are treated as translation keys.
143+
- Week labels use the key `gantt_chart.week` by default.

0 commit comments

Comments
 (0)