diff --git a/app/modules/project/templates/project/inbox.html b/app/modules/project/templates/project/inbox.html index ad0c92a..ffb35ed 100644 --- a/app/modules/project/templates/project/inbox.html +++ b/app/modules/project/templates/project/inbox.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + {% endblock %} @@ -45,5 +45,5 @@ {% endif %} - + {% endblock %} diff --git a/app/modules/project/templates/project/index.html b/app/modules/project/templates/project/index.html index f278d0f..4217a8f 100644 --- a/app/modules/project/templates/project/index.html +++ b/app/modules/project/templates/project/index.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + {% endblock %} @@ -100,5 +100,5 @@ - + {% endblock %} diff --git a/app/modules/project/templates/project/project.html b/app/modules/project/templates/project/project.html index 040c358..cdc913a 100644 --- a/app/modules/project/templates/project/project.html +++ b/app/modules/project/templates/project/project.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + @@ -290,5 +290,5 @@ - + {% endblock %} diff --git a/app/static/project.js b/app/static/project.js index ff12b57..476977d 100644 --- a/app/static/project.js +++ b/app/static/project.js @@ -242,9 +242,39 @@ }); if (timeline) { timeline.destroy(); timeline = null; } if (!items.length) { node.innerHTML = '
기간이 설정된 업무가 없습니다.
'; return; } + const koWd = function (d) { return ["일", "월", "화", "수", "목", "금", "토"][d.getDay()]; }; + const pad2 = function (n) { return ("0" + n).slice(-2); }; timeline = new vis.Timeline(node, new vis.DataSet(items), { - locale: "ko", stack: true, height: "520px", zoomKey: "ctrlKey", + stack: true, height: "520px", + horizontalScroll: true, // 마우스 휠 = 좌우 이동(패닝) + verticalScroll: false, + zoomKey: "ctrlKey", // 확대/축소는 Ctrl+휠 margin: { item: 8 }, + format: { + minorLabels: function (date, scale) { + const d = new Date(date.valueOf()); + switch (scale) { + case "millisecond": case "second": case "minute": case "hour": + return pad2(d.getHours()) + ":" + pad2(d.getMinutes()); + case "weekday": case "day": return d.getDate() + "일 (" + koWd(d) + ")"; + case "week": return d.getDate() + "일"; + case "month": return (d.getMonth() + 1) + "월"; + case "year": return d.getFullYear() + "년"; + default: return d.getDate() + "일"; + } + }, + majorLabels: function (date, scale) { + const d = new Date(date.valueOf()); + switch (scale) { + case "millisecond": case "second": case "minute": case "hour": + return (d.getMonth() + 1) + "월 " + d.getDate() + "일 (" + koWd(d) + ")"; + case "weekday": case "day": case "week": + return d.getFullYear() + "년 " + (d.getMonth() + 1) + "월"; + case "month": return d.getFullYear() + "년"; + default: return ""; + } + }, + }, }); timeline.on("select", function (props) { if (!canManage || !props.items.length) return; @@ -709,9 +739,15 @@ // 최초 렌더 — 달력은 서버 렌더, 클릭 핸들러만 연결 wireCalendar(); - // 사이드 트리에서 업무 클릭(?task=ID)으로 들어오면 해당 업무 모달 자동 열기 - const taskParam = new URLSearchParams(location.search).get("task"); + // 사이드 트리에서 업무 클릭(?task=ID)으로 들어오면 해당 업무 모달 자동 열기. + // 단, 처리 후 URL 에서 task 파라미터를 제거한다 — 드래그 이동 후 location.reload() + // 시 이 파라미터가 남아 모달이 다시 뜨는 것을 방지. + const params = new URLSearchParams(location.search); + const taskParam = params.get("task"); if (taskParam) { + params.delete("task"); + const qs = params.toString(); + history.replaceState({}, "", location.pathname + (qs ? "?" + qs : "")); const t = tasks.find(function (x) { return String(x.id) === String(taskParam); }); if (t) openTaskModal(t); }