mirror of
https://github.com/tenrok/vue-ganttastic.git
synced 2026-06-20 07:50:33 +03:00
refactor: remove hardcode format and unit of time
This commit is contained in:
+334
-250
@@ -1,46 +1,45 @@
|
||||
<template>
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
class="g-gantt-bar"
|
||||
<div
|
||||
class="g-gantt-bar"
|
||||
ref="g-gantt-bar"
|
||||
:style="barStyle"
|
||||
@mouseenter.stop="onMouseenter($event)"
|
||||
@mouseleave.stop ="onMouseleave($event)"
|
||||
@mouseleave.stop="onMouseleave($event)"
|
||||
@mousedown.stop="onMousedown($event)"
|
||||
@click.stop="onClick($event)"
|
||||
@dblclick="onDblclick($event)"
|
||||
@contextmenu="onContextmenu($event)"
|
||||
>
|
||||
<div class="g-gantt-bar-label">
|
||||
<slot
|
||||
name="bar-label"
|
||||
:bar="bar"
|
||||
>
|
||||
{{barConfig.label || ""}}
|
||||
<slot name="bar-label" :bar="bar">
|
||||
{{ barConfig.label || '' }}
|
||||
</slot>
|
||||
</div>
|
||||
<template v-if="barConfig.handles">
|
||||
<div class="g-gantt-bar-handle-left"/>
|
||||
<div class="g-gantt-bar-handle-right"/>
|
||||
<div class="g-gantt-bar-handle-left" />
|
||||
<div class="g-gantt-bar-handle-right" />
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<transition name="fade" mode="out-in">
|
||||
<div
|
||||
<div
|
||||
v-if="!barConfig.noTooltip && (showTooltip || isDragging)"
|
||||
class="g-gantt-tooltip"
|
||||
:style="tooltipStyle"
|
||||
>
|
||||
<div
|
||||
<div
|
||||
class="color-indicator"
|
||||
:style="{background: this.barStyle.background || this.barStyle.backgroundColor}"
|
||||
:style="{
|
||||
background:
|
||||
this.barStyle.background || this.barStyle.backgroundColor,
|
||||
}"
|
||||
/>
|
||||
{{bar[barStart] | TimeFilter}}
|
||||
-
|
||||
{{bar[barEnd] | TimeFilter}}
|
||||
{{ bar[barStart] }}
|
||||
-
|
||||
{{ bar[barEnd] }}
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -48,28 +47,30 @@
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
name: "GGanttBar",
|
||||
name: 'GGanttBar',
|
||||
|
||||
props:{
|
||||
bar: {type: Object},
|
||||
barStart: {type: String}, // property name of the bar objects that represents the start datetime
|
||||
barEnd: {type: String}, // property name of the bar objects that represents the end datetime,
|
||||
props: {
|
||||
bar: { type: Object },
|
||||
barStart: { type: String }, // property name of the bar objects that represents the start datetime
|
||||
barEnd: { type: String }, // property name of the bar objects that represents the end datetime,
|
||||
barContainer: [Object, DOMRect],
|
||||
allBarsInRow: {type: Array}
|
||||
allBarsInRow: { type: Array },
|
||||
},
|
||||
|
||||
inject: [
|
||||
"getHourCount",
|
||||
"ganttChartProps",
|
||||
"initDragOfBarsFromBundle",
|
||||
"moveBarsFromBundleOfPushedBar",
|
||||
"setDragLimitsOfGanttBar",
|
||||
"onBarEvent",
|
||||
"onDragendBar",
|
||||
"getMinGapBetweenBars",
|
||||
'getTimeCount',
|
||||
'ganttChartProps',
|
||||
'initDragOfBarsFromBundle',
|
||||
'moveBarsFromBundleOfPushedBar',
|
||||
'setDragLimitsOfGanttBar',
|
||||
'onBarEvent',
|
||||
'onDragendBar',
|
||||
'getMinGapBetweenBars',
|
||||
'getTimeUnit',
|
||||
'getTimeFormat',
|
||||
],
|
||||
|
||||
data(){
|
||||
data() {
|
||||
return {
|
||||
showTooltip: false,
|
||||
tooltipTimeout: null,
|
||||
@@ -77,48 +78,56 @@ export default {
|
||||
dragLimitRight: null,
|
||||
isDragging: false,
|
||||
isMainBarOfDrag: false, // is this the bar that was clicked on when starting to drag
|
||||
// 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,
|
||||
mousemoveCallback: null, // gets initialized when starting to drag
|
||||
// possible values: drag, dragByHandleLeft, dragByHandleRight,
|
||||
mousemoveCallback: null, // gets initialized when starting to drag
|
||||
// possible values: drag, dragByHandleLeft, dragByHandleRight,
|
||||
barStartBeforeDrag: null,
|
||||
barEndBeforeDrag: null,
|
||||
timeUnit: this.getTimeUnit(),
|
||||
timeChildKey: this.getTimeUnit() === 'days' ? 'hours' : 'minutes',
|
||||
timeFormat: this.getTimeFormat(),
|
||||
}
|
||||
},
|
||||
|
||||
computed:{
|
||||
computed: {
|
||||
// use these computed moment objects to work with the bar's start/end dates:
|
||||
// instead of directly mutating them:
|
||||
barStartMoment:{
|
||||
get(){
|
||||
barStartMoment: {
|
||||
get() {
|
||||
return moment(this.bar[this.barStart])
|
||||
},
|
||||
set(value){
|
||||
this.bar[this.barStart] = moment(value).format("YYYY-MM-DD HH:mm:ss")
|
||||
}
|
||||
set(value) {
|
||||
this.bar[this.barStart] = moment(value).format(this.timeFormat)
|
||||
},
|
||||
},
|
||||
|
||||
barEndMoment: {
|
||||
get(){
|
||||
get() {
|
||||
return moment(this.bar[this.barEnd])
|
||||
},
|
||||
set(value){
|
||||
this.bar[this.barEnd] = moment(value).format("YYYY-MM-DD HH:mm:ss")
|
||||
}
|
||||
set(value) {
|
||||
this.bar[this.barEnd] = moment(value).format(this.timeFormat)
|
||||
},
|
||||
},
|
||||
|
||||
barConfig(){
|
||||
if(this.bar.ganttBarConfig) {
|
||||
barConfig() {
|
||||
if (this.bar.ganttBarConfig) {
|
||||
return {
|
||||
...this.bar.ganttBarConfig,
|
||||
background: this.bar.ganttBarConfig.isShadow ? "grey" : this.bar.ganttBarConfig.background || this.bar.ganttBarConfig.backgroundColor,
|
||||
opacity: this.bar.ganttBarConfig.isShadow ? "0.3" : this.bar.ganttBarConfig.opacity
|
||||
background: this.bar.ganttBarConfig.isShadow
|
||||
? 'grey'
|
||||
: this.bar.ganttBarConfig.background ||
|
||||
this.bar.ganttBarConfig.backgroundColor,
|
||||
opacity: this.bar.ganttBarConfig.isShadow
|
||||
? '0.3'
|
||||
: this.bar.ganttBarConfig.opacity,
|
||||
}
|
||||
}
|
||||
return {}
|
||||
},
|
||||
|
||||
barStyle(){
|
||||
barStyle() {
|
||||
let xStart = this.mapTimeToPosition(this.barStartMoment)
|
||||
let xEnd = this.mapTimeToPosition(this.barEndMoment)
|
||||
return {
|
||||
@@ -126,77 +135,87 @@ export default {
|
||||
left: `${xStart}px`,
|
||||
width: `${xEnd - xStart}px`,
|
||||
height: `${this.ganttChartProps.rowHeight - 6}px`,
|
||||
zIndex: this.barConfig.zIndex || (this.isDragging ? 2 : 1)
|
||||
zIndex: this.barConfig.zIndex || (this.isDragging ? 2 : 1),
|
||||
}
|
||||
},
|
||||
|
||||
tooltipStyle(){
|
||||
return{
|
||||
tooltipStyle() {
|
||||
return {
|
||||
left: this.barStyle.left,
|
||||
top:`${this.ganttChartProps.rowHeight}px`,
|
||||
top: `${this.ganttChartProps.rowHeight}px`,
|
||||
}
|
||||
},
|
||||
|
||||
chartStartMoment(){
|
||||
chartStartMoment() {
|
||||
return moment(this.ganttChartProps.chartStart)
|
||||
},
|
||||
|
||||
chartEndMoment(){
|
||||
chartEndMoment() {
|
||||
return moment(this.ganttChartProps.chartEnd)
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods:{
|
||||
|
||||
onMouseenter(e){
|
||||
if(this.tooltipTimeout){
|
||||
methods: {
|
||||
onMouseenter(e) {
|
||||
if (this.tooltipTimeout) {
|
||||
clearTimeout(this.tooltipTimeout)
|
||||
}
|
||||
this.tooltipTimeout = setTimeout(() => this.showTooltip = true, 800)
|
||||
this.onBarEvent({event: e, type: e.type}, this)
|
||||
this.tooltipTimeout = setTimeout(() => (this.showTooltip = true), 800)
|
||||
this.onBarEvent({ event: e, type: e.type }, this)
|
||||
},
|
||||
|
||||
onMouseleave(e){
|
||||
onMouseleave(e) {
|
||||
clearTimeout(this.tooltipTimeout)
|
||||
this.showTooltip = false
|
||||
this.onBarEvent({event: e, type: e.type}, this)
|
||||
this.onBarEvent({ event: e, type: e.type }, this)
|
||||
},
|
||||
|
||||
onContextmenu(e){
|
||||
const time = this.mapPositionToTime(e.clientX - this.barContainer.left).format("YYYY-MM-DD HH:mm:ss")
|
||||
this.onBarEvent({event: e, type: e.type, time}, this)
|
||||
onContextmenu(e) {
|
||||
const time = this.mapPositionToTime(
|
||||
e.clientX - this.barContainer.left
|
||||
).format(this.timeFormat)
|
||||
this.onBarEvent({ event: e, type: e.type, time }, this)
|
||||
},
|
||||
|
||||
onClick(e){
|
||||
const time = this.mapPositionToTime(e.clientX - this.barContainer.left).format("YYYY-MM-DD HH:mm:ss")
|
||||
this.onBarEvent({event: e, type: e.type, time}, this)
|
||||
onClick(e) {
|
||||
const time = this.mapPositionToTime(
|
||||
e.clientX - this.barContainer.left
|
||||
).format(this.timeFormat)
|
||||
this.onBarEvent({ event: e, type: e.type, time }, this)
|
||||
},
|
||||
|
||||
onDblclick(e) {
|
||||
const time = this.mapPositionToTime(e.clientX - this.barContainer.left).format("YYYY-MM-DD HH:mm:ss")
|
||||
this.onBarEvent({event: e, type: e.type, time}, this)
|
||||
const time = this.mapPositionToTime(
|
||||
e.clientX - this.barContainer.left
|
||||
).format(this.timeFormat)
|
||||
this.onBarEvent({ event: e, type: e.type, time }, this)
|
||||
},
|
||||
|
||||
onMousedown(e){
|
||||
onMousedown(e) {
|
||||
e.preventDefault()
|
||||
if(e.button === 2){
|
||||
if (e.button === 2) {
|
||||
return
|
||||
}
|
||||
if(!this.barConfig.immobile && !this.barConfig.isShadow) {
|
||||
if (!this.barConfig.immobile && !this.barConfig.isShadow) {
|
||||
this.setDragLimitsOfGanttBar(this)
|
||||
// initialize the dragging on next mousemove event:
|
||||
window.addEventListener("mousemove", this.onFirstMousemove, {once: true})
|
||||
window.addEventListener('mousemove', this.onFirstMousemove, {
|
||||
once: true,
|
||||
})
|
||||
// if next mousemove happens after mouse up (if user just presses mouse button down, then up, without moving):
|
||||
window.addEventListener("mouseup",
|
||||
() => window.removeEventListener("mousemove", this.onFirstMousemove),
|
||||
{once: true}
|
||||
window.addEventListener(
|
||||
'mouseup',
|
||||
() => window.removeEventListener('mousemove', this.onFirstMousemove),
|
||||
{ once: true }
|
||||
)
|
||||
}
|
||||
const time = this.mapPositionToTime(e.clientX - this.barContainer.left).format("YYYY-MM-DD HH:mm:ss")
|
||||
this.onBarEvent({event: e, type: e.type, time}, this)
|
||||
const time = this.mapPositionToTime(
|
||||
e.clientX - this.barContainer.left
|
||||
).format(this.timeFormat)
|
||||
this.onBarEvent({ event: e, type: e.type, time }, this)
|
||||
},
|
||||
|
||||
onFirstMousemove(e){
|
||||
onFirstMousemove(e) {
|
||||
this.isMainBarOfDrag = true
|
||||
// this method is injected here by GGanttChart.vue, and calls initDrag()
|
||||
// for all GGanttBars that belong to the same bundle as this bar:
|
||||
@@ -206,165 +225,230 @@ export default {
|
||||
/* --------------------------------------------------------- */
|
||||
/* ------------- METHODS FOR DRAGGING THE BAR -------------- */
|
||||
/* --------------------------------------------------------- */
|
||||
initDrag(e){ // "e" must be the mousedown event
|
||||
initDrag(e) {
|
||||
// "e" must be the mousedown event
|
||||
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
|
||||
let mousedownType = e.target.className
|
||||
switch(mousedownType){
|
||||
case "g-gantt-bar-handle-left":
|
||||
document.body.style.cursor = "w-resize"
|
||||
switch (mousedownType) {
|
||||
case 'g-gantt-bar-handle-left':
|
||||
document.body.style.cursor = 'w-resize'
|
||||
this.mousemoveCallback = this.dragByHandleLeft
|
||||
break
|
||||
case "g-gantt-bar-handle-right":
|
||||
document.body.style.cursor = "w-resize"
|
||||
case 'g-gantt-bar-handle-right':
|
||||
document.body.style.cursor = 'w-resize'
|
||||
this.mousemoveCallback = this.dragByHandleRight
|
||||
break
|
||||
default: this.mousemoveCallback = this.drag
|
||||
default:
|
||||
this.mousemoveCallback = this.drag
|
||||
}
|
||||
window.addEventListener("mousemove", this.mousemoveCallback)
|
||||
window.addEventListener("mouseup", this.endDrag)
|
||||
window.addEventListener('mousemove', this.mousemoveCallback)
|
||||
window.addEventListener('mouseup', this.endDrag)
|
||||
},
|
||||
|
||||
drag(e){
|
||||
let barWidth = this.$refs["g-gantt-bar"].getBoundingClientRect().width
|
||||
let newXStart = (e.clientX-this.barContainer.left) - this.cursorOffsetX
|
||||
drag(e) {
|
||||
let barWidth = this.$refs['g-gantt-bar'].getBoundingClientRect().width
|
||||
let newXStart = e.clientX - this.barContainer.left - this.cursorOffsetX
|
||||
let newXEnd = newXStart + barWidth
|
||||
if(this.isPosOutOfDragRange(newXStart, newXEnd)){
|
||||
if (this.isPosOutOfDragRange(newXStart, newXEnd)) {
|
||||
return
|
||||
}
|
||||
this.barStartMoment = this.mapPositionToTime(newXStart)
|
||||
this.barEndMoment = this.mapPositionToTime(newXEnd)
|
||||
this.manageOverlapping()
|
||||
this.onBarEvent({event: e, type: "drag"}, this)
|
||||
this.onBarEvent({ event: e, type: 'drag' }, this)
|
||||
},
|
||||
|
||||
dragByHandleLeft(e){
|
||||
dragByHandleLeft(e) {
|
||||
let newXStart = e.clientX - this.barContainer.left
|
||||
let newStartMoment = this.mapPositionToTime(newXStart)
|
||||
if(newStartMoment.isSameOrAfter(this.barEndMoment) || this.isPosOutOfDragRange(newXStart, null)){
|
||||
if (
|
||||
newStartMoment.isSameOrAfter(this.barEndMoment) ||
|
||||
this.isPosOutOfDragRange(newXStart, null)
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.barStartMoment = newStartMoment
|
||||
this.manageOverlapping()
|
||||
},
|
||||
|
||||
dragByHandleRight(e){
|
||||
dragByHandleRight(e) {
|
||||
let newXEnd = e.clientX - this.barContainer.left
|
||||
let newEndMoment = this.mapPositionToTime(newXEnd)
|
||||
if(newEndMoment.isSameOrBefore(this.barStartMoment) || this.isPosOutOfDragRange(null, newXEnd)){
|
||||
if (
|
||||
newEndMoment.isSameOrBefore(this.barStartMoment) ||
|
||||
this.isPosOutOfDragRange(null, newXEnd)
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.barEndMoment = newEndMoment
|
||||
this.manageOverlapping()
|
||||
},
|
||||
|
||||
isPosOutOfDragRange(xStart, xEnd){
|
||||
isPosOutOfDragRange(xStart, xEnd) {
|
||||
// 不能推动旁边的bar时,拖拽就不停止
|
||||
if(!this.ganttChartProps.pushOnOverlap) {
|
||||
if (!this.ganttChartProps.pushOnOverlap) {
|
||||
return false
|
||||
}
|
||||
if(xStart && xStart < 0) {
|
||||
if (xStart && xStart < 0) {
|
||||
return true
|
||||
}
|
||||
if(xStart && this.dragLimitLeft !== null && xStart < this.dragLimitLeft + this.getMinGapBetweenBars()){
|
||||
if (
|
||||
xStart &&
|
||||
this.dragLimitLeft !== null &&
|
||||
xStart < this.dragLimitLeft + this.getMinGapBetweenBars()
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if(xEnd && this.dragLimitRight !== null && xEnd > this.dragLimitRight - this.getMinGapBetweenBars()){
|
||||
if (
|
||||
xEnd &&
|
||||
this.dragLimitRight !== null &&
|
||||
xEnd > this.dragLimitRight - this.getMinGapBetweenBars()
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
endDrag(e){
|
||||
endDrag(e) {
|
||||
this.isDragging = false
|
||||
this.dragLimitLeft = null
|
||||
this.dragLimitRight = null
|
||||
document.body.style.cursor = "auto"
|
||||
window.removeEventListener("mousemove", this.mousemoveCallback)
|
||||
window.removeEventListener("mouseup", this.endDrag)
|
||||
if(this.isMainBarOfDrag){
|
||||
document.body.style.cursor = 'auto'
|
||||
window.removeEventListener('mousemove', this.mousemoveCallback)
|
||||
window.removeEventListener('mouseup', this.endDrag)
|
||||
if (this.isMainBarOfDrag) {
|
||||
this.onDragendBar(e, this)
|
||||
this.isMainBarOfDrag = false
|
||||
}
|
||||
},
|
||||
|
||||
snapBack(){
|
||||
snapBack() {
|
||||
this.barStartMoment = this.barStartBeforeDrag
|
||||
this.barEndMoment = this.barEndBeforeDrag
|
||||
},
|
||||
|
||||
manageOverlapping(){
|
||||
if(!this.ganttChartProps.pushOnOverlap || this.barConfig.pushOnOverlap === false){
|
||||
manageOverlapping() {
|
||||
if (
|
||||
!this.ganttChartProps.pushOnOverlap ||
|
||||
this.barConfig.pushOnOverlap === false
|
||||
) {
|
||||
return
|
||||
}
|
||||
let currentBar = this.bar
|
||||
let {overlapBar, overlapType} = this.getOverlapBarAndType(currentBar)
|
||||
while(overlapBar){
|
||||
let { overlapBar, overlapType } = this.getOverlapBarAndType(currentBar)
|
||||
while (overlapBar) {
|
||||
let minuteDiff
|
||||
let currentStartMoment = moment(currentBar[this.barStart])
|
||||
let currentEndMoment = moment(currentBar[this.barEnd])
|
||||
let overlapStartMoment = moment(overlapBar[this.barStart])
|
||||
let overlapEndMoment = moment(overlapBar[this.barEnd])
|
||||
switch(overlapType){
|
||||
case "left":
|
||||
minuteDiff = overlapEndMoment.diff(currentStartMoment, "minutes", true) + this.getMinGapBetweenBars()
|
||||
overlapBar[this.barEnd] = currentStartMoment.subtract(this.getMinGapBetweenBars(), "minutes", true).format("YYYY-MM-DD HH:mm:ss")
|
||||
overlapBar[this.barStart] = overlapStartMoment.subtract(minuteDiff, "minutes", true).format("YYYY-MM-DD HH:mm:ss")
|
||||
let overlapEndMoment = moment(overlapBar[this.barEnd])
|
||||
switch (overlapType) {
|
||||
case 'left':
|
||||
minuteDiff =
|
||||
overlapEndMoment.diff(
|
||||
currentStartMoment,
|
||||
this.timeChildKey,
|
||||
true
|
||||
) + this.getMinGapBetweenBars()
|
||||
overlapBar[this.barEnd] = currentStartMoment
|
||||
.subtract(this.getMinGapBetweenBars(), this.timeChildKey, true)
|
||||
.format(this.timeFormat)
|
||||
overlapBar[this.barStart] = overlapStartMoment
|
||||
.subtract(minuteDiff, this.timeChildKey, true)
|
||||
.format(this.timeFormat)
|
||||
break
|
||||
case "right":
|
||||
minuteDiff = currentEndMoment.diff(overlapStartMoment, "minutes", true) + this.getMinGapBetweenBars()
|
||||
overlapBar[this.barStart] = currentEndMoment.add(this.getMinGapBetweenBars(), "minutes", true).format("YYYY-MM-DD HH:mm:ss")
|
||||
overlapBar[this.barEnd] = overlapEndMoment.add(minuteDiff, "minutes", true).format("YYYY-MM-DD HH:mm:ss")
|
||||
case 'right':
|
||||
minuteDiff =
|
||||
currentEndMoment.diff(
|
||||
overlapStartMoment,
|
||||
this.timeChildKey,
|
||||
true
|
||||
) + this.getMinGapBetweenBars()
|
||||
overlapBar[this.barStart] = currentEndMoment
|
||||
.add(this.getMinGapBetweenBars(), this.timeChildKey, true)
|
||||
.format(this.timeFormat)
|
||||
overlapBar[this.barEnd] = overlapEndMoment
|
||||
.add(minuteDiff, this.timeChildKey, true)
|
||||
.format(this.timeFormat)
|
||||
break
|
||||
default:
|
||||
// eslint-disable-next-line
|
||||
console.warn("One bar is inside of the other one! This should never occur while push-on-overlap is active!")
|
||||
console.warn(
|
||||
'One bar is inside of the other one! This should never occur while push-on-overlap is active!'
|
||||
)
|
||||
return
|
||||
}
|
||||
this.moveBarsFromBundleOfPushedBar(overlapBar, minuteDiff, overlapType)
|
||||
currentBar = overlapBar;
|
||||
({overlapBar, overlapType} = this.getOverlapBarAndType(overlapBar))
|
||||
currentBar = overlapBar
|
||||
;({ overlapBar, overlapType } = this.getOverlapBarAndType(overlapBar))
|
||||
}
|
||||
},
|
||||
|
||||
getOverlapBarAndType(bar){
|
||||
getOverlapBarAndType(bar) {
|
||||
let barStartMoment = moment(bar[this.barStart])
|
||||
let barEndMoment = moment(bar[this.barEnd])
|
||||
let overlapLeft, overlapRight, overlapInBetween
|
||||
let overlapBar = this.allBarsInRow.find(otherBar => {
|
||||
if(otherBar === bar || otherBar.ganttBarConfig.pushOnOverlap === false){
|
||||
let overlapBar = this.allBarsInRow.find((otherBar) => {
|
||||
if (
|
||||
otherBar === bar ||
|
||||
otherBar.ganttBarConfig.pushOnOverlap === false
|
||||
) {
|
||||
return false
|
||||
}
|
||||
let otherBarStart = moment(otherBar[this.barStart])
|
||||
let otherBarEnd = moment(otherBar[this.barEnd])
|
||||
overlapLeft = barStartMoment.isBetween(otherBarStart, otherBarEnd)
|
||||
overlapLeft = barStartMoment.isBetween(otherBarStart, otherBarEnd)
|
||||
overlapRight = barEndMoment.isBetween(otherBarStart, otherBarEnd)
|
||||
overlapInBetween = otherBarStart.isBetween(barStartMoment, barEndMoment)
|
||||
|| otherBarEnd.isBetween(barStartMoment, barEndMoment)
|
||||
overlapInBetween =
|
||||
otherBarStart.isBetween(barStartMoment, barEndMoment) ||
|
||||
otherBarEnd.isBetween(barStartMoment, barEndMoment)
|
||||
return overlapLeft || overlapRight || overlapInBetween
|
||||
})
|
||||
let overlapType = overlapLeft ? "left" : (overlapRight ? "right" : (overlapInBetween ? "between" : null))
|
||||
return {overlapBar, overlapType}
|
||||
let overlapType = overlapLeft
|
||||
? 'left'
|
||||
: overlapRight
|
||||
? 'right'
|
||||
: overlapInBetween
|
||||
? 'between'
|
||||
: null
|
||||
return { overlapBar, overlapType }
|
||||
},
|
||||
|
||||
// this is used in GGanttChart, when a bar from a bundle is pushed
|
||||
// so that bars from its bundle also get pushed
|
||||
moveBarByMinutesAndPush(minuteCount, direction){
|
||||
switch(direction){
|
||||
case "left":
|
||||
this.barStartMoment = moment(this.barStartMoment).subtract(minuteCount, "minutes", true)
|
||||
this.barEndMoment = moment(this.barEndMoment).subtract(minuteCount, "minutes", true)
|
||||
moveBarByMinutesAndPush(minuteCount, direction) {
|
||||
switch (direction) {
|
||||
case 'left':
|
||||
this.barStartMoment = moment(this.barStartMoment).subtract(
|
||||
minuteCount,
|
||||
this.timeChildKey,
|
||||
true
|
||||
)
|
||||
this.barEndMoment = moment(this.barEndMoment).subtract(
|
||||
minuteCount,
|
||||
this.timeChildKey,
|
||||
true
|
||||
)
|
||||
break
|
||||
case "right":
|
||||
this.barStartMoment = moment(this.barStartMoment).add(minuteCount, "minutes", true)
|
||||
this.barEndMoment = moment(this.barEndMoment).add(minuteCount, "minutes", true)
|
||||
case 'right':
|
||||
this.barStartMoment = moment(this.barStartMoment).add(
|
||||
minuteCount,
|
||||
this.timeChildKey,
|
||||
true
|
||||
)
|
||||
this.barEndMoment = moment(this.barEndMoment).add(
|
||||
minuteCount,
|
||||
this.timeChildKey,
|
||||
true
|
||||
)
|
||||
break
|
||||
default:
|
||||
// eslint-disable-next-line
|
||||
console.warn("wrong direction in moveBarByMinutesAndPush")
|
||||
console.warn('wrong direction in moveBarByMinutesAndPush')
|
||||
return
|
||||
}
|
||||
this.manageOverlapping()
|
||||
@@ -373,127 +457,127 @@ export default {
|
||||
/* --------------------------------------------------------- */
|
||||
/* ------- MAPPING POSITION TO TIME (AND VICE VERSA) ------- */
|
||||
/* --------------------------------------------------------- */
|
||||
mapTimeToPosition(time){
|
||||
let hourDiffFromStart = moment(time).diff(this.chartStartMoment, "hour", true)
|
||||
return (hourDiffFromStart / this.getHourCount()) * this.barContainer.width
|
||||
mapTimeToPosition(time) {
|
||||
let timeDiffFromStart = moment(time).diff(
|
||||
this.chartStartMoment,
|
||||
this.timeUnit,
|
||||
true
|
||||
)
|
||||
return (timeDiffFromStart / this.getTimeCount()) * this.barContainer.width
|
||||
},
|
||||
|
||||
mapPositionToTime(xPos){
|
||||
let hourDiffFromStart = (xPos/this.barContainer.width)*this.getHourCount()
|
||||
return this.chartStartMoment.clone().add(hourDiffFromStart, "hours")
|
||||
mapPositionToTime(xPos) {
|
||||
let timeDiffFromStart =
|
||||
(xPos / this.barContainer.width) * this.getTimeCount()
|
||||
return this.chartStartMoment.clone().add(timeDiffFromStart, this.timeUnit)
|
||||
},
|
||||
},
|
||||
|
||||
filters:{
|
||||
TimeFilter(value){
|
||||
return moment(value).format("HH:mm")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.g-gantt-bar {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: white;
|
||||
width: 300px;
|
||||
height: 34px;
|
||||
border-radius: 15px;
|
||||
background: #79869c;
|
||||
overflow: hidden;
|
||||
}
|
||||
.g-gantt-bar {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: white;
|
||||
width: 300px;
|
||||
height: 34px;
|
||||
border-radius: 15px;
|
||||
background: #79869c;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.g-gantt-bar-label {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 14px 0 14px; /* 14px is the width of the handle */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.g-gantt-bar-label {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 14px 0 14px; /* 14px is the width of the handle */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.g-gantt-bar-label > * {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.g-gantt-bar-label > * {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.g-gantt-bar > .g-gantt-bar-handle-left, .g-gantt-bar > .g-gantt-bar-handle-right {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
background: white;
|
||||
opacity: 0.7;
|
||||
border-radius: 40px;
|
||||
cursor: w-resize;
|
||||
}
|
||||
.g-gantt-bar > .g-gantt-bar-handle-left,
|
||||
.g-gantt-bar > .g-gantt-bar-handle-right {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
background: white;
|
||||
opacity: 0.7;
|
||||
border-radius: 40px;
|
||||
cursor: w-resize;
|
||||
}
|
||||
|
||||
.g-gantt-bar-handle-left {
|
||||
left: 0;
|
||||
}
|
||||
.g-gantt-bar-handle-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.g-gantt-bar-handle-right {
|
||||
right: 0;
|
||||
}
|
||||
.g-gantt-bar-handle-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.g-gantt-bar-label img {
|
||||
pointer-events: none;
|
||||
}
|
||||
.g-gantt-bar-label img {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.g-gantt-tooltip{
|
||||
position: absolute;
|
||||
background: black;
|
||||
color: white;
|
||||
z-index: 3;
|
||||
font-size: 0.70em;
|
||||
padding: 3px;
|
||||
border-radius: 3px;
|
||||
transition: opacity 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.g-gantt-tooltip {
|
||||
position: absolute;
|
||||
background: black;
|
||||
color: white;
|
||||
z-index: 3;
|
||||
font-size: 0.7em;
|
||||
padding: 3px;
|
||||
border-radius: 3px;
|
||||
transition: opacity 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.g-gantt-tooltip:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 10%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 10px solid transparent;
|
||||
border-bottom-color: black;
|
||||
border-top: 0;
|
||||
margin-left: -5px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
.g-gantt-tooltip:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 10%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 10px solid transparent;
|
||||
border-bottom-color: black;
|
||||
border-top: 0;
|
||||
margin-left: -5px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.g-gantt-tooltip > .color-indicator {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 100%;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.g-gantt-tooltip > .color-indicator {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 100%;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.fade-enter-active {
|
||||
animation: fade-in .3s;
|
||||
}
|
||||
.fade-enter-active {
|
||||
animation: fade-in 0.3s;
|
||||
}
|
||||
|
||||
.fade-leave-active {
|
||||
animation: fade-in .3s reverse;
|
||||
.fade-leave-active {
|
||||
animation: fade-in 0.3s reverse;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+228
-149
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
<div
|
||||
id="g-gantt-chart"
|
||||
:style="{width: width, background: themeColors.background}"
|
||||
:style="{ width: width, background: themeColors.background }"
|
||||
>
|
||||
<g-gantt-timeaxis
|
||||
v-if="!hideTimeaxis"
|
||||
@@ -13,18 +13,18 @@
|
||||
:locale="locale"
|
||||
/>
|
||||
|
||||
<g-gantt-grid
|
||||
<g-gantt-grid
|
||||
v-if="grid"
|
||||
:chart-start="chartStart"
|
||||
:chart-end="chartEnd"
|
||||
:row-label-width="rowLabelWidth"
|
||||
:highlighted-hours="highlightedHours"
|
||||
/>
|
||||
|
||||
|
||||
<div id="g-gantt-rows-container">
|
||||
<slot/> <!-- the g-gantt-row components go here -->
|
||||
<slot />
|
||||
<!-- the g-gantt-row components go here -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -37,82 +37,93 @@ import GGanttRow from './GGanttRow.vue'
|
||||
import GGanttBar from './GGanttBar.vue'
|
||||
|
||||
export default {
|
||||
name: 'GGanttChart',
|
||||
|
||||
name: "GGanttChart",
|
||||
|
||||
components:{
|
||||
components: {
|
||||
GGanttTimeaxis,
|
||||
GGanttGrid
|
||||
GGanttGrid,
|
||||
},
|
||||
|
||||
props:{
|
||||
chartStart: {type: String, default: moment().startOf("day").format("YYYY-MM-DD HH:mm:ss")},
|
||||
chartEnd: {type: String, default: moment().startOf("day").add(12,"hours").format("YYYY-MM-DD HH:mm:ss")},
|
||||
props: {
|
||||
chartStart: { type: String },
|
||||
chartEnd: { type: String },
|
||||
hideTimeaxis: Boolean,
|
||||
rowLabelWidth: {type: String, default: "10%"},
|
||||
rowHeight: {type: Number, default: 40},
|
||||
locale: {type: String, default: "en"},
|
||||
theme: {type: String},
|
||||
grid: {type: Boolean},
|
||||
highlightedHours: {type: Array, default: () => []},
|
||||
width: {type: String, default: "100%"}, // the total width of the entire ganttastic component in %
|
||||
pushOnOverlap: {type: Boolean},
|
||||
snapBackOnOverlap: {type: Boolean},
|
||||
rowLabelWidth: { type: String, default: '10%' },
|
||||
rowHeight: { type: Number, default: 40 },
|
||||
locale: { type: String, default: 'en' },
|
||||
theme: { type: String },
|
||||
grid: { type: Boolean },
|
||||
highlightedHours: { type: Array, default: () => [] },
|
||||
width: { type: String, default: '100%' }, // the total width of the entire ganttastic component in %
|
||||
pushOnOverlap: { type: Boolean },
|
||||
snapBackOnOverlap: { type: Boolean },
|
||||
minGapBetweenBars: {
|
||||
type: Number,
|
||||
default: 0
|
||||
default: 0,
|
||||
},
|
||||
defaultBarLength: { type: Number, default: 1 },
|
||||
// ["month_days", "day_hours"]
|
||||
timeaxisMode: {type: String, default: "month_days"}
|
||||
timeaxisMode: { type: String, default: 'month_days' },
|
||||
},
|
||||
|
||||
data(){
|
||||
return{
|
||||
data() {
|
||||
return {
|
||||
timemarkerOffset: 0,
|
||||
movedBarsInDrag: new Set()
|
||||
movedBarsInDrag: new Set(),
|
||||
timeUnit: this.timeaxisMode === 'month_days' ? 'days' : 'hours',
|
||||
timeFormat:
|
||||
this.timeaxisMode === 'month_days' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm',
|
||||
}
|
||||
},
|
||||
|
||||
computed:{
|
||||
|
||||
hourCount(){
|
||||
computed: {
|
||||
timeCount() {
|
||||
let momentChartStart = moment(this.chartStart)
|
||||
let momentChartEnd = moment(this.chartEnd)
|
||||
return Math.floor(momentChartEnd.diff(momentChartStart, "hour", true))
|
||||
return Math.floor(momentChartEnd.diff(momentChartStart, this.timeUnit, true))
|
||||
},
|
||||
|
||||
themeColors(){
|
||||
themeColors() {
|
||||
return GanttasticThemeColors[this.theme] || GanttasticThemeColors.default
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
getGanttBarChildrenList(){
|
||||
getGanttBarChildrenList() {
|
||||
let ganttBarChildren = []
|
||||
let ganttRowChildrenList = this.$children.filter(childComp => childComp.$options.name === GGanttRow.name)
|
||||
ganttRowChildrenList.forEach(row => {
|
||||
let ganttBarChildrenOfRow = row.$children.filter(childComp => childComp.$options.name === GGanttBar.name)
|
||||
let ganttRowChildrenList = this.$children.filter(
|
||||
(childComp) => childComp.$options.name === GGanttRow.name
|
||||
)
|
||||
ganttRowChildrenList.forEach((row) => {
|
||||
let ganttBarChildrenOfRow = row.$children.filter(
|
||||
(childComp) => childComp.$options.name === GGanttBar.name
|
||||
)
|
||||
ganttBarChildren.push(...ganttBarChildrenOfRow)
|
||||
})
|
||||
return ganttBarChildren
|
||||
},
|
||||
|
||||
getBarsFromBundle(bundleId){
|
||||
if(bundleId === undefined || bundleId === null){
|
||||
getBarsFromBundle(bundleId) {
|
||||
if (bundleId === undefined || bundleId === null) {
|
||||
return []
|
||||
}
|
||||
return this.getGanttBarChildrenList().filter(ganttBarChild => ganttBarChild.barConfig.bundle === bundleId)
|
||||
return this.getGanttBarChildrenList().filter(
|
||||
(ganttBarChild) => ganttBarChild.barConfig.bundle === bundleId
|
||||
)
|
||||
},
|
||||
|
||||
initDragOfBarsFromBundle(gGanttBar, e){
|
||||
initDragOfBarsFromBundle(gGanttBar, e) {
|
||||
gGanttBar.initDrag(e)
|
||||
this.movedBarsInDrag.add(gGanttBar.bar)
|
||||
if(gGanttBar.barConfig.bundle !== null && gGanttBar.barConfig.bundle !== undefined){
|
||||
this.getGanttBarChildrenList().forEach(ganttBarChild => {
|
||||
if(ganttBarChild.barConfig.bundle === gGanttBar.barConfig.bundle && ganttBarChild !== gGanttBar){
|
||||
if (
|
||||
gGanttBar.barConfig.bundle !== null &&
|
||||
gGanttBar.barConfig.bundle !== undefined
|
||||
) {
|
||||
this.getGanttBarChildrenList().forEach((ganttBarChild) => {
|
||||
if (
|
||||
ganttBarChild.barConfig.bundle === gGanttBar.barConfig.bundle &&
|
||||
ganttBarChild !== gGanttBar
|
||||
) {
|
||||
ganttBarChild.initDrag(e)
|
||||
this.movedBarsInDrag.add(ganttBarChild.bar)
|
||||
}
|
||||
@@ -120,47 +131,56 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
moveBarsFromBundleOfPushedBar(pushedBar, minuteDiff, overlapType){
|
||||
moveBarsFromBundleOfPushedBar(pushedBar, minuteDiff, overlapType) {
|
||||
this.movedBarsInDrag.add(pushedBar)
|
||||
let bundleId = pushedBar.ganttBarConfig.bundle
|
||||
if(bundleId === undefined || bundleId === null){
|
||||
if (bundleId === undefined || bundleId === null) {
|
||||
return
|
||||
}
|
||||
this.getGanttBarChildrenList().forEach(ganttBarChild => {
|
||||
if(ganttBarChild.barConfig.bundle === bundleId && ganttBarChild.bar !== pushedBar){
|
||||
this.getGanttBarChildrenList().forEach((ganttBarChild) => {
|
||||
if (
|
||||
ganttBarChild.barConfig.bundle === bundleId &&
|
||||
ganttBarChild.bar !== pushedBar
|
||||
) {
|
||||
ganttBarChild.moveBarByMinutesAndPush(minuteDiff, overlapType)
|
||||
this.movedBarsInDrag.add(ganttBarChild.bar)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
shouldSnapBackBar(ganttBar){
|
||||
if(this.snapBackOnOverlap && ganttBar.barConfig.pushOnOverlap !== false){
|
||||
let {overlapBar} = ganttBar.getOverlapBarAndType(ganttBar.bar)
|
||||
shouldSnapBackBar(ganttBar) {
|
||||
if (
|
||||
this.snapBackOnOverlap &&
|
||||
ganttBar.barConfig.pushOnOverlap !== false
|
||||
) {
|
||||
let { overlapBar } = ganttBar.getOverlapBarAndType(ganttBar.bar)
|
||||
return !!overlapBar
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
snapBackBundleIfNeeded(ganttBar){
|
||||
snapBackBundleIfNeeded(ganttBar) {
|
||||
let barsFromBundle = this.getBarsFromBundle(ganttBar.barConfig.bundle)
|
||||
if(this.shouldSnapBackBar(ganttBar) || barsFromBundle.some(gBar => this.shouldSnapBackBar(gBar))){
|
||||
if (
|
||||
this.shouldSnapBackBar(ganttBar) ||
|
||||
barsFromBundle.some((gBar) => this.shouldSnapBackBar(gBar))
|
||||
) {
|
||||
ganttBar.snapBack()
|
||||
barsFromBundle.forEach(gBar => gBar.snapBack())
|
||||
barsFromBundle.forEach((gBar) => gBar.snapBack())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
onBarEvent({event, type, time}, ganttBar){
|
||||
this.$emit(`${type}-bar`, {event, bar: ganttBar.bar, time})
|
||||
onBarEvent({ event, type, time }, ganttBar) {
|
||||
this.$emit(`${type}-bar`, { event, bar: ganttBar.bar, time })
|
||||
},
|
||||
|
||||
onDragendBar(e, ganttBar){
|
||||
|
||||
onDragendBar(e, ganttBar) {
|
||||
let didSnapBack = this.snapBackBundleIfNeeded(ganttBar)
|
||||
let movedBars = didSnapBack ? new Set() : this.movedBarsInDrag
|
||||
this.movedBarsInDrag = new Set()
|
||||
this.$emit("dragend-bar", {event: e, bar: ganttBar.bar, movedBars})
|
||||
this.$emit('dragend-bar', { event: e, bar: ganttBar.bar, movedBars })
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@@ -170,162 +190,221 @@ export default {
|
||||
// how far you can drag a bar depends on the position of the closest immobile bar
|
||||
// note that if a bar from the same row belongs to a bundle
|
||||
// other rows might need to be taken into consideration, too
|
||||
setDragLimitsOfGanttBar(bar){
|
||||
if(!this.pushOnOverlap || bar.barConfig.pushOnOverlap === false){
|
||||
setDragLimitsOfGanttBar(bar) {
|
||||
if (!this.pushOnOverlap || bar.barConfig.pushOnOverlap === false) {
|
||||
return
|
||||
}
|
||||
for(let side of ["left", "right"]){
|
||||
let [totalGapDistance, bundleBarsOnPath] = this.countGapDistanceToNextImmobileBar(bar, null, side, false)
|
||||
for(let i=0; i< bundleBarsOnPath.length; i++){
|
||||
for (let side of ['left', 'right']) {
|
||||
let [
|
||||
totalGapDistance,
|
||||
bundleBarsOnPath,
|
||||
] = this.countGapDistanceToNextImmobileBar(bar, null, side, false)
|
||||
for (let i = 0; i < bundleBarsOnPath.length; i++) {
|
||||
let barFromBundle = bundleBarsOnPath[i].bar
|
||||
let gapDist = bundleBarsOnPath[i].gapDistance
|
||||
let otherBarsFromBundle = this.getBarsFromBundle(barFromBundle.barConfig.bundle).filter(otherBar => otherBar !== barFromBundle)
|
||||
otherBarsFromBundle.forEach(otherBar => {
|
||||
let [newGapDistance, newBundleBars] = this.countGapDistanceToNextImmobileBar(otherBar, gapDist, side)
|
||||
if(newGapDistance !== null && (newGapDistance < totalGapDistance || !totalGapDistance)){
|
||||
let otherBarsFromBundle = this.getBarsFromBundle(
|
||||
barFromBundle.barConfig.bundle
|
||||
).filter((otherBar) => otherBar !== barFromBundle)
|
||||
otherBarsFromBundle.forEach((otherBar) => {
|
||||
let [
|
||||
newGapDistance,
|
||||
newBundleBars,
|
||||
] = this.countGapDistanceToNextImmobileBar(otherBar, gapDist, side)
|
||||
if (
|
||||
newGapDistance !== null &&
|
||||
(newGapDistance < totalGapDistance || !totalGapDistance)
|
||||
) {
|
||||
totalGapDistance = newGapDistance
|
||||
}
|
||||
newBundleBars.forEach(newBundleBar => {
|
||||
if(!bundleBarsOnPath.find(barAndGap => barAndGap.bar === newBundleBar.bar)){
|
||||
newBundleBars.forEach((newBundleBar) => {
|
||||
if (
|
||||
!bundleBarsOnPath.find(
|
||||
(barAndGap) => barAndGap.bar === newBundleBar.bar
|
||||
)
|
||||
) {
|
||||
bundleBarsOnPath.push(newBundleBar)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if(totalGapDistance != null && side === "left"){
|
||||
bar.dragLimitLeft = bar.$refs['g-gantt-bar'].offsetLeft - totalGapDistance
|
||||
} else if(totalGapDistance != null && side === "right"){
|
||||
bar.dragLimitRight = bar.$refs['g-gantt-bar'].offsetLeft+ bar.$refs['g-gantt-bar'].offsetWidth + totalGapDistance
|
||||
if (totalGapDistance != null && side === 'left') {
|
||||
bar.dragLimitLeft =
|
||||
bar.$refs['g-gantt-bar'].offsetLeft - totalGapDistance
|
||||
} else if (totalGapDistance != null && side === 'right') {
|
||||
bar.dragLimitRight =
|
||||
bar.$refs['g-gantt-bar'].offsetLeft +
|
||||
bar.$refs['g-gantt-bar'].offsetWidth +
|
||||
totalGapDistance
|
||||
}
|
||||
}
|
||||
// all bars from the bundle of the clicked bar need to have the same drag limit:
|
||||
let barsFromBundleOfClickedBar = this.getBarsFromBundle(bar.barConfig.bundle)
|
||||
barsFromBundleOfClickedBar.forEach(barFromBundle => {
|
||||
barFromBundle.dragLimitLeft = bar.dragLimitLeft
|
||||
let barsFromBundleOfClickedBar = this.getBarsFromBundle(
|
||||
bar.barConfig.bundle
|
||||
)
|
||||
barsFromBundleOfClickedBar.forEach((barFromBundle) => {
|
||||
barFromBundle.dragLimitLeft = bar.dragLimitLeft
|
||||
barFromBundle.dragLimitRight = bar.dragLimitRight
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
// returns the gap distance to the next immobile bar
|
||||
// in the row where the given bar (parameter) is (added to gapDistanceSoFar)
|
||||
// and a list of all bars on that path that belong to a bundle
|
||||
countGapDistanceToNextImmobileBar(bar, gapDistanceSoFar, side="left", ignoreShadows = true){
|
||||
let bundleBarsAndGapDist = bar.barConfig.bundle ? [{bar, gapDistance: gapDistanceSoFar}] : []
|
||||
countGapDistanceToNextImmobileBar(
|
||||
bar,
|
||||
gapDistanceSoFar,
|
||||
side = 'left',
|
||||
ignoreShadows = true
|
||||
) {
|
||||
let bundleBarsAndGapDist = bar.barConfig.bundle
|
||||
? [{ bar, gapDistance: gapDistanceSoFar }]
|
||||
: []
|
||||
let currentBar = bar
|
||||
let nextBar = this.getNextGanttBar(currentBar, side)
|
||||
// left side:
|
||||
if(side === "left"){
|
||||
while(nextBar){
|
||||
let nextBarOffsetRight = nextBar.$refs['g-gantt-bar'].offsetLeft + nextBar.$refs['g-gantt-bar'].offsetWidth
|
||||
gapDistanceSoFar += currentBar.$refs['g-gantt-bar'].offsetLeft - nextBarOffsetRight
|
||||
if(nextBar.barConfig.immobile || (nextBar.barConfig.isShadow && !ignoreShadows)){
|
||||
if (side === 'left') {
|
||||
while (nextBar) {
|
||||
let nextBarOffsetRight =
|
||||
nextBar.$refs['g-gantt-bar'].offsetLeft +
|
||||
nextBar.$refs['g-gantt-bar'].offsetWidth
|
||||
gapDistanceSoFar +=
|
||||
currentBar.$refs['g-gantt-bar'].offsetLeft - nextBarOffsetRight
|
||||
if (
|
||||
nextBar.barConfig.immobile ||
|
||||
(nextBar.barConfig.isShadow && !ignoreShadows)
|
||||
) {
|
||||
return [gapDistanceSoFar, bundleBarsAndGapDist]
|
||||
} else if(nextBar.barConfig.bundle){
|
||||
bundleBarsAndGapDist.push({bar: nextBar, gapDistance: gapDistanceSoFar})
|
||||
} else if (nextBar.barConfig.bundle) {
|
||||
bundleBarsAndGapDist.push({
|
||||
bar: nextBar,
|
||||
gapDistance: gapDistanceSoFar,
|
||||
})
|
||||
}
|
||||
currentBar = nextBar
|
||||
nextBar = this.getNextGanttBar(nextBar, "left")
|
||||
nextBar = this.getNextGanttBar(nextBar, 'left')
|
||||
}
|
||||
}
|
||||
if(side === "right"){
|
||||
while(nextBar){
|
||||
let currentBarOffsetRight = currentBar.$refs['g-gantt-bar'].offsetLeft + currentBar.$refs['g-gantt-bar'].offsetWidth
|
||||
gapDistanceSoFar += nextBar.$refs['g-gantt-bar'].offsetLeft - currentBarOffsetRight
|
||||
if(nextBar.barConfig.immobile || (nextBar.barConfig.isShadow && !ignoreShadows)){
|
||||
if (side === 'right') {
|
||||
while (nextBar) {
|
||||
let currentBarOffsetRight =
|
||||
currentBar.$refs['g-gantt-bar'].offsetLeft +
|
||||
currentBar.$refs['g-gantt-bar'].offsetWidth
|
||||
gapDistanceSoFar +=
|
||||
nextBar.$refs['g-gantt-bar'].offsetLeft - currentBarOffsetRight
|
||||
if (
|
||||
nextBar.barConfig.immobile ||
|
||||
(nextBar.barConfig.isShadow && !ignoreShadows)
|
||||
) {
|
||||
return [gapDistanceSoFar, bundleBarsAndGapDist]
|
||||
} else if(nextBar.barConfig.bundle){
|
||||
bundleBarsAndGapDist.push({bar: nextBar, gapDistance: gapDistanceSoFar})
|
||||
} else if (nextBar.barConfig.bundle) {
|
||||
bundleBarsAndGapDist.push({
|
||||
bar: nextBar,
|
||||
gapDistance: gapDistanceSoFar,
|
||||
})
|
||||
}
|
||||
currentBar = nextBar
|
||||
nextBar = this.getNextGanttBar(nextBar, "right")
|
||||
nextBar = this.getNextGanttBar(nextBar, 'right')
|
||||
}
|
||||
}
|
||||
return [null, bundleBarsAndGapDist]
|
||||
},
|
||||
|
||||
getNextGanttBar(bar, side="left"){
|
||||
getNextGanttBar(bar, side = 'left') {
|
||||
let allBarsLeftOrRight = []
|
||||
if(side === "left"){
|
||||
allBarsLeftOrRight = bar.$parent.$children.filter(gBar => {
|
||||
return gBar.$options.name === GGanttBar.name
|
||||
&& gBar.$parent === bar.$parent
|
||||
&& gBar.$refs['g-gantt-bar']
|
||||
&& gBar.$refs['g-gantt-bar'].offsetLeft < bar.$refs['g-gantt-bar'].offsetLeft
|
||||
&& gBar.barConfig.pushOnOverlap !== false
|
||||
if (side === 'left') {
|
||||
allBarsLeftOrRight = bar.$parent.$children.filter((gBar) => {
|
||||
return (
|
||||
gBar.$options.name === GGanttBar.name &&
|
||||
gBar.$parent === bar.$parent &&
|
||||
gBar.$refs['g-gantt-bar'] &&
|
||||
gBar.$refs['g-gantt-bar'].offsetLeft <
|
||||
bar.$refs['g-gantt-bar'].offsetLeft &&
|
||||
gBar.barConfig.pushOnOverlap !== false
|
||||
)
|
||||
})
|
||||
} else {
|
||||
allBarsLeftOrRight = bar.$parent.$children.filter(gBar => {
|
||||
return gBar.$options.name === GGanttBar.name
|
||||
&& gBar.$parent === bar.$parent
|
||||
&& gBar.$refs['g-gantt-bar']
|
||||
&& gBar.$refs['g-gantt-bar'].offsetLeft > bar.$refs['g-gantt-bar'].offsetLeft
|
||||
&& gBar.barConfig.pushOnOverlap !== false
|
||||
allBarsLeftOrRight = bar.$parent.$children.filter((gBar) => {
|
||||
return (
|
||||
gBar.$options.name === GGanttBar.name &&
|
||||
gBar.$parent === bar.$parent &&
|
||||
gBar.$refs['g-gantt-bar'] &&
|
||||
gBar.$refs['g-gantt-bar'].offsetLeft >
|
||||
bar.$refs['g-gantt-bar'].offsetLeft &&
|
||||
gBar.barConfig.pushOnOverlap !== false
|
||||
)
|
||||
})
|
||||
}
|
||||
if(allBarsLeftOrRight.length > 0){
|
||||
return allBarsLeftOrRight.reduce(
|
||||
(bar1, bar2) => {
|
||||
let bar1Dist = Math.abs(bar1.$refs['g-gantt-bar'].offsetLeft - bar.$refs['g-gantt-bar'].offsetLeft)
|
||||
let bar2Dist = Math.abs(bar2.$refs['g-gantt-bar'].offsetLeft - bar.$refs['g-gantt-bar'].offsetLeft)
|
||||
return bar1Dist < bar2Dist ? bar1 : bar2
|
||||
},
|
||||
allBarsLeftOrRight[0]
|
||||
)
|
||||
if (allBarsLeftOrRight.length > 0) {
|
||||
return allBarsLeftOrRight.reduce((bar1, bar2) => {
|
||||
let bar1Dist = Math.abs(
|
||||
bar1.$refs['g-gantt-bar'].offsetLeft -
|
||||
bar.$refs['g-gantt-bar'].offsetLeft
|
||||
)
|
||||
let bar2Dist = Math.abs(
|
||||
bar2.$refs['g-gantt-bar'].offsetLeft -
|
||||
bar.$refs['g-gantt-bar'].offsetLeft
|
||||
)
|
||||
return bar1Dist < bar2Dist ? bar1 : bar2
|
||||
}, allBarsLeftOrRight[0])
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
},
|
||||
|
||||
|
||||
// all child components of GGanttChart may have access to
|
||||
// the following values by using Vue's "inject" option:
|
||||
provide(){
|
||||
provide() {
|
||||
return {
|
||||
getChartStart: () => this.chartStart,
|
||||
getChartEnd: () => this.chartEnd,
|
||||
getHourCount: () => this.hourCount,
|
||||
getTimeCount: () => this.timeCount,
|
||||
ganttChartProps: this.$props,
|
||||
getThemeColors: () => this.themeColors,
|
||||
initDragOfBarsFromBundle: (bundleId, e) => this.initDragOfBarsFromBundle(bundleId, e),
|
||||
moveBarsFromBundleOfPushedBar: (bar, minuteDiff, overlapType) => this.moveBarsFromBundleOfPushedBar(bar, minuteDiff, overlapType),
|
||||
setDragLimitsOfGanttBar : (ganttBar) => this.setDragLimitsOfGanttBar(ganttBar),
|
||||
initDragOfBarsFromBundle: (bundleId, e) =>
|
||||
this.initDragOfBarsFromBundle(bundleId, e),
|
||||
moveBarsFromBundleOfPushedBar: (bar, minuteDiff, overlapType) =>
|
||||
this.moveBarsFromBundleOfPushedBar(bar, minuteDiff, overlapType),
|
||||
setDragLimitsOfGanttBar: (ganttBar) =>
|
||||
this.setDragLimitsOfGanttBar(ganttBar),
|
||||
onBarEvent: (e, ganttBar) => this.onBarEvent(e, ganttBar),
|
||||
onDragendBar: (e, ganttBar) => this.onDragendBar(e, ganttBar),
|
||||
shouldSnapBackOnOverlap: () => this.snapBackOnOverlap,
|
||||
snapBackBundle: (ganttBar) => this.snapBackBundle(ganttBar),
|
||||
getMinGapBetweenBars: () => this.minGapBetweenBars,
|
||||
getDefaultBarLength: () => this.defaultBarLength,
|
||||
getTimeaxisMode:() => this.timeaxisMode
|
||||
getTimeaxisMode: () => this.timeaxisMode,
|
||||
getTimeUnit: () => this.timeUnit,
|
||||
getTimeFormat: () => this.timeFormat
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#g-gantt-chart{
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
padding-bottom: 23px;
|
||||
}
|
||||
#g-gantt-chart {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
padding-bottom: 23px;
|
||||
}
|
||||
|
||||
#g-gantt-chart >>> * {
|
||||
font-family: Roboto, Verdana;
|
||||
}
|
||||
#g-gantt-chart >>> * {
|
||||
font-family: Roboto, Verdana;
|
||||
}
|
||||
|
||||
#g-gantt-rows-container{
|
||||
position: relative;
|
||||
}
|
||||
#g-gantt-rows-container {
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
+110
-101
@@ -2,18 +2,15 @@
|
||||
<div
|
||||
class="g-gantt-row"
|
||||
ref="g-gantt-row"
|
||||
:style="{height: `${$parent.rowHeight}px`}"
|
||||
:style="{ height: `${$parent.rowHeight}px` }"
|
||||
v-on="$listeners"
|
||||
>
|
||||
<div
|
||||
class="g-gantt-row-label"
|
||||
:style="rowLabelStyle"
|
||||
>
|
||||
<div class="g-gantt-row-label" :style="rowLabelStyle">
|
||||
<slot name="label">
|
||||
{{label}}
|
||||
{{ label }}
|
||||
</slot>
|
||||
</div>
|
||||
<div
|
||||
<div
|
||||
class="g-gantt-row-bars-container"
|
||||
ref="barContainer"
|
||||
:style="barsContainerStyle"
|
||||
@@ -23,8 +20,8 @@
|
||||
@dblclick="onDoubleClick($event)"
|
||||
@mouseover="onMouseover()"
|
||||
@mouseleave="onMouseleave()"
|
||||
>
|
||||
<g-gantt-bar
|
||||
>
|
||||
<g-gantt-bar
|
||||
v-for="(bar, index) in bars"
|
||||
:key="`ganttastic_bar_${index}`"
|
||||
:bar="bar"
|
||||
@@ -34,11 +31,8 @@
|
||||
:bar-container="barContainer"
|
||||
:all-bars-in-row="bars"
|
||||
>
|
||||
<template #bar-label="{bar}">
|
||||
<slot
|
||||
name="bar-label"
|
||||
:bar="bar"
|
||||
/>
|
||||
<template #bar-label="{ bar }">
|
||||
<slot name="bar-label" :bar="bar" />
|
||||
</template>
|
||||
</g-gantt-bar>
|
||||
</div>
|
||||
@@ -50,147 +44,162 @@ import GGanttBar from './GGanttBar.vue'
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
name: 'GGanttRow',
|
||||
|
||||
name: "GGanttRow",
|
||||
|
||||
components:{
|
||||
GGanttBar
|
||||
components: {
|
||||
GGanttBar,
|
||||
},
|
||||
|
||||
props:{
|
||||
label: {type: String, default: "Row"},
|
||||
bars: {type: Array, default: () => []},
|
||||
barStart: {type: String, required: true}, // property name of the bar objects that represents the start datetime
|
||||
barEnd: {type: String, required: true}, // property name of the bar objects that represents the end datetime,
|
||||
props: {
|
||||
label: { type: String, default: 'Row' },
|
||||
bars: { type: Array, default: () => [] },
|
||||
barStart: { type: String, required: true }, // property name of the bar objects that represents the start datetime
|
||||
barEnd: { type: String, required: true }, // property name of the bar objects that represents the end datetime,
|
||||
highlightOnHover: Boolean,
|
||||
},
|
||||
|
||||
inject: [
|
||||
"ganttChartProps",
|
||||
"getThemeColors",
|
||||
"getHourCount",
|
||||
"getChartStart",
|
||||
"getChartEnd",
|
||||
"getDefaultBarLength"
|
||||
'ganttChartProps',
|
||||
'getThemeColors',
|
||||
'getTimeCount',
|
||||
'getChartStart',
|
||||
'getChartEnd',
|
||||
'getDefaultBarLength',
|
||||
'getTimeUnit',
|
||||
'getTimeFormat',
|
||||
],
|
||||
|
||||
data(){
|
||||
data() {
|
||||
return {
|
||||
barContainer: {}
|
||||
barContainer: {},
|
||||
timeUnit: this.getTimeUnit(),
|
||||
timeFormat: this.getTimeFormat(),
|
||||
}
|
||||
},
|
||||
|
||||
computed:{
|
||||
|
||||
rowLabelStyle(){
|
||||
computed: {
|
||||
rowLabelStyle() {
|
||||
return {
|
||||
width: this.ganttChartProps.rowLabelWidth,
|
||||
height: this.ganttChartProps.rowHeight,
|
||||
background: this.$parent.themeColors.ternary,
|
||||
color: this.$parent.themeColors.text
|
||||
color: this.$parent.themeColors.text,
|
||||
}
|
||||
},
|
||||
|
||||
barsContainerStyle(){
|
||||
return{
|
||||
width: `${100 - this.ganttChartProps.rowLabelWidth.replace('%','')}%`,
|
||||
barsContainerStyle() {
|
||||
return {
|
||||
width: `${100 - this.ganttChartProps.rowLabelWidth.replace('%', '')}%`,
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
mounted(){
|
||||
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
|
||||
window.addEventListener("resize", this.onWindowResize)
|
||||
mounted() {
|
||||
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
|
||||
window.addEventListener('resize', this.onWindowResize)
|
||||
},
|
||||
|
||||
methods:{
|
||||
|
||||
methods: {
|
||||
onDragover(e) {
|
||||
e.preventDefault() // enables dropping content on row
|
||||
if(this.highlightOnHover){
|
||||
console.log({backgroundColor: this.$refs["g-gantt-row"].style.backgroundColor })
|
||||
this.$refs["g-gantt-row"].style.backgroundColor = this.getThemeColors().hoverHighlight
|
||||
console.log({backgroundColor: this.$refs["g-gantt-row"].style.backgroundColor })
|
||||
e.preventDefault() // enables dropping content on row
|
||||
if (this.highlightOnHover) {
|
||||
console.log({
|
||||
backgroundColor: this.$refs['g-gantt-row'].style.backgroundColor,
|
||||
})
|
||||
this.$refs[
|
||||
'g-gantt-row'
|
||||
].style.backgroundColor = this.getThemeColors().hoverHighlight
|
||||
console.log({
|
||||
backgroundColor: this.$refs['g-gantt-row'].style.backgroundColor,
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
onDragleave() {
|
||||
this.$refs["g-gantt-row"].style.backgroundColor = null
|
||||
this.$refs['g-gantt-row'].style.backgroundColor = null
|
||||
},
|
||||
|
||||
|
||||
onDrop(e){
|
||||
onDrop(e) {
|
||||
let barContainer = this.$refs.barContainer.getBoundingClientRect()
|
||||
let xPos = e.clientX - barContainer.left
|
||||
let hourDiffFromStart = (xPos/barContainer.width) * this.getHourCount()
|
||||
let time = moment(this.getChartStart()).add(hourDiffFromStart, "hours")
|
||||
let bar = this.bars.find(bar => time.isBetween(bar[this.barStart], bar[this.barEnd]))
|
||||
this.$emit("drop", {event: e, bar, time: time.format("YYYY-MM-DD HH:mm:ss")})
|
||||
let timeDiffFromStart = (xPos / barContainer.width) * this.getTimeCount()
|
||||
let time = moment(this.getChartStart()).add(
|
||||
timeDiffFromStart,
|
||||
this.timeUnit
|
||||
)
|
||||
let bar = this.bars.find((bar) =>
|
||||
time.isBetween(bar[this.barStart], bar[this.barEnd])
|
||||
)
|
||||
this.$emit('drop', { event: e, bar, time: time.format(this.timeFormat) })
|
||||
},
|
||||
|
||||
onDoubleClick(e){
|
||||
onDoubleClick(e) {
|
||||
let barContainer = this.$refs.barContainer.getBoundingClientRect()
|
||||
let xPos = e.clientX - barContainer.left
|
||||
let hourDiffFromStart = (xPos/barContainer.width) * this.getHourCount()
|
||||
let time = moment(this.getChartStart()).add(hourDiffFromStart, "hours")
|
||||
let bar = {};
|
||||
bar[this.barStart] = time.format("YYYY-MM-DD HH:mm:ss")
|
||||
bar[this.barEnd] = time.add(this.getDefaultBarLength(), "hours").format("YYYY-MM-DD HH:mm:ss")
|
||||
bar.ganttBarConfig = {handles: true}
|
||||
let timeDiffFromStart = (xPos / barContainer.width) * this.getTimeCount()
|
||||
let time = moment(this.getChartStart()).add(
|
||||
timeDiffFromStart,
|
||||
this.timeUnit
|
||||
)
|
||||
let bar = {}
|
||||
bar[this.barStart] = time
|
||||
bar[this.barEnd] = time.add(this.getDefaultBarLength(), this.timeUnit)
|
||||
|
||||
bar.ganttBarConfig = { handles: true }
|
||||
this.bars.push(bar)
|
||||
},
|
||||
|
||||
onMouseover(){
|
||||
if(this.highlightOnHover){
|
||||
this.$refs["g-gantt-row"].style.backgroundColor = this.getThemeColors().hoverHighlight
|
||||
onMouseover() {
|
||||
if (this.highlightOnHover) {
|
||||
this.$refs[
|
||||
'g-gantt-row'
|
||||
].style.backgroundColor = this.getThemeColors().hoverHighlight
|
||||
}
|
||||
},
|
||||
|
||||
onMouseleave(){
|
||||
this.$refs["g-gantt-row"].style.backgroundColor = null
|
||||
onMouseleave() {
|
||||
this.$refs['g-gantt-row'].style.backgroundColor = null
|
||||
},
|
||||
|
||||
onWindowResize(){
|
||||
onWindowResize() {
|
||||
// re-initialize the barContainer DOMRect variable, which will trigger re-rendering in the gantt bars
|
||||
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
|
||||
}
|
||||
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
|
||||
},
|
||||
},
|
||||
|
||||
watch:{
|
||||
'ganttChartProps.rowLabelWidth' : function(){
|
||||
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
|
||||
}
|
||||
}
|
||||
watch: {
|
||||
'ganttChartProps.rowLabelWidth': function () {
|
||||
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.g-gantt-row{
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
.g-gantt-row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.g-gantt-row > .g-gantt-row-label{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 20%;
|
||||
background: #E8E8E8;
|
||||
color: #424242;
|
||||
font-size: 0.9em;
|
||||
z-index: 3;
|
||||
overflow: hidden;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.g-gantt-row > .g-gantt-row-bars-container{
|
||||
position: relative;
|
||||
border-top: 1px solid #eaeaea;
|
||||
width: 70%;
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
}
|
||||
.g-gantt-row > .g-gantt-row-label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 20%;
|
||||
background: #e8e8e8;
|
||||
color: #424242;
|
||||
font-size: 0.9em;
|
||||
z-index: 3;
|
||||
overflow: hidden;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.g-gantt-row > .g-gantt-row-bars-container {
|
||||
position: relative;
|
||||
border-top: 1px solid #eaeaea;
|
||||
width: 70%;
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
}
|
||||
</style>
|
||||
+14
-14
@@ -55,7 +55,7 @@ import moment from 'moment'
|
||||
export default {
|
||||
name: 'GGanttTimeaxis',
|
||||
|
||||
inject: ['getTimeaxisMode'],
|
||||
inject: ['getTimeaxisMode', 'getTimeUnit', 'getTimeFormat'],
|
||||
|
||||
props: {
|
||||
chartStart: String,
|
||||
@@ -74,6 +74,8 @@ export default {
|
||||
hourFontSize: '11px',
|
||||
dayFormat: 'MM-DD', // ISO 8601
|
||||
mode: this.getTimeaxisMode(),
|
||||
timeUnit: this.getTimeUnit(),
|
||||
timeFormat: this.getTimeFormat()
|
||||
}
|
||||
},
|
||||
|
||||
@@ -100,10 +102,9 @@ export default {
|
||||
let end = moment(this.chartEnd)
|
||||
this.childPointCount = Math.floor(end.diff(start, 'day', true))
|
||||
while (start.isBefore(end)) {
|
||||
let dayCountOfMonth =
|
||||
start.isSame(end, 'day')
|
||||
? end.date()
|
||||
: start.daysInMonth() - start.date() + 1
|
||||
let dayCountOfMonth = start.isSame(end, 'month')
|
||||
? end.date()
|
||||
: start.daysInMonth() - start.date() + 1
|
||||
let widthPercentage = (dayCountOfMonth / this.childPointCount) * 100
|
||||
let endDay =
|
||||
start.month() === end.month() ? end.date() : end.daysInMonth()
|
||||
@@ -119,10 +120,9 @@ export default {
|
||||
let end = moment(this.chartEnd)
|
||||
this.childPointCount = Math.floor(end.diff(start, 'hour', true))
|
||||
while (start.isBefore(end)) {
|
||||
let hourCountOfDay =
|
||||
start.isSame(end, 'day')
|
||||
? end.hour()
|
||||
: 24 - start.hour()
|
||||
let hourCountOfDay = start.isSame(end, 'day')
|
||||
? end.hour()
|
||||
: 24 - start.hour()
|
||||
|
||||
let widthPercentage = (hourCountOfDay / this.childPointCount) * 100
|
||||
let endHour = start.day() === end.day() ? end.hour() - 1 : 23 // -1 because the last hour is not included e.g if chartEnd=04:00 the last interval we display is between 03 and 04
|
||||
@@ -137,14 +137,14 @@ export default {
|
||||
let datetimeMoment = moment(datetime)
|
||||
let axisMonthObject = {
|
||||
widthPercentage: widthPercentage,
|
||||
value: moment(datetime, 'YYYY-MM'), // ISO 8601
|
||||
value: moment(datetime, 'YYYY-MM'), // ISO 8601
|
||||
ganttDays: [],
|
||||
}
|
||||
let startDay = datetimeMoment.date()
|
||||
for (let i = 0; i <= endDay - startDay; i++) {
|
||||
let day = {
|
||||
text: datetimeMoment.format('D'),
|
||||
fullDatetime: datetimeMoment.format('YYYY-MM-DD'), // ISO 8601
|
||||
fullDatetime: datetimeMoment.format(this.timeFormat),
|
||||
}
|
||||
axisMonthObject.ganttDays.push(day)
|
||||
datetimeMoment.add(1, 'day')
|
||||
@@ -156,14 +156,14 @@ export default {
|
||||
let datetimeMoment = moment(datetime)
|
||||
let axisDayObject = {
|
||||
widthPercentage: widthPercentage,
|
||||
value: moment(datetime, 'YYYY-MM-DD'), // ISO 8601
|
||||
value: moment(datetime, 'YYYY-MM-DD'), // ISO 8601
|
||||
ganttHours: [],
|
||||
}
|
||||
let startHour = datetimeMoment.hour()
|
||||
for (let i = 0; i <= endHour - startHour; i++) {
|
||||
let hour = {
|
||||
text: datetimeMoment.format('HH'),
|
||||
fullDatetime: datetimeMoment.format('YYYY-MM-DD HH:mm'), // ISO 8601
|
||||
fullDatetime: datetimeMoment.format(this.timeFormat),
|
||||
}
|
||||
axisDayObject.ganttHours.push(hour)
|
||||
datetimeMoment.add(1, 'hour')
|
||||
@@ -190,7 +190,7 @@ export default {
|
||||
) + 'px'
|
||||
},
|
||||
|
||||
pointFormatted(point){
|
||||
pointFormatted(point) {
|
||||
if (this.mode === 'month_days') {
|
||||
return this.monthFormatted(point)
|
||||
} else if (this.mode === 'day_hours') {
|
||||
|
||||
Reference in New Issue
Block a user