푸들푸들

[Error] 모달 fetch 404 본문

구디아카데미/Error

[Error] 모달 fetch 404

COCO_develop 2025. 1. 23. 15:30

조직도 그리기

우여곡절 끝에 차트 그리기 성공!

<div class="container" style="margin-top: 50px; margin-bottom: 300px; width: 100%;">
    <div class="orgChart tree">
        <!-- 조직도 차트 -->
    </div>
</div> 

<!-- Modal - 부서장 정보-->
<div class="modal fade" id="empModal" tabindex="-1" role="dialog" aria-labelledby="empModal" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">부서장 정보</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true">
                    <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
                        stroke-linecap="round" stroke-linejoin="round" class="feather feather-x">
                        <line x1="18" y1="6" x2="6" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line></svg>
                </button>
            </div>

            <div class="modal-body">
                <div class="mb-3">
                    <label class="form-label">이름</label> 
                    <input type="text" class="form-control" name="ename" readonly>
                </div>
                <div class="mb-3">
                    <label class="form-label">부서</label> 
                    <input type="text" class="form-control" name="dname" readonly>
                </div>
                <div class="mb-3">
                    <label class="form-label">직급</label> 
                    <input type="text" class="form-control" name="location" readonly>
                </div>
                <div class="mb-3">
                    <label class="form-label">이메일</label> 
                    <input type="text" class="form-control" name="email" readonly>
                </div>
                <div class="mb-3">
                    <label class="form-label">내선번호</label> 
                    <input type="text" class="form-control" name="extNum" readonly>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary mt-2 mb-2 btn-no-effect" data-bs-dismiss="modal">확인</button>
            </div>
        </div>
    </div>
</div> <!-- END Modal - 부서장 정보-->

<!-- Modal - 부서 정보-->
<div class="modal fade" id="deptModal" tabindex="-1" role="dialog" aria-labelledby="deptModal" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">부서 정보</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true">
                    <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
                        stroke-linecap="round" stroke-linejoin="round" class="feather feather-x">
                        <line x1="18" y1="6" x2="6" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line></svg>
                </button>
            </div>

            <div class="modal-body">
                <div class="mb-3">
                    <label class="form-label">부서명</label> 
                    <input type="text" class="form-control" name="dname" readonly>
                </div>
                <table class="table">
                    <thead>
                        <tr>
                            <th>이름</th>
                            <th>직급</th>
                            <th>이메일</th>
                            <th>내선번호</th>
                        </tr>
                    </thead>
                    <tbody>
                        <!-- 직원 정보 -->
                    </tbody>
                </table>

            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary mt-2 mb-2 btn-no-effect" data-bs-dismiss="modal">확인</button>
            </div>
        </div>
    </div>
</div><!-- END Modal - 부서 정보 -->

 

<script>
const deptList =  JSON.parse('${deptListJson}'); // 서버에서 전달된 deptList를 JSON으로 변환

// 1. 계층 구조 생성
const treeData = {
  id: "root",
  name: "CEO <br>${c.leader}", // 회사 대표 이름
  children: []
};

deptList.forEach((dept) => {
  // 부서 찾기
  let department = treeData.children.find(d => d.id === String(dept.depNo));
  if (!department) { // 부서 존재하지 않으면 새로 추가
    department = {
      id: String(dept.depNo),
      name: dept.dname,
      children: []
    };
    treeData.children.push(department);
  }

  // 부서장 추가
  department.children.push({
    id: String(dept.headEmpNo),
    name: dept.headName || '-',
    dname: dept.dname,
    location: dept.location,
    position: "부서장",
    email: dept.email, 
    extNum: dept.extNum
  });

});

// 2. 계층 구조를 HTML로 변환
function generateTreeHTML(node) {
    if (!node.children || node.children.length === 0) {
      return `
              <li>
                 <a class="btn head" data-bs-toggle="modal" data-bs-target="#empModal" 
                        data-name="\${node.name || '-'}" data-dname="\${node.dname}" data-location="\${node.location}" data-email="\${node.email || '-'}" data-extnum="\${node.extNum || '-'}" 
                        onclick="setModalDataFromElement(this)">\${node.name}</a>
               </li>
          `;
    }

    let childrenHTML = node.children.map(child => generateTreeHTML(child)).join("");
    return `
            <li>
                <a class="btn dept" data-bs-toggle="modal" 
                        data-bs-target="\${node.name === 'CEO <br>${c.leader}' ? '' : '#deptModal'}" 
                        data-dname="\${node.name}" data-depno="\${node.id}" 
                        onclick="if('${node.name}' === 'CEO <br>${c.leader}') return false; else setModalDataFromElement(this)">\${node.name}</a>
                <ul>
                   \${childrenHTML}
                 </ul>
            </li>
         `; // CEO는 모달 XX
}

// 3. 트리 HTML 생성 및 삽입
const treeHTML = generateTreeHTML(treeData);
// console.log(treeHTML);
document.addEventListener("DOMContentLoaded", () => {
    document.querySelector(".orgChart").innerHTML = `<ul>\${treeHTML}</ul>`;
});

// 모달창마다 데이터 받기
function setModalDataFromElement(element) {
    const name = element.getAttribute('data-name');
    const dname = element.getAttribute('data-dname');
    const location = element.getAttribute('data-location');
    const email = element.getAttribute('data-email');
    const extNum = element.getAttribute('data-extnum');

    if (element.classList.contains('head')) { // 부서장 클릭
        setEmpModalData({
            name: name,
            dname: dname,
            location: location,
            email: email,
            extNum: extNum
        });
    } else {
        // 부서 클릭
        const depNo = element.getAttribute('data-depno'); 
        getEmployeesByDept(depNo).then(employees => {
            setDeptModalData({
                dname: dname,
                employees: employees
            });
        });
    }
}

// 부서장 정보 모달 데이터 설정 함수
function setEmpModalData(nodeData) {
    // nodeData는 선택된 부서장 또는 부서의 데이터
    const position = {
        'I01': '사원',
        'I02': '팀장',
        'I03': '부서장'		
    }

    document.querySelector('.modal-body .form-control[name="ename"]').value = nodeData.name || '';
    document.querySelector('.modal-body .form-control[name="dname"]').value = nodeData.dname || '';
    document.querySelector('.modal-body .form-control[name="location"]').value =  position[nodeData.location] || '-';
    document.querySelector('.modal-body .form-control[name="email"]').value = nodeData.email || '';
    document.querySelector('.modal-body .form-control[name="extNum"]').value = nodeData.extNum || '';
}

// 부서별 직원 모달 데이터 설정 함수
function setDeptModalData(department) {
    document.querySelector('#deptModal .modal-body .form-control[name="dname"]').value = department.dname || '';

    // 직원 정보 출력
    const employeeList = department.employees.map(emp => `
        <tr>
            <td>${emp.ename}</td>
            <td>${emp.location || '-'}</td>
            <td>${emp.email || '-'}</td>
            <td>${emp.extNum || '-'}</td>
        </tr>
    `).join('');

    console.log('Employee List:', employeeList);
    document.querySelector('#deptModal .modal-body .table tbody').innerHTML = employeeList;
}

var contextPath = '${pageContext.request.contextPath}';

// 부서별 직원 정보를 가져오는 함수
function getEmployeesByDept(depNo) {
    return fetch(contextPath + '/depts/employees?depNo=' + depNo)
        .then(response => {
            if (!response.ok) {
                throw new Error('서버 응답 실패');
            }
            return response.json(); // JSON 형태로 응답을 파싱
        })
       .then(data => {
           console.log('Employees Data:',data);
            return data; // 가져온 데이터를 반환
        })
        .catch(error => {
            console.error('Fetch Error:',  error);
            return []; // 오류가 발생하면 빈 배열 반환
        });
}
</script>

부서를 클릭하면 해당 부서의 직원 정보 테이블 모달창이 뜨고,

부서장 이름을 클릭하면 해당 부서장의 정보 모달창이 뜨게 구현 중.

부서장 정보는 잘 불러오지만,

부서 직원 정보가 오류.

 

콘솔창에 404오류. depNo 값은 잘 들어감.

 

컨트롤러 불러오는게 문제가 있는 거 같아 컨트롤러 확인.

@GetMapping("/depts/chart")
public String deptChart(Model model) {
    List<Map<String,Object>> deptList = deptService.getDeptHead();

    Company company = companyService.getCompanyInfo();
    model.addAttribute("c", company);

    // JSON 문자열로 변환
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        String deptListJson = objectMapper.writeValueAsString(deptList);
        // System.out.println("deptListJson: " + deptListJson);
        model.addAttribute("deptListJson", deptListJson);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "dept/chart";
}

@GetMapping("/depts/employees")
public List<Map<String, Object>> EmployeesByDept(@RequestParam Integer depNo) {
    return empService.getEmpBydept(depNo);
}

@GetMapping("/depts/employees") -> 이 컨트롤러가 문제인듯 함.

empService.getEmpBydept(depNo)

-> 쿼리 

SELECT
    e.emp_no empNo
    , e.dep_no depNo
    , d.dname dname
    , e.ename ename
    , e.location location
    , e.email email
    , e.ext_num extNum
FROM emp e
INNER JOIN dept d
    ON e.dep_no = d.dep_no
WHERE e.dep_no = #{depNo} AND e.exit_date IS NULL
ORDER BY e.location DESC, e.ename

 

페이지 전환이 없으니 Rest controller로 바꿔봄.

@RestController
public class DeptRestController {
	@GetMapping("/depts/employees")
	public ResponseEntity<List<Map<String, Object>>> getEmployeesByDept(@RequestParam Integer depNo) {
        List<Map<String, Object>> employees = empService.getEmpBydept(depNo);
        return ResponseEntity.ok(employees);
    }
}

뭔가 뜨긴 했다.. 값이 제대로 매치가 안되는 듯 함

-> 출력하는 부분 백틱(`) 안 ${}에 역슬래시(\) 넣어보기

// 부서별 직원 모달 데이터 설정 함수
function setDeptModalData(department) {
    document.querySelector('#deptModal .modal-body .form-control[name="dname"]').value = department.dname || '';

    // 직원 정보 출력
    const employeeList = department.employees.map(emp => `
        <tr>
            <td>\${emp.ename}</td>
            <td>\${emp.location || '-'}</td>
            <td>\${emp.email || '-'}</td>
            <td>\${emp.extNum || '-'}</td>
        </tr>
    `).join('');

    console.log('Employee List:', employeeList);
    document.querySelector('#deptModal .modal-body .table tbody').innerHTML = employeeList;
}

 

값 불러오기는 성공!

 

이제 모달창 크기를 동적 적용 시켜야겠다..

 

<div class="modal-dialog" role="document" style="max-width: 900px; width: 75%;">

크기 조절까지 해결!

 

직급 코드를 직급명으로 바꾸기

// 직급 코드 -> 직급명
const position = {
    'I01': '사원',
    'I02': '팀장',
    'I03': '부서장'		
}

// 부서별 직원 모달 데이터 설정 함수
function setDeptModalData(department) {
    document.querySelector('#deptModal .modal-body .form-control[name="dname"]').value = department.dname || '';

    // 직원 정보 출력
    const employeeList = department.employees.map(emp => `
        <tr>
            <td>\${emp.ename}</td>
            <td>\${position[emp.location] || '-'}</td>
            <td>\${emp.email || '-'}</td>
            <td>\${emp.extNum || '-'}</td>
        </tr>
    `).join('');

    // console.log('Employee List:', employeeList);
    document.querySelector('#deptModal .modal-body .table tbody').innerHTML = employeeList;
}

emp.location -> position[emp.location]

해결!

'구디아카데미 > Error' 카테고리의 다른 글

[Error] 탭 변경 시 CSS 깨짐  (0) 2025.01.14
[Error] Jsp <script> ${} 오류  (1) 2025.01.14
[Error] 400 오류 - Spring Security  (0) 2025.01.13
[Error] 500 오류  (0) 2024.11.14
[Error] 400 오류 / 검색 기능  (0) 2024.11.13