Gathering detailed insights and metrics for gantt-group
Gathering detailed insights and metrics for gantt-group
Gathering detailed insights and metrics for gantt-group
Gathering detailed insights and metrics for gantt-group
gantt-elastic-group
Gantt chart. Elastic javascript gantt chart. Vue gantt. Project manager responsive gantt. jquery gantt.
frappe-gantt-fix-for-grouping
A simple, modern, interactive gantt library for the web
aio-table
all in one table. tree mode , simple mode , tree mode, gantt mode , groupby mode, freeze mode.
ganttgrouping
gantt grouping
Gantt Chart [ javascript gantt chart, gantt component, vue gantt, vue gantt chart, responsive gantt, project manager , vue projects ]
npm install gantt-group
Typescript
Module System
Node Version
NPM Version
Vue (68.33%)
HTML (17.03%)
JavaScript (14.64%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
1,348 Stars
767 Commits
316 Forks
43 Watchers
14 Branches
5 Contributors
Updated on Jul 11, 2025
Latest Version
2.0.13
Package Id
gantt-group@2.0.13
Unpacked Size
9.12 MB
Size
8.69 MB
File Count
54
NPM Version
6.14.14
Node Version
14.17.4
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
4
Keywords: [ gantt, javascript gantt, gantt chart,js gantt,vue gantt,project manager,gantt project manager,responsive gantt ]
本组件基于gantt-elastic进行二次封装,甘特图一行可以显示多个任务
Gantt-Group is a vue component but it could be used in other frameworks or even with jQuery (vue is kind of elastic and lightweight framework).
For now you can look at WIKI There is also full example vue project at https://github.com/neuronetio/vue-gantt-elastic
npm install --save gantt-group
1 2//原有gantt-elastic属性不变,新增一个type属性:group 3//The gantt-elastic attribute will remain unchanged. Add a new type attribute: group 4//sample task code,使用dayjs处理时间 5tasks: [ 6 { 7 id: 5, 8 label: '202204', 9 start: dayjs('2022-05-08').valueOf(), 10 end:dayjs('2022-9-10').valueOf(), 11 percent: 25, 12 type: 'group', 13 tasks: [ 14 { 15 id: 6, 16 label: 'V0', 17 start: dayjs('2022-06-16').valueOf(), 18 end:dayjs('2022-06-24').valueOf(), 19 percent: 50, 20 type: 'task', 21 style: { 22 base: { 23 fill: '#C0E2D9', 24 stroke: '#C0E2D9', 25 }, 26 }, 27 }, 28 { 29 id: 7, 30 label: 'V1', 31 start: dayjs('2022-07-01').valueOf(), 32 end:dayjs('2022-07-16').valueOf(), 33 percent: 50, 34 type: 'task', 35 style: { 36 base: { 37 fill: '#FEE4D5', 38 stroke: '#FEE4D5', 39 }, 40 }, 41 }, 42 { 43 id: 8, 44 label: 'V2', 45 start: dayjs('2022-08-02').valueOf(), 46 end:dayjs('2022-08-16').valueOf(), 47 percent: 50, 48 type: 'task', 49 style: { 50 base: { 51 fill: '#C6EBFE', 52 stroke: '#C6EBFE', 53 }, 54 }, 55 }, 56 { 57 id: 9, 58 label: 'V3', 59 start: dayjs('2022-08-24').valueOf(), 60 end:dayjs('2022-09-16').valueOf(), 61 percent: 50, 62 type: 'task', 63 style: { 64 base: { 65 fill: '#E7E7E7', 66 stroke: '#E7E7E7', 67 }, 68 }, 69 }, 70 ], 71 }, 72 { 73 id: 6, 74 label: '202205', 75 start: dayjs('2022-04-08').valueOf(), 76 end:dayjs('2022-9-30').valueOf(), 77 percent: 25, 78 type: 'group', 79 tasks: [ 80 { 81 id: 7, 82 label: 'V0', 83 start: dayjs('2022-06-01').valueOf(), 84 end:dayjs('2022-06-16').valueOf(), 85 percent: 50, 86 type: 'task', 87 style: { 88 base: { 89 fill: '#C0E2D9', 90 stroke: '#C0E2D9', 91 }, 92 }, 93 }, 94 { 95 id: 8, 96 label: 'V1', 97 start: dayjs('2022-06-18').valueOf(), 98 end:dayjs('2022-07-28').valueOf(), 99 percent: 50, 100 type: 'task', 101 style: { 102 base: { 103 fill: '#FEE4D5', 104 stroke: '#FEE4D5', 105 }, 106 }, 107 }, 108 { 109 id: 9, 110 label: 'V2', 111 start: dayjs('2022-08-01').valueOf(), 112 end:dayjs('2022-08-10').valueOf(), 113 percent: 50, 114 type: 'task', 115 style: { 116 base: { 117 fill: '#C6EBFE', 118 stroke: '#C6EBFE', 119 }, 120 }, 121 }, 122 { 123 id: 10, 124 label: 'V3', 125 start: dayjs('2022-08-21').valueOf(), 126 end:dayjs('2022-09-06').valueOf(), 127 percent: 50, 128 type: 'task', 129 style: { 130 base: { 131 fill: '#E7E7E7', 132 stroke: '#E7E7E7', 133 }, 134 }, 135 }, 136 ], 137 }, 138 ],
1<!DOCTYPE html> 2<html charset="utf-8"> 3 <head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> 6 <title>GanttElastic editor demo</title> 7 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 8 <script src="https://cdn.jsdelivr.net/npm/dayjs"></script> 9 10 <script src="https://unpkg.com/gantt-elastic/dist/GanttElastic.umd.js"></script> 11 <script src="https://unpkg.com/gantt-elastic-header/dist/Header.umd.js"></script> 12 </head> 13 14 <body> 15 <div style="width:100%;height:100%"> 16 <div id="app" v-if="!destroy"> 17 <gantt-elastic :tasks="tasks" :options="options" :dynamic-style="dynamicStyle"> 18 <gantt-header slot="header"></gantt-header> 19 <gantt-footer slot="footer"></gantt-footer> 20 </gantt-elastic> 21 </div> 22 </div> 23 24 <script> 25 // just helper to get current dates 26 function getDate(hours) { 27 const currentDate = new Date(); 28 const currentYear = currentDate.getFullYear(); 29 const currentMonth = currentDate.getMonth(); 30 const currentDay = currentDate.getDate(); 31 const timeStamp = new Date(currentYear, currentMonth, currentDay, 0, 0, 0).getTime(); 32 return new Date(timeStamp + hours * 60 * 60 * 1000).getTime(); 33 } 34 35 let tasks = [ 36 { 37 id: 1, 38 label: 'Make some noise', 39 user: '<a href="https://www.google.com/search?q=John+Doe" target="_blank" style="color:#0077c0;">John Doe</a>', 40 start: getDate(-24 * 5), 41 duration: 15 * 24 * 60 * 60 * 1000, 42 progress: 85, 43 type: 'project', 44 //collapsed: true, 45 }, 46 { 47 id: 2, 48 label: 'With great power comes great responsibility', 49 user: '<a href="https://www.google.com/search?q=Peter+Parker" target="_blank" style="color:#0077c0;">Peter Parker</a>', 50 parentId: 1, 51 start: getDate(-24 * 4), 52 duration: 4 * 24 * 60 * 60 * 1000, 53 progress: 50, 54 type: 'milestone', 55 collapsed: true, 56 style: { 57 base: { 58 fill: '#1EBC61', 59 stroke: '#0EAC51', 60 }, 61 /*'tree-row-bar': { 62 fill: '#1EBC61', 63 stroke: '#0EAC51' 64 }, 65 'tree-row-bar-polygon': { 66 stroke: '#0EAC51' 67 }*/ 68 }, 69 }, 70 { 71 id: 3, 72 label: 'Courage is being scared to death, but saddling up anyway.', 73 user: '<a href="https://www.google.com/search?q=John+Wayne" target="_blank" style="color:#0077c0;">John Wayne</a>', 74 parentId: 2, 75 start: getDate(-24 * 3), 76 duration: 2 * 24 * 60 * 60 * 1000, 77 progress: 100, 78 type: 'task', 79 }, 80 { 81 id: 4, 82 label: 'Put that toy AWAY!', 83 user: '<a href="https://www.google.com/search?q=Clark+Kent" target="_blank" style="color:#0077c0;">Clark Kent</a>', 84 start: getDate(-24 * 2), 85 duration: 2 * 24 * 60 * 60 * 1000, 86 progress: 50, 87 type: 'task', 88 dependentOn: [3], 89 }, 90 ]; 91 92 let options = { 93 maxRows: 100, 94 maxHeight: 300, 95 title: { 96 label: 'Your project title as html (link or whatever...)', 97 html: false, 98 }, 99 row: { 100 height: 24, 101 }, 102 calendar: { 103 hour: { 104 display: false, 105 }, 106 }, 107 chart: { 108 progress: { 109 bar: false, 110 }, 111 expander: { 112 display: true, 113 }, 114 }, 115 taskList: { 116 expander: { 117 straight: false, 118 }, 119 columns: [ 120 { 121 id: 1, 122 label: 'ID', 123 value: 'id', 124 width: 40, 125 }, 126 { 127 id: 2, 128 label: 'Description', 129 value: 'label', 130 width: 200, 131 expander: true, 132 html: true, 133 events: { 134 click({ data, column }) { 135 alert('description clicked!\n' + data.label); 136 }, 137 }, 138 }, 139 { 140 id: 3, 141 label: 'Assigned to', 142 value: 'user', 143 width: 130, 144 html: true, 145 }, 146 { 147 id: 3, 148 label: 'Start', 149 value: (task) => dayjs(task.start).format('YYYY-MM-DD'), 150 width: 78, 151 }, 152 { 153 id: 4, 154 label: 'Type', 155 value: 'type', 156 width: 68, 157 }, 158 { 159 id: 5, 160 label: '%', 161 value: 'progress', 162 width: 35, 163 style: { 164 'task-list-header-label': { 165 'text-align': 'center', 166 width: '100%', 167 }, 168 'task-list-item-value-container': { 169 'text-align': 'center', 170 width: '100%', 171 }, 172 }, 173 }, 174 ], 175 }, 176 /*locale:{ 177 name: 'pl', // name String 178 weekdays: 'Poniedziałek_Wtorek_Środa_Czwartek_Piątek_Sobota_Niedziela'.split('_'), // weekdays Array 179 weekdaysShort: 'Pon_Wto_Śro_Czw_Pią_Sob_Nie'.split('_'), // OPTIONAL, short weekdays Array, use first three letters if not provided 180 weekdaysMin: 'Pn_Wt_Śr_Cz_Pt_So_Ni'.split('_'), // OPTIONAL, min weekdays Array, use first two letters if not provided 181 months: 'Styczeń_Luty_Marzec_Kwiecień_Maj_Czerwiec_Lipiec_Sierpień_Wrzesień_Październik_Listopad_Grudzień'.split('_'), // months Array 182 monthsShort: 'Sty_Lut_Mar_Kwi_Maj_Cze_Lip_Sie_Wrz_Paź_Lis_Gru'.split('_'), // OPTIONAL, short months Array, use first three letters if not provided 183 ordinal: n => `${n}`, // ordinal Function (number) => return number + output 184 relativeTime: { // relative time format strings, keep %s %d as the same 185 future: 'za %s', // e.g. in 2 hours, %s been replaced with 2hours 186 past: '%s temu', 187 s: 'kilka sekund', 188 m: 'minutę', 189 mm: '%d minut', 190 h: 'godzinę', 191 hh: '%d godzin', // e.g. 2 hours, %d been replaced with 2 192 d: 'dzień', 193 dd: '%d dni', 194 M: 'miesiąc', 195 MM: '%d miesięcy', 196 y: 'rok', 197 yy: '%d lat' 198 } 199 }*/ 200 }; 201 202 // create instance 203 const app = new Vue({ 204 components: { 205 'gantt-header': Header, 206 'gantt-elastic': GanttElastic, 207 'gantt-footer': { 208 template: `<span>this is a footer</span>`, 209 }, 210 }, 211 data: { 212 tasks: tasks.map((task) => Object.assign({}, task)), 213 options, 214 dynamicStyle: { 215 'task-list-header-label': { 216 'font-weight': 'bold', 217 }, 218 }, 219 destroy: false, 220 }, 221 }); 222 223 // gantt state which will be updated in realtime 224 let ganttState, ganttInstance; 225 226 // listen to 'gantt-elastic.ready' or 'gantt-elastic.mounted' event 227 // to get the gantt state for real time modification 228 app.$on('gantt-elastic-ready', (ganttElasticInstance) => { 229 ganttInstance = ganttElasticInstance; 230 231 ganttInstance.$on('tasks-changed', (tasks) => { 232 app.tasks = tasks; 233 }); 234 ganttInstance.$on('options-changed', (options) => { 235 app.options = options; 236 }); 237 ganttInstance.$on('dynamic-style-changed', (style) => { 238 app.dynamicStyle = style; 239 }); 240 241 ganttInstance.$on('chart-task-mouseenter', ({ data, event }) => { 242 console.log('task mouse enter', { data, event }); 243 }); 244 ganttInstance.$on('updated', () => { 245 //console.log('gantt view was updated'); 246 }); 247 ganttInstance.$on('destroyed', () => { 248 //console.log('gantt was destroyed'); 249 }); 250 ganttInstance.$on('times-timeZoom-updated', () => { 251 console.log('time zoom changed'); 252 }); 253 ganttInstance.$on('taskList-task-click', ({ event, data, column }) => { 254 console.log('task list clicked! (task)', { data, column }); 255 }); 256 }); 257 258 // mount gantt to DOM 259 app.$mount('#app'); 260 </script> 261 </body> 262</html>
Take a look at the vue.html
inside examples folder file to see how you could add gantt-elastic inside <script>
tag along with the Vue framework
Demo project: https://github.com/neuronetio/vue-gantt-elastic
You can also import gantt-elastic as compiled js component in commonjs or umd format (examples folder) or just grab GanttElastic.vue from src directory and add to your existing vue project.
1import Vue from 'vue'; 2import GanttElastic from "gantt-elastic"; 3import Header from "gantt-elastic-header"; // if you want standard header (npm i -s gantt-elastic-header) 4new Vue({ 5 el:'#gantt', 6 template:`<gantt-elastic :tasks="tasks" :options="options"> 7 <gantt-elastic-header slot="header"></gantt-elastic-header> 8 <gantt-elastic-footer slot="footer"></gantt-elastic-footer> 9 </gantt-elastic>`, 10 components: { 11 ganttElasticHeader: {template:`<span>your header</span>`}, // or Header 12 ganttElastic: GanttElastic 13 ganttElasticFooter: {template:`<span>your footer</span>`}, 14 }, 15 data() { 16 return { 17 tasks: tasks, 18 options: options 19 }; 20 } 21});
or
1import Vue from 'vue'; 2import App from './App.vue'; // your app that uses gantt-elastic from 'gantt-elastic/src/GanttElastic.vue' 3 4new Vue({ 5 el: '#app', 6 render: (h) => h(App), 7});
Take a look at this demo project: https://github.com/neuronetio/gantt-elastic-webpack for other bundlers use umd or commonjs from dist folder.
1import GanttElastic from 'gantt-elastic/dist/GantElastic.umd.js'; 2import GanttElastic from 'gantt-elastic/dist/GantElastic.common.js'; // same as import GanttElastic from 'gantt-elastic'; 3import GanttElastic from 'gantt-elastic/src/GantElastic.vue'; // if you want vue component directly without compilation - look above 4// and the same with require 5const GanttElastic = require('gantt-elastic/dist/GantElastic.common.js');
If you are using uglifyjs in your project be sure to have es6 compatible version like uglify-es
MIT
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 2/26 approved changesets -- score normalized to 0
Reason
project is archived
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
project is not fuzzed
Details
Reason
118 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More