fix: 사용자 관리 페이지 공통 헤더 적용 및 권한 설정 오류 수정
Issues Fixed: 1. 개인 페이지 헤더 제거 - 기존 Header와 Navigation 삭제 - 공통 헤더 자동 삽입으로 변경 - padding-top: 120px 추가로 레이아웃 조정 2. showPagePermissionGrid 함수 오류 수정 - 'pages' 변수 참조 오류 해결 - pageCategories 기반으로 HTML 생성 로직 재작성 - 카테고리별 그룹화 UI 개선 3. 권한 시스템 완성 - users_manage 페이지 권한 추가 - 백엔드 DEFAULT_PAGES에 users_manage 추가 - 프론트엔드 권한 체크 로직 통합 4. UI/UX 개선 - 체크박스 상태에 따른 시각적 피드백 - 기본 권한 표시 배지 추가 - 호버 효과 및 트랜지션 개선 - 카테고리별 구분선 추가 Technical Changes: - 모든 페이지 권한을 포함한 allPages 배열 업데이트 - 권한 저장 시 존재하지 않는 체크박스 검증 추가 - 공통 헤더 초기화 및 페이지 접근 권한 체크 추가 - 백엔드 재시작으로 권한 시스템 변경사항 적용 Result: ✅ 사용자 선택 시 권한 설정 그리드 정상 표시 ✅ 모든 페이지 권한 (수신함, 관리함, 폐기함 포함) 관리 가능 ✅ 공통 헤더 통합으로 일관된 UI 제공 ✅ 권한 저장 및 로드 기능 정상 작동
This commit is contained in:
@@ -50,7 +50,8 @@ DEFAULT_PAGES = {
|
||||
'issues_archive': {'title': '폐기함', 'default_access': False},
|
||||
'projects_manage': {'title': '프로젝트 관리', 'default_access': False},
|
||||
'daily_work': {'title': '일일 공수', 'default_access': False},
|
||||
'reports': {'title': '보고서', 'default_access': False}
|
||||
'reports': {'title': '보고서', 'default_access': False},
|
||||
'users_manage': {'title': '사용자 관리', 'default_access': False}
|
||||
}
|
||||
|
||||
@router.post("/page-permissions/grant")
|
||||
|
||||
@@ -59,48 +59,10 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header -->
|
||||
<header class="bg-white shadow-sm sticky top-0 z-50">
|
||||
<div class="container mx-auto px-4 py-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<h1 class="text-xl font-bold text-gray-800">
|
||||
<i class="fas fa-clipboard-list mr-2"></i>작업보고서 시스템 - 관리자
|
||||
</h1>
|
||||
<button onclick="AuthAPI.logout()" class="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600 transition-colors text-sm">
|
||||
<i class="fas fa-sign-out-alt mr-1"></i>로그아웃
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav class="bg-white border-b">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="flex gap-2 py-2 overflow-x-auto">
|
||||
<a href="daily-work.html" class="nav-link">
|
||||
<i class="fas fa-calendar-check mr-2"></i>일일 공수
|
||||
</a>
|
||||
<a href="index.html" class="nav-link">
|
||||
<i class="fas fa-camera-retro mr-2"></i>부적합 등록
|
||||
</a>
|
||||
<a href="issue-view.html" class="nav-link">
|
||||
<i class="fas fa-search mr-2"></i>부적합 조회
|
||||
</a>
|
||||
<a href="index.html#list" class="nav-link">
|
||||
<i class="fas fa-list mr-2"></i>목록 관리
|
||||
</a>
|
||||
<a href="index.html#summary" class="nav-link">
|
||||
<i class="fas fa-chart-bar mr-2"></i>보고서
|
||||
</a>
|
||||
<a href="admin.html" class="nav-link active">
|
||||
<i class="fas fa-users-cog mr-2"></i>사용자 관리
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- 공통 헤더가 여기에 자동으로 삽입됩니다 -->
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="container mx-auto px-4 py-8 max-w-6xl">
|
||||
<main class="container mx-auto px-4 py-8 max-w-6xl" style="padding-top: 120px;">
|
||||
<div class="grid md:grid-cols-2 gap-6">
|
||||
<!-- 사용자 추가 섹션 -->
|
||||
<div class="bg-white rounded-xl shadow-sm p-6">
|
||||
@@ -295,6 +257,15 @@
|
||||
// 공통 헤더 초기화
|
||||
await window.commonHeader.init(user, 'users_manage');
|
||||
|
||||
// 페이지 접근 권한 체크
|
||||
setTimeout(() => {
|
||||
if (!canAccessPage('users_manage')) {
|
||||
alert('사용자 관리 페이지에 접근할 권한이 없습니다.');
|
||||
window.location.href = '/index.html';
|
||||
return;
|
||||
}
|
||||
}, 500);
|
||||
|
||||
} catch (error) {
|
||||
console.error('인증 실패:', error);
|
||||
localStorage.removeItem('access_token');
|
||||
@@ -571,30 +542,65 @@
|
||||
const grid = document.getElementById('pagePermissionGrid');
|
||||
const gridContainer = grid.querySelector('.grid');
|
||||
|
||||
// 페이지 권한 체크박스 생성
|
||||
const pages = {
|
||||
'issues_create': '부적합 등록',
|
||||
'issues_view': '부적합 조회',
|
||||
'issues_manage': '부적합 관리',
|
||||
'projects_manage': '프로젝트 관리',
|
||||
'daily_work': '일일 공수',
|
||||
'reports': '보고서'
|
||||
// 페이지 권한 체크박스 생성 (카테고리별로 그룹화)
|
||||
const pageCategories = {
|
||||
'부적합 관리': {
|
||||
'issues_create': { title: '부적합 등록', icon: 'fas fa-plus-circle', color: 'text-green-600' },
|
||||
'issues_view': { title: '부적합 조회', icon: 'fas fa-search', color: 'text-purple-600' },
|
||||
'issues_manage': { title: '목록 관리 (통합)', icon: 'fas fa-tasks', color: 'text-orange-600' }
|
||||
},
|
||||
'목록 관리 세부': {
|
||||
'issues_inbox': { title: '📥 수신함', icon: 'fas fa-inbox', color: 'text-blue-600' },
|
||||
'issues_management': { title: '⚙️ 관리함', icon: 'fas fa-cog', color: 'text-green-600' },
|
||||
'issues_archive': { title: '🗃️ 폐기함', icon: 'fas fa-archive', color: 'text-gray-600' }
|
||||
},
|
||||
'시스템 관리': {
|
||||
'projects_manage': { title: '프로젝트 관리', icon: 'fas fa-folder-open', color: 'text-indigo-600' },
|
||||
'daily_work': { title: '일일 공수', icon: 'fas fa-calendar-check', color: 'text-blue-600' },
|
||||
'reports': { title: '보고서', icon: 'fas fa-chart-bar', color: 'text-red-600' },
|
||||
'users_manage': { title: '사용자 관리', icon: 'fas fa-users-cog', color: 'text-purple-600' }
|
||||
}
|
||||
};
|
||||
|
||||
gridContainer.innerHTML = Object.entries(pages).map(([pageName, title]) => `
|
||||
<div class="flex items-center p-3 border rounded-lg">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="perm_${pageName}"
|
||||
${currentPermissions[pageName] ? 'checked' : ''}
|
||||
class="mr-3 h-4 w-4 text-purple-600 rounded focus:ring-purple-500"
|
||||
>
|
||||
<label for="perm_${pageName}" class="text-sm font-medium text-gray-700">
|
||||
${title}
|
||||
</label>
|
||||
</div>
|
||||
`).join('');
|
||||
let html = '';
|
||||
|
||||
// 카테고리별로 그룹화하여 표시
|
||||
Object.entries(pageCategories).forEach(([categoryName, pages]) => {
|
||||
html += `
|
||||
<div class="col-span-full">
|
||||
<h4 class="text-sm font-semibold text-gray-800 mb-3 pb-2 border-b border-gray-200">
|
||||
${categoryName}
|
||||
</h4>
|
||||
</div>
|
||||
`;
|
||||
|
||||
Object.entries(pages).forEach(([pageName, pageInfo]) => {
|
||||
const isChecked = currentPermissions[pageName] || false;
|
||||
const isDefault = currentPermissions[pageName] === undefined ?
|
||||
(pageInfo.title.includes('등록') || pageInfo.title.includes('조회') || pageInfo.title.includes('수신함')) : false;
|
||||
|
||||
html += `
|
||||
<div class="flex items-center p-3 border rounded-lg hover:bg-gray-50 transition-colors ${isChecked ? 'border-blue-300 bg-blue-50' : 'border-gray-200'}">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="perm_${pageName}"
|
||||
${isChecked ? 'checked' : ''}
|
||||
class="mr-3 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||
onchange="this.parentElement.classList.toggle('border-blue-300', this.checked); this.parentElement.classList.toggle('bg-blue-50', this.checked);"
|
||||
>
|
||||
<label for="perm_${pageName}" class="flex-1 cursor-pointer">
|
||||
<div class="flex items-center">
|
||||
<i class="${pageInfo.icon} ${pageInfo.color} mr-2"></i>
|
||||
<span class="text-sm font-medium text-gray-700">${pageInfo.title}</span>
|
||||
${isDefault ? '<span class="ml-2 text-xs bg-green-100 text-green-800 px-2 py-1 rounded-full">기본</span>' : ''}
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
});
|
||||
|
||||
gridContainer.innerHTML = html;
|
||||
grid.classList.remove('hidden');
|
||||
}
|
||||
|
||||
@@ -615,13 +621,19 @@
|
||||
statusSpan.textContent = '';
|
||||
|
||||
try {
|
||||
// 체크박스 상태 수집
|
||||
const pages = ['issues_create', 'issues_view', 'issues_manage', 'projects_manage', 'daily_work', 'reports'];
|
||||
// 체크박스 상태 수집 (모든 페이지 포함)
|
||||
const allPages = [
|
||||
'issues_create', 'issues_view', 'issues_manage',
|
||||
'issues_inbox', 'issues_management', 'issues_archive',
|
||||
'projects_manage', 'daily_work', 'reports', 'users_manage'
|
||||
];
|
||||
const permissions = {};
|
||||
|
||||
pages.forEach(pageName => {
|
||||
allPages.forEach(pageName => {
|
||||
const checkbox = document.getElementById(`perm_${pageName}`);
|
||||
permissions[pageName] = checkbox.checked;
|
||||
if (checkbox) {
|
||||
permissions[pageName] = checkbox.checked;
|
||||
}
|
||||
});
|
||||
|
||||
// 실제 API 호출로 권한 저장
|
||||
|
||||
Reference in New Issue
Block a user