vue-gantt-3
Version:
A gantt component for Vue 3
354 lines (353 loc) • 13.3 kB
JavaScript
import { defineComponent, ref, onBeforeMount, onMounted, watch, inject, provide, createElementBlock, openBlock, createVNode, withModifiers, withCtx } from "vue";
import _sfc_main$2 from "../scrollbar/ScrollBar.vue.mjs";
/* empty css */
import _sfc_main$1 from "./ganttHeader/GanttHeader.vue.mjs";
/* empty css */
import dayjs from "dayjs";
import minMax from "dayjs/plugin/minMax";
import _sfc_main$3 from "./ganttBody/GanttBody.vue.mjs";
/* empty css */
import { getRound, treeForEach } from "../../utils/common.mjs";
const perHourSpacingScale = 1.2;
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "GanttView",
props: {
getRowId: {},
columns: {},
rows: {},
defaultCol: {},
rowHeight: {},
headerHeight: {},
rowBuffer: {},
rowNodeMap: {},
firstLevelRowNode: {},
visibleRowIds: {},
defaultPerHourSpacing: { default: 0.1 },
defaultTimeScale: {},
styleOption: {},
timePointComp: {},
locale: {},
timeLineRender: {},
timeLineRenderParams: {},
headerTextRender: {},
headerTipRender: {}
},
emits: ["triggerTableViewScroll", "ganttBodyResize", "perHourSpacingChange"],
setup(__props, { expose: __expose, emit: __emit }) {
dayjs.extend(minMax);
const props = __props;
const emit = __emit;
const ganttMinDate = ref(dayjs());
const ganttMaxDate = ref(null);
const edgeSpacing = ref(20);
const perHourSpacing = ref(props.defaultPerHourSpacing);
const ganttBodyRef = ref();
const ganttHeaderRef = ref();
const scrollBarRef = ref();
const ganttGanttView = ref();
const scrollbarWrap = ref();
const minPerHourSpacing = ref(7e-3);
const maxPerHourSpacing = ref(1400);
const ganttViewWidth = ref(0);
const scrollFromTableView = ref(false);
const maxAndMindateCache = /* @__PURE__ */ new Map();
onBeforeMount(() => {
updateMinAndMaxDate();
updateGanttViewWidth();
});
onMounted(() => {
var _a;
scrollbarWrap.value = (_a = scrollBarRef.value) == null ? void 0 : _a.$el.querySelector(".vg-scrollbar-wrap");
});
watch([() => props.defaultPerHourSpacing, () => props.defaultTimeScale], ([currentPerHourSpacing, currentTimeScale]) => {
if (currentTimeScale) {
switch (currentTimeScale) {
case "day":
perHourSpacing.value = 2;
break;
case "week":
perHourSpacing.value = 0.6;
break;
case "month":
perHourSpacing.value = 0.1;
break;
case "quarter":
perHourSpacing.value = 0.05;
break;
case "year":
perHourSpacing.value = 0.02;
break;
}
} else {
perHourSpacing.value = currentPerHourSpacing;
}
}, { immediate: true });
const getTopLevelRow = inject("getTopLevelRow");
const getGanttMinAndMaxDate = (excludeRowIds = [], freshStartDate = true, freshEndDate = true) => {
const isSingleExclude = excludeRowIds.length === 1;
if (isSingleExclude) {
if (maxAndMindateCache.has("minStartDate") && maxAndMindateCache.has("maxEndDate")) {
return {
minStartDate: maxAndMindateCache.get("minStartDate"),
maxEndDate: maxAndMindateCache.get("maxEndDate")
};
}
}
const excludeRowIdSet = new Set(excludeRowIds);
const excludeFirstLevelRowId = excludeRowIds.map((rowId) => getTopLevelRow(rowId, props.rowNodeMap).id);
const excludeFirstLevelRowIdSet = new Set(excludeFirstLevelRowId);
const needFirstLevelRowNode = [];
const excludeFirstLevelRowNode = [];
for (let rowNode of props.firstLevelRowNode) {
if (excludeFirstLevelRowIdSet.has(rowNode.id)) {
excludeFirstLevelRowNode.push(rowNode);
} else {
needFirstLevelRowNode.push(rowNode);
}
}
const { minStartDate, maxEndDate } = getMinAndMaxDate(needFirstLevelRowNode, freshStartDate, freshEndDate);
let allMinStartDates = [];
let allMaxEndDates = [];
if (minStartDate) {
allMinStartDates.push(minStartDate);
}
if (maxEndDate) {
allMaxEndDates.push(maxEndDate);
}
treeForEach(excludeFirstLevelRowNode, (rowNode) => {
if (!rowNode.hasChildren && !excludeRowIdSet.has(rowNode.id)) {
rowNode.startDate && allMinStartDates.push(rowNode.startDate);
rowNode.endDate && allMaxEndDates.push(rowNode.endDate);
}
});
const finalMinStartDate = dayjs.min(allMinStartDates);
const finalMaxEndDate = dayjs.max(allMaxEndDates);
if (isSingleExclude && finalMinStartDate && finalMaxEndDate) {
maxAndMindateCache.set("minStartDate", finalMinStartDate);
maxAndMindateCache.set("maxEndDate", finalMaxEndDate);
}
return {
minStartDate: finalMinStartDate,
maxEndDate: finalMaxEndDate
};
};
provide(
"getGanttMinAndMaxDate",
getGanttMinAndMaxDate
);
const clearDateCache = () => {
maxAndMindateCache.clear();
};
provide(
"clearDateCache",
clearDateCache
);
const updateMinAndMaxDate = () => {
const { minStartDate, maxEndDate } = getMinAndMaxDate(props.firstLevelRowNode);
if (minStartDate) {
ganttMinDate.value = minStartDate;
}
if (maxEndDate) {
ganttMaxDate.value = maxEndDate;
}
};
const updateMinDate = (minDate) => {
ganttMinDate.value = minDate;
};
const updateMaxDate = (maxDate) => {
ganttMaxDate.value = maxDate;
};
const updateGanttViewWidth = () => {
var _a;
const diffHour = ((_a = ganttMaxDate.value) == null ? void 0 : _a.diff(ganttMinDate.value, "hour", true)) || 0;
if (diffHour > 0) {
ganttViewWidth.value = getRound(diffHour * perHourSpacing.value + edgeSpacing.value * 2);
}
maxPerHourSpacing.value = Math.floor((16777200 - edgeSpacing.value * 2) / diffHour);
};
watch([perHourSpacing, ganttMinDate, ganttMaxDate, edgeSpacing], updateGanttViewWidth);
const getMinAndMaxDate = (expectRowNodes, freshStartDate = true, freshEndDate = true) => {
const startDateArr = [];
const endDateArr = [];
if (freshStartDate) {
for (let rowNode of expectRowNodes) {
rowNode.startDate && startDateArr.push(rowNode.startDate);
}
}
if (freshEndDate) {
for (let rowNode of expectRowNodes) {
rowNode.endDate && endDateArr.push(rowNode.endDate);
}
}
return {
minStartDate: dayjs.min(startDateArr),
maxEndDate: dayjs.max(endDateArr)
};
};
const updateMinAndMaxDateByChangeRowNode = ({ addedRowNodes = [], deletedRowNodes = [], updatedRowNodes = [] }, freshRowNodes) => {
var _a, _b;
let freshStartDate = false;
let freshEndDate = false;
for (let updatedRowNode of updatedRowNodes) {
addedRowNodes.push({
...updatedRowNode
});
const oldStartDate = updatedRowNode.oldStartDate;
const oldEndDate = updatedRowNode.oldEndDate;
deletedRowNodes.push({
...updatedRowNode,
startDate: oldStartDate,
endDate: oldEndDate
});
}
for (let deletedRowNode of deletedRowNodes) {
if (!freshStartDate && ((_a = deletedRowNode.startDate) == null ? void 0 : _a.isSame(ganttMinDate.value))) {
freshStartDate = true;
}
if (!freshEndDate && ((_b = deletedRowNode.endDate) == null ? void 0 : _b.isSame(ganttMaxDate.value))) {
freshEndDate = true;
}
}
if (freshStartDate || freshEndDate) {
const { minStartDate, maxEndDate } = getMinAndMaxDate(freshRowNodes, freshStartDate, freshEndDate);
if (minStartDate) {
ganttMinDate.value = minStartDate;
}
if (maxEndDate) {
ganttMaxDate.value = maxEndDate;
}
}
for (let addedRowNode of addedRowNodes) {
if (addedRowNode.startDate && addedRowNode.startDate.isBefore(ganttMinDate.value)) {
ganttMinDate.value = addedRowNode.startDate;
}
if (addedRowNode.endDate && (!ganttMaxDate.value || addedRowNode.endDate.isAfter(ganttMaxDate.value))) {
ganttMaxDate.value = addedRowNode.endDate;
}
}
};
const onScroll = ({ scrollTop, scrollLeft }) => {
if (scrollFromTableView.value) {
scrollFromTableView.value = false;
} else {
emit("triggerTableViewScroll", { top: scrollTop });
}
if (ganttBodyRef.value) {
ganttBodyRef.value.onScroll({ scrollTop, scrollLeft });
}
if (ganttHeaderRef.value) {
ganttHeaderRef.value.onScroll({ scrollLeft });
}
};
const onWheel = (e) => {
var _a, _b;
if (!scrollbarWrap.value) return;
if (Math.abs(e.deltaY) < 3) return;
const scrollSpeed = 100;
const scrollDistance = e.deltaY > 0 ? scrollSpeed : -100;
const scrollTop = ((_a = scrollbarWrap.value) == null ? void 0 : _a.scrollTop) + scrollDistance;
(_b = scrollBarRef.value) == null ? void 0 : _b.triggerScrollFromOutSide({ top: scrollTop });
scrollFromTableView.value = true;
emit("triggerTableViewScroll", { top: scrollTop }, true);
};
const onResize = (target) => {
if (ganttBodyRef.value) {
ganttBodyRef.value.onResize();
}
if (ganttHeaderRef.value) {
ganttHeaderRef.value.onResize();
}
emit("ganttBodyResize", target);
};
const onShiftScroll = (e) => {
if (Math.abs(e.deltaY) < 3) return;
if (e.deltaY > 0) {
const newPerHourSpacing = perHourSpacing.value / perHourSpacingScale;
perHourSpacing.value = Math.max(newPerHourSpacing, minPerHourSpacing.value);
} else if (e.deltaY < 0) {
const newPerHourSpacing = perHourSpacing.value * perHourSpacingScale;
perHourSpacing.value = Math.min(newPerHourSpacing, maxPerHourSpacing.value);
}
emit("perHourSpacingChange", perHourSpacing.value);
};
const onVerticalScrollBarShow = ({ show, scrollbarWidth }) => {
if (ganttHeaderRef.value) {
ganttHeaderRef.value.updateGanttHeaderWidth(show, scrollbarWidth);
}
};
const scrollTo = (options) => {
var _a;
scrollFromTableView.value = true;
(_a = scrollBarRef.value) == null ? void 0 : _a.triggerScrollFromOutSide(options);
};
const freshTimeLines = (rowNodes) => {
if (ganttBodyRef.value) {
ganttBodyRef.value.freshTimeLines(rowNodes);
}
};
__expose({
scrollTo,
updateMinAndMaxDateByChangeRowNode,
freshTimeLines
});
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
ref_key: "ganttGanttView",
ref: ganttGanttView,
class: "vg-gantt-view"
}, [
createVNode(_sfc_main$1, {
ref_key: "ganttHeaderRef",
ref: ganttHeaderRef,
edgeSpacing: edgeSpacing.value,
perHourSpacing: perHourSpacing.value,
ganttMinDate: ganttMinDate.value,
ganttViewWidth: ganttViewWidth.value,
headerHeight: _ctx.headerHeight,
locale: _ctx.locale,
headerTextRender: _ctx.headerTextRender,
headerTipRender: _ctx.headerTipRender
}, null, 8, ["edgeSpacing", "perHourSpacing", "ganttMinDate", "ganttViewWidth", "headerHeight", "locale", "headerTextRender", "headerTipRender"]),
createVNode(_sfc_main$2, {
ref_key: "scrollBarRef",
ref: scrollBarRef,
"intercept-shift-scroll": true,
alwayHorizontal: true,
onScroll,
onWheel: withModifiers(onWheel, ["prevent"]),
onResize,
onShiftScroll: withModifiers(onShiftScroll, ["prevent"]),
onVerticalScrollBarShow
}, {
default: withCtx(() => [
createVNode(_sfc_main$3, {
ref_key: "ganttBodyRef",
ref: ganttBodyRef,
rows: _ctx.rows,
rowNodeMap: _ctx.rowNodeMap,
rowHeight: _ctx.rowHeight,
edgeSpacing: edgeSpacing.value,
perHourSpacing: perHourSpacing.value,
ganttMinDate: ganttMinDate.value,
ganttMaxDate: ganttMaxDate.value,
rowBuffer: _ctx.rowBuffer,
ganttViewWidth: ganttViewWidth.value,
visibleRowIds: _ctx.visibleRowIds,
styleOption: _ctx.styleOption,
timePointComp: _ctx.timePointComp,
timeLineRender: _ctx.timeLineRender,
timeLineRenderParams: _ctx.timeLineRenderParams,
onUpdateMinDate: updateMinDate,
onUpdateMaxDate: updateMaxDate
}, null, 8, ["rows", "rowNodeMap", "rowHeight", "edgeSpacing", "perHourSpacing", "ganttMinDate", "ganttMaxDate", "rowBuffer", "ganttViewWidth", "visibleRowIds", "styleOption", "timePointComp", "timeLineRender", "timeLineRenderParams"])
]),
_: 1
}, 512)
], 512);
};
}
});
export {
_sfc_main as default
};
//# sourceMappingURL=GanttView.vue.mjs.map