Skip to content

Commit f82a7dc

Browse files
committed
refactor: 30% reduction in package size
1 parent 9d5f18f commit f82a7dc

File tree

5 files changed

+393
-0
lines changed

5 files changed

+393
-0
lines changed

docs/api/props.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ interface VisualProps {
5050
markConnection?: MarkConnection; // Type of marker in connections
5151
showLabel?: boolean; // Show bar labels
5252
showProgress?: boolean; // Show progress indicators
53+
showPlannedBars?: boolean; // Show planned bars alongside actual bars
5354
showEventsAxis?: boolean; // Show events axis
5455
eventsAxisHeight?: number; // Height of events axis
5556
timeaxisEvents?: TimeaxisEvent[]; // Events to display on time axis

docs/api/types.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,14 @@ interface GanttBarConfig {
3838
progress?: number;
3939
progressResizable?: boolean;
4040
progressStyle?: CSSProperties;
41+
plannedStyle?: CSSProperties; // Styling for planned bars
4142
}
4243

4344
interface GanttBarObject {
4445
[key: string]: any;
4546
ganttBarConfig: GanttBarConfig;
47+
start_planned?: string | Date; // Planned start date
48+
end_planned?: string | Date; // Planned end date
4649
}
4750

4851
interface GanttBarConnection {
@@ -70,6 +73,62 @@ interface GanttBarObjectWithoutStyles extends Omit<GanttBarObject, "ganttBarConf
7073
}
7174
```
7275

76+
## Planned Bars Types
77+
78+
The planned bars feature introduces additional properties for displaying planned/expected dates alongside actual dates:
79+
80+
```typescript
81+
// Planned Bars Configuration
82+
interface PlannedBarConfig {
83+
start_planned?: string | Date; // Planned start date
84+
end_planned?: string | Date; // Planned end date
85+
plannedStyle?: CSSProperties; // Custom styling for planned bars
86+
}
87+
88+
// Extended Bar Object with Planned Dates
89+
interface GanttBarObjectWithPlanned extends GanttBarObject {
90+
start_planned?: string | Date;
91+
end_planned?: string | Date;
92+
}
93+
94+
// Tooltip Data with Planned Information
95+
interface BarTooltipData {
96+
bar: GanttBarObject;
97+
barStart: string | Date;
98+
barEnd: string | Date;
99+
barStartPlanned?: string | Date; // Available when showPlannedBars is true
100+
barEndPlanned?: string | Date; // Available when showPlannedBars is true
101+
}
102+
```
103+
104+
### Planned Bars Usage Example
105+
106+
```typescript
107+
const barsWithPlanning: GanttBarObject[] = [
108+
{
109+
start: '2024-02-15', // Actual start
110+
end: '2024-02-28', // Actual end
111+
start_planned: '2024-02-01', // Planned start
112+
end_planned: '2024-02-20', // Planned end
113+
ganttBarConfig: {
114+
id: 'task-1',
115+
label: 'Development Task',
116+
// Styling for the actual bar
117+
style: {
118+
backgroundColor: '#2196f3',
119+
color: 'white'
120+
},
121+
// Styling for the planned bar (shown as overlay/underlay)
122+
plannedStyle: {
123+
backgroundColor: '#e3f2fd',
124+
border: '2px dashed #1976d2',
125+
opacity: 0.7
126+
}
127+
}
128+
}
129+
]
130+
```
131+
73132
## Connection Label Styling
74133

75134
```typescript

docs/components/g-gantt-chart.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Here's a minimal example of using the GGanttChart component:
7979
| markerConnection| `MarkerConnection` | `forward` | Choose the type of marker in connection |
8080
| showLabel| `boolean` | `true` | Enable the visualization of bar label |
8181
| showProgress| `boolean` | `true` | Enable the visualization of percentage bar progress |
82+
| showPlannedBars| `boolean` | `false` | Enable the visualization of planned bars alongside actual bars |
8283
| defaultProgressResizable | `boolean` | `true` | Enable progress adjustment through dragging |
8384
| enableConnectionCreation | `boolean` | `false` | Enable the possibility to draw connections |
8485
| enableConnectionDelete | `boolean` | `false` | Enable the possibility to delete connections |

docs/examples/advanced.md

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,275 @@ const rows = ref([
123123
</style>
124124
```
125125

126+
## Planned vs Actual Timeline Tracking
127+
128+
The planned bars feature allows you to visualize both planned and actual timelines for project tracking and variance analysis:
129+
130+
```vue
131+
<template>
132+
<g-gantt-chart
133+
v-bind="chartConfig"
134+
:show-planned-bars="true"
135+
>
136+
<g-gantt-row
137+
v-for="row in projectRows"
138+
:key="row.label"
139+
:label="row.label"
140+
:bars="row.bars"
141+
/>
142+
</g-gantt-chart>
143+
</template>
144+
145+
<script setup lang="ts">
146+
import { ref } from 'vue'
147+
148+
const chartConfig = ref({
149+
chartStart: '2024-01-01',
150+
chartEnd: '2024-03-31',
151+
precision: 'day',
152+
barStart: 'start',
153+
barEnd: 'end'
154+
})
155+
156+
const projectRows = ref([
157+
{
158+
label: 'Planning Phase',
159+
bars: [{
160+
start: '2024-01-03', // Actual started 2 days late
161+
end: '2024-01-18', // Finished 3 days late
162+
start_planned: '2024-01-01', // Originally planned start
163+
end_planned: '2024-01-15', // Originally planned end
164+
ganttBarConfig: {
165+
id: 'planning',
166+
label: 'Requirements & Design',
167+
style: {
168+
backgroundColor: '#4caf50',
169+
color: 'white'
170+
},
171+
plannedStyle: {
172+
backgroundColor: '#e8f5e8',
173+
border: '2px dashed #4caf50',
174+
opacity: 0.6
175+
}
176+
}
177+
}]
178+
},
179+
{
180+
label: 'Development',
181+
bars: [{
182+
start: '2024-01-20', // Started on time
183+
end: '2024-02-25', // Running 5 days over
184+
start_planned: '2024-01-20', // Planned start
185+
end_planned: '2024-02-20', // Planned end
186+
ganttBarConfig: {
187+
id: 'development',
188+
label: 'Core Implementation',
189+
style: {
190+
backgroundColor: '#2196f3',
191+
color: 'white'
192+
},
193+
plannedStyle: {
194+
backgroundColor: '#e3f2fd',
195+
border: '2px dashed #2196f3',
196+
opacity: 0.6
197+
}
198+
}
199+
}]
200+
},
201+
{
202+
label: 'Testing',
203+
bars: [{
204+
start: '2024-03-01', // Delayed start due to dev overrun
205+
end: '2024-03-20', // Compressed timeline
206+
start_planned: '2024-02-25', // Originally planned earlier
207+
end_planned: '2024-03-15', // Originally shorter duration
208+
ganttBarConfig: {
209+
id: 'testing',
210+
label: 'QA & Bug Fixes',
211+
style: {
212+
backgroundColor: '#ff9800',
213+
color: 'white'
214+
},
215+
plannedStyle: {
216+
backgroundColor: '#fff3e0',
217+
border: '2px dashed #ff9800',
218+
opacity: 0.6
219+
}
220+
}
221+
}]
222+
}
223+
])
224+
</script>
225+
```
226+
227+
### Project Variance Analysis Example
228+
229+
```vue
230+
<template>
231+
<div class="project-dashboard">
232+
<h3>Project Dashboard with Variance Tracking</h3>
233+
234+
<!-- Summary Stats -->
235+
<div class="variance-summary">
236+
<div class="stat-card">
237+
<strong>Total Delay:</strong> {{ calculateTotalDelay() }} days
238+
</div>
239+
<div class="stat-card">
240+
<strong>Tasks Over Budget:</strong> {{ tasksOverBudget() }}
241+
</div>
242+
</div>
243+
244+
<g-gantt-chart
245+
v-bind="chartConfig"
246+
:show-planned-bars="true"
247+
@click-bar="handleBarClick"
248+
>
249+
<g-gantt-row
250+
v-for="row in varianceRows"
251+
:key="row.label"
252+
:label="row.label"
253+
:bars="row.bars"
254+
>
255+
<template #bar-tooltip="{ bar, barStart, barEnd }">
256+
<div class="variance-tooltip">
257+
<h4>{{ bar.ganttBarConfig.label }}</h4>
258+
<div><strong>Actual:</strong> {{ barStart }} → {{ barEnd }}</div>
259+
<div v-if="bar.start_planned">
260+
<strong>Planned:</strong> {{ bar.start_planned }} → {{ bar.end_planned }}
261+
</div>
262+
<div class="variance-info">
263+
<strong>Variance:</strong>
264+
<span :class="getVarianceClass(bar)">
265+
{{ calculateVariance(bar) }}
266+
</span>
267+
</div>
268+
</div>
269+
</template>
270+
</g-gantt-row>
271+
</g-gantt-chart>
272+
</div>
273+
</template>
274+
275+
<script setup lang="ts">
276+
import dayjs from 'dayjs'
277+
278+
const varianceRows = ref([
279+
{
280+
label: 'Frontend Development',
281+
bars: [{
282+
start: '2024-01-10',
283+
end: '2024-02-15',
284+
start_planned: '2024-01-05',
285+
end_planned: '2024-02-05',
286+
ganttBarConfig: {
287+
id: 'frontend',
288+
label: 'React Components',
289+
plannedStyle: {
290+
backgroundColor: '#ffebee',
291+
border: '2px dashed #f44336',
292+
opacity: 0.7
293+
}
294+
}
295+
}]
296+
},
297+
{
298+
label: 'Backend API',
299+
bars: [{
300+
start: '2024-01-08',
301+
end: '2024-01-28',
302+
start_planned: '2024-01-10',
303+
end_planned: '2024-02-10',
304+
ganttBarConfig: {
305+
id: 'backend',
306+
label: 'REST API Development',
307+
plannedStyle: {
308+
backgroundColor: '#e8f5e8',
309+
border: '2px dashed #4caf50',
310+
opacity: 0.7
311+
}
312+
}
313+
}]
314+
}
315+
])
316+
317+
function calculateVariance(bar) {
318+
if (!bar.start_planned || !bar.end_planned) return 'N/A'
319+
320+
const actualDuration = dayjs(bar.end).diff(dayjs(bar.start), 'days')
321+
const plannedDuration = dayjs(bar.end_planned).diff(dayjs(bar.start_planned), 'days')
322+
const variance = actualDuration - plannedDuration
323+
324+
return variance > 0 ? `+${variance} days` : `${variance} days`
325+
}
326+
327+
function getVarianceClass(bar) {
328+
if (!bar.start_planned) return ''
329+
const variance = dayjs(bar.end).diff(dayjs(bar.end_planned), 'days')
330+
return variance > 0 ? 'over-budget' : variance < 0 ? 'under-budget' : 'on-time'
331+
}
332+
333+
function calculateTotalDelay() {
334+
return varianceRows.value.reduce((total, row) => {
335+
return total + row.bars.reduce((rowTotal, bar) => {
336+
const delay = bar.start_planned
337+
? Math.max(0, dayjs(bar.end).diff(dayjs(bar.end_planned), 'days'))
338+
: 0
339+
return rowTotal + delay
340+
}, 0)
341+
}, 0)
342+
}
343+
344+
function tasksOverBudget() {
345+
return varianceRows.value.reduce((count, row) => {
346+
return count + row.bars.filter(bar =>
347+
bar.start_planned && dayjs(bar.end).isAfter(dayjs(bar.end_planned))
348+
).length
349+
}, 0)
350+
}
351+
352+
function handleBarClick({ bar }) {
353+
console.log('Bar clicked:', bar.ganttBarConfig.label)
354+
// Handle bar interaction
355+
}
356+
</script>
357+
358+
<style scoped>
359+
.project-dashboard {
360+
padding: 20px;
361+
}
362+
363+
.variance-summary {
364+
display: flex;
365+
gap: 20px;
366+
margin-bottom: 20px;
367+
}
368+
369+
.stat-card {
370+
padding: 12px;
371+
background: #f5f5f5;
372+
border-radius: 6px;
373+
border-left: 4px solid #2196f3;
374+
}
375+
376+
.variance-tooltip {
377+
padding: 10px;
378+
background: white;
379+
border-radius: 4px;
380+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
381+
}
382+
383+
.variance-info {
384+
margin-top: 8px;
385+
padding-top: 8px;
386+
border-top: 1px solid #eee;
387+
}
388+
389+
.over-budget { color: #f44336; font-weight: bold; }
390+
.under-budget { color: #4caf50; font-weight: bold; }
391+
.on-time { color: #2196f3; font-weight: bold; }
392+
</style>
393+
```
394+
126395
## Multi Label Columns
127396

128397
```vue

0 commit comments

Comments
 (0)