2
0
mirror of https://github.com/tenrok/vue-ganttastic.git synced 2026-05-17 05:09:37 +03:00

chore(deps-dev): bump sass from 1.51.0 to 1.52.1

This commit is contained in:
2022-05-24 09:13:18 +03:00
parent c22d31e8df
commit 429a40e65c
43 changed files with 2630 additions and 2630 deletions
+3 -3
View File
@@ -1,3 +1,3 @@
> 1%
last 2 versions
not dead
> 1%
last 2 versions
not dead
+9 -9
View File
@@ -1,9 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
+2 -2
View File
@@ -1,2 +1,2 @@
demo
dist
demo
dist
+17 -17
View File
@@ -1,17 +1,17 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}
+27 -27
View File
@@ -1,27 +1,27 @@
.DS_Store
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# npm
node_modules
# output directories
/demo
/dist
.DS_Store
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# npm
node_modules
# output directories
/demo
/dist
+11 -11
View File
@@ -1,11 +1,11 @@
module.exports = {
arrowParens: 'avoid',
bracketSpacing: true,
printWidth: 80,
semi: false,
singleQuote: true,
tabWidth: 2,
trailingComma: 'none',
useTabs: false,
vueIndentScriptAndStyle: true
}
module.exports = {
arrowParens: 'avoid',
bracketSpacing: true,
printWidth: 80,
semi: false,
singleQuote: true,
tabWidth: 2,
trailingComma: 'none',
useTabs: false,
vueIndentScriptAndStyle: true
}
+5 -5
View File
@@ -1,5 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
File diff suppressed because it is too large Load Diff
+481 -481
View File
@@ -1,481 +1,481 @@
<template>
<div
class="g-gantt-chart-container"
:data-theme="theme"
:style="{ width, height }"
>
<div class="g-gantt-chart">
<g-gantt-timeaxis
v-if="!hideTimeaxis"
:chart-start="chartStart"
:chart-end="chartEnd"
:row-label-width="rowLabelWidth"
:timemarker-offset="timemarkerOffset"
:locale="locale"
:precision="precision"
:time-format="timeFormat"
:time-count="timeCount"
:grid-size="gridSize"
:day-format="dayFormat"
:month-format="monthFormat"
/>
<div
class="g-gantt-rows-container"
:style="{ width: `${timeCount * gridSize + rowLabelWidth}px` }"
>
<g-gantt-grid
v-if="grid"
:chart-start="chartStart"
:chart-end="chartEnd"
:row-label-width="rowLabelWidth"
:highlighted-hours="highlightedHours"
:highlighted-days="highlightedDays"
:precision="precision"
:time-count="timeCount"
:grid-size="gridSize"
/>
<slot />
</div>
</div>
</div>
</template>
<script>
import moment from 'moment'
import GGanttTimeaxis from './GGanttTimeaxis.vue'
import GGanttGrid from './GGanttGrid.vue'
import GGanttRow from './GGanttRow.vue'
import GGanttBar from './GGanttBar.vue'
export default {
name: 'GGanttChart',
components: {
GGanttTimeaxis,
GGanttGrid
},
props: {
chartStart: { type: String, required: true },
chartEnd: { type: String, required: true },
hideTimeaxis: { type: Boolean, default: false },
rowLabelWidth: { type: Number, default: 200 },
rowHeight: { type: Number, default: 40 },
locale: { type: String, default: 'en' },
theme: { type: String },
grid: { type: Boolean, default: false },
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 },
minGapBetweenBars: { type: Number, default: 0 },
defaultBarLength: { type: Number, default: 1 },
precision: { type: String, default: 'month' }, // 'month', 'day'
barConfigKey: { type: String, default: 'ganttBarConfig' },
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
allowAdd: { type: Boolean, default: true },
dayFormat: { type: String, default: 'ddd DD MMMM' },
monthFormat: { type: String, default: 'MMMM YYYY' },
tooltipFormat: {
type: String,
default: '{start} - {end} duration: {duration}'
}
},
data() {
return {
timemarkerOffset: 0,
movedBarsInDrag: new Set()
}
},
computed: {
timeUnit() {
return this.precision === 'month' ? 'days' : 'hours'
},
timeFormat() {
return this.precision === 'month' ? 'YYYY-MM-DD HH' : 'YYYY-MM-DD HH:mm'
},
timeCount() {
let momentChartStart = moment(this.chartStart)
let momentChartEnd = moment(this.chartEnd)
return Math.floor(
momentChartEnd.diff(momentChartStart, this.timeUnit, true)
)
}
},
methods: {
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
)
ganttBarChildren.push(...ganttBarChildrenOfRow)
})
return ganttBarChildren
},
getBarsFromBundle(bundleId) {
if (bundleId === undefined || bundleId === null) {
return []
}
return this.getGanttBarChildrenList().filter(
ganttBarChild => ganttBarChild.barConfig.bundle === bundleId
)
},
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
) {
ganttBarChild.initDrag(e)
this.movedBarsInDrag.add(ganttBarChild.bar)
}
})
}
},
moveBarsFromBundleOfPushedBar(pushedBar, minuteDiff, overlapType) {
this.movedBarsInDrag.add(pushedBar)
let bundleId = pushedBar[this.barConfigKey]
? pushedBar[this.barConfigKey].bundle
: null
if (bundleId === undefined || bundleId === null) {
return
}
this.getGanttBarChildrenList().forEach(ganttBarChild => {
if (
ganttBarChild.barConfig.bundle === bundleId &&
ganttBarChild.bar !== pushedBar
) {
ganttBarChild.moveBarByChildPointsAndPush(minuteDiff, overlapType)
this.movedBarsInDrag.add(ganttBarChild.bar)
}
})
},
shouldSnapBackBar(ganttBar) {
if (
this.snapBackOnOverlap &&
ganttBar.barConfig.pushOnOverlap !== false
) {
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({ event, type, time }, ganttBar) {
this.$emit(`${type}-bar`, { event, bar: ganttBar.bar, time })
},
onDragendBar(e, ganttBar, action) {
let didSnapBack = this.snapBackBundleIfNeeded(ganttBar)
let movedBars = didSnapBack ? new Set() : this.movedBarsInDrag
// Magnetic suction
if (movedBars.size && this.isMagnetic) {
let { left, right /*, move*/ } = action
movedBars.forEach(bar => {
if (this.precision === 'month') {
if (left && bar == ganttBar.bar) {
if (moment(bar[this.barStartKey]).hours() < 12) {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.hours(0)
.format()
} else {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.hours(24)
.format()
}
} else if (right && bar == ganttBar.bar) {
if (moment(bar[this.barEndKey]).hours() < 12) {
bar[this.barEndKey] = moment(bar[this.barEndKey])
.hours(0)
.format()
} else {
bar[this.barEndKey] = moment(bar[this.barEndKey])
.hours(24)
.format()
}
} else {
if (moment(bar[this.barStartKey]).hours() < 12) {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.hours(0)
.format()
bar[this.barEndKey] = moment(bar[this.barEndKey])
.hours(0)
.format()
} else {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.hours(24)
.format()
bar[this.barEndKey] = moment(bar[this.barEndKey])
.hours(24)
.format()
}
}
} else {
if (left && bar == ganttBar.bar) {
if (moment(bar[this.barStartKey]).minutes() < 30) {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.minutes(0)
.format()
} else {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.minutes(60)
.format()
}
} else if (right && bar == ganttBar.bar) {
if (moment(bar[this.barEndKey]).minutes() < 30) {
bar[this.barEndKey] = moment(bar[this.barEndKey])
.minutes(0)
.format()
} else {
bar[this.barEndKey] = moment(bar[this.barEndKey])
.minutes(60)
.format()
}
} else {
if (moment(bar[this.barStartKey]).minutes() < 30) {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.minutes(0)
.format()
bar[this.barEndKey] = moment(bar[this.barEndKey])
.minutes(0)
.format()
} else {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.minutes(60)
.format()
bar[this.barEndKey] = moment(bar[this.barEndKey])
.minutes(60)
.format()
}
}
}
})
}
this.movedBarsInDrag = new Set()
this.$emit('dragend-bar', { event: e, bar: ganttBar.bar, movedBars })
},
// ------------------------------------------------------------------------
// -------- METHODS FOR SETTING THE DRAG LIMIT OF A BAR ----------------
// ------------------------------------------------------------------------
// 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) {
return
}
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)
) {
totalGapDistance = newGapDistance
}
newBundleBars.forEach(newBundleBar => {
if (
!bundleBarsOnPath.find(
barAndGap => barAndGap.bar === newBundleBar.bar
)
) {
bundleBarsOnPath.push(newBundleBar)
}
})
})
}
if (totalGapDistance != null && side === 'left') {
bar.dragLimitLeft = bar.$refs['g-bar'].offsetLeft - totalGapDistance
} else if (totalGapDistance != null && side === 'right') {
bar.dragLimitRight =
bar.$refs['g-bar'].offsetLeft +
bar.$refs['g-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
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 }]
: []
let currentBar = bar
let nextBar = this.getNextGanttBar(currentBar, side)
// left side:
if (side === 'left') {
while (nextBar) {
let nextBarOffsetRight =
nextBar.$refs['g-bar'].offsetLeft +
nextBar.$refs['g-bar'].offsetWidth
gapDistanceSoFar +=
currentBar.$refs['g-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
})
}
currentBar = nextBar
nextBar = this.getNextGanttBar(nextBar, 'left')
}
}
if (side === 'right') {
while (nextBar) {
let currentBarOffsetRight =
currentBar.$refs['g-bar'].offsetLeft +
currentBar.$refs['g-bar'].offsetWidth
gapDistanceSoFar +=
nextBar.$refs['g-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
})
}
currentBar = nextBar
nextBar = this.getNextGanttBar(nextBar, 'right')
}
}
return [null, bundleBarsAndGapDist]
},
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-bar'] &&
gBar.$refs['g-bar'].offsetLeft < bar.$refs['g-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-bar'] &&
gBar.$refs['g-bar'].offsetLeft > bar.$refs['g-bar'].offsetLeft &&
gBar.barConfig.pushOnOverlap !== false
)
})
}
if (allBarsLeftOrRight.length > 0) {
return allBarsLeftOrRight.reduce((bar1, bar2) => {
let bar1Dist = Math.abs(
bar1.$refs['g-bar'].offsetLeft - bar.$refs['g-bar'].offsetLeft
)
let bar2Dist = Math.abs(
bar2.$refs['g-bar'].offsetLeft - bar.$refs['g-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() {
return {
getTimeCount: () => this.timeCount,
getChartProps: () => this.$props,
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, action) =>
this.onDragendBar(e, ganttBar, action),
getTimeUnit: () => this.timeUnit,
getTimeFormat: () => this.timeFormat
}
}
}
</script>
<template>
<div
class="g-gantt-chart-container"
:data-theme="theme"
:style="{ width, height }"
>
<div class="g-gantt-chart">
<g-gantt-timeaxis
v-if="!hideTimeaxis"
:chart-start="chartStart"
:chart-end="chartEnd"
:row-label-width="rowLabelWidth"
:timemarker-offset="timemarkerOffset"
:locale="locale"
:precision="precision"
:time-format="timeFormat"
:time-count="timeCount"
:grid-size="gridSize"
:day-format="dayFormat"
:month-format="monthFormat"
/>
<div
class="g-gantt-rows-container"
:style="{ width: `${timeCount * gridSize + rowLabelWidth}px` }"
>
<g-gantt-grid
v-if="grid"
:chart-start="chartStart"
:chart-end="chartEnd"
:row-label-width="rowLabelWidth"
:highlighted-hours="highlightedHours"
:highlighted-days="highlightedDays"
:precision="precision"
:time-count="timeCount"
:grid-size="gridSize"
/>
<slot />
</div>
</div>
</div>
</template>
<script>
import moment from 'moment'
import GGanttTimeaxis from './GGanttTimeaxis.vue'
import GGanttGrid from './GGanttGrid.vue'
import GGanttRow from './GGanttRow.vue'
import GGanttBar from './GGanttBar.vue'
export default {
name: 'GGanttChart',
components: {
GGanttTimeaxis,
GGanttGrid
},
props: {
chartStart: { type: String, required: true },
chartEnd: { type: String, required: true },
hideTimeaxis: { type: Boolean, default: false },
rowLabelWidth: { type: Number, default: 200 },
rowHeight: { type: Number, default: 40 },
locale: { type: String, default: 'en' },
theme: { type: String },
grid: { type: Boolean, default: false },
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 },
minGapBetweenBars: { type: Number, default: 0 },
defaultBarLength: { type: Number, default: 1 },
precision: { type: String, default: 'month' }, // 'month', 'day'
barConfigKey: { type: String, default: 'ganttBarConfig' },
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
allowAdd: { type: Boolean, default: true },
dayFormat: { type: String, default: 'ddd DD MMMM' },
monthFormat: { type: String, default: 'MMMM YYYY' },
tooltipFormat: {
type: String,
default: '{start} - {end} duration: {duration}'
}
},
data() {
return {
timemarkerOffset: 0,
movedBarsInDrag: new Set()
}
},
computed: {
timeUnit() {
return this.precision === 'month' ? 'days' : 'hours'
},
timeFormat() {
return this.precision === 'month' ? 'YYYY-MM-DD HH' : 'YYYY-MM-DD HH:mm'
},
timeCount() {
let momentChartStart = moment(this.chartStart)
let momentChartEnd = moment(this.chartEnd)
return Math.floor(
momentChartEnd.diff(momentChartStart, this.timeUnit, true)
)
}
},
methods: {
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
)
ganttBarChildren.push(...ganttBarChildrenOfRow)
})
return ganttBarChildren
},
getBarsFromBundle(bundleId) {
if (bundleId === undefined || bundleId === null) {
return []
}
return this.getGanttBarChildrenList().filter(
ganttBarChild => ganttBarChild.barConfig.bundle === bundleId
)
},
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
) {
ganttBarChild.initDrag(e)
this.movedBarsInDrag.add(ganttBarChild.bar)
}
})
}
},
moveBarsFromBundleOfPushedBar(pushedBar, minuteDiff, overlapType) {
this.movedBarsInDrag.add(pushedBar)
let bundleId = pushedBar[this.barConfigKey]
? pushedBar[this.barConfigKey].bundle
: null
if (bundleId === undefined || bundleId === null) {
return
}
this.getGanttBarChildrenList().forEach(ganttBarChild => {
if (
ganttBarChild.barConfig.bundle === bundleId &&
ganttBarChild.bar !== pushedBar
) {
ganttBarChild.moveBarByChildPointsAndPush(minuteDiff, overlapType)
this.movedBarsInDrag.add(ganttBarChild.bar)
}
})
},
shouldSnapBackBar(ganttBar) {
if (
this.snapBackOnOverlap &&
ganttBar.barConfig.pushOnOverlap !== false
) {
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({ event, type, time }, ganttBar) {
this.$emit(`${type}-bar`, { event, bar: ganttBar.bar, time })
},
onDragendBar(e, ganttBar, action) {
let didSnapBack = this.snapBackBundleIfNeeded(ganttBar)
let movedBars = didSnapBack ? new Set() : this.movedBarsInDrag
// Magnetic suction
if (movedBars.size && this.isMagnetic) {
let { left, right /*, move*/ } = action
movedBars.forEach(bar => {
if (this.precision === 'month') {
if (left && bar == ganttBar.bar) {
if (moment(bar[this.barStartKey]).hours() < 12) {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.hours(0)
.format()
} else {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.hours(24)
.format()
}
} else if (right && bar == ganttBar.bar) {
if (moment(bar[this.barEndKey]).hours() < 12) {
bar[this.barEndKey] = moment(bar[this.barEndKey])
.hours(0)
.format()
} else {
bar[this.barEndKey] = moment(bar[this.barEndKey])
.hours(24)
.format()
}
} else {
if (moment(bar[this.barStartKey]).hours() < 12) {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.hours(0)
.format()
bar[this.barEndKey] = moment(bar[this.barEndKey])
.hours(0)
.format()
} else {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.hours(24)
.format()
bar[this.barEndKey] = moment(bar[this.barEndKey])
.hours(24)
.format()
}
}
} else {
if (left && bar == ganttBar.bar) {
if (moment(bar[this.barStartKey]).minutes() < 30) {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.minutes(0)
.format()
} else {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.minutes(60)
.format()
}
} else if (right && bar == ganttBar.bar) {
if (moment(bar[this.barEndKey]).minutes() < 30) {
bar[this.barEndKey] = moment(bar[this.barEndKey])
.minutes(0)
.format()
} else {
bar[this.barEndKey] = moment(bar[this.barEndKey])
.minutes(60)
.format()
}
} else {
if (moment(bar[this.barStartKey]).minutes() < 30) {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.minutes(0)
.format()
bar[this.barEndKey] = moment(bar[this.barEndKey])
.minutes(0)
.format()
} else {
bar[this.barStartKey] = moment(bar[this.barStartKey])
.minutes(60)
.format()
bar[this.barEndKey] = moment(bar[this.barEndKey])
.minutes(60)
.format()
}
}
}
})
}
this.movedBarsInDrag = new Set()
this.$emit('dragend-bar', { event: e, bar: ganttBar.bar, movedBars })
},
// ------------------------------------------------------------------------
// -------- METHODS FOR SETTING THE DRAG LIMIT OF A BAR ----------------
// ------------------------------------------------------------------------
// 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) {
return
}
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)
) {
totalGapDistance = newGapDistance
}
newBundleBars.forEach(newBundleBar => {
if (
!bundleBarsOnPath.find(
barAndGap => barAndGap.bar === newBundleBar.bar
)
) {
bundleBarsOnPath.push(newBundleBar)
}
})
})
}
if (totalGapDistance != null && side === 'left') {
bar.dragLimitLeft = bar.$refs['g-bar'].offsetLeft - totalGapDistance
} else if (totalGapDistance != null && side === 'right') {
bar.dragLimitRight =
bar.$refs['g-bar'].offsetLeft +
bar.$refs['g-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
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 }]
: []
let currentBar = bar
let nextBar = this.getNextGanttBar(currentBar, side)
// left side:
if (side === 'left') {
while (nextBar) {
let nextBarOffsetRight =
nextBar.$refs['g-bar'].offsetLeft +
nextBar.$refs['g-bar'].offsetWidth
gapDistanceSoFar +=
currentBar.$refs['g-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
})
}
currentBar = nextBar
nextBar = this.getNextGanttBar(nextBar, 'left')
}
}
if (side === 'right') {
while (nextBar) {
let currentBarOffsetRight =
currentBar.$refs['g-bar'].offsetLeft +
currentBar.$refs['g-bar'].offsetWidth
gapDistanceSoFar +=
nextBar.$refs['g-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
})
}
currentBar = nextBar
nextBar = this.getNextGanttBar(nextBar, 'right')
}
}
return [null, bundleBarsAndGapDist]
},
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-bar'] &&
gBar.$refs['g-bar'].offsetLeft < bar.$refs['g-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-bar'] &&
gBar.$refs['g-bar'].offsetLeft > bar.$refs['g-bar'].offsetLeft &&
gBar.barConfig.pushOnOverlap !== false
)
})
}
if (allBarsLeftOrRight.length > 0) {
return allBarsLeftOrRight.reduce((bar1, bar2) => {
let bar1Dist = Math.abs(
bar1.$refs['g-bar'].offsetLeft - bar.$refs['g-bar'].offsetLeft
)
let bar2Dist = Math.abs(
bar2.$refs['g-bar'].offsetLeft - bar.$refs['g-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() {
return {
getTimeCount: () => this.timeCount,
getChartProps: () => this.$props,
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, action) =>
this.onDragendBar(e, ganttBar, action),
getTimeUnit: () => this.timeUnit,
getTimeFormat: () => this.timeFormat
}
}
}
</script>
+78 -78
View File
@@ -1,78 +1,78 @@
<template>
<div
class="g-gantt-grid"
:style="{ left: `${rowLabelWidth}px`, width: `${timeCount * gridSize}px` }"
>
<div
v-for="(childPoint, index) in allChildPoints"
:key="index"
:class="[
'g-gantt-grid__line',
{ 'g-gantt-grid-line-last': index === allChildPoints.length - 1 },
{ 'g-gantt-line-highlighted': isHighlighted(childPoint) }
]"
:style="{ width: `${gridSize}px` }"
/>
</div>
</template>
<script>
import moment from 'moment'
export default {
name: 'GGanttGrid',
props: {
chartStart: { type: String },
chartEnd: { type: String },
rowLabelWidth: { type: Number },
highlightedHours: { type: Array, default: () => [] },
highlightedDays: { type: Array, default: () => [] },
precision: { type: String },
timeCount: { type: Number },
gridSize: { type: Number }
},
computed: {
allChildPoints() {
const start = moment(this.chartStart)
const end = moment(this.chartEnd)
const res = []
while (start.isBefore(end)) {
switch (this.precision) {
case 'day':
res.push(start.format('YYYY-MM-DD H'))
start.add(1, 'hour')
break
case 'month':
res.push(start.format('YYYY-MM-DD'))
start.add(1, 'day').hour(23)
break
}
}
return res
}
},
methods: {
isHighlighted(point) {
switch (this.precision) {
case 'day':
if (
this.highlightedDays.includes(
moment(point, 'YYYY-MM-DD').format('YYYY-MM-DD')
)
) {
return true
} else {
return this.highlightedHours.includes(
moment(point, 'YYYY-MM-DD H').get('hour')
)
}
case 'month':
return this.highlightedDays.includes(point)
}
}
}
}
</script>
<template>
<div
class="g-gantt-grid"
:style="{ left: `${rowLabelWidth}px`, width: `${timeCount * gridSize}px` }"
>
<div
v-for="(childPoint, index) in allChildPoints"
:key="index"
:class="[
'g-gantt-grid__line',
{ 'g-gantt-grid-line-last': index === allChildPoints.length - 1 },
{ 'g-gantt-line-highlighted': isHighlighted(childPoint) }
]"
:style="{ width: `${gridSize}px` }"
/>
</div>
</template>
<script>
import moment from 'moment'
export default {
name: 'GGanttGrid',
props: {
chartStart: { type: String },
chartEnd: { type: String },
rowLabelWidth: { type: Number },
highlightedHours: { type: Array, default: () => [] },
highlightedDays: { type: Array, default: () => [] },
precision: { type: String },
timeCount: { type: Number },
gridSize: { type: Number }
},
computed: {
allChildPoints() {
const start = moment(this.chartStart)
const end = moment(this.chartEnd)
const res = []
while (start.isBefore(end)) {
switch (this.precision) {
case 'day':
res.push(start.format('YYYY-MM-DD H'))
start.add(1, 'hour')
break
case 'month':
res.push(start.format('YYYY-MM-DD'))
start.add(1, 'day').hour(23)
break
}
}
return res
}
},
methods: {
isHighlighted(point) {
switch (this.precision) {
case 'day':
if (
this.highlightedDays.includes(
moment(point, 'YYYY-MM-DD').format('YYYY-MM-DD')
)
) {
return true
} else {
return this.highlightedHours.includes(
moment(point, 'YYYY-MM-DD H').get('hour')
)
}
case 'month':
return this.highlightedDays.includes(point)
}
}
}
}
</script>
+203 -203
View File
@@ -1,203 +1,203 @@
<template>
<div
ref="g-row"
class="g-gantt-row"
:style="{ height: `${chartProps.rowHeight}px` }"
v-on="$listeners"
>
<div class="g-gantt-row__label" :style="rowLabelStyle">
<span :title="label">
<slot name="label">{{ label }}</slot>
</span>
</div>
<div
class="g-gantt-row__bars-container"
ref="barContainer"
:style="rowStyle"
@dragover="onDragover($event)"
@dragleave="onDragleave($event)"
@drop="onDrop($event)"
@dblclick.self="onDoubleClick($event)"
@mouseover="onMouseover()"
@mouseleave="onMouseleave()"
>
<g-gantt-bar
v-for="(bar, index) in localBars"
:key="`ganttastic_bar_${index}`"
ref="ganttBar"
:bar="bar"
:bar-container="barContainer"
:all-bars-in-row="localBars"
>
<template #bar-label="{ bar }">
<slot name="bar-label" :bar="bar" />
</template>
</g-gantt-bar>
</div>
</div>
</template>
<script>
import GGanttBar from './GGanttBar.vue'
import moment from 'moment'
export default {
name: 'GGanttRow',
components: {
GGanttBar
},
props: {
label: { type: String, default: 'Row' },
labelStyle: { type: Object },
rowStyle: { type: Object },
bars: { type: Array, default: () => [] },
highlightOnHover: { type: Boolean }
},
inject: ['getChartProps', 'getTimeCount', 'getTimeUnit', 'getTimeFormat'],
data() {
return {
barContainer: {},
localBars: this.bars
}
},
computed: {
defaultBarLength() {
return this.chartProps.defaultBarLength
},
chartProps() {
return this.getChartProps()
},
chartStart() {
return this.chartProps.chartStart
},
barConfigKey() {
return this.chartProps.barConfigKey
},
timeUnit() {
return this.getTimeUnit()
},
timeFormat() {
return this.getTimeFormat()
},
timeCount() {
return this.getTimeCount()
},
rowLabelStyle() {
return {
width: `${this.chartProps.rowLabelWidth}px`,
...this.labelStyle
}
}
},
watch: {
'chartProps.chartStart'() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
},
'chartProps.chartEnd'() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
},
'chartProps.rowLabelWidth'() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
},
'chartProps.gridSize'() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
},
bars(value) {
this.localBars = value
}
},
mounted() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
window.addEventListener('resize', this.onWindowResize)
},
destroyed() {
window.removeEventListener('resize', this.onWindowResize)
},
methods: {
onDragover(e) {
e.preventDefault() // enables dropping content on row
if (this.highlightOnHover) {
this.$refs['g-row'].classList.add('g-gantt-row-highlighted')
}
},
onDragleave() {
this.$refs['g-row'].classList.remove('g-gantt-row-highlighted')
},
onDrop(e) {
const barContainer = this.$refs.barContainer.getBoundingClientRect()
const xPos = e.clientX - barContainer.left
const timeDiffFromStart = (xPos / barContainer.width) * this.timeCount
const time = moment(this.chartStart).add(timeDiffFromStart, this.timeUnit)
const bar = this.localBars.find(bar =>
time.isBetween(
bar[this.chartProps.barStartKey],
bar[this.chartProps.barEndKey]
)
)
this.$emit('drop', { event: e, bar, time: time.format(this.timeFormat) })
},
onDoubleClick(e) {
if (!this.chartProps.allowAdd) return
let barContainer = this.$refs.barContainer.getBoundingClientRect()
let xPos = e.clientX - barContainer.left
let timeDiffFromStart = Math.floor(
(xPos / barContainer.width) * this.timeCount
)
let time = moment(this.chartStart).add(timeDiffFromStart, this.timeUnit)
let bar = {}
bar[this.chartProps.barStartKey] = time.format()
bar[this.chartProps.barEndKey] = time
.add(this.defaultBarLength, this.timeUnit)
.format()
bar[this.barConfigKey] = { handles: true }
this.localBars.push(bar)
this.localBars.sort((first, second) =>
moment(first[this.chartProps.barStartKey]).diff(
second[this.chartProps.barStartKey]
)
)
},
onMouseover() {
if (this.highlightOnHover) {
this.$refs['g-row'].classList.add('g-gantt-row-highlighted')
}
},
onMouseleave() {
this.$refs['g-row'].classList.remove('g-gantt-row-highlighted')
},
onWindowResize() {
// re-initialize the barContainer DOMRect variable, which will trigger re-rendering in the gantt bars
if (this.$refs.barContainer) {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
}
}
}
}
</script>
<template>
<div
ref="g-row"
class="g-gantt-row"
:style="{ height: `${chartProps.rowHeight}px` }"
v-on="$listeners"
>
<div class="g-gantt-row__label" :style="rowLabelStyle">
<span :title="label">
<slot name="label">{{ label }}</slot>
</span>
</div>
<div
class="g-gantt-row__bars-container"
ref="barContainer"
:style="rowStyle"
@dragover="onDragover($event)"
@dragleave="onDragleave($event)"
@drop="onDrop($event)"
@dblclick.self="onDoubleClick($event)"
@mouseover="onMouseover()"
@mouseleave="onMouseleave()"
>
<g-gantt-bar
v-for="(bar, index) in localBars"
:key="`ganttastic_bar_${index}`"
ref="ganttBar"
:bar="bar"
:bar-container="barContainer"
:all-bars-in-row="localBars"
>
<template #bar-label="{ bar }">
<slot name="bar-label" :bar="bar" />
</template>
</g-gantt-bar>
</div>
</div>
</template>
<script>
import GGanttBar from './GGanttBar.vue'
import moment from 'moment'
export default {
name: 'GGanttRow',
components: {
GGanttBar
},
props: {
label: { type: String, default: 'Row' },
labelStyle: { type: Object },
rowStyle: { type: Object },
bars: { type: Array, default: () => [] },
highlightOnHover: { type: Boolean }
},
inject: ['getChartProps', 'getTimeCount', 'getTimeUnit', 'getTimeFormat'],
data() {
return {
barContainer: {},
localBars: this.bars
}
},
computed: {
defaultBarLength() {
return this.chartProps.defaultBarLength
},
chartProps() {
return this.getChartProps()
},
chartStart() {
return this.chartProps.chartStart
},
barConfigKey() {
return this.chartProps.barConfigKey
},
timeUnit() {
return this.getTimeUnit()
},
timeFormat() {
return this.getTimeFormat()
},
timeCount() {
return this.getTimeCount()
},
rowLabelStyle() {
return {
width: `${this.chartProps.rowLabelWidth}px`,
...this.labelStyle
}
}
},
watch: {
'chartProps.chartStart'() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
},
'chartProps.chartEnd'() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
},
'chartProps.rowLabelWidth'() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
},
'chartProps.gridSize'() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
},
bars(value) {
this.localBars = value
}
},
mounted() {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
window.addEventListener('resize', this.onWindowResize)
},
destroyed() {
window.removeEventListener('resize', this.onWindowResize)
},
methods: {
onDragover(e) {
e.preventDefault() // enables dropping content on row
if (this.highlightOnHover) {
this.$refs['g-row'].classList.add('g-gantt-row-highlighted')
}
},
onDragleave() {
this.$refs['g-row'].classList.remove('g-gantt-row-highlighted')
},
onDrop(e) {
const barContainer = this.$refs.barContainer.getBoundingClientRect()
const xPos = e.clientX - barContainer.left
const timeDiffFromStart = (xPos / barContainer.width) * this.timeCount
const time = moment(this.chartStart).add(timeDiffFromStart, this.timeUnit)
const bar = this.localBars.find(bar =>
time.isBetween(
bar[this.chartProps.barStartKey],
bar[this.chartProps.barEndKey]
)
)
this.$emit('drop', { event: e, bar, time: time.format(this.timeFormat) })
},
onDoubleClick(e) {
if (!this.chartProps.allowAdd) return
let barContainer = this.$refs.barContainer.getBoundingClientRect()
let xPos = e.clientX - barContainer.left
let timeDiffFromStart = Math.floor(
(xPos / barContainer.width) * this.timeCount
)
let time = moment(this.chartStart).add(timeDiffFromStart, this.timeUnit)
let bar = {}
bar[this.chartProps.barStartKey] = time.format()
bar[this.chartProps.barEndKey] = time
.add(this.defaultBarLength, this.timeUnit)
.format()
bar[this.barConfigKey] = { handles: true }
this.localBars.push(bar)
this.localBars.sort((first, second) =>
moment(first[this.chartProps.barStartKey]).diff(
second[this.chartProps.barStartKey]
)
)
},
onMouseover() {
if (this.highlightOnHover) {
this.$refs['g-row'].classList.add('g-gantt-row-highlighted')
}
},
onMouseleave() {
this.$refs['g-row'].classList.remove('g-gantt-row-highlighted')
},
onWindowResize() {
// re-initialize the barContainer DOMRect variable, which will trigger re-rendering in the gantt bars
if (this.$refs.barContainer) {
this.barContainer = this.$refs.barContainer.getBoundingClientRect()
}
}
}
}
</script>
+224 -224
View File
@@ -1,224 +1,224 @@
<template>
<div
ref="g-timeaxis"
class="g-gantt-timeaxis"
:style="{ width: `${timeCount * gridSize + rowLabelWidth}px` }"
>
<div
class="g-gantt-timeaxis__empty-space"
:style="{
minWidth: `${rowLabelWidth}px`
}"
/>
<div class="g-gantt-timeaxis__days">
<div
v-for="point in axisPoints"
:key="point.text"
class="g-gantt-timeaxis__day"
>
<div v-html="pointFormatted(point) || '&nbsp;'"></div>
<div class="g-gantt-timeaxis__hours">
<div
v-for="childPoint in point.childPoints"
:key="childPoint.fullDatetime"
class="g-gantt-timeaxis__hour"
:style="{ width: `${gridSize}px` }"
>
<span :style="{ fontSize: hourFontSize }">{{
childPoint.text
}}</span>
<div class="g-gantt-timeaxis__hour-pin" />
</div>
</div>
</div>
</div>
<div ref="g-timeaxis-marker" class="g-gantt-timeaxis__marker" />
</div>
</template>
<script>
import moment from 'moment'
export default {
name: 'GGanttTimeaxis',
props: {
chartStart: { type: String },
chartEnd: { type: String },
rowLabelWidth: { type: Number },
timemarkerOffset: { type: Number, default: 0 },
locale: { type: String },
precision: { type: String },
timeFormat: { type: String },
timeCount: { type: Number },
gridSize: { type: Number },
dayFormat: { type: String },
monthFormat: { type: String }
},
data() {
return {
axisPoints: [],
timemarker: null,
hourFontSize: '11px'
}
},
watch: {
chartStart() {
this.initAxis()
},
chartEnd() {
this.initAxis()
},
gridSize() {
this.onWindowResize()
}
},
mounted() {
this.timemarker = this.$refs['g-timeaxis-marker']
this.initAxis()
this.onWindowResize()
window.addEventListener('resize', this.onWindowResize)
window.addEventListener('mousemove', this.moveTimemarker)
window.addEventListener('dragover', this.moveTimemarker)
},
destroyed() {
window.removeEventListener('resize', this.onWindowResize)
window.removeEventListener('mousemove', this.moveTimemarker)
window.removeEventListener('dragover', this.moveTimemarker)
},
methods: {
initAxis() {
this.precision === 'day'
? this.initAxisDaysAndHours()
: this.initAxisMonthsAndDays()
},
initAxisMonthsAndDays() {
let start = moment(this.chartStart)
let end = moment(this.chartEnd)
this.axisPoints = []
while (start.isBefore(end)) {
let dayCountOfMonth = start.isSame(end, 'month')
? end.date() - 1
: start.daysInMonth() - start.date() + 1
let widthPercentage = (dayCountOfMonth / this.timeCount) * 100
let endDay = start.isSame(end, 'month')
? end.date() - 1
: start.daysInMonth()
this.axisPoints.push(
this.getAxisMonthObject(start, widthPercentage, endDay)
)
start.add(1, 'month').date(1).hour(0)
}
},
initAxisDaysAndHours() {
let start = moment(this.chartStart)
let end = moment(this.chartEnd)
this.axisPoints = []
while (start.isBefore(end)) {
let hourCountOfDay = start.isSame(end, 'day')
? end.hour()
: 24 - start.hour()
let widthPercentage = (hourCountOfDay / this.timeCount) * 100
let endHour = start.isSame(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
this.axisPoints.push(
this.getAxisDayObject(start, widthPercentage, endHour)
)
start.add(1, 'day').hour(0)
}
},
getAxisMonthObject(datetime, widthPercentage, endDay) {
let datetimeMoment = moment(datetime)
let axisMonthObject = {
widthPercentage: widthPercentage,
value: moment(datetime, 'YYYY-MM'),
childPoints: []
}
let startDay = datetimeMoment.date()
for (let i = 0; i <= endDay - startDay; i++) {
let day = {
text: datetimeMoment.format('D'),
fullDatetime: datetimeMoment.format(this.timeFormat)
}
axisMonthObject.childPoints.push(day)
datetimeMoment.add(1, 'day')
}
return axisMonthObject
},
getAxisDayObject(datetime, widthPercentage, endHour) {
let datetimeMoment = moment(datetime)
let axisDayObject = {
widthPercentage: widthPercentage,
value: moment(datetime, 'YYYY-MM-DD'), // ISO 8601
childPoints: []
}
let startHour = datetimeMoment.hour()
for (let i = 0; i <= endHour - startHour; i++) {
let hour = {
text: datetimeMoment.format('HH'),
fullDatetime: datetimeMoment.format(this.timeFormat)
}
axisDayObject.childPoints.push(hour)
datetimeMoment.add(1, 'hour')
}
return axisDayObject
},
moveTimemarker(event) {
const chart = this.timemarker.closest('.g-gantt-chart')
if (!chart) return
let pos =
chart.scrollLeft +
event.clientX -
this.timemarkerOffset -
this.horizontalAxisContainer.left
if (pos > this.horizontalAxisContainer.width)
pos = this.horizontalAxisContainer.width
this.timemarker.style.left = `${pos}px`
},
onWindowResize() {
if (!this.$refs['g-timeaxis']) return
this.horizontalAxisContainer =
this.$refs['g-timeaxis'].getBoundingClientRect()
this.hourFontSize =
Math.min(
9.5,
0.75 * (this.horizontalAxisContainer.width / this.timeCount)
) + 'px'
},
pointFormatted(point) {
switch (this.precision) {
case 'day':
return this.dayFormatted(point)
case 'month':
return this.monthFormatted(point)
}
},
monthFormatted(point) {
// do not display month text if the month is smaller than x%
return point.widthPercentage >= (3 / 32) * 100
? moment(point.value).locale(this.locale).format(this.monthFormat)
: ''
},
dayFormatted(point) {
// do not display day text if the day is smaller than 12%
// return point.widthPercentage >= 12
// ? moment(point.value).locale(this.locale).format(this.dayFormat)
// : ''
return moment(point.value).locale(this.locale).format(this.dayFormat)
}
}
}
</script>
<template>
<div
ref="g-timeaxis"
class="g-gantt-timeaxis"
:style="{ width: `${timeCount * gridSize + rowLabelWidth}px` }"
>
<div
class="g-gantt-timeaxis__empty-space"
:style="{
minWidth: `${rowLabelWidth}px`
}"
/>
<div class="g-gantt-timeaxis__days">
<div
v-for="point in axisPoints"
:key="point.text"
class="g-gantt-timeaxis__day"
>
<div v-html="pointFormatted(point) || '&nbsp;'"></div>
<div class="g-gantt-timeaxis__hours">
<div
v-for="childPoint in point.childPoints"
:key="childPoint.fullDatetime"
class="g-gantt-timeaxis__hour"
:style="{ width: `${gridSize}px` }"
>
<span :style="{ fontSize: hourFontSize }">{{
childPoint.text
}}</span>
<div class="g-gantt-timeaxis__hour-pin" />
</div>
</div>
</div>
</div>
<div ref="g-timeaxis-marker" class="g-gantt-timeaxis__marker" />
</div>
</template>
<script>
import moment from 'moment'
export default {
name: 'GGanttTimeaxis',
props: {
chartStart: { type: String },
chartEnd: { type: String },
rowLabelWidth: { type: Number },
timemarkerOffset: { type: Number, default: 0 },
locale: { type: String },
precision: { type: String },
timeFormat: { type: String },
timeCount: { type: Number },
gridSize: { type: Number },
dayFormat: { type: String },
monthFormat: { type: String }
},
data() {
return {
axisPoints: [],
timemarker: null,
hourFontSize: '11px'
}
},
watch: {
chartStart() {
this.initAxis()
},
chartEnd() {
this.initAxis()
},
gridSize() {
this.onWindowResize()
}
},
mounted() {
this.timemarker = this.$refs['g-timeaxis-marker']
this.initAxis()
this.onWindowResize()
window.addEventListener('resize', this.onWindowResize)
window.addEventListener('mousemove', this.moveTimemarker)
window.addEventListener('dragover', this.moveTimemarker)
},
destroyed() {
window.removeEventListener('resize', this.onWindowResize)
window.removeEventListener('mousemove', this.moveTimemarker)
window.removeEventListener('dragover', this.moveTimemarker)
},
methods: {
initAxis() {
this.precision === 'day'
? this.initAxisDaysAndHours()
: this.initAxisMonthsAndDays()
},
initAxisMonthsAndDays() {
let start = moment(this.chartStart)
let end = moment(this.chartEnd)
this.axisPoints = []
while (start.isBefore(end)) {
let dayCountOfMonth = start.isSame(end, 'month')
? end.date() - 1
: start.daysInMonth() - start.date() + 1
let widthPercentage = (dayCountOfMonth / this.timeCount) * 100
let endDay = start.isSame(end, 'month')
? end.date() - 1
: start.daysInMonth()
this.axisPoints.push(
this.getAxisMonthObject(start, widthPercentage, endDay)
)
start.add(1, 'month').date(1).hour(0)
}
},
initAxisDaysAndHours() {
let start = moment(this.chartStart)
let end = moment(this.chartEnd)
this.axisPoints = []
while (start.isBefore(end)) {
let hourCountOfDay = start.isSame(end, 'day')
? end.hour()
: 24 - start.hour()
let widthPercentage = (hourCountOfDay / this.timeCount) * 100
let endHour = start.isSame(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
this.axisPoints.push(
this.getAxisDayObject(start, widthPercentage, endHour)
)
start.add(1, 'day').hour(0)
}
},
getAxisMonthObject(datetime, widthPercentage, endDay) {
let datetimeMoment = moment(datetime)
let axisMonthObject = {
widthPercentage: widthPercentage,
value: moment(datetime, 'YYYY-MM'),
childPoints: []
}
let startDay = datetimeMoment.date()
for (let i = 0; i <= endDay - startDay; i++) {
let day = {
text: datetimeMoment.format('D'),
fullDatetime: datetimeMoment.format(this.timeFormat)
}
axisMonthObject.childPoints.push(day)
datetimeMoment.add(1, 'day')
}
return axisMonthObject
},
getAxisDayObject(datetime, widthPercentage, endHour) {
let datetimeMoment = moment(datetime)
let axisDayObject = {
widthPercentage: widthPercentage,
value: moment(datetime, 'YYYY-MM-DD'), // ISO 8601
childPoints: []
}
let startHour = datetimeMoment.hour()
for (let i = 0; i <= endHour - startHour; i++) {
let hour = {
text: datetimeMoment.format('HH'),
fullDatetime: datetimeMoment.format(this.timeFormat)
}
axisDayObject.childPoints.push(hour)
datetimeMoment.add(1, 'hour')
}
return axisDayObject
},
moveTimemarker(event) {
const chart = this.timemarker.closest('.g-gantt-chart')
if (!chart) return
let pos =
chart.scrollLeft +
event.clientX -
this.timemarkerOffset -
this.horizontalAxisContainer.left
if (pos > this.horizontalAxisContainer.width)
pos = this.horizontalAxisContainer.width
this.timemarker.style.left = `${pos}px`
},
onWindowResize() {
if (!this.$refs['g-timeaxis']) return
this.horizontalAxisContainer =
this.$refs['g-timeaxis'].getBoundingClientRect()
this.hourFontSize =
Math.min(
9.5,
0.75 * (this.horizontalAxisContainer.width / this.timeCount)
) + 'px'
},
pointFormatted(point) {
switch (this.precision) {
case 'day':
return this.dayFormatted(point)
case 'month':
return this.monthFormatted(point)
}
},
monthFormatted(point) {
// do not display month text if the month is smaller than x%
return point.widthPercentage >= (3 / 32) * 100
? moment(point.value).locale(this.locale).format(this.monthFormat)
: ''
},
dayFormatted(point) {
// do not display day text if the day is smaller than 12%
// return point.widthPercentage >= 12
// ? moment(point.value).locale(this.locale).format(this.dayFormat)
// : ''
return moment(point.value).locale(this.locale).format(this.dayFormat)
}
}
}
</script>
+19 -19
View File
@@ -1,19 +1,19 @@
import GGanttChart from './components/GGanttChart.vue'
import GGanttRow from './components/GGanttRow.vue'
import './scss/index.scss'
const VueGanttastic = { GGanttChart, GGanttRow }
const install = Vue => {
Object.keys(VueGanttastic).forEach(name => {
Vue.component(name, VueGanttastic[name])
})
}
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default VueGanttastic
export { GGanttChart, GGanttRow }
import GGanttChart from './components/GGanttChart.vue'
import GGanttRow from './components/GGanttRow.vue'
import './scss/index.scss'
const VueGanttastic = { GGanttChart, GGanttRow }
const install = Vue => {
Object.keys(VueGanttastic).forEach(name => {
Vue.component(name, VueGanttastic[name])
})
}
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default VueGanttastic
export { GGanttChart, GGanttRow }
+273 -273
View File
@@ -1,273 +1,273 @@
.g-gantt-chart {
position: relative;
overflow: auto;
-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: 34px;
border: 1px solid $border-color;
box-sizing: border-box;
background: $background;
flex: 1;
& >>> * {
font-family: Roboto, Verdana;
}
}
.g-gantt-timeaxis,
.g-gantt-timeaxis__days,
.g-gantt-timeaxis__day,
.g-gantt-timeaxis__day > div {
display: flex;
}
.g-gantt-timeaxis {
position: sticky;
top: 0;
background: $timeaxis-background;
z-index: 4;
box-shadow: 0px 1px 3px 2px rgba(50, 50, 50, 0.5);
}
.g-gantt-timeaxis__empty-space {
min-height: 100%;
background: $secondary;
z-index: 5;
left: 0;
position: sticky;
}
.g-gantt-timeaxis__days {
position: relative;
height: 100%;
}
.g-gantt-timeaxis__day {
height: 100%;
flex-direction: column;
color: $text;
&:nth-child(even) {
background: $secondary;
}
&:nth-child(odd) {
background: $primary;
}
& > div:nth-child(1) {
/* day text */
justify-content: space-around;
font-weight: bold;
align-items: center;
}
}
.g-gantt-timeaxis__days {
align-items: flex-end;
justify-content: space-between;
background: $ternary;
color: $text;
}
.g-gantt-timeaxis__hour {
display: flex;
justify-content: space-between;
align-items: flex-start;
flex-direction: column;
opacity: 0.5;
color: $text;
&:nth-child(even) {
background: $secondary;
}
&:nth-child(odd) {
background: $primary;
}
}
.g-gantt-timeaxis__hour-pin {
width: 1px;
height: 5px;
background: $text;
}
.g-gantt-timeaxis__marker {
position: absolute;
left: 0;
bottom: 0;
height: 5px;
width: 3px;
background: $marker-background;
}
.g-gantt-rows-container {
position: relative;
}
.g-gantt-grid {
position: absolute;
top: 0;
bottom: 0;
overflow: hidden;
}
.g-gantt-grid__line {
height: 100%;
border: 1px solid transparent;
border-left: 1px solid $border-color;
box-sizing: border-box;
display: inline-block;
}
.g-gantt-grid-line-last {
border-right: 1px solid $border-color;
}
.g-gantt-grid-line-highlighted {
background: $highlighted;
}
.g-gantt-row {
display: flex;
width: 100%;
height: 40px;
transition: background-color 0.2s;
position: relative;
}
.g-gantt-row-highlighted {
background-color: $hover-highlight;
}
.g-gantt-row__label {
display: flex;
align-items: center;
background: $ternary;
color: $text;
font-size: 0.9em;
z-index: 3;
font-weight: bold;
left: 0;
position: sticky;
padding: 0 10px;
box-sizing: border-box;
border-top: 1px solid $row-label-border-color;
border-bottom: 1px solid $row-label-border-color;
& > * {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.g-gantt-row__bars-container {
position: relative;
border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color;
flex: 1;
}
.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;
cursor: move;
}
.g-gantt-bar-immobile {
cursor: unset;
}
.g-gantt-bar__label {
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 0 4px 0 4px;
display: flex;
justify-content: center;
align-items: center;
img {
pointer-events: none;
}
& > * {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.g-gantt-bar-resizable .g-gantt-bar__label {
padding: 0 14px 0 14px; /* 14px is the width of the handle */
}
.g-gantt-bar__handle-left,
.g-gantt-bar__handle-right {
position: absolute;
width: 10px;
height: 100%;
background: white;
opacity: 0.7;
border-radius: 40px;
}
.g-gantt-bar__handle-left {
left: 0;
cursor: w-resize;
}
.g-gantt-bar__handle-right {
right: 0;
cursor: e-resize;
}
.g-gantt-bar__tooltip {
position: absolute;
background: $tooltip-background;
color: $tooltip-color;
z-index: 3;
font-size: 0.7em;
padding: 3px;
border-radius: 3px;
transition: opacity 0.2s;
display: flex;
align-items: center;
&:before {
content: '';
position: absolute;
top: 0;
left: 10%;
width: 0;
height: 0;
border: 10px solid transparent;
border-bottom-color: $tooltip-background;
border-top: 0;
margin-left: -5px;
margin-top: -5px;
}
& > .color-indicator {
width: 8px;
height: 8px;
border-radius: 100%;
margin-right: 4px;
}
}
.g-gantt-chart {
position: relative;
overflow: auto;
-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: 34px;
border: 1px solid $border-color;
box-sizing: border-box;
background: $background;
flex: 1;
& >>> * {
font-family: Roboto, Verdana;
}
}
.g-gantt-timeaxis,
.g-gantt-timeaxis__days,
.g-gantt-timeaxis__day,
.g-gantt-timeaxis__day > div {
display: flex;
}
.g-gantt-timeaxis {
position: sticky;
top: 0;
background: $timeaxis-background;
z-index: 4;
box-shadow: 0px 1px 3px 2px rgba(50, 50, 50, 0.5);
}
.g-gantt-timeaxis__empty-space {
min-height: 100%;
background: $secondary;
z-index: 5;
left: 0;
position: sticky;
}
.g-gantt-timeaxis__days {
position: relative;
height: 100%;
}
.g-gantt-timeaxis__day {
height: 100%;
flex-direction: column;
color: $text;
&:nth-child(even) {
background: $secondary;
}
&:nth-child(odd) {
background: $primary;
}
& > div:nth-child(1) {
/* day text */
justify-content: space-around;
font-weight: bold;
align-items: center;
}
}
.g-gantt-timeaxis__days {
align-items: flex-end;
justify-content: space-between;
background: $ternary;
color: $text;
}
.g-gantt-timeaxis__hour {
display: flex;
justify-content: space-between;
align-items: flex-start;
flex-direction: column;
opacity: 0.5;
color: $text;
&:nth-child(even) {
background: $secondary;
}
&:nth-child(odd) {
background: $primary;
}
}
.g-gantt-timeaxis__hour-pin {
width: 1px;
height: 5px;
background: $text;
}
.g-gantt-timeaxis__marker {
position: absolute;
left: 0;
bottom: 0;
height: 5px;
width: 3px;
background: $marker-background;
}
.g-gantt-rows-container {
position: relative;
}
.g-gantt-grid {
position: absolute;
top: 0;
bottom: 0;
overflow: hidden;
}
.g-gantt-grid__line {
height: 100%;
border: 1px solid transparent;
border-left: 1px solid $border-color;
box-sizing: border-box;
display: inline-block;
}
.g-gantt-grid-line-last {
border-right: 1px solid $border-color;
}
.g-gantt-grid-line-highlighted {
background: $highlighted;
}
.g-gantt-row {
display: flex;
width: 100%;
height: 40px;
transition: background-color 0.2s;
position: relative;
}
.g-gantt-row-highlighted {
background-color: $hover-highlight;
}
.g-gantt-row__label {
display: flex;
align-items: center;
background: $ternary;
color: $text;
font-size: 0.9em;
z-index: 3;
font-weight: bold;
left: 0;
position: sticky;
padding: 0 10px;
box-sizing: border-box;
border-top: 1px solid $row-label-border-color;
border-bottom: 1px solid $row-label-border-color;
& > * {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.g-gantt-row__bars-container {
position: relative;
border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color;
flex: 1;
}
.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;
cursor: move;
}
.g-gantt-bar-immobile {
cursor: unset;
}
.g-gantt-bar__label {
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 0 4px 0 4px;
display: flex;
justify-content: center;
align-items: center;
img {
pointer-events: none;
}
& > * {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.g-gantt-bar-resizable .g-gantt-bar__label {
padding: 0 14px 0 14px; /* 14px is the width of the handle */
}
.g-gantt-bar__handle-left,
.g-gantt-bar__handle-right {
position: absolute;
width: 10px;
height: 100%;
background: white;
opacity: 0.7;
border-radius: 40px;
}
.g-gantt-bar__handle-left {
left: 0;
cursor: w-resize;
}
.g-gantt-bar__handle-right {
right: 0;
cursor: e-resize;
}
.g-gantt-bar__tooltip {
position: absolute;
background: $tooltip-background;
color: $tooltip-color;
z-index: 3;
font-size: 0.7em;
padding: 3px;
border-radius: 3px;
transition: opacity 0.2s;
display: flex;
align-items: center;
&:before {
content: '';
position: absolute;
top: 0;
left: 10%;
width: 0;
height: 0;
border: 10px solid transparent;
border-bottom-color: $tooltip-background;
border-top: 0;
margin-left: -5px;
margin-top: -5px;
}
& > .color-indicator {
width: 8px;
height: 8px;
border-radius: 100%;
margin-right: 4px;
}
}
+13 -13
View File
@@ -1,13 +1,13 @@
$primary: #eee !default;
$secondary: #e0e0e0 !default;
$ternary: #f5f5f5 !default;
$hover-highlight: rgba(204, 216, 219, 0.5) !default;
$text: #404040 !default;
$background: #fff !default;
$highlighted: #dcefff !default;
$border-color: #eaeaea !default;
$timeaxis-background: #fff !default;
$marker-background: #000 !default;
$row-label-border-color: $border-color !default;
$tooltip-background: #000;
$tooltip-color: #fff;
$primary: #eee !default;
$secondary: #e0e0e0 !default;
$ternary: #f5f5f5 !default;
$hover-highlight: rgba(204, 216, 219, 0.5) !default;
$text: #404040 !default;
$background: #fff !default;
$highlighted: #dcefff !default;
$border-color: #eaeaea !default;
$timeaxis-background: #fff !default;
$marker-background: #000 !default;
$row-label-border-color: $border-color !default;
$tooltip-background: #000;
$tooltip-color: #fff;
+36 -36
View File
@@ -1,36 +1,36 @@
@use "sass:meta";
// default
@import './variables';
@import './ganttastic';
[data-theme] {
display: flex;
flex-direction: column;
}
$themes: 'creamy', 'crimson', 'dark', 'flare', 'fuchsia', 'grove',
'material-blue', 'sky', 'slumber', 'vue';
@each $theme in $themes {
[data-theme='#{$theme}'] {
@include meta.load-css('./themes/#{$theme}');
}
}
.fade-enter-active {
animation: fade-in 0.3s;
}
.fade-leave-active {
animation: fade-in 0.3s reverse;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@use "sass:meta";
// default
@import './variables';
@import './ganttastic';
[data-theme] {
display: flex;
flex-direction: column;
}
$themes: 'creamy', 'crimson', 'dark', 'flare', 'fuchsia', 'grove',
'material-blue', 'sky', 'slumber', 'vue';
@each $theme in $themes {
[data-theme='#{$theme}'] {
@include meta.load-css('./themes/#{$theme}');
}
}
.fade-enter-active {
animation: fade-in 0.3s;
}
.fade-leave-active {
animation: fade-in 0.3s reverse;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
+7 -7
View File
@@ -1,7 +1,7 @@
$primary: #ffe8d9;
$secondary: #fcdcc5;
$ternary: #fff6f0;
$hover-highlight: rgba(230, 221, 202, 0.5);
$text: #542d05;
$background: #fff;
$row-label-border-color: #f7efe9;
$primary: #ffe8d9;
$secondary: #fcdcc5;
$ternary: #fff6f0;
$hover-highlight: rgba(230, 221, 202, 0.5);
$text: #542d05;
$background: #fff;
$row-label-border-color: #f7efe9;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
+7 -7
View File
@@ -1,7 +1,7 @@
$primary: #a82039;
$secondary: #c41238;
$ternary: #db4f56;
$hover-highlight: rgba(196, 141, 141, 0.5);
$text: white;
$background: white;
$row-label-border-color: #e6535a;
$primary: #a82039;
$secondary: #c41238;
$ternary: #db4f56;
$hover-highlight: rgba(196, 141, 141, 0.5);
$text: white;
$background: white;
$row-label-border-color: #e6535a;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
+10 -10
View File
@@ -1,10 +1,10 @@
$primary: #404040;
$secondary: #303030;
$ternary: #353535;
$hover-highlight: rgba(159, 160, 161, 0.5);
$text: #adb5bd;
$background: #525252;
$highlighted: #7e7e7e;
$border-color: #444444;
$marker-background: #666666;
$row-label-border-color: $border-color;
$primary: #404040;
$secondary: #303030;
$ternary: #353535;
$hover-highlight: rgba(159, 160, 161, 0.5);
$text: #adb5bd;
$background: #525252;
$highlighted: #7e7e7e;
$border-color: #444444;
$marker-background: #666666;
$row-label-border-color: $border-color;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
+7 -7
View File
@@ -1,7 +1,7 @@
$primary: #e08a38;
$secondary: #e67912;
$ternary: #5e5145;
$hover-highlight: rgba(196, 141, 141, 0.5);
$text: #fff;
$background: #fff;
$row-label-border-color: #6b5c4e;
$primary: #e08a38;
$secondary: #e67912;
$ternary: #5e5145;
$hover-highlight: rgba(196, 141, 141, 0.5);
$text: #fff;
$background: #fff;
$row-label-border-color: #6b5c4e;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
+9 -9
View File
@@ -1,9 +1,9 @@
$primary: #de1d5a;
$secondary: #b50b41;
$ternary: #ff7da6;
$hover-highlight: rgba(196, 141, 141, 0.5);
$text: #fff;
$background: #fff;
$row-label-border-color: #f2779e;
$tooltip-background: $primary;
$tooltip-color: #fff;
$primary: #de1d5a;
$secondary: #b50b41;
$ternary: #ff7da6;
$hover-highlight: rgba(196, 141, 141, 0.5);
$text: #fff;
$background: #fff;
$row-label-border-color: #f2779e;
$tooltip-background: $primary;
$tooltip-color: #fff;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
+7 -7
View File
@@ -1,7 +1,7 @@
$primary: #3d9960;
$secondary: #288542;
$ternary: #72b585;
$hover-highlight: rgba(160, 219, 171, 0.5);
$text: white;
$background: white;
$row-label-border-color: #73bd88;
$primary: #3d9960;
$secondary: #288542;
$ternary: #72b585;
$hover-highlight: rgba(160, 219, 171, 0.5);
$text: white;
$background: white;
$row-label-border-color: #73bd88;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@@ -1,7 +1,7 @@
$primary: #0d47a1;
$secondary: #1565c0;
$ternary: #42a5f5;
$hover-highlight: rgba(110, 165, 196, 0.5);
$text: white;
$background: white;
$row-label-border-color: #45abff;
$primary: #0d47a1;
$secondary: #1565c0;
$ternary: #42a5f5;
$hover-highlight: rgba(110, 165, 196, 0.5);
$text: white;
$background: white;
$row-label-border-color: #45abff;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
+7 -7
View File
@@ -1,7 +1,7 @@
$primary: #b5e3ff;
$secondary: #a1d6f7;
$ternary: #d6f7ff;
$hover-highlight: rgba(193, 202, 214, 0.5);
$text: #022c47;
$background: white;
$row-label-border-color: #cbf4fe;
$primary: #b5e3ff;
$secondary: #a1d6f7;
$ternary: #d6f7ff;
$hover-highlight: rgba(193, 202, 214, 0.5);
$text: #022c47;
$background: white;
$row-label-border-color: #cbf4fe;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
+10 -10
View File
@@ -1,10 +1,10 @@
$primary: #2c2e36;
$secondary: #2f3447;
$ternary: #35394d;
$hover-highlight: rgba(179, 162, 127, 0.5);
$text: #ffe0b3;
$background: #38383b;
$highlighted: #7e7e7e;
$border-color: #444;
$marker-background: #666;
$row-label-border-color: $border-color;
$primary: #2c2e36;
$secondary: #2f3447;
$ternary: #35394d;
$hover-highlight: rgba(179, 162, 127, 0.5);
$text: #ffe0b3;
$background: #38383b;
$highlighted: #7e7e7e;
$border-color: #444;
$marker-background: #666;
$row-label-border-color: $border-color;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
+7 -7
View File
@@ -1,7 +1,7 @@
$primary: #258a5d;
$secondary: #41b883;
$ternary: #35495e;
$hover-highlight: rgba(160, 219, 171, 0.5);
$text: #fff;
$background: #fff;
$row-label-border-color: #384d63;
$primary: #258a5d;
$secondary: #41b883;
$ternary: #35495e;
$hover-highlight: rgba(160, 219, 171, 0.5);
$text: #fff;
$background: #fff;
$row-label-border-color: #384d63;
+3 -3
View File
@@ -1,3 +1,3 @@
@import '../../variables';
@import './variables';
@import '../../ganttastic';
@import '../../variables';
@import './variables';
@import '../../ganttastic';
+7 -7
View File
@@ -18,7 +18,7 @@
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^8.7.1",
"sass": "^1.51.0",
"sass": "^1.52.1",
"sass-loader": "^10.2.1",
"vue-template-compiler": "^2.6.11"
},
@@ -12809,9 +12809,9 @@
"dev": true
},
"node_modules/sass": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.51.0.tgz",
"integrity": "sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA==",
"version": "1.52.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.52.1.tgz",
"integrity": "sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
@@ -26849,9 +26849,9 @@
"dev": true
},
"sass": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.51.0.tgz",
"integrity": "sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA==",
"version": "1.52.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.52.1.tgz",
"integrity": "sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
+1 -1
View File
@@ -55,7 +55,7 @@
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^8.7.1",
"sass": "^1.51.0",
"sass": "^1.52.1",
"sass-loader": "^10.2.1",
"vue-template-compiler": "^2.6.11"
},
+17 -17
View File
@@ -1,17 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
+382 -382
View File
@@ -1,382 +1,382 @@
<template>
<div>
<select v-model="theme">
<option v-for="option in themes" :key="option" :value="option">
{{ option }}
</option>
</select>
<h2>Chart #1</h2>
<g-gantt-chart
:chart-start="chart1.chartStart"
:chart-end="chart1.chartEnd"
:grid="chart1.grid"
:grid-size="chart1.gridSize"
day-format="dddd, DD. MMMM"
:hide-timeaxis="chart1.hideTimeaxis"
:push-on-overlap="chart1.pushOnOverlap"
snap-back-on-overlap
:precision="chart1.precision"
:is-magnetic="chart1.isMagnetic"
:highlighted-hours="chart1.highlightedHours"
:highlighted-days="chart1.highlightedDays"
:row-label-width="chart1.rowLabelWidth"
:row-height="chart1.rowHeight"
:theme="theme"
bar-config-key="config"
bar-start-key="myStart"
bar-end-key="myEnd"
@dragend-bar="onDragend($event)"
>
<g-gantt-row
v-for="row in chart1.rows"
:key="row.label"
:label="row.label"
:label-style="row.labelStyle"
:row-style="row.style"
: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="theme"
:width="chart2.width"
:height="chart2.height"
:allow-add="chart2.allowAdd"
>
<g-gantt-row
v-for="row in chart2.rows"
:key="row.label"
:label="row.label"
:row-style="row.style"
:bars="row.bars"
:highlight-on-hover="chart2.highlightOnHover"
>
<template #bar-label="{ bar }">
<span>{{ bar.label }}</span>
</template>
</g-gantt-row>
</g-gantt-chart>
</div>
</template>
<script>
export default {
data: () => ({
theme: 'default',
themes: [
'creamy',
'crimson',
'dark',
'default',
'flare',
'fuchsia',
'grove',
'material-blue',
'sky',
'slumber',
'vue'
],
chart1: {
chartStart: '2020-03-02 00:00',
chartEnd: '2020-03-10 10:00',
precision: 'day',
pushOnOverlap: true,
isMagnetic: true,
grid: true,
gridSize: 30,
rowHeight: 40,
rowLabelWidth: 200,
hideTimeaxis: false,
highlightOnHover: true,
highlightedDays: ['2020-03-08'],
highlightedHours: [10, 12],
rows: [
{
label: 'Row #1',
bars: [
{
myStart: '2020-03-03 18:00',
myEnd: '2020-03-03 23:00',
label: 'Immobile',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#404040',
opacity: 0.5,
immobile: true
}
},
{
myStart: '2020-03-03 04:00',
myEnd: '2020-03-03 15:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#2e74a3',
bundle: 'blueBundle'
}
}
]
},
{
label: 'Row #2',
labelStyle: {
justifyContent: 'end'
},
style: {
background: '#ffb0b07f'
},
bars: [
{
myStart: '2020-03-02 09:00',
myEnd: '2020-03-02 18:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#de3b26',
bundle: 'redBundle'
}
},
{
myStart: '2020-03-03 04:00',
myEnd: '2020-03-03 15:00',
label: 'We belong together ^',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#2e74a3',
bundle: 'blueBundle'
}
},
{
myStart: '2020-03-03 18:00',
myEnd: '2020-03-03 22:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: { color: 'white', backgroundColor: '#aa34a3' }
}
]
},
{
label: 'Row #3',
bars: [
{
myStart: '2020-03-02 09:00',
myEnd: '2020-03-02 18:00',
label: 'We belong together ^',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#de3b26',
bundle: 'redBundle'
}
},
{
myStart: '2020-03-02 22:30',
myEnd: '2020-03-03 05:00',
label: 'With handles!',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#a23def',
handles: true
}
},
{
myStart: '2020-03-02 01:00',
myEnd: '2020-03-02 07:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#5effad',
pushOnOverlap: false,
zIndex: 2
}
},
{
myStart: '2020-03-03 14:00',
myEnd: '2020-03-03 20:00',
label: 'Woooow!',
tooltip: 'Bar tooltip',
config: {
color: 'white',
background:
'repeating-linear-gradient(45deg, #de7359, #de7359 10px, #ffc803 10px, #ffc803 20px)'
}
}
]
},
{
label: 'Row #4',
bars: [
{
myStart: '2020-03-03 06:30',
myEnd: '2020-03-03 20:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#d18aaf',
handles: true
}
},
{
myStart: '2020-03-02 00:30',
myEnd: '2020-03-03 01:00',
label: 'Rectangular',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#f2840f',
borderRadius: 0
}
}
]
}
]
},
chart2: {
chartStart: '2020-03-01 00:00',
chartEnd: '2020-04-01 00:00',
precision: 'month',
pushOnOverlap: false,
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'
],
width: '90vw',
height: '250px',
allowAdd: false,
rows: [
{
label: 'Row #1',
bars: [
{
start: '2020-03-05 00:00',
end: '2020-03-10 23:59',
label: 'Bar',
tooltip: 'Bar tooltip',
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 ^',
tooltip: 'Bar tooltip',
ganttBarConfig: {
color: 'white',
backgroundColor: '#2e74a3',
bundle: 'blueBundle'
}
},
{
start: '2020-03-24 00:00',
end: '2020-03-26 23:00',
label: 'Bar',
tooltip: 'Bar tooltip',
ganttBarConfig: {
color: 'white',
backgroundColor: '#de3b26'
}
}
]
},
{
label: 'Row #3',
bars: [
{
start: '2020-03-15 00:00',
end: '2020-03-18 23:59',
label: 'Bar',
tooltip: 'Bar tooltip',
ganttBarConfig: {
color: 'white',
backgroundColor: '#408e2f'
}
}
],
style: {
background:
'linear-gradient(-45deg, rgba(0, 0, 0, 0) 48%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0) 52%)',
backgroundSize: '1em 1em'
}
},
{
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) {
const { event, bar, movedBars } = e
// eslint-disable-next-line
console.log('onDragend', { event: event.type, bar, movedBars })
}
}
}
</script>
<style lang="scss" src="../lib/scss/index.scss"></style>
<template>
<div>
<select v-model="theme">
<option v-for="option in themes" :key="option" :value="option">
{{ option }}
</option>
</select>
<h2>Chart #1</h2>
<g-gantt-chart
:chart-start="chart1.chartStart"
:chart-end="chart1.chartEnd"
:grid="chart1.grid"
:grid-size="chart1.gridSize"
day-format="dddd, DD. MMMM"
:hide-timeaxis="chart1.hideTimeaxis"
:push-on-overlap="chart1.pushOnOverlap"
snap-back-on-overlap
:precision="chart1.precision"
:is-magnetic="chart1.isMagnetic"
:highlighted-hours="chart1.highlightedHours"
:highlighted-days="chart1.highlightedDays"
:row-label-width="chart1.rowLabelWidth"
:row-height="chart1.rowHeight"
:theme="theme"
bar-config-key="config"
bar-start-key="myStart"
bar-end-key="myEnd"
@dragend-bar="onDragend($event)"
>
<g-gantt-row
v-for="row in chart1.rows"
:key="row.label"
:label="row.label"
:label-style="row.labelStyle"
:row-style="row.style"
: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="theme"
:width="chart2.width"
:height="chart2.height"
:allow-add="chart2.allowAdd"
>
<g-gantt-row
v-for="row in chart2.rows"
:key="row.label"
:label="row.label"
:row-style="row.style"
:bars="row.bars"
:highlight-on-hover="chart2.highlightOnHover"
>
<template #bar-label="{ bar }">
<span>{{ bar.label }}</span>
</template>
</g-gantt-row>
</g-gantt-chart>
</div>
</template>
<script>
export default {
data: () => ({
theme: 'default',
themes: [
'creamy',
'crimson',
'dark',
'default',
'flare',
'fuchsia',
'grove',
'material-blue',
'sky',
'slumber',
'vue'
],
chart1: {
chartStart: '2020-03-02 00:00',
chartEnd: '2020-03-10 10:00',
precision: 'day',
pushOnOverlap: true,
isMagnetic: true,
grid: true,
gridSize: 30,
rowHeight: 40,
rowLabelWidth: 200,
hideTimeaxis: false,
highlightOnHover: true,
highlightedDays: ['2020-03-08'],
highlightedHours: [10, 12],
rows: [
{
label: 'Row #1',
bars: [
{
myStart: '2020-03-03 18:00',
myEnd: '2020-03-03 23:00',
label: 'Immobile',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#404040',
opacity: 0.5,
immobile: true
}
},
{
myStart: '2020-03-03 04:00',
myEnd: '2020-03-03 15:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#2e74a3',
bundle: 'blueBundle'
}
}
]
},
{
label: 'Row #2',
labelStyle: {
justifyContent: 'end'
},
style: {
background: '#ffb0b07f'
},
bars: [
{
myStart: '2020-03-02 09:00',
myEnd: '2020-03-02 18:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#de3b26',
bundle: 'redBundle'
}
},
{
myStart: '2020-03-03 04:00',
myEnd: '2020-03-03 15:00',
label: 'We belong together ^',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#2e74a3',
bundle: 'blueBundle'
}
},
{
myStart: '2020-03-03 18:00',
myEnd: '2020-03-03 22:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: { color: 'white', backgroundColor: '#aa34a3' }
}
]
},
{
label: 'Row #3',
bars: [
{
myStart: '2020-03-02 09:00',
myEnd: '2020-03-02 18:00',
label: 'We belong together ^',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#de3b26',
bundle: 'redBundle'
}
},
{
myStart: '2020-03-02 22:30',
myEnd: '2020-03-03 05:00',
label: 'With handles!',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#a23def',
handles: true
}
},
{
myStart: '2020-03-02 01:00',
myEnd: '2020-03-02 07:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#5effad',
pushOnOverlap: false,
zIndex: 2
}
},
{
myStart: '2020-03-03 14:00',
myEnd: '2020-03-03 20:00',
label: 'Woooow!',
tooltip: 'Bar tooltip',
config: {
color: 'white',
background:
'repeating-linear-gradient(45deg, #de7359, #de7359 10px, #ffc803 10px, #ffc803 20px)'
}
}
]
},
{
label: 'Row #4',
bars: [
{
myStart: '2020-03-03 06:30',
myEnd: '2020-03-03 20:00',
label: 'Bar',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#d18aaf',
handles: true
}
},
{
myStart: '2020-03-02 00:30',
myEnd: '2020-03-03 01:00',
label: 'Rectangular',
tooltip: 'Bar tooltip',
config: {
color: 'white',
backgroundColor: '#f2840f',
borderRadius: 0
}
}
]
}
]
},
chart2: {
chartStart: '2020-03-01 00:00',
chartEnd: '2020-04-01 00:00',
precision: 'month',
pushOnOverlap: false,
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'
],
width: '90vw',
height: '250px',
allowAdd: false,
rows: [
{
label: 'Row #1',
bars: [
{
start: '2020-03-05 00:00',
end: '2020-03-10 23:59',
label: 'Bar',
tooltip: 'Bar tooltip',
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 ^',
tooltip: 'Bar tooltip',
ganttBarConfig: {
color: 'white',
backgroundColor: '#2e74a3',
bundle: 'blueBundle'
}
},
{
start: '2020-03-24 00:00',
end: '2020-03-26 23:00',
label: 'Bar',
tooltip: 'Bar tooltip',
ganttBarConfig: {
color: 'white',
backgroundColor: '#de3b26'
}
}
]
},
{
label: 'Row #3',
bars: [
{
start: '2020-03-15 00:00',
end: '2020-03-18 23:59',
label: 'Bar',
tooltip: 'Bar tooltip',
ganttBarConfig: {
color: 'white',
backgroundColor: '#408e2f'
}
}
],
style: {
background:
'linear-gradient(-45deg, rgba(0, 0, 0, 0) 48%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0) 52%)',
backgroundSize: '1em 1em'
}
},
{
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) {
const { event, bar, movedBars } = e
// eslint-disable-next-line
console.log('onDragend', { event: event.type, bar, movedBars })
}
}
}
</script>
<style lang="scss" src="../lib/scss/index.scss"></style>
+12 -12
View File
@@ -1,12 +1,12 @@
import Vue from 'vue'
import App from './App.vue'
import { GGanttChart, GGanttRow } from '../lib'
Vue.component('GGanttChart', GGanttChart)
Vue.component('GGanttRow', GGanttRow)
Vue.config.productionTip = false
new Vue({
render: h => h(App)
}).$mount('#app')
import Vue from 'vue'
import App from './App.vue'
import { GGanttChart, GGanttRow } from '../lib'
Vue.component('GGanttChart', GGanttChart)
Vue.component('GGanttRow', GGanttRow)
Vue.config.productionTip = false
new Vue({
render: h => h(App)
}).$mount('#app')
+8 -8
View File
@@ -1,8 +1,8 @@
// vetur.config.js
/** @type {import('vls').VeturConfig} */
module.exports = {
settings: {
'vetur.ignoreProjectWarning': true,
},
projects: ['./'],
}
// vetur.config.js
/** @type {import('vls').VeturConfig} */
module.exports = {
settings: {
'vetur.ignoreProjectWarning': true,
},
projects: ['./'],
}
+24 -24
View File
@@ -1,24 +1,24 @@
const isBuildLib =
(process.env.npm_lifecycle_script || '').indexOf('--target lib') > 0
module.exports = {
publicPath: '',
outputDir: isBuildLib ? 'dist' : 'demo',
css: {
loaderOptions: {
sass: {
implementation: require('sass')
}
},
extract: true
},
productionSourceMap: false,
chainWebpack: config => {
if (process.env.VUE_CLI_BUILD_TARGET === 'lib') {
config.externals({
...config.get('externals'),
moment: 'moment'
})
}
}
}
const isBuildLib =
(process.env.npm_lifecycle_script || '').indexOf('--target lib') > 0
module.exports = {
publicPath: '',
outputDir: isBuildLib ? 'dist' : 'demo',
css: {
loaderOptions: {
sass: {
implementation: require('sass')
}
},
extract: true
},
productionSourceMap: false,
chainWebpack: config => {
if (process.env.VUE_CLI_BUILD_TARGET === 'lib') {
config.externals({
...config.get('externals'),
moment: 'moment'
})
}
}
}