c51873ab85
fix(frontend): a11y/호환성 — backdrop-filter webkit prefix + Button/Input/Select 접근 이름
...
axe/forms/backdrop 에러 3종 모두 해결:
1) CSS: backdrop-filter Safari 호환성
- design-system CSS에 -webkit-backdrop-filter 추가
- trk-pulse 애니메이션을 outline-color → opacity로 변경
(composite만 트리거, paint/layout 없음 → 더 나은 성능)
2) 아이콘 전용 <button> aria-label 추가 (9곳):
- MainLayout 알림 버튼 → '알림'
- UserRoleAssignDialog 닫기 → '닫기'
- AIAssistant/MLOpsPage 전송 → '전송'
- ChinaFishing 좌/우 네비 → '이전'/'다음'
- 공통 컴포넌트 (PrintButton/ExcelExport/SaveButton) type=button 누락 보정
3) <input>/<textarea> 접근 이름 27곳 추가:
- 로그인 폼, ParentReview/LabelSession/ParentExclusion 폼 (10)
- NoticeManagement 제목/내용/시작일/종료일 (4)
- SystemConfig/DataHub/PermissionsPanel 검색·역할 입력 (5)
- VesselDetail 조회 시작/종료/MMSI (3)
- GearIdentification InputField에 label prop 추가
- AIAssistant/MLOpsPage 질의 input/textarea
- MainLayout 페이지 내 검색
- 공통 placeholder → aria-label 자동 복제 (3)
Button 컴포넌트에는 접근성 정책 JSDoc 명시 (타입 강제는 API 복잡도 대비
이득 낮아 문서 가이드 + 코드 리뷰로 대응).
검증:
- 실제 위반 지표: inaccessible button 0, inaccessible input 0, textarea 0
- tsc ✅ , eslint ✅ , vite build ✅
- dist CSS에 -webkit-backdrop-filter 확인됨
2026-04-08 13:04:23 +09:00
a07c745cbc
feat(frontend): 40+ 페이지 Badge/시맨틱 토큰 마이그레이션
...
- 모든 feature 페이지의 Badge className 패턴을 intent/size prop으로 변환
- 컬러풀 액션 버튼 (bg-*-500/600/700 + text-heading) -> text-on-vivid
- 검색/필터 버튼 배경 bg-blue-400 + text-on-bright (밝은 배경 위 검정)
- ROLE_COLORS 4곳 중복 제거 (MainLayout/UserRoleAssignDialog/
PermissionsPanel/AccessControl) -> getRoleBadgeStyle 공통 호출
- PermissionsPanel 역할 생성/수정에 ColorPicker 통합
- MainLayout: PagePagination + scroll page state 제거 (데이터 페이지네이션 혼동)
- Dashboard RiskBar 단위 버그 수정 (0~100 정수 처리)
- ReportManagement, TransferDetection p-5 space-y-4 padding 복구
- EnforcementHistory 그리드 minmax 적용으로 컬럼 잘림 해소
- timeline 시간 formatDateTime 적용 (ISO T 구분자 처리)
- 각 feature 페이지가 공통 카탈로그 API (getXxxIntent/Label/Classes) 사용
2026-04-08 10:53:58 +09:00
febfb2cbe8
feat: Phase 5 - 권한 관리 UI 고도화 (트리 RBAC PermissionsPanel)
...
버그 수정:
- AccessControl 무한 새로고침 (loadRoles의 userStats 의존성 → setUserStats 호출 → 무한 루프)
loadRoles에서 항상 fetchUserStats를 같이 호출하도록 변경
백엔드 API 추가:
- RoleManagementService (역할/권한 매트릭스 CRUD)
- createRole / updateRole / deleteRole (built-in 보호)
- updatePermissions (Y/N upsert + null 시 명시 권한 제거)
- assignUserRoles (전체 교체 방식, 권한 캐시 evict)
- 모든 액션에 @Auditable 자동 기록
- PermTreeController 확장:
- POST /api/roles (admin:role-management:CREATE)
- PUT /api/roles/{sn} (admin:role-management:UPDATE)
- DELETE /api/roles/{sn} (admin:role-management:DELETE)
- PUT /api/roles/{sn}/permissions (admin:permission-management:UPDATE)
- PUT /api/admin/users/{id}/roles (admin:user-management:UPDATE)
- DTO: RoleCreateRequest, RoleUpdateRequest, PermissionUpdateRequest, UserRoleAssignRequest
- GlobalExceptionHandler:
- IllegalArgumentException → 400 BAD_REQUEST
- IllegalStateException → 409 CONFLICT
- AccessDeniedException → 403 FORBIDDEN
프론트엔드:
- lib/permission/permResolver.ts (TypeScript 미러)
- resolveSingleRoleEffective: 백엔드 PermResolver와 동일 알고리즘
- 4가지 셀 상태 계산 (explicit-granted/inherited-granted/explicit-denied/forced-denied)
- PermissionsPanel.tsx (트리 + R/C/U/D/E 매트릭스)
- 좌측: 역할 목록 + 신규 생성 + 삭제 (built-in 보호)
- 우측: 트리 표 + 셀 클릭 (Y → N → 미지정 순환)
- 부모 READ 게이팅 시각화 (강제 거부 회색 비활성)
- 변경된 셀만 일괄 저장 (dirty 추적)
- UserRoleAssignDialog.tsx
- 사용자에게 역할 다중 선택 배정 (체크박스)
- adminApi.ts 확장: createRole/updateRole/deleteRole/updateRolePermissions/assignUserRoles
- AccessControl.tsx 갱신:
- 역할 관리 탭 → PermissionsPanel 통합
- 사용자 관리 탭 → 역할 배정 버튼 추가 (UserCog 아이콘)
검증:
- 역할 생성 → TESTROLE 6번으로 추가
- 권한 매트릭스 갱신 → dashboard/monitoring READ 부여 (changed: 2)
- 역할 삭제 → built-in이 아니면 OK
- built-in ADMIN 삭제 시도 → 400 BAD_REQUEST (BUILTIN_ROLE_CANNOT_DELETE)
- viewer에게 OPERATOR + ANALYST 다중 배정 → roles=[OPERATOR, ANALYST]
→ 재로그인 시 detection READ 등 자동 상속 확인
- 권한 캐시 evictAllPermissions 즉시 반영
- 프론트 빌드 통과 (533ms)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 10:11:27 +09:00