feat(project): 세션 색상/편집, 프로젝트 트리 드래그, 멤버업무 정렬, 댓글팝업 버그수정
- 좌측 프로젝트 리스트 드래그 재정렬(관리자, 홈 카드와 동일 API) - 세션 추가/편집 팝업: 이름 + 아사나 10색 색상표(project_stages.color, 마이그레이션 004) - 보드 세션 hover 아이콘 확대, 세션 제목 강조(업무 카드보다 크고 굵게) - 완료 세션 반투명 + 보드 끝으로(정렬 기준만 변경 — 해제 시 원래 순서 자동 복귀) - 전체 멤버 업무 팝업에 표 헤더(가운데정렬/굵게) + 정렬 아이콘 + 더블클릭 편집 - 댓글 채팅 팝업을 initCommentsChat() 공용화 — project.html에 모달이 없어 "내 업무" 패널 댓글 더블클릭이 전혀 동작 안 했던 버그 수정(동적 배지 재바인딩 누락도 같이 수정) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -238,11 +238,13 @@ class ProjectStore:
|
||||
return [self._serialize(r) for r in rows]
|
||||
|
||||
def add_stage(
|
||||
self, *, project_id: int, name: str, is_done_stage: bool = False, created_by: str = ""
|
||||
self, *, project_id: int, name: str, is_done_stage: bool = False,
|
||||
color: str | None = None, created_by: str = "",
|
||||
) -> dict[str, Any]:
|
||||
nm = store.norm_str(name)
|
||||
if not nm:
|
||||
raise ValueError("세션 이름은 필수입니다.")
|
||||
col = store.validate_stage_color(color)
|
||||
with self._pool.connection() as conn:
|
||||
nxt = conn.execute(
|
||||
"SELECT COALESCE(MAX(sort_order), -1) + 1 AS n "
|
||||
@@ -250,9 +252,9 @@ class ProjectStore:
|
||||
(project_id,),
|
||||
).fetchone()
|
||||
row = conn.execute(
|
||||
"INSERT INTO project_stages (project_id, name, sort_order, is_done_stage, created_by) "
|
||||
"VALUES (%s,%s,%s,%s,%s) RETURNING *",
|
||||
(project_id, nm, int(nxt["n"]), bool(is_done_stage),
|
||||
"INSERT INTO project_stages (project_id, name, sort_order, is_done_stage, color, created_by) "
|
||||
"VALUES (%s,%s,%s,%s,%s,%s) RETURNING *",
|
||||
(project_id, nm, int(nxt["n"]), bool(is_done_stage), col,
|
||||
store.norm_str(created_by, lower=True)),
|
||||
).fetchone()
|
||||
return self._serialize(row)
|
||||
@@ -776,8 +778,10 @@ class ProjectStore:
|
||||
# ════════════════════════════════════════════════════════════
|
||||
def update_stage(
|
||||
self, *, stage_id: int, name: str | None = None,
|
||||
is_done_stage: bool | None = None,
|
||||
is_done_stage: bool | None = None, color: Any = ...,
|
||||
) -> dict[str, Any]:
|
||||
"""color 는 지정 안 함(기본 `...`)과 명시적으로 지우기(`None`)를
|
||||
구분해야 해서 다른 필드처럼 `is None` 이 아니라 `is not ...` 로 검사한다."""
|
||||
sets: list[str] = []
|
||||
params: list[Any] = []
|
||||
if name is not None:
|
||||
@@ -789,6 +793,9 @@ class ProjectStore:
|
||||
if is_done_stage is not None:
|
||||
sets.append("is_done_stage = %s")
|
||||
params.append(bool(is_done_stage))
|
||||
if color is not ...:
|
||||
sets.append("color = %s")
|
||||
params.append(store.validate_stage_color(color))
|
||||
if not sets:
|
||||
raise ValueError("변경할 내용이 없습니다.")
|
||||
params.append(stage_id)
|
||||
|
||||
Reference in New Issue
Block a user