2
0
mirror of https://github.com/tenrok/vue-ganttastic.git synced 2026-06-23 15:30:33 +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:
Marko Zunic
2020-03-27 14:32:56 +01:00
parent de719040e9
commit 2a0fa28533
7 changed files with 254 additions and 8 deletions
+23
View File
@@ -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?
+12
View File
@@ -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/)
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
} }
} }
} }
+176
View File
@@ -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>