2
0
mirror of https://github.com/tenrok/vue-ganttastic.git synced 2026-06-22 17:30:32 +03:00

feat: highlight days

This commit is contained in:
2021-10-15 16:06:44 +03:00
parent 1917c82292
commit 7ab91b8b05
7 changed files with 238 additions and 85 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tenrok/vue-ganttastic",
"version": "0.10.9",
"version": "0.10.10",
"description": "A simple and customizable Gantt chart component for Vue.js",
"keywords": [
"gantt",
+5 -5
View File
@@ -356,14 +356,14 @@ export default {
newXEnd &&
moment(this.bar[this.barEndKey]).isAfter(this.barEndBeforeDrag)
const currentIndex = this.allBarsInRow.findIndex((bar) => bar == this.bar)
const currentIndex = this.allBarsInRow.findIndex(bar => bar == this.bar)
let otherBars = []
if (isSqueezeToRight) {
otherBars = this.allBarsInRow.slice(currentIndex + 1)
if (otherBars.length) {
let otherBarTotalWidth = otherBars
.map((bar) => this.getBarWidth(bar))
.map(bar => this.getBarWidth(bar))
.reduce((accumulator, currentValue) => accumulator + currentValue)
if (newXEnd > this.barContainer.width - otherBarTotalWidth) {
return true
@@ -373,7 +373,7 @@ export default {
otherBars = this.allBarsInRow.slice(0, currentIndex)
if (otherBars.length) {
let otherBarTotalWidth = otherBars
.map((bar) => this.getBarWidth(bar))
.map(bar => this.getBarWidth(bar))
.reduce((accumulator, currentValue) => accumulator + currentValue)
if (newXStart < otherBarTotalWidth) {
return true
@@ -478,7 +478,7 @@ export default {
let barStartMoment = moment(bar[this.barStartKey])
let barEndMoment = moment(bar[this.barEndKey])
let overlapLeft, overlapRight, overlapInBetween
let overlapBar = this.allBarsInRow.find((otherBar) => {
let overlapBar = this.allBarsInRow.find(otherBar => {
if (
otherBar === bar ||
otherBar.ganttBarConfig.pushOnOverlap === false
@@ -685,4 +685,4 @@ export default {
opacity: 1;
}
}
</style>
</style>
+26 -20
View File
@@ -1,7 +1,7 @@
<template>
<div
class="g-gantt-chart"
:style="{ width: width, background: themeColors.background }"
:style="{ width, height, background: themeColors.background }"
>
<g-gantt-timeaxis
v-if="!hideTimeaxis"
@@ -23,6 +23,7 @@
:chart-end="chartEnd"
:row-label-width="rowLabelWidth"
:highlighted-hours="highlightedHours"
:highlighted-days="highlightedDays"
:precision="precision"
:time-count="timeCount"
:grid-size="gridSize"
@@ -65,7 +66,9 @@ export default {
grid: { type: Boolean },
gridSize: { type: Number, default: 30 },
highlightedHours: { type: Array, default: () => [] },
highlightedDays: { type: Array, default: () => [] }, // format YYYY-MM-DD
width: { type: String, default: '100%' }, // the total width of the entire ganttastic component in %
height: { type: String, default: '100%' },
pushOnOverlap: { type: Boolean },
isMagnetic: { type: Boolean },
snapBackOnOverlap: { type: Boolean },
@@ -73,7 +76,8 @@ export default {
defaultBarLength: { type: Number, default: 1 },
precision: { type: String, default: 'month' }, // 'month', 'day'
barStartKey: { type: String, default: 'start' }, // property name of the bar objects that represents the start datetime
barEndKey: { type: String, default: 'end' }, // property name of the bar objects that represents the end datetime,
barEndKey: { type: String, default: 'end' }, // property name of the bar objects that represents the end datetime
mayAdd: { type: Boolean, default: true },
},
data() {
@@ -109,11 +113,11 @@ export default {
getGanttBarChildrenList() {
let ganttBarChildren = []
let ganttRowChildrenList = this.$children.filter(
(childComp) => childComp.$options.name === GGanttRow.name
childComp => childComp.$options.name === GGanttRow.name
)
ganttRowChildrenList.forEach((row) => {
ganttRowChildrenList.forEach(row => {
let ganttBarChildrenOfRow = row.$children.filter(
(childComp) => childComp.$options.name === GGanttBar.name
childComp => childComp.$options.name === GGanttBar.name
)
ganttBarChildren.push(...ganttBarChildrenOfRow)
})
@@ -125,7 +129,7 @@ export default {
return []
}
return this.getGanttBarChildrenList().filter(
(ganttBarChild) => ganttBarChild.barConfig.bundle === bundleId
ganttBarChild => ganttBarChild.barConfig.bundle === bundleId
)
},
@@ -136,7 +140,7 @@ export default {
gGanttBar.barConfig.bundle !== null &&
gGanttBar.barConfig.bundle !== undefined
) {
this.getGanttBarChildrenList().forEach((ganttBarChild) => {
this.getGanttBarChildrenList().forEach(ganttBarChild => {
if (
ganttBarChild.barConfig.bundle === gGanttBar.barConfig.bundle &&
ganttBarChild !== gGanttBar
@@ -154,7 +158,7 @@ export default {
if (bundleId === undefined || bundleId === null) {
return
}
this.getGanttBarChildrenList().forEach((ganttBarChild) => {
this.getGanttBarChildrenList().forEach(ganttBarChild => {
if (
ganttBarChild.barConfig.bundle === bundleId &&
ganttBarChild.bar !== pushedBar
@@ -180,10 +184,10 @@ export default {
let barsFromBundle = this.getBarsFromBundle(ganttBar.barConfig.bundle)
if (
this.shouldSnapBackBar(ganttBar) ||
barsFromBundle.some((gBar) => this.shouldSnapBackBar(gBar))
barsFromBundle.some(gBar => this.shouldSnapBackBar(gBar))
) {
ganttBar.snapBack()
barsFromBundle.forEach((gBar) => gBar.snapBack())
barsFromBundle.forEach(gBar => gBar.snapBack())
return true
}
return false
@@ -200,7 +204,7 @@ export default {
if (movedBars.size && this.isMagnetic) {
let { left, right /*, move*/ } = action
movedBars.forEach((bar) => {
movedBars.forEach(bar => {
if (this.precision === 'month') {
if (left && bar == ganttBar.bar) {
if (moment(bar[this.barStartKey]).hours() < 12) {
@@ -303,8 +307,8 @@ export default {
let gapDist = bundleBarsOnPath[i].gapDistance
let otherBarsFromBundle = this.getBarsFromBundle(
barFromBundle.barConfig.bundle
).filter((otherBar) => otherBar !== barFromBundle)
otherBarsFromBundle.forEach((otherBar) => {
).filter(otherBar => otherBar !== barFromBundle)
otherBarsFromBundle.forEach(otherBar => {
let [newGapDistance, newBundleBars] =
this.countGapDistanceToNextImmobileBar(otherBar, gapDist, side)
if (
@@ -313,10 +317,10 @@ export default {
) {
totalGapDistance = newGapDistance
}
newBundleBars.forEach((newBundleBar) => {
newBundleBars.forEach(newBundleBar => {
if (
!bundleBarsOnPath.find(
(barAndGap) => barAndGap.bar === newBundleBar.bar
barAndGap => barAndGap.bar === newBundleBar.bar
)
) {
bundleBarsOnPath.push(newBundleBar)
@@ -338,7 +342,7 @@ export default {
let barsFromBundleOfClickedBar = this.getBarsFromBundle(
bar.barConfig.bundle
)
barsFromBundleOfClickedBar.forEach((barFromBundle) => {
barsFromBundleOfClickedBar.forEach(barFromBundle => {
barFromBundle.dragLimitLeft = bar.dragLimitLeft
barFromBundle.dragLimitRight = bar.dragLimitRight
})
@@ -409,7 +413,7 @@ export default {
getNextGanttBar(bar, side = 'left') {
let allBarsLeftOrRight = []
if (side === 'left') {
allBarsLeftOrRight = bar.$parent.$children.filter((gBar) => {
allBarsLeftOrRight = bar.$parent.$children.filter(gBar => {
return (
gBar.$options.name === GGanttBar.name &&
gBar.$parent === bar.$parent &&
@@ -420,7 +424,7 @@ export default {
)
})
} else {
allBarsLeftOrRight = bar.$parent.$children.filter((gBar) => {
allBarsLeftOrRight = bar.$parent.$children.filter(gBar => {
return (
gBar.$options.name === GGanttBar.name &&
gBar.$parent === bar.$parent &&
@@ -466,13 +470,13 @@ export default {
this.initDragOfBarsFromBundle(bundleId, e),
moveBarsFromBundleOfPushedBar: (bar, minuteDiff, overlapType) =>
this.moveBarsFromBundleOfPushedBar(bar, minuteDiff, overlapType),
setDragLimitsOfGanttBar: (ganttBar) =>
setDragLimitsOfGanttBar: ganttBar =>
this.setDragLimitsOfGanttBar(ganttBar),
onBarEvent: (e, ganttBar) => this.onBarEvent(e, ganttBar),
onDragendBar: (e, ganttBar, action) =>
this.onDragendBar(e, ganttBar, action),
shouldSnapBackOnOverlap: () => this.snapBackOnOverlap,
snapBackBundle: (ganttBar) => this.snapBackBundle(ganttBar),
snapBackBundle: ganttBar => this.snapBackBundle(ganttBar),
getMinGapBetweenBars: () => this.minGapBetweenBars,
getDefaultBarLength: () => this.defaultBarLength,
getTimeUnit: () => this.timeUnit,
@@ -495,6 +499,8 @@ export default {
-ms-user-select: none;
user-select: none;
padding-bottom: 23px;
border: 1px solid #eaeaea;
box-sizing: border-box;
}
.g-gantt-chart >>> * {
+36 -3
View File
@@ -1,7 +1,13 @@
<template>
<div
ref="g-grid-container"
class="g-grid-container"
:style="{ left: `${rowLabelWidth}px`, width: `${timeCount * gridSize}px` }"
:style="{
left: `${rowLabelWidth}px`,
width: `${timeCount * gridSize}px`,
top,
height,
}"
>
<div
v-for="(childPoint, index) in allChildPoints"
@@ -11,7 +17,8 @@
{ 'g-grid-line-last': index === allChildPoints.length - 1 },
{
'g-grid-line-highlighted':
precision === 'day' && highlightedHours.includes(childPoint),
(precision === 'day' && highlightedHours.includes(childPoint)) ||
(precision === 'month' && highlightedDays.includes(childPoint)),
},
]"
:style="{ width: `${gridSize}px` }"
@@ -30,11 +37,17 @@ export default {
chartEnd: { type: String },
rowLabelWidth: { type: Number },
highlightedHours: { type: Array, default: () => [] },
highlightedDays: { type: Array, default: () => [] },
precision: { type: String },
timeCount: { type: Number },
gridSize: { type: Number },
},
data: () => ({
top: '0px',
height: '0px',
}),
computed: {
allChildPoints() {
let start = moment(this.chartStart)
@@ -47,7 +60,7 @@ export default {
start.add(1, 'hour')
break
case 'month':
res.push(start.date())
res.push(start.format('YYYY-MM-DD'))
start.add(1, 'day').hour(23)
break
}
@@ -55,6 +68,26 @@ export default {
return res
},
},
mounted() {
this.$nextTick(() => this.onWindowResize())
window.addEventListener('resize', this.onWindowResize)
},
destroyed() {
window.removeEventListener('resize', this.onWindowResize)
},
methods: {
onWindowResize() {
let gridContainer = this.$refs['g-grid-container']
if (!gridContainer) return
let rowsContainer = gridContainer.nextSibling
if (!rowsContainer) return
this.top = `${rowsContainer.offsetTop}px`
this.height = `${rowsContainer.offsetHeight}px`
},
},
}
</script>
+2 -1
View File
@@ -112,7 +112,7 @@ export default {
timeDiffFromStart,
this.timeUnit
)
let bar = this.bars.find((bar) =>
let bar = this.bars.find(bar =>
time.isBetween(
bar[this.$parent.barStartKey],
bar[this.$parent.barEndKey]
@@ -122,6 +122,7 @@ export default {
},
onDoubleClick(e) {
if (!this.$parent.mayAdd) return
let barContainer = this.$refs.barContainer.getBoundingClientRect()
let xPos = e.clientX - barContainer.left
let timeDiffFromStart = Math.floor(
+3 -3
View File
@@ -96,8 +96,8 @@ export default {
this.initAxis()
this.onWindowResize()
window.addEventListener('resize', this.onWindowResize)
window.addEventListener('mousemove', (event) => this.moveTimemarker(event))
window.addEventListener('dragover', (event) => this.moveTimemarker(event))
window.addEventListener('mousemove', event => this.moveTimemarker(event))
window.addEventListener('dragover', event => this.moveTimemarker(event))
},
destroyed() {
@@ -324,4 +324,4 @@ export default {
width: 3px;
background: black;
}
</style>
</style>
+165 -52
View File
@@ -1,29 +1,64 @@
<template>
<div>
<h2>Chart #1</h2>
<g-gantt-chart
:chart-start="chartStart"
:chart-end="chartEnd"
:grid="grid"
:grid-size="gridSize"
:hide-timeaxis="hideTimeaxis"
:push-on-overlap="pushOnOverlap"
:chart-start="chart1.chartStart"
:chart-end="chart1.chartEnd"
:grid="chart1.grid"
:grid-size="chart1.gridSize"
:hide-timeaxis="chart1.hideTimeaxis"
:push-on-overlap="chart1.pushOnOverlap"
snap-back-on-overlap
:precision="precision"
:is-magnetic="isMagnetic"
:highlighted-hours="highlightedHours"
:row-label-width="rowLabelWidth"
:row-height="rowHeight"
:theme="selectedTheme"
barStartKey="myStart"
barEndKey="myEnd"
:precision="chart1.precision"
:is-magnetic="chart1.isMagnetic"
:highlighted-hours="chart1.highlightedHours"
:row-label-width="chart1.rowLabelWidth"
:row-height="chart1.rowHeight"
:theme="chart1.selectedTheme"
bar-start-key="myStart"
bar-end-key="myEnd"
@dragend-bar="onDragend($event)"
>
<g-gantt-row
v-for="row in rowList"
v-for="row in chart1.rows"
:key="row.label"
:label="row.label"
:bars="row.barList"
:highlight-on-hover="highlightOnHover"
:bars="row.bars"
:highlight-on-hover="chart1.highlightOnHover"
>
<template #bar-label="{ bar }">
<span>{{ bar.label }}</span>
</template>
</g-gantt-row>
</g-gantt-chart>
<h2>Chart #2</h2>
<g-gantt-chart
:chart-start="chart2.chartStart"
:chart-end="chart2.chartEnd"
:grid="chart2.grid"
:grid-size="chart2.gridSize"
:hide-timeaxis="chart2.hideTimeaxis"
:push-on-overlap="chart2.pushOnOverlap"
snap-back-on-overlap
:precision="chart2.precision"
:is-magnetic="chart2.isMagnetic"
:highlighted-days="chart2.highlightedDays"
:row-label-width="chart2.rowLabelWidth"
:row-height="chart2.rowHeight"
:theme="chart2.selectedTheme"
:width="chart2.width"
:height="chart2.height"
:may-add="chart2.mayAdd"
>
<g-gantt-row
v-for="row in chart2.rows"
:key="row.label"
:label="row.label"
:bars="row.bars"
:highlight-on-hover="chart2.highlightOnHover"
>
<template #bar-label="{ bar }">
<span>{{ bar.label }}</span>
@@ -42,43 +77,25 @@ export default {
GGanttChart,
GGanttRow,
},
data() {
return {
data: () => ({
chart1: {
chartStart: '2020-03-02 00:00',
chartEnd: '2020-03-10 10:00',
precision: 'day',
pushOnOverlap: true,
isMagnetic: true,
grid: true,
gridSize: 50,
gridSize: 30,
rowHeight: 40,
rowLabelWidth: 200,
hideTimeaxis: false,
highlightOnHover: true,
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: [
selectedTheme: 'default', // 'default', 'vue', 'dark', 'material-blue', 'creamy', 'slumber', 'sky', 'crimson', 'grove', 'fuchsia', 'flare'
rows: [
{
label: 'Row #1',
barList: [
bars: [
{
myStart: '2020-03-03 18:00',
myEnd: '2020-03-03 23:00',
@@ -102,15 +119,13 @@ export default {
},
],
},
{
label: 'Row #2',
barList: [
bars: [
{
myStart: '2020-03-02 09:00',
myEnd: '2020-03-02 18:00',
image: 'vue_ganttastic_logo_no_text.png',
label: 'I have an image',
label: 'Bar',
ganttBarConfig: {
color: 'white',
backgroundColor: '#de3b26',
@@ -135,14 +150,13 @@ export default {
},
],
},
{
label: 'Row #3',
barList: [
bars: [
{
myStart: '2020-03-02 09:00',
myEnd: '2020-03-02 18:00',
label: 'I am with stupid ^',
label: 'We belong together ^',
ganttBarConfig: {
color: 'white',
backgroundColor: '#de3b26',
@@ -182,10 +196,9 @@ export default {
},
],
},
{
label: 'Row #4',
barList: [
bars: [
{
myStart: '2020-03-03 06:30',
myEnd: '2020-03-03 20:00',
@@ -209,8 +222,108 @@ export default {
],
},
],
}
},
},
chart2: {
chartStart: '2020-03-01 00:00',
chartEnd: '2020-04-01 00:00',
precision: 'month',
pushOnOverlap: true,
isMagnetic: true,
grid: true,
gridSize: 50,
rowHeight: 40,
rowLabelWidth: 300,
hideTimeaxis: false,
highlightOnHover: true,
highlightedDays: [
'2020-03-01',
'2020-03-08',
'2020-03-15',
'2020-03-22',
'2020-03-29',
],
selectedTheme: 'vue', // 'default', 'vue', 'dark', 'material-blue', 'creamy', 'slumber', 'sky', 'crimson', 'grove', 'fuchsia', 'flare'
width: '1100px',
height: '250px',
mayAdd: false,
rows: [
{
label: 'Row #1',
bars: [
{
start: '2020-03-05 00:00',
end: '2020-03-10 23:59',
label: 'Bar',
ganttBarConfig: {
color: 'white',
backgroundColor: '#2e74a3',
bundle: 'blueBundle',
},
},
],
},
{
label: 'Row #2',
bars: [
{
start: '2020-03-02 00:00',
end: '2020-03-09 23:59',
label: 'We belong together ^',
ganttBarConfig: {
color: 'white',
backgroundColor: '#2e74a3',
bundle: 'blueBundle',
},
},
{
start: '2020-03-24 00:00',
end: '2020-03-26 23:00',
label: 'Bar',
ganttBarConfig: {
color: 'white',
backgroundColor: '#de3b26',
},
},
],
},
{
label: 'Row #3',
bars: [
{
start: '2020-03-15 00:00',
end: '2020-03-18 23:59',
label: 'Bar',
ganttBarConfig: {
color: 'white',
backgroundColor: '#408e2f',
},
},
],
},
{
label:
'Lorem ipsum dolor sit amet. Vel odit debitis qui aliquam sequi et reprehenderit Quis. Et ipsam enim aut culpa quia sed maiores veniam in consequuntur accusantium.',
bars: [],
},
{
label: 'Row #5',
bars: [],
},
{
label: 'Row #6',
bars: [],
},
{
label: 'Row #7',
bars: [],
},
{
label: 'Row #8',
bars: [],
},
],
},
}),
methods: {
onDragend(e) {