fix(project): 설명란 이미지 삭제 시 첨부파일 목록에서도 같이 삭제
설명에 붙여넣기/업로드로 넣은 이미지는 실제로는 task_attachments 레코드라, 에디터에서 이미지만 지우면(× 버튼 또는 Delete/Backspace) 서버 첨부는 그대로 남아 첨부파일 목록에 계속 보였다. src 의 attachment id 를 뽑아 DELETE 호출까지 같이 하고, 첨부파일 목록도 새로고침한다. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -45,5 +45,5 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script src="/static/project.js?v=20260917b" defer></script>
|
||||
<script src="/static/project.js?v=20260917c" defer></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -392,5 +392,5 @@
|
||||
<script>
|
||||
window.PJ_COLORS = {{ ["#4573d2","#37a3a3","#62a420","#e8a33d","#e8384f","#aa62e3","#f06a6a","#5a6772"] | tojson }};
|
||||
</script>
|
||||
<script src="/static/project.js?v=20260917b" defer></script>
|
||||
<script src="/static/project.js?v=20260917c" defer></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -405,5 +405,5 @@
|
||||
</script>
|
||||
|
||||
<script src="/static/vendor/vis-timeline/vis-timeline-graph2d.min.js"></script>
|
||||
<script src="/static/project.js?v=20260917b" defer></script>
|
||||
<script src="/static/project.js?v=20260917c" defer></script>
|
||||
{% endblock %}
|
||||
|
||||
+31
-6
@@ -211,6 +211,12 @@
|
||||
const descEditor = initDescEditor();
|
||||
const subtaskBlock = initSubtaskBlock();
|
||||
const linksBlock = initLinksBlock();
|
||||
if (descEditor) {
|
||||
descEditor.setOnImageRemoved(function () {
|
||||
const tid = el("pj-t-id").value;
|
||||
if (tid) loadHomeAttachments(tid);
|
||||
});
|
||||
}
|
||||
|
||||
// 닫을 때(배경 클릭·Esc·취소 버튼) 수정한 내용이 있으면 저장할지 물어본다.
|
||||
let homeTaskSnapshot = null;
|
||||
@@ -1631,6 +1637,12 @@
|
||||
const descEditor = initDescEditor();
|
||||
const subtaskBlock = initSubtaskBlock();
|
||||
const linksBlock = initLinksBlock();
|
||||
if (descEditor) {
|
||||
descEditor.setOnImageRemoved(function () {
|
||||
const tid = el("pj-t-id").value;
|
||||
if (tid) loadAttachments(tid);
|
||||
});
|
||||
}
|
||||
|
||||
// 닫을 때(배경 클릭·Esc·취소 버튼) 수정한 내용이 있으면 저장할지 물어본다.
|
||||
// 하위업무/첨부/댓글/연결은 각자 즉시 저장돼서 여기서 추적할 필요 없다 —
|
||||
@@ -2139,6 +2151,22 @@
|
||||
const imgDelBtn = imgTools.querySelector(".pj-img-del");
|
||||
const imgHandle = imgTools.querySelector(".pj-img-handle");
|
||||
let selectedImg = null;
|
||||
let onImageRemoved = null;
|
||||
|
||||
// 설명란 이미지는 첨부파일 업로드로 들어간 실제 첨부 레코드다 — 에디터에서
|
||||
// 지우면 첨부파일 목록에도 안 남게 서버 첨부도 같이 삭제한다.
|
||||
async function deleteSelectedImage() {
|
||||
if (!selectedImg) return;
|
||||
const img = selectedImg;
|
||||
const m = (img.getAttribute("src") || "").match(/\/attachments\/(\d+)\/inline/);
|
||||
img.remove();
|
||||
selectImg(null);
|
||||
if (!m) return;
|
||||
try {
|
||||
await api("DELETE", "/project/api/attachments/" + m[1]);
|
||||
} catch (_) { /* 이미 지워졌을 수 있음 — 에디터에서는 이미 빠졌으니 조용히 무시 */ }
|
||||
if (onImageRemoved) onImageRemoved();
|
||||
}
|
||||
|
||||
function positionImgTools() {
|
||||
if (!selectedImg || !selectedImg.isConnected) { selectedImg = null; imgTools.hidden = true; return; }
|
||||
@@ -2161,10 +2189,7 @@
|
||||
document.addEventListener("click", function (e) {
|
||||
if (selectedImg && !wrap.contains(e.target)) selectImg(null);
|
||||
});
|
||||
imgDelBtn.addEventListener("click", function () {
|
||||
if (selectedImg) selectedImg.remove();
|
||||
selectImg(null);
|
||||
});
|
||||
imgDelBtn.addEventListener("click", function () { deleteSelectedImage(); });
|
||||
let dragging = false, dragStartX = 0, dragStartW = 0;
|
||||
imgHandle.addEventListener("mousedown", function (e) {
|
||||
if (!selectedImg) return;
|
||||
@@ -2190,8 +2215,7 @@
|
||||
const active = document.activeElement;
|
||||
if (active && ["INPUT", "TEXTAREA", "SELECT"].indexOf(active.tagName) >= 0) return;
|
||||
e.preventDefault();
|
||||
selectedImg.remove();
|
||||
selectImg(null);
|
||||
deleteSelectedImage();
|
||||
});
|
||||
|
||||
// 업로드 버튼 클릭 → 파일 선택창이 뜨는 동안 contenteditable의 선택 범위가
|
||||
@@ -2322,6 +2346,7 @@
|
||||
setHtml: function (html) { selectImg(null); lastRange = null; box.innerHTML = html || ""; },
|
||||
getHtml: function () { return box.innerHTML; },
|
||||
isUploading: function () { return pendingUploads > 0; },
|
||||
setOnImageRemoved: function (fn) { onImageRemoved = fn; },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user