fix(project): 설명란 이미지 삽입 시 원본이 너비 초과하면 90%로 축소

이미지가 설명란 너비와 같거나 넓게 삽입되면 크기조절 핸들(이미지 우하단
바깥쪽 -6px 오프셋)이 설명란 테두리 밖으로 삐져나갔다. 붙여넣기/업로드로
삽입하기 전 원본 크기를 확인해, 설명란보다 넓은 경우 width 속성을 설명란
너비의 90%로 지정해서 넣는다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 22:34:45 +09:00
parent 428e5845b4
commit 022a161dda
4 changed files with 24 additions and 5 deletions
@@ -45,5 +45,5 @@
{% endif %}
</div>
<script src="/static/project.js?v=20260916j" defer></script>
<script src="/static/project.js?v=20260916k" defer></script>
{% endblock %}
@@ -376,5 +376,5 @@
<script>
window.PJ_COLORS = {{ ["#4573d2","#37a3a3","#62a420","#e8a33d","#e8384f","#aa62e3","#f06a6a","#5a6772"] | tojson }};
</script>
<script src="/static/project.js?v=20260916j" defer></script>
<script src="/static/project.js?v=20260916k" defer></script>
{% endblock %}
@@ -379,5 +379,5 @@
</script>
<script src="/static/vendor/vis-timeline/vis-timeline-graph2d.min.js"></script>
<script src="/static/project.js?v=20260916j" defer></script>
<script src="/static/project.js?v=20260916k" defer></script>
{% endblock %}
+21 -2
View File
@@ -2079,15 +2079,34 @@
}
}
// 삽입 전 원본 크기를 확인해, 설명란보다 넓으면 90%로 줄여서 넣는다
// (그대로 넣으면 크기조절 핸들이 설명란 밖으로 삐져나간다).
function naturalImageSize(file) {
return new Promise(function (resolve) {
const url = URL.createObjectURL(file);
const img = new Image();
img.onload = function () { URL.revokeObjectURL(url); resolve({ width: img.naturalWidth }); };
img.onerror = function () { URL.revokeObjectURL(url); resolve(null); };
img.src = url;
});
}
async function insertImageFile(file) {
if (!taskId) { alert("먼저 저장한 뒤 이미지를 추가할 수 있습니다."); return; }
const fd = new FormData();
fd.append("file", file);
try {
const res = await fetch("/project/api/tasks/" + taskId + "/attachments", { method: "POST", body: fd });
const results = await Promise.all([
naturalImageSize(file),
fetch("/project/api/tasks/" + taskId + "/attachments", { method: "POST", body: fd }),
]);
const dims = results[0], res = results[1];
if (!res.ok) { let m = res.statusText; try { m = (await res.json()).detail; } catch (_) {} throw new Error(m); }
const data = await res.json();
insertHtmlAtCursor('<img src="/project/api/attachments/' + data.attachment.id + '/inline" alt="">');
const boxW = box.clientWidth || 0;
const widthAttr = (dims && dims.width && boxW && dims.width > boxW)
? ' width="' + Math.round(boxW * 0.9) + '"' : "";
insertHtmlAtCursor('<img src="/project/api/attachments/' + data.attachment.id + '/inline" alt=""' + widthAttr + '>');
} catch (e) { alert("이미지 업로드 실패: " + e.message); }
}