From 866b432a29b786acf79a44c35f4f012d1a0b351c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Jun 2026 15:05:53 +0900 Subject: [PATCH] feat: use full-width row buttons for history list to avoid radio button selection --- app.py | 110 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/app.py b/app.py index bec3477..fb3207a 100644 --- a/app.py +++ b/app.py @@ -782,66 +782,66 @@ def page_history(): if st.session_state["selected_analysis_id"] not in valid_ids and records: st.session_state["selected_analysis_id"] = records[0]["id"] - # 2컬럼 대시보드 레이아웃 구성 - col_list, col_detail = st.columns([1, 2.5]) + st.write("### 📋 분석 이력 목록") + st.caption("💡 아래 목록에서 **원하는 행(보고서 카드)**을 누르시면 하단의 상세 분석 내역이 즉시 갱신됩니다.") - # 1. 왼쪽 컬럼: 분석 이력 카드 버튼 목록 (마우스로 편하게 누르는 영역) - with col_list: - st.write("### 📋 보고서 목록") - st.caption("아래 목록을 클릭하시면 상세 내역이 오른쪽에 즉시 표시됩니다.") - status_emoji = {"critical": "🔴", "warning": "🟡", "healthy": "🟢"} - - with st.container(height=650): - for r in records: - emoji = status_emoji.get(r['overall_status'], '🟢') - is_selected = (r["id"] == st.session_state["selected_analysis_id"]) - - # 선택된 보고서는 강조 표시 - prefix = "▶️ " if is_selected else "" - btn_label = f"{prefix}{emoji} [ID: {r['id']}] {r['filename'][:23]}\n({r['created_at'].split()[0]})" - - # 버튼으로 구현하여 일반 마우스 클릭이 100% 동작하도록 처리 - if st.button( - btn_label, - key=f"btn_hist_{r['id']}", - use_container_width=True, - type="primary" if is_selected else "secondary" - ): - st.session_state["selected_analysis_id"] = r["id"] - st.rerun() + status_emoji = {"critical": "🔴", "warning": "🟡", "healthy": "🟢"} - # 2. 오른쪽 컬럼: 선택된 보고서의 상세 분석 내용 렌더링 - with col_detail: - selected_id = st.session_state["selected_analysis_id"] - detail = get_analysis_detail(selected_id) - - if not detail: - st.warning(f"ID {selected_id}에 해당하는 분석 결과가 없습니다.") - else: - st.write(f"### 🔎 상세 분석 결과 (보고서 ID: {selected_id})") + # 스크롤 가능한 컨테이너 내부에 라디오 버튼이 없는 가로형 통짜 클릭 행 렌더링 + with st.container(height=380): + for r in records: + emoji = status_emoji.get(r['overall_status'], '🟢') + is_selected = (r["id"] == st.session_state["selected_analysis_id"]) - # 메모 편집 (editor/admin만) - perms = get_perms() - current_memo = detail.get("memo", "") or "" - if perms["can_edit_memo"]: - new_memo = st.text_area("📝 메모 수정", value=current_memo, key=f"memo_{selected_id}") - if new_memo != current_memo: - update_memo(selected_id, new_memo) - st.success("메모가 업데이트되었습니다.") - elif current_memo: - st.text_area("📝 메모", value=current_memo, key=f"memo_{selected_id}", disabled=True) + # 행 전체를 하나의 널찍한 버튼으로 구성 (마우스 클릭 영역 극대화) + # 라벨 포맷: 상태이모지 | 파일명 | 분석일시 | 요약통계 + btn_label = ( + f"{emoji} [ID: {r['id']}] {r['filename'][:30]} | " + f"🕒 {r['created_at']} | " + f"🎮 GPU {r['gpu_count']}개 / ⚠️ XID {r['xid_count']}건 / 🔧 RMA {r['rma_count']}대" + ) + + # 버튼 클릭 시 해당 보고서 ID로 세션 상태를 저장하고 화면 갱신 + if st.button( + btn_label, + key=f"btn_row_{r['id']}", + use_container_width=True, + type="primary" if is_selected else "secondary" + ): + st.session_state["selected_analysis_id"] = r["id"] + st.rerun() - # 삭제 버튼 (admin만) - if perms["can_delete"]: - if st.button("🗑️ 이 분석 기록 삭제", type="secondary"): - delete_analysis(selected_id) - st.success(f"ID {selected_id} 삭제 완료.") - # 삭제 후 첫 번째 보고서로 세션 초기화 및 리런 - st.session_state["selected_analysis_id"] = records[0]["id"] if len(records) > 1 else 1 - st.rerun() + # 상세 조회 + st.markdown("---") + selected_id = st.session_state["selected_analysis_id"] + detail = get_analysis_detail(selected_id) + + if not detail: + st.warning(f"ID {selected_id}에 해당하는 분석 결과가 없습니다.") + return - # 상세 내용 렌더링 시작 - render_status_badge(detail["overall_status"]) + # 메모 편집 (editor/admin만) + perms = get_perms() + current_memo = detail.get("memo", "") or "" + if perms["can_edit_memo"]: + new_memo = st.text_area("📝 메모 수정", value=current_memo, key=f"memo_{selected_id}") + if new_memo != current_memo: + update_memo(selected_id, new_memo) + st.success("메모가 업데이트되었습니다.") + elif current_memo: + st.text_area("📝 메모", value=current_memo, key=f"memo_{selected_id}", disabled=True) + + # 삭제 버튼 (admin만) + if perms["can_delete"]: + if st.button("🗑️ 이 분석 기록 삭제", type="secondary"): + delete_analysis(selected_id) + st.success(f"ID {selected_id} 삭제 완료.") + # 삭제 후 첫 번째 보고서로 세션 초기화 및 리런 + st.session_state["selected_analysis_id"] = records[0]["id"] if len(records) > 1 else 1 + st.rerun() + + # 상세 내용 렌더링 시작 + render_status_badge(detail["overall_status"]) dc1, dc2, dc3, dc4 = st.columns(4) dc1.metric("파일명", detail["filename"][:30])