feat(project): 완료 토글, 설명 이미지 크기조절/삭제, 연결폼 가독성, 모달 고정크기 800x1100

- 업무 편집 모달에 "완료로 표시" 버튼 추가(완료 시 리스트뷰는 기존 취소선
  스타일 그대로 적용됨). 완료 상태에 따라 버튼 색/문구 토글.
- 설명란 이미지 클릭 시 선택되어 우하단 드래그로 크기 조절, × 버튼으로 삭제
  가능. 크기는 style이 아닌 width 속성으로 저장해 서버 sanitize 후에도 유지.
- 연결된 프로젝트 select 를 세로 배치+작은 폰트로 바꿔 글자 잘림 해결.
- 업무 편집 모달을 800x1100 고정 크기로 바꾸고 좌(메타/설명)·우(하위업무·
  첨부·연결·댓글) 칼럼이 각자 내부 스크롤하도록 재정비.

fix(shell): 사이드바 접힘 상태를 localStorage에서 첫 페인트 전에 반영해
페이지 이동 시 "펼쳐졌다 다시 접히는" 깜빡임 제거.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 21:02:37 +09:00
parent 8449b404b2
commit b3d6a35651
6 changed files with 169 additions and 26 deletions
+46 -13
View File
@@ -310,16 +310,23 @@
.pj-modal { position: fixed; inset: 0; background: rgba(20,22,26,.46); display: flex; align-items: center; justify-content: center; z-index: 1000; }
.pj-modal[hidden] { display: none; }
.pj-modal-card { background: #fff; border-radius: 16px; padding: 22px; width: min(480px, 92vw); box-shadow: 0 20px 60px rgba(0,0,0,.25); max-height: 90vh; overflow-y: auto; }
/* 업무 편집 팝업만 넓게 — 메타/설명(좌) + 하위업무·첨부·연결·댓글(우) 2단.
우측 칼럼만 자체 스크롤 시켜 팝업 전체 스크롤은 웬만하면 안 생기게 한다. */
.pj-task-modal-card { width: min(780px, 96vw); }
.pj-modal-body { display: grid; grid-template-columns: 1.15fr .85fr; gap: 0 26px; align-items: start; }
.pj-modal-col-main, .pj-modal-col-side { min-width: 0; }
.pj-modal-col-side { max-height: 66vh; overflow-y: auto; padding-right: 4px; }
/* 업무 편집 팝업만 고정 크기(800x1100) — 메타/설명(좌) + 하위업무·첨부·연결·
댓글(우) 2단. 카드 자체 스크롤 없이 고정하고, 좌우 칼럼이 각자 내부
스크롤한다(우측은 늘 자체 스크롤, 좌측은 내용이 넘칠 때만). */
.pj-task-modal-card {
width: 800px; max-width: 96vw; height: 1100px; max-height: 94vh;
display: flex; flex-direction: column; overflow: hidden;
}
.pj-task-modal-card > .pj-t-title-input { flex: none; }
.pj-task-modal-card .pj-modal-body { flex: 1 1 auto; min-height: 0; }
.pj-task-modal-card .pj-modal-actions { flex: none; }
.pj-modal-body { display: grid; grid-template-columns: 1.15fr .85fr; gap: 0 26px; align-items: stretch; height: 100%; }
.pj-modal-col-main, .pj-modal-col-side { min-width: 0; min-height: 0; overflow-y: auto; padding-right: 4px; }
.pj-modal-col-side .pj-task-extra:first-child { margin-top: 0; padding-top: 0; border-top: none; }
@media (max-width: 720px) {
.pj-modal-body { grid-template-columns: 1fr; }
.pj-modal-col-side { max-height: none; overflow-y: visible; padding-right: 0; }
.pj-task-modal-card { width: min(480px, 94vw); height: auto; max-height: 90vh; overflow-y: auto; display: block; }
.pj-modal-body { display: block; height: auto; }
.pj-modal-col-main, .pj-modal-col-side { overflow: visible; height: auto; padding-right: 0; }
.pj-modal-col-side .pj-task-extra:first-child { border-top: 1px solid #eef0f2; margin-top: 14px; padding-top: 12px; }
}
.pj-modal-card h3 { margin: 0 0 16px; font-size: 17px; }
@@ -359,8 +366,10 @@
.pj-form-row input[type="time"] { display: block; width: 100%; margin-top: 5px; padding: 8px 10px; border: 1px solid #d8dce2; border-radius: 8px; font-size: 13.5px; font-family: inherit; box-sizing: border-box; }
.pj-form-row input[type="time"]:disabled { background: #f2f2f2; color: #aaa; cursor: not-allowed; }
#pj-time-row:has(input:disabled) label { color: #aaa; }
.pj-modal-actions { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.pj-modal-actions .pj-btn:last-child { }
.pj-modal-actions { display: flex; align-items: center; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.pj-btn-complete { background: #e9f7ef; color: #1e8e5a; border: 1px solid #bfe8d2; font-weight: 700; }
.pj-btn-complete:hover { background: #d9f2e4; }
.pj-btn-complete.is-done { background: #f2f2f4; color: #6b6f76; border-color: var(--pj-border); }
.pj-color-palette, #pj-f-colors { display: flex; gap: 8px; margin-top: 6px; }
.pj-color-swatch { width: 24px; height: 24px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; }
@@ -476,9 +485,27 @@
line-height: 1.5; margin-bottom: 12px; background: #fff;
}
.pj-desc-editor:empty::before { content: attr(data-placeholder); color: #b7bdc5; }
.pj-desc-editor img { max-width: 100%; border-radius: 6px; margin: 4px 0; display: block; }
.pj-desc-editor img { max-width: 100%; border-radius: 6px; margin: 4px 0; display: block; cursor: pointer; }
.pj-desc-editor img.pj-img-selected { outline: 2px solid var(--pj-accent); outline-offset: 1px; }
.pj-desc-editor[contenteditable="false"] { background: #f6f7f8; color: #9aa1a9; }
/* 설명란 이미지 선택 시 오버레이(삭제 × / 우하단 크기조절 핸들) — wrap 은
position:relative, tools 는 선택된 img 의 offsetLeft/Top/Width/Height 로
자리를 맞춘다(box 자체는 static 이라 offsetParent 가 wrap 이 된다). */
.pj-desc-wrap { position: relative; }
.pj-img-tools { position: absolute; pointer-events: none; }
.pj-img-del {
position: absolute; top: -9px; right: -9px; pointer-events: auto;
width: 20px; height: 20px; border-radius: 50%; border: none; background: #1e1f21; color: #fff;
font-size: 13px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0;
}
.pj-img-del:hover { background: #c22b10; }
.pj-img-handle {
position: absolute; bottom: -6px; right: -6px; pointer-events: auto;
width: 13px; height: 13px; border-radius: 3px; background: var(--pj-accent); cursor: nwse-resize;
border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,.25);
}
/* ── 하위 업무(인라인) ── */
.pj-subtask-list { list-style: none; margin: 0 0 8px; padding: 0; }
.pj-subtask-row { display: flex; align-items: center; gap: 6px; padding: 4px 2px; }
@@ -518,8 +545,14 @@
}
.pj-link-chip .pj-link-del { border: none; background: transparent; cursor: pointer; color: #9aa1a9; font-size: 13px; line-height: 1; padding: 2px; }
.pj-link-chip .pj-link-del:hover { color: #c22b10; }
.pj-link-form { display: flex; gap: 6px; align-items: center; }
.pj-link-form select { flex: 1; padding: 7px 8px; border: 1px solid #d8dce2; border-radius: 8px; font-size: 13px; font-family: inherit; }
/* 세로로 쌓기 — 옆 칼럼이 좁아 가로 배치면 select 글자가 잘린다. */
.pj-link-form { display: flex; flex-direction: column; gap: 6px; align-items: stretch; }
.pj-link-form select {
width: 100% !important; flex: none; margin: 0 !important;
padding: 6px 8px !important; border: 1px solid #d8dce2 !important; border-radius: 8px;
font-size: 11.5px !important; font-family: inherit; box-sizing: border-box;
}
.pj-link-form .pj-btn { align-self: flex-end; }
/* ── 알림센터 ── */
.pj-inbox { list-style: none; margin: 0; padding: 0; }