mirror of
https://github.com/tenrok/vue-ganttastic.git
synced 2026-06-23 16:50:34 +03:00
New prop for g-gantt-chart: snap-back-on-overlap
If true (and if push-on-overlap is false), if a bar ends up overlapping with another bar after a drag, the bar (or its whole bundle, if it belongs to one) snaps back to its original position Added .npmignore Bumped npm package version Updated README
This commit is contained in:
+23
@@ -0,0 +1,23 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
src/Playground.vue
|
||||||
|
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
@@ -96,6 +96,18 @@ export default {
|
|||||||
## Contributing
|
## Contributing
|
||||||
Pull requests are warmly welcomed, while every major change or proposal ought to be discussed in an issue first. As the project is still new, I will gladly accept suggestions, proposals, contributions etc.
|
Pull requests are warmly welcomed, while every major change or proposal ought to be discussed in an issue first. As the project is still new, I will gladly accept suggestions, proposals, contributions etc.
|
||||||
|
|
||||||
|
### Contributing - How to run the project
|
||||||
|
1. Clone the project
|
||||||
|
2. Install the Vue CLI service, if you don't already have it installed:
|
||||||
|
```
|
||||||
|
npm install -g @vue/cli
|
||||||
|
npm install -g @vue/cli-service-global
|
||||||
|
```
|
||||||
|
3. <code>Playground.vue</code> is a dedicated Vue SFC where all Vue-Ganttastic components can be
|
||||||
|
played around with and tested out. Get it running using:
|
||||||
|
```
|
||||||
|
vue serve src/Playground.vue
|
||||||
|
```
|
||||||
## Dependencies
|
## Dependencies
|
||||||
[Moment.js](https://momentjs.com/)
|
[Moment.js](https://momentjs.com/)
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-ganttastic-beta",
|
"name": "vue-ganttastic",
|
||||||
"version": "0.9.1",
|
"version": "0.9.4",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+5
-1
@@ -1,7 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-ganttastic",
|
"name": "vue-ganttastic",
|
||||||
"version": "0.9.4",
|
"version": "0.9.5",
|
||||||
"description": "A simple and customizable Gantt chart component for Vue.js",
|
"description": "A simple and customizable Gantt chart component for Vue.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/InfectoOne/vue-ganttastic"
|
||||||
|
},
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
|||||||
+10
-1
@@ -78,7 +78,9 @@ export default {
|
|||||||
// or is it dragged along some other bar from the same bundle
|
// or is it dragged along some other bar from the same bundle
|
||||||
cursorOffsetX: 0,
|
cursorOffsetX: 0,
|
||||||
mousemoveCallback: null, // gets initialized when starting to drag
|
mousemoveCallback: null, // gets initialized when starting to drag
|
||||||
// possible values: drag, dragByHandleLeft, dragByHandleRight
|
// possible values: drag, dragByHandleLeft, dragByHandleRight,
|
||||||
|
barStartBeforeDrag: null,
|
||||||
|
barEndBeforeDrag: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -178,6 +180,8 @@ export default {
|
|||||||
/* --------------------------------------------------------- */
|
/* --------------------------------------------------------- */
|
||||||
initDrag(e){ // "e" must be the mousedown event
|
initDrag(e){ // "e" must be the mousedown event
|
||||||
this.isDragging = true
|
this.isDragging = true
|
||||||
|
this.barStartBeforeDrag = this.bar[this.barStart]
|
||||||
|
this.barEndBeforeDrag = this.bar[this.barEnd]
|
||||||
let barX = this.$refs["g-gantt-bar"].getBoundingClientRect().left
|
let barX = this.$refs["g-gantt-bar"].getBoundingClientRect().left
|
||||||
this.cursorOffsetX = e.clientX - barX
|
this.cursorOffsetX = e.clientX - barX
|
||||||
let mousedownType = e.target.className
|
let mousedownType = e.target.className
|
||||||
@@ -252,6 +256,11 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
snapBack(){
|
||||||
|
this.barStartMoment = this.barStartBeforeDrag
|
||||||
|
this.barEndMoment = this.barEndBeforeDrag
|
||||||
|
},
|
||||||
|
|
||||||
manageOverlapping(){
|
manageOverlapping(){
|
||||||
if(!this.ganttChartProps.pushOnOverlap){
|
if(!this.ganttChartProps.pushOnOverlap){
|
||||||
return
|
return
|
||||||
|
|||||||
+26
-4
@@ -56,7 +56,8 @@ export default {
|
|||||||
grid: Boolean,
|
grid: Boolean,
|
||||||
highlightedHours: {type: Array, default: () => []},
|
highlightedHours: {type: Array, default: () => []},
|
||||||
width: {type: String, default: "100%"}, // the total width of the entire ganttastic component in %
|
width: {type: String, default: "100%"}, // the total width of the entire ganttastic component in %
|
||||||
pushOnOverlap: {type: Boolean}
|
pushOnOverlap: {type: Boolean},
|
||||||
|
snapBackOnOverlap: {type: Boolean},
|
||||||
},
|
},
|
||||||
|
|
||||||
data(){
|
data(){
|
||||||
@@ -126,14 +127,33 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
shouldSnapBackBar(ganttBar){
|
||||||
|
if(this.snapBackOnOverlap){
|
||||||
|
let {overlapBar} = ganttBar.getOverlapBarAndType(ganttBar.bar)
|
||||||
|
return !!overlapBar
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
|
snapBackBundleIfNeeded(ganttBar){
|
||||||
|
let barsFromBundle = this.getBarsFromBundle(ganttBar.barConfig.bundle)
|
||||||
|
if(this.shouldSnapBackBar(ganttBar) || barsFromBundle.some(gBar => this.shouldSnapBackBar(gBar))){
|
||||||
|
ganttBar.snapBack()
|
||||||
|
barsFromBundle.forEach(gBar => gBar.snapBack())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
onBarEvent(e, ganttBar){
|
onBarEvent(e, ganttBar){
|
||||||
this.$emit(`${e.type}-bar`, {event: e, bar: ganttBar.bar})
|
this.$emit(`${e.type}-bar`, {event: e, bar: ganttBar.bar})
|
||||||
},
|
},
|
||||||
|
|
||||||
onDragendBar(e, ganttBar){
|
onDragendBar(e, ganttBar){
|
||||||
let movedBarsInDrag = this.movedBarsInDrag
|
let didSnapBack = this.snapBackBundleIfNeeded(ganttBar)
|
||||||
|
let movedBars = didSnapBack ? new Set() : this.movedBarsInDrag
|
||||||
this.movedBarsInDrag = new Set()
|
this.movedBarsInDrag = new Set()
|
||||||
this.$emit("dragend-bar", {event: e, bar: ganttBar.bar, movedBars: movedBarsInDrag})
|
this.$emit("dragend-bar", {event: e, bar: ganttBar.bar, movedBars})
|
||||||
},
|
},
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@@ -260,7 +280,9 @@ export default {
|
|||||||
moveBarsFromBundleOfPushedBar: (bar, minuteDiff, overlapType) => this.moveBarsFromBundleOfPushedBar(bar, minuteDiff, overlapType),
|
moveBarsFromBundleOfPushedBar: (bar, minuteDiff, overlapType) => this.moveBarsFromBundleOfPushedBar(bar, minuteDiff, overlapType),
|
||||||
setDragLimitsOfGanttBar : (ganttBar) => this.setDragLimitsOfGanttBar(ganttBar),
|
setDragLimitsOfGanttBar : (ganttBar) => this.setDragLimitsOfGanttBar(ganttBar),
|
||||||
onBarEvent: (e, ganttBar) => this.onBarEvent(e, ganttBar),
|
onBarEvent: (e, ganttBar) => this.onBarEvent(e, ganttBar),
|
||||||
onDragendBar: (e, ganttBar) => this.onDragendBar(e, ganttBar)
|
onDragendBar: (e, ganttBar) => this.onDragendBar(e, ganttBar),
|
||||||
|
shouldSnapBackOnOverlap: () => this.snapBackOnOverlap,
|
||||||
|
snapBackBundle: (ganttBar) => this.snapBackBundle(ganttBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
<!-- use Playground.vue to play around with the gantt chart components and test out new features -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<g-gantt-chart
|
||||||
|
:chart-start="chartStart"
|
||||||
|
:chart-end="chartEnd"
|
||||||
|
:grid="grid"
|
||||||
|
:hide-timeaxis="hideTimeaxis"
|
||||||
|
:push-on-overlap="false"
|
||||||
|
snap-back-on-overlap
|
||||||
|
:highlighted-hours="highlightedHours"
|
||||||
|
:row-label-width="`${rowLabelWidth}%`"
|
||||||
|
:row-height="rowHeight"
|
||||||
|
:theme="selectedTheme"
|
||||||
|
>
|
||||||
|
<template v-for="row in rowList">
|
||||||
|
<div style="width: 100%; padding: 5px; background: white;" :key="`div${row.label}`">
|
||||||
|
test
|
||||||
|
</div>
|
||||||
|
<g-gantt-row
|
||||||
|
:key="row.label"
|
||||||
|
:label="row.label"
|
||||||
|
:bars="row.barList"
|
||||||
|
:highlight-on-hover="highlightOnHover"
|
||||||
|
bar-start="myStart"
|
||||||
|
bar-end="myEnd"
|
||||||
|
>
|
||||||
|
<template #bar-label="{bar}">
|
||||||
|
<span>{{bar.label}}</span>
|
||||||
|
</template>
|
||||||
|
</g-gantt-row>
|
||||||
|
</template>
|
||||||
|
</g-gantt-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import GGanttChart from './GGanttChart.vue'
|
||||||
|
import GGanttRow from './GGanttRow.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components:{
|
||||||
|
GGanttChart,
|
||||||
|
GGanttRow
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
chartStart: "2020-03-02 00:00",
|
||||||
|
chartEnd: "2020-03-04 00:00",
|
||||||
|
pushOnOverlap: true,
|
||||||
|
grid: true,
|
||||||
|
rowHeight: 40,
|
||||||
|
rowLabelWidth: 15,
|
||||||
|
hideTimeaxis: false,
|
||||||
|
highlightOnHover: false,
|
||||||
|
hours: [...Array(24).keys()],
|
||||||
|
highlightedHours: [10,12],
|
||||||
|
showContextmenu: false,
|
||||||
|
contextmenuTimeout: null,
|
||||||
|
contextmenuX: 0,
|
||||||
|
contextmenuY: 0,
|
||||||
|
selectedTheme: "default",
|
||||||
|
themes: [
|
||||||
|
"default",
|
||||||
|
"vue",
|
||||||
|
"dark",
|
||||||
|
"material-blue",
|
||||||
|
"creamy",
|
||||||
|
"slumber",
|
||||||
|
"sky",
|
||||||
|
"crimson",
|
||||||
|
"grove",
|
||||||
|
"fuchsia",
|
||||||
|
"flare"
|
||||||
|
],
|
||||||
|
rowList: [
|
||||||
|
{
|
||||||
|
label: "Row #1",
|
||||||
|
barList: [
|
||||||
|
{
|
||||||
|
myStart: "2020-03-03 18:00",
|
||||||
|
myEnd: "2020-03-03 23:00",
|
||||||
|
label: "Immobile",
|
||||||
|
ganttBarConfig: {color:"white", backgroundColor: "#404040", opacity: 0.5, immobile: true}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
myStart: "2020-03-03 04:00",
|
||||||
|
myEnd: "2020-03-03 15:00",
|
||||||
|
label: "Bar",
|
||||||
|
ganttBarConfig: {color:"white", backgroundColor: "#2e74a3", bundle: "blueBundle"}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: "Row #2",
|
||||||
|
barList: [
|
||||||
|
{
|
||||||
|
myStart: "2020-03-02 09:00",
|
||||||
|
myEnd: "2020-03-02 18:00",
|
||||||
|
image: "vue_ganttastic_logo_no_text.png",
|
||||||
|
label: "I have an image",
|
||||||
|
ganttBarConfig: {color:"white", backgroundColor: "#de3b26", bundle:"redBundle"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
myStart: "2020-03-03 04:00",
|
||||||
|
myEnd: "2020-03-03 15:00",
|
||||||
|
label: "We belong together ^",
|
||||||
|
ganttBarConfig: {color:"white", backgroundColor: "#2e74a3", bundle:"blueBundle"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
myStart: "2020-03-03 18:00",
|
||||||
|
myEnd: "2020-03-03 22:00",
|
||||||
|
label: "Bar",
|
||||||
|
ganttBarConfig: {color:"white", backgroundColor: "#aa34a3"}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: "Row #3",
|
||||||
|
barList: [
|
||||||
|
{
|
||||||
|
myStart: "2020-03-02 09:00",
|
||||||
|
myEnd: "2020-03-02 18:00",
|
||||||
|
label: "I am with stupid ^",
|
||||||
|
ganttBarConfig: {color:"white", backgroundColor: "#de3b26", bundle: "redBundle"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
myStart: "2020-03-02 22:30",
|
||||||
|
myEnd: "2020-03-03 05:00",
|
||||||
|
label: "With handles!",
|
||||||
|
ganttBarConfig: {color:"white", backgroundColor: "#a23def", handles: true}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
myStart: "2020-03-02 01:00",
|
||||||
|
myEnd: "2020-03-02 07:00",
|
||||||
|
label: "Bar",
|
||||||
|
ganttBarConfig: {color:"white", backgroundColor: "#5effad"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
myStart: "2020-03-03 14:00",
|
||||||
|
myEnd: "2020-03-03 20:00",
|
||||||
|
label: "Woooow!",
|
||||||
|
ganttBarConfig: {color:"white", background: "repeating-linear-gradient(45deg,#de7359,#de7359 10px,#ffc803 10px,#ffc803 20px)"}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: "Row #4",
|
||||||
|
barList: [
|
||||||
|
{
|
||||||
|
myStart: "2020-03-03 06:30",
|
||||||
|
myEnd: "2020-03-03 20:00",
|
||||||
|
label: "Bar",
|
||||||
|
ganttBarConfig:{color:"white", backgroundColor: "#d18aaf", handles: true}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
myStart: "2020-03-02 00:30",
|
||||||
|
myEnd: "2020-03-03 01:00",
|
||||||
|
label: "Rectangular",
|
||||||
|
ganttBarConfig: {color:"white", backgroundColor: "#f2840f", borderRadius: 0}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user