From a6adb5fc4124fb79781b6a564d34fec3b18494bb Mon Sep 17 00:00:00 2001 From: king Date: Thu, 25 Jun 2026 13:27:41 +0900 Subject: [PATCH] =?UTF-8?q?fix(project):=20=EB=93=9C=EB=9E=98=EA=B7=B8=20?= =?UTF-8?q?=ED=9B=84=20=EB=AA=A8=EB=8B=AC=20=EC=9E=AC=EC=98=A4=ED=94=88=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80=20+=20=ED=83=80=EC=9E=84=EB=9D=BC=EC=9D=B8?= =?UTF-8?q?=20=ED=95=9C=EA=B8=80=20=EB=82=A0=EC=A7=9C=C2=B7=ED=9C=A0=20?= =?UTF-8?q?=EC=A2=8C=EC=9A=B0=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 드래그 이동 후 location.reload() 시 URL 의 ?task= 가 남아 업무 모달이 다시 뜨던 문제 수정: ?task 처리 직후 history.replaceState 로 파라미터 제거 - 타임라인 날짜 라벨 한글화(format minor/major 함수: 'M월 D일 (요일)', 'YYYY년 M월') - 타임라인 마우스 휠 = 좌우 이동(horizontalScroll), 확대/축소는 Ctrl+휠 Co-Authored-By: Claude Opus 4.8 --- .../project/templates/project/inbox.html | 4 +- .../project/templates/project/index.html | 4 +- .../project/templates/project/project.html | 4 +- app/static/project.js | 42 +++++++++++++++++-- 4 files changed, 45 insertions(+), 9 deletions(-) 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); }