import { vars } from './variable.js'; import { toggleBannerNoticeArea } from '../main.js'; import { addCommasToNumber, getDepth, // getRootFolderPath, updatePartialPath, splitTopPathAndTargetName, extractPathByLength, getDataFromTreeObject, targetFocus } from './common.js'; import { removeCountdownTooltip, preparePageRendering, prepareRecycleBinRendering, renderViewer, resetViewer, renderSizeBar, renderLog, renderMemo, changeHeaderBtnStyle, changeTreeItemStyle, changeListItemStyle, } from './pageRenderer.js'; import { toggleModal } from './modalManager.js' import { mgmtFunc_addClickLog } from './managementFunctions.js'; import { updateAiButtonState } from './dataManager.js'; import { toggleArchiveMainRight } from './eventManager.js'; let archiveMain = document.querySelector('.archive-main'); let mainNotice = document.querySelector('.main-notice'); let treeContainer = document.querySelector('.archive-main-left .tree-container'); let treeNotice = document.querySelector('.archive-main-left .tree-container .tree-notice'); let treeWrap = document.querySelector('.archive-main-left .tree-container .tree-wrap'); let listContainer = document.querySelector('.archive-main-center .list-container'); let listNotice = document.querySelector('.archive-main-center .list-notice'); let listWrapBody = listContainer?.querySelector('.list-wrap.list-body'); let viewerContainer = document.querySelector('.archive-main-right .viewer-container'); let viewerNotice = document.querySelector('.archive-main-right .viewer-notice'); const socket = io(); //// 소켓은 하나만... vars.socket = socket; function getMyCurPath() { if (vars.users && vars.users[socket.id] && vars.users[socket.id].curPath) { return vars.users[socket.id].curPath; } if (vars.userInfoString) { try { return JSON.parse(vars.userInfoString).curPath || ''; } catch (e) {} } return ''; } //// 접속자 정보 가져오기 export function getUsers() { vars.socket.emit('getUsers'); } //// 유저 정보 받기 socket.on('getUsers', async (getUsersResult) => { let devMenuModal = document.querySelector('.dev-menu-modal'); if (devMenuModal && devMenuModal.style.display == 'flex') { let totalUserCount = devMenuModal.querySelector('.total-user-count'); let totalUserList = devMenuModal.querySelector('.total-user-list'); // 전체 프로젝트 전역변수로 projectNameList, projectCategoryList 객체 생성 let projectNameList = {}, projectCategoryList = {}; Object.entries(vars.allProject).forEach(entry => { let key = entry[0]; let value = entry[1]; projectNameList[key] = value.project_nm; projectCategoryList[value.project_nm] = value.category; }) // 소켓 getUsers로 받아온 전체 유저 데이터를 프로젝트별로 그룹화해서 groupedUsersList 객체 생성 let users = Object.values(getUsersResult); // console.log(users); totalUserCount.innerHTML = `전체 접속 인원 총 ${users.length} 명`; // ecma 2024부터 Object.groupBy 사용 가능 let groupedUsersList = Object.groupBy( users, ({ project_id }) => projectNameList[project_id] || project_id ); // 접속 해제한 클라이언트 아이디를 구분하기 위해 전체 클라이언트 아이디를 담는 배열 let allClientID = []; // 가나다순 정렬순으로 project 표시 let sortedProjectNames = Object.keys(groupedUsersList).sort((a, b) => a.localeCompare(b, 'ko')); sortedProjectNames.forEach(projectName => { let usersArr = groupedUsersList[projectName]; let projectDom = document.querySelector(`.dev-menu-modal .total-user-list .project[data-project-name="${projectName}"]`); let project, projectCount, projectUserWrap; // projectName별 dom이 존재하는지 확인해서 존재하면 기존 dom 사용하고 없으면 dom 생성 if (projectDom) { project = projectDom; projectCount = projectDom.querySelector('.title-wrap .count'); projectUserWrap = projectDom.querySelector('.user-wrap'); // ✅ 위치 재정렬 totalUserList.appendChild(project); } else { project = document.createElement('div'); project.classList.add('project'); project.dataset.projectName = projectName; let projectTitleWrap = document.createElement('div'); projectTitleWrap.classList.add('title-wrap'); let projectText = document.createElement('div'); projectText.classList.add('text'); projectText.innerHTML = `[${projectCategoryList[projectName].toUpperCase()}] ${projectName}`; projectCount = document.createElement('div'); projectCount.classList.add('count'); projectTitleWrap.appendChild(projectText); projectTitleWrap.appendChild(projectCount); projectUserWrap = document.createElement('div'); projectUserWrap.classList.add('user-wrap'); project.appendChild(projectTitleWrap); project.appendChild(projectUserWrap); totalUserList.appendChild(project); } // 프로젝트 별 접속 인원 업데이트 projectCount.innerHTML = `${usersArr.length} 명`; // 사용자 dom 재정렬: 기존 dom 재사용 + 가나다 정렬 let existingUserDoms = Array.from(projectUserWrap.querySelectorAll('.user')); let clientDomMap = {}; existingUserDoms.forEach(dom => { clientDomMap[dom.dataset.clientId] = dom; }); let currentClientId = JSON.parse(vars.userInfoString).clientId; usersArr .slice() .sort((a, b) => a.user_nm.localeCompare(b.user_nm, 'ko')) .forEach(item => { let { clientId, user_id, user_nm, position } = item; allClientID.push(clientId); let userName = `${user_nm} ${position}`; userName.trim(); let userDom = clientDomMap[clientId]; // 기존 user DOM이 없으면 생성 if (!userDom) { userDom = document.createElement('div'); userDom.classList.add('user'); userDom.dataset.user = `${clientId}_${projectName}_${user_nm}_${position}`; userDom.dataset.userId = user_id; userDom.dataset.clientId = clientId; let textWrap = document.createElement('div'); textWrap.classList.add('text-wrap'); let text = document.createElement('div'); text.classList.add('text'); text.innerHTML = `- ${user_nm} ${position}`; let btnWrap = document.createElement('div'); btnWrap.classList.add('btn-wrap'); let message = document.createElement('div'); message.classList.add('btn'); message.classList.add('message'); let messageImg = document.createElement('div'); messageImg.classList.add('message-img'); textWrap.appendChild(text); if (clientId == currentClientId) { // 이름 옆에 본인 표시 추가 let meBadge = document.createElement('div'); meBadge.classList.add('me-badge'); let h6 = document.createElement('h6'); h6.innerText = '나'; meBadge.appendChild(h6); textWrap.appendChild(meBadge); // 본인한테는 메시지 보내지 못하도록 처리 message.classList.add('disabled'); } else { message.addEventListener('click', function(e) { let targetClientId = e.target.closest('.user').dataset.clientId; let userInfo = JSON.parse(vars.userInfoString); let sender = `${userInfo.user_nm} ${userInfo.position}`; sender = sender.trim(); let toggleParams = { title: '메시지 전송', text: `메시지 내용을 입력한 후 확인을 눌러주세요.`, type: 'sendMessage', targetClientId: targetClientId, sender: sender.trim() }; toggleModal(true, toggleParams); }) } message.appendChild(messageImg); btnWrap.appendChild(message); userDom.appendChild(textWrap); userDom.appendChild(btnWrap); } // 정렬된 순서대로 append (재배치) projectUserWrap.appendChild(userDom); }); }); // 접속중인 모든 클라이언트 아이디 배열에 포함되어 있지 않은 유저 dom 삭제 let userDoms = document.querySelectorAll('.dev-menu-modal .total-user-list .user'); for (let user of userDoms) { let clientId = user.dataset.clientId; if (!allClientID.includes(clientId)) user.remove(); } // 프로젝트에 접속자가 없는 경우 해당 프로젝트 dom 삭제 let projectDoms = document.querySelectorAll('.dev-menu-modal .total-user-list .project'); for (let project of projectDoms) { let projectName = project.dataset.projectName; if (!groupedUsersList[projectName]) project.remove(); } } }); //// 프로젝트 상태 설정 socket.on('updateProject_isActive_success', async (data) => { let { allProject, projectIdList, type, state, text } = data; projectIdList = JSON.parse(projectIdList); // 전체 프로젝트 정보 갱신 for (let project of allProject) { vars.allProject[project.project_id] = project; } // 현재 프로젝트 정보 갱신 vars.project = vars.allProject[vars.project_id]; // 아카이브 모달 > 프로젝트 리스트 > sign 스타일 변경 for (let projectId of projectIdList) { let projectItem = document.querySelector(`.archive-modal .project-list-wrap .${type} .project-item[data-project-id="${projectId}"]`); if (projectItem) projectItem.querySelector('.sign').classList.toggle('inactive', !state); } if (projectIdList.includes(vars.project.project_id)) { alert(text); if (vars.permission.checkPermission('dev-menu')) { //// 개발자 계정인 경우 // projectIdList에 현재 프로젝트 id가 포함되어 있으면 토글 상태 변경 let projectStateToggle = document.querySelector('.dev-menu-modal .modal-body .toggle-wrap .project-state-toggle'); // project-inactive-sign on/off let projectInactiveSign = document.querySelector('.project-inactive-sign'); if (state) { // 비활성화 -> 활성화 if (projectStateToggle) projectStateToggle.classList.remove('inactive'); if (projectInactiveSign) projectInactiveSign.style.display = 'none'; } else { // 활성화 -> 비활성화 if (projectStateToggle) projectStateToggle.classList.add('inactive'); if (projectInactiveSign) projectInactiveSign.style.display = 'flex'; } } else { //// 개발자 계정 아닌 경우 // window.location.href = '/auth/logout'; window.location.href = `${window.location.origin}/user/login?path=/${vars.project.category}`; } } }) //// 배너 공지 설정 socket.on('updateProject_bannerNotice_success', async (data) => { let { allProject, projectIdList, type, state } = data; projectIdList = JSON.parse(projectIdList); // 전체 프로젝트 정보 갱신 for (let project of allProject) { vars.allProject[project.project_id] = project; } // 현재 프로젝트 정보 갱신 vars.project = vars.allProject[vars.project_id]; // 아카이브 모달 > 프로젝트 리스트 > sign 스타일 변경 for (let projectId of projectIdList) { let projectItem = document.querySelector(`.archive-modal .project-list-wrap .${type} .project-item[data-project-id="${projectId}"]`); if (projectItem) projectItem.querySelector('.sign').classList.toggle('inactive', !state); } if (projectIdList.includes(vars.project.project_id)) { if (vars.permission.checkPermission('dev-menu')) { //// 개발자 계정인 경우 // projectIdList에 현재 프로젝트 id가 포함되어 있으면 토글 상태 변경 let bannerNoticeToggle = document.querySelector('.dev-menu-modal .modal-body .toggle-wrap .banner-notice-toggle'); if (state) { // 비활성화 -> 활성화 if (bannerNoticeToggle) bannerNoticeToggle.classList.remove('inactive'); } else { // 활성화 -> 비활성화 if (bannerNoticeToggle) bannerNoticeToggle.classList.add('inactive'); } } toggleBannerNoticeArea(); } }) //// 팝업 공지 발송 socket.on('popupNotice', (data)=>{ let { text } = data; alert(text); }) //// 강제 로그아웃 socket.on('forcedLogout', () => { alert('프로젝트 재시작으로 인해 자동으로 로그아웃됩니다.\n다시 로그인 후 사용해주세요.'); if (vars.permission.checkPermission('dev-menu')) return; window.location.href = `${window.location.origin}/user/login?path=/${vars.project_id}/archive`; }) //// 메시지 전송 socket.on('sendMessage', (data)=>{ let { sender, text } = data; alert(`${sender} 님으로부터 메시지가 도착했습니다. \n\n ${text}`); }) // 변환시작, 변환완료 등 상태에 따른 실시간 UI 변경 처리는 socket.on에서 처리 // 서버에 현재 변환중인 파일 경로를 보내는 등 로직 처리는 working // 변환 파일 포함 폴더 강조 기능 //// 변환 시작 socket.on('convert_start', (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; let resourcePath = resultData.resourcePath; vars.convertingDataArr = resultData.convertingDataArr; let state = document.querySelector(`.list-item[data-resource-path="${resourcePath}"] .state`); if (!state) return; state.classList.remove('convert'); state.classList.add('working'); let convertBtnText = state.querySelector('.convert-btn-text'); if (convertBtnText) convertBtnText.innerHTML = '변환중'; }) //// 변환 완료 후 변환 로그 기록 (queue.js에서 io.emit) socket.on('convertPdf_success', async (resultData) => { let { userInfoString, previewKey, projectId, userIp, resourcePath, dataId, storageType } = resultData; let resultDataUserInfo = JSON.parse(resultData.userInfoString); let varsUserInfo = JSON.parse(vars.userInfoString); // 변환된 아이템 데이터에 previewKey 추가 let convertTarget = getDataFromTreeObject(resourcePath, 'file', vars.allTreeObject).data; if (convertTarget && previewKey) convertTarget.previewKey = previewKey; // 변환을 실행한 유저의 clientId와 접속중인 유저의 clientId 비교해서 같을 때 변환 로그 기록 실행 // -> clientId가 다른데 변환 로그 기록을 실행하면 소켓 이벤트를 전송받은 모든 유저가 변환 로그 기록을 실행하게 돼서 중복 기록됨 if (resultDataUserInfo.clientId != varsUserInfo.clientId) return; let activity = 'convertPdf'; let addConvetPdfLogParams = { projectId: projectId, activity: activity, userInfoString: userInfoString, userIp: userIp, resourcePath: resourcePath, resourcePathArr: [resourcePath], dataId: dataId, dataIdArr: [dataId], storageType: storageType, } await axios.post(`${vars.path_name}/addConvetPdfLog`, { params: addConvetPdfLogParams }); }) //// 변환 로그 기록 완료 socket.on('addConvetPdfLog_success', async (resultData) => { let { projectId, userInfoString, resourcePath, dataId } = resultData; let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != projectId) return; renderLog(); vars.convertingDataArr = resultData.convertingDataArr; let state = document.querySelector(`.list-item[data-resource-path="${resourcePath}"] .state`); if (!state) return; state.classList.remove('working'); state.classList.add('viewable'); let stateText = state.querySelector('.state-text'); if (stateText) stateText.innerHTML = '열람가능'; let convertBtn = state.querySelector('.convert-btn'); if (convertBtn) convertBtn.remove(); // 클릭 로그 추가 (addConvetPdfLog_success) // 변환 버튼 클릭한 유저만 실행 if (JSON.parse(userInfoString).clientId == JSON.parse(vars.userInfoString).clientId) { // console.log('클릭 로그 추가 (addConvetPdfLog_success)'); let params = { userInfoString: vars.userInfoString, dataIdArr: [String(dataId)], resourcePathArr: [resourcePath], activity: 'click_convertBtn' } mgmtFunc_addClickLog(params); } if (vars.lastListItem) { let lastListItemPath = vars.lastListItem.dataset.resourcePath; if (resourcePath == lastListItemPath) { // 변환 버튼 클릭할 때 vars.viewerConnectingTime이 0으로 설정되기 때문에 // 변환 완료 후 뷰어 실행하기 전에 vars.viewerConnectingTime을 1000으로 설정 // vars.viewerConnectingTime = vars.viewerConnectingTimeValue; let shouldAddClickLog = false; renderViewer(resourcePath, dataId, shouldAddClickLog); } } }) //// 변환 실패 (queue.js에서 io.emit) socket.on('convertPdf_failed', async (resultData) => { console.log('-------- convertPdf_failed'); console.log(resultData); let resourcePath = (resultData.jobData.resourcePath) ? resultData.jobData.resourcePath : resultData.jobProgress.resourcePath; let dataId = (resultData.jobData.dataId) ? resultData.jobData.dataId : resultData.jobProgress.dataId; let userInfoString = (resultData.jobData.userInfoString) ? resultData.jobData.userInfoString : resultData.jobProgress.userInfoString; // 서버의 convertingDataArr에서 변환 실패한 파일 정보 삭제 let removeConvertingDataParams = { resourcePath: resourcePath, dataId: dataId, userInfoString: userInfoString } let removeConvertingDataResult = await axios.post(`${vars.path_name}/removeConvertingData`, { params: removeConvertingDataParams }); console.log(removeConvertingDataResult); // 클릭 로그 추가 (convertPdf_failed) // 변환 버튼 클릭한 유저만 실행 if (JSON.parse(userInfoString).clientId == JSON.parse(vars.userInfoString).clientId) { // console.log('클릭 로그 추가 (convertPdf_failed)'); let params = { userInfoString: vars.userInfoString, dataIdArr: [String(dataId)], resourcePathArr: [resourcePath], activity: 'click_convertBtn' } mgmtFunc_addClickLog(params); } }) socket.on('removeConvertingData_success', async (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; // 변환중인 파일 정보 갱신 vars.convertingDataArr = resultData.convertingDataArr; // 변환 실패한 파일의 변환버튼 초기화 let resourcePath = resultData.resourcePath; let state = document.querySelector(`.list-item[data-resource-path="${resourcePath}"] .state`); if (!state) return; // 변환버튼을 클릭했던 리스트가 아닌 다른 리스트를 보고 있으면 아래 오류 모달 실행 안됨 state.classList.remove('working'); state.classList.add('convert'); let convertBtnText = state.querySelector('.convert-btn-text'); if (convertBtnText) convertBtnText.innerHTML = '변환필요'; let resultUserInfo = JSON.parse(resultData.userInfoString); let resultUserId = resultUserInfo.user_id; // let resultClientId = resultUserInfo.clientId; let resultProjectId = resultUserInfo.project_id; let currentUserInfo = JSON.parse(vars.userInfoString); let currentUserId = currentUserInfo.user_id; // let currentClientId = currentUserInfo.clientId; let currentProjectId = currentUserInfo.project_id; // console.log('@@@@@'); // console.log(resultUserId); // console.log(resultClientId); // console.log(resultProjectId); // console.log('#####'); // console.log(currentUserId); // console.log(currentClientId); // console.log(currentProjectId); if (resultProjectId == currentProjectId && resultUserId == currentUserId) { let toggleParams = { // text: ` // <오류> ${resultData.stdout} // 오류로 인해 PDF 변환이 실패했습니다. // GSIM 개발팀에 문의해주시기 바랍니다. // `, text: ` <오류> ${resultData.stdout} 오류로 인해 PDF 변환이 실패했습니다. GSIM 개발팀에 문의해주시기 바랍니다. `, type: 'alertModal' }; toggleModal(true, toggleParams); } }) socket.on('mgmtFunc_resetConvert_success', async (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; // console.log(resultData); vars.convertingDataArr = resultData.convertingDataArr; let state = document.querySelector(`.list-item[data-resource-path="${resultData.resourcePath}"] .state`); if (!state) return; // 변환버튼을 클릭했던 리스트가 아닌 다른 리스트를 보고 있으면 아래 오류 모달 실행 안됨 state.classList.remove('working'); state.classList.add('convert'); let convertBtnText = state.querySelector('.convert-btn-text'); if (convertBtnText) convertBtnText.innerHTML = '변환필요'; }) //// 폴더 생성 완료 // 로그 작성 socket.on('createFolder_success', async (resultData) => { // console.log('//////// 폴더 생성'); // console.log(resultData); let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; renderLog(); let userCurPath = getMyCurPath(); let extractedPath = extractPathByLength(userCurPath, 1); // let resourcePath = resultData.resourcePath; // let resourcePathSplit = resourcePath.split('/'); // let extractedPath = extractPathByLength(resourcePathSplit, 1); //// depth1 폴더 영역 렌더링 let pageRanderingOption = { scope: 'headerBtn', from: 'createFolder - depth1 - headerBtn', resourcePath: userCurPath, pushState: false, // userCurPath: userCurPath, } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth1 폴더의 경로 let lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; let lastHeaderBtn = document.querySelector(`body > .header .center .menu-tab .btn[data-resource-path="${lastHeaderBtnPath}"]`); //// 마지막으로 선택된 depth1 폴더의 스타일 강조 if (lastHeaderBtn) changeHeaderBtnStyle(lastHeaderBtn); lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; //// depth2, depth3 폴더 생성 //// 마지막으로 선택된 depth1 폴더 안에 depth2, depth3 폴더를 생성할 때 아래 코드 실행 //// -> 다른 depth1 폴더를 보고 있는 사용자는 해당 안됨 if (extractedPath == lastHeaderBtnPath) { //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 let pageRanderingOption = { scope: 'tree', resourcePath: extractedPath, userCurPath: userCurPath, pushState: false } await preparePageRendering(pageRanderingOption); if (vars.lastMainTreeItem) { let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${vars.lastMainTreeItem.dataset.resourcePath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); } // 폴더 생성 시 중앙 리스트 영역(list) 즉시 갱신 추가 let pageRanderingOptionList = { scope: 'list', resourcePath: userCurPath, pushState: false, debug: '폴더생성완료 - list' } await preparePageRendering(pageRanderingOptionList); if (vars.lastListItem) { let lastListItemPath = vars.lastListItem.dataset.resourcePath; let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`); if (listItem) changeListItemStyle(listItem); } } }) //// 업로드 완료 socket.on('uploadData_success', async (resultData) => { // console.log('//////// 업로드'); // console.log(resultData); let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; renderLog(); renderSizeBar(); //// 업로드 된 첫 번째 파일 경로 let firstResourcePath = resultData.resourcePathArr[0]; let firstResourcePathSplit = firstResourcePath.split('/'); //// 업로드 된 타겟의 상위 폴더(depth3) 경로 let uploadTargetTopPath = splitTopPathAndTargetName(firstResourcePath).topPath; // 추가 파일(버전/첨부) 업로드인 경우 uploadTargetTopPath가 상위파일경로_(version/attachment)이므로 // splitTopPathAndTargetName 함수 한번 더 실행해서 depth3 폴더 경로로 설정 if (resultData.activity?.includes('addOn_')) uploadTargetTopPath = splitTopPathAndTargetName(uploadTargetTopPath).topPath; let userCurPath; if (vars.users[socket.id] && vars.users[socket.id].curPath) userCurPath = vars.users[socket.id].curPath; //// vars.allTreeObject에서 depth1, depth2 폴더 데이터에 filesCount 갱신을 위해 헤더 버튼 렌더링 필요 (getTreeObject: false) let pageRanderingOption = { scope: 'headerBtn', resourcePath: userCurPath, pushState: false, getTreeObject: false } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth1 폴더의 경로 let lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; let lastHeaderBtn = document.querySelector(`body > .header .center .menu-tab .btn[data-resource-path="${lastHeaderBtnPath}"]`); //// 마지막으로 선택된 depth1 폴더의 스타일 강조 if (lastHeaderBtn) changeHeaderBtnStyle(lastHeaderBtn); lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; // 251114 김아름 if (lastHeaderBtnPath == undefined) return; //// depth3 폴더명 몇 파일 개수 표시 업데이트를 위해 트리 렌더링 필요 //// 선택된 헤더 버튼 경로와 treeContainer의 dataset.resourcePath가 같을 때 트리 렌더링 let extractedPath = extractPathByLength(firstResourcePathSplit, 1); if (treeContainer.dataset.resourcePath == extractedPath) { let pageRanderingOption = { scope: 'tree', resourcePath: extractedPath, userCurPath: uploadTargetTopPath, pushState: false, debug: '업로드완료 - tree' } await preparePageRendering(pageRanderingOption); if (vars.lastMainTreeItem) { let lastMainTreeItemPath = vars.lastMainTreeItem.dataset.resourcePath; let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${lastMainTreeItemPath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); } } //// depth3 폴더가 선택된 상태인 경우 depth3 폴더 경로로 리스트 렌더링 /// 251104 박지은 ol 소켓처리 // fileAreaMode 체크 // let isMapMode = document.querySelector('.archive-main .archive-main-left .control-box .contents-wrap .file-area-mode-btn-wrap .file-area-mode-btn.btn.map')?.classList.contains('selected'); if (treeContainer.dataset.resourcePath == extractedPath && vars.lastMainTreeItem) { let pageRanderingOption = { scope: 'list', resourcePath: vars.lastMainTreeItem.dataset.resourcePath, pushState: false, debug: '업로드완료 - list' } await preparePageRendering(pageRanderingOption); //// depth4 파일이 선택된 상태인 경우 depth4 파일 경로로 스타일 강조 if (vars.lastListItem) { let lastListItemPath = vars.lastListItem.dataset.resourcePath; let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`); if (listItem) changeListItemStyle(listItem); } // 251104 박지은 ol 소켓처리 // // 위치보기(map) 모드인 경우 - 새 파일만 추가 // if (isMapMode) { // // getTreeObject만 갱신하여 새 파일 데이터 가져오기 // let pageRanderingOption = { // scope: 'updateTreeObject', // 새로운 scope 추가 필요 // resourcePath: vars.lastMainTreeItem.dataset.resourcePath, // pushState: false, // getTreeObject: true, // debug: '업로드완료 - 위치보기 모드 데이터 갱신' // } // await preparePageRendering(pageRanderingOption); // // 새로 업로드된 파일만 지도에 추가 // await createNewMapItems(resultData.resourcePathArr); // } else { // // 일반/그리드 모드인 경우 - 전체 리스트 렌더링 // let pageRanderingOption = { // scope: 'list', // resourcePath: vars.lastMainTreeItem.dataset.resourcePath, // pushState: false, // debug: '업로드완료 - list' // } // await preparePageRendering(pageRanderingOption); // //// depth4 파일이 선택된 상태인 경우 depth4 파일 경로로 스타일 강조 // if (vars.lastListItem) { // let lastListItemPath = vars.lastListItem.dataset.resourcePath; // let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`) // if (listItem) changeListItemStyle(listItem); // } // } } }) //// gif생성 + 위치 추출 // socket.on('postProcessVideo_success', async (resultData) => { // let dataId = resultData.dataId; // let thumbnailKey = resultData.thumbnailKey; // let resourcePath = resultData.resourcePath; // let lon = resultData.lon; // let lat = resultData.lat; // // 동영상 후처리 된 dataId에 매칭되는 gridItem이 있는 경우 썸네일 교체 // let gridItem = document.querySelector(`.list-container.grid .grid-item[data-id="${dataId}"]`); // if (gridItem) { // if (lon && lat) { // console.log(gridItem.querySelector('.gps-data')); // gridItem.querySelector('.gps-data').classList.add('gps-data-yes'); // gridItem.querySelector('.gps-data').classList.remove('gps-data-no'); // } // let generateDownloadUrlParams = { // objectKey: thumbnailKey, // resourcePath: resourcePath // } // let generateDownloadUrlRes = await axios.post(`${vars.path_name}/generateDownloadUrl`, generateDownloadUrlParams); // if (generateDownloadUrlRes.data.message == 'generateDownloadUrl_success') { // let presignedUrl = generateDownloadUrlRes.data.url; // gridItem.querySelector('.wrap .thumbnail').src = presignedUrl; // gridItem.querySelector('.loading-progress-wrap').remove(); // } // } // }) //// 위치 추출 socket.on('postProcessVideo_success', async (resultData) => { let dataId = resultData.dataId; let lon = resultData.lon; let lat = resultData.lat; // 동영상 후처리 된 dataId에 매칭되는 gridItem이 있는 경우 gpsData 아이콘 교체 let gridItem = document.querySelector(`.list-container.grid .grid-item[data-id="${dataId}"]`); if (gridItem && lon && lat) { gridItem.querySelector('.gps-data').classList.add('gps-data-yes'); gridItem.querySelector('.gps-data').classList.remove('gps-data-no'); } }) //// 이름 변경 // 로그 작성 socket.on('renameTarget_success', async (resultData) => { // console.log('//////// 이름 변경'); // console.log(resultData); let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; renderLog(); let userCurPath; if (vars.users[socket.id] && vars.users[socket.id].curPath) userCurPath = vars.users[socket.id].curPath; let oldPath = resultData.oldPath; let newPath = resultData.newPath; let depth = getDepth(newPath); // oldPath와 newPath의 depth는 동일 // 이 depth만큼 userCurPath를 추출 let extractedUserCurPath = extractPathByLength(userCurPath, depth); // extractedUserCurPath와 oldPath가 같으면 userCurPath에서 oldPath 부분을 newPath로 업데이트 if (extractedUserCurPath == oldPath) userCurPath = updatePartialPath(newPath, userCurPath); let pathSplit = userCurPath.split('/'); let depth1Path, depth2Path, depth3Path; if (pathSplit[1]) depth1Path = `${pathSplit[0]}/${pathSplit[1]}`; if (pathSplit[2]) depth2Path = `${depth1Path}/${pathSplit[2]}`; if (pathSplit[3]) depth3Path = `${depth2Path}/${pathSplit[3]}`; //// depth1 폴더 영역 렌더링 let pageRanderingOption = { scope: 'headerBtn', resourcePath: userCurPath, pushState: false } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth1 폴더의 경로 let lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; let lastHeaderBtn = document.querySelector(`body > .header .center .menu-tab .btn[data-resource-path="${lastHeaderBtnPath}"]`); //// 마지막으로 선택된 depth1 폴더의 스타일 강조 if (lastHeaderBtn) { //// lastHeaderBtn이 있는 경우 -> 마지막으로 선택된 depth1 폴더와 다른 폴더 이름을 변경한 경우 changeHeaderBtnStyle(lastHeaderBtn); } else { //// lastHeaderBtn이 없는 경우 -> 마지막으로 선택된 depth1 폴더 이름을 변경한 경우 //// data-resource-path가 newPath인 delth1 폴더를 lastHeaderBtn으로 지정 lastHeaderBtn = document.querySelector(`body > .header .center .menu-tab .btn[data-resource-path="${newPath}"]`); changeHeaderBtnStyle(lastHeaderBtn); } lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; // 251114 김아름 if (lastHeaderBtnPath == undefined) return; //// depth1 폴더 이름을 변경할 때 아래 코드 실행 if (depth == 1) { //// 마지막으로 선택된 depth1 폴더 경로와 변경하려는 depth1 폴더 경로가 동일할 때 아래 코드 실행 //// -> 다른 depth1 폴더를 보고 있는 사용자는 코드 실행 안됨 if (lastHeaderBtnPath == depth1Path) { //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 let pageRanderingOption = { scope: 'tree', resourcePath: depth1Path, userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth3 폴더가 있을 때 아래 코드 실행 if (vars.lastMainTreeItem) { //// 마지막으로 선택된 depth3 폴더의 경로 수정 후 스타일 강조 let lastMainTreeItemPath = vars.lastMainTreeItem.dataset.resourcePath; lastMainTreeItemPath = updatePartialPath(depth1Path, lastMainTreeItemPath); let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${lastMainTreeItemPath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); //// 파일 리스트 헤더, 바디의 resourcePath 변경 document.querySelector('.archive-main-center .list-container .list-header').dataset.resourcePath = lastMainTreeItemPath; document.querySelector('.archive-main-center .list-container .list-body').dataset.resourcePath = lastMainTreeItemPath; // 리스트 렌더링 pageRanderingOption = { scope: 'list', resourcePath: lastMainTreeItemPath, userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); /// 251104 박지은 ol 소켓처리 // fileAreaMode 체크 // let isMapMode = document.querySelector('.archive-main .archive-main-left .control-box .contents-wrap .file-area-mode-btn-wrap .file-area-mode-btn.btn.map')?.classList.contains('selected'); // if (!isMapMode) { // // 일반/그리드 모드인 경우만 - 전체 리스트 렌더링 // //// 리스트 렌더링 // pageRanderingOption = { // scope: 'list', // resourcePath: lastMainTreeItemPath, // userCurPath: userCurPath // } // await preparePageRendering(pageRanderingOption); // } //// 마지막으로 선택된 depth4 파일이 있을 때 아래 코드 실행 if (vars.lastListItem) { //// 마지막으로 선택된 depth4 파일의 경로 수정 후 스타일 강조 let lastListItemPath = vars.lastListItem.dataset.resourcePath; lastListItemPath = updatePartialPath(depth1Path, lastListItemPath); let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`) if (listItem) changeListItemStyle(listItem); } } } } //// depth2 폴더 이름을 변경할 때 아래 코드 실행 if (depth == 2) { //// 마지막으로 선택된 depth1 폴더 경로와 변경하려는 depth2 폴더를 포함하고 있는 depth1 폴더 경로가 동일할 때 아래 코드 실행 //// -> 다른 depth1 폴더를 보고 있는 사용자는 코드 실행 안됨 if (lastHeaderBtnPath == depth1Path) { //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 let pageRanderingOption = { scope: 'tree', resourcePath: depth1Path, userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth3 폴더가 있을 때 아래 코드 실행 if (vars.lastMainTreeItem) { //// 마지막으로 선택된 depth3 폴더의 경로 let lastMainTreeItemPath = vars.lastMainTreeItem.dataset.resourcePath; //// 마지막으로 선택된 depth3 폴더의 상위 폴더 경로 let lastMainTreeItemTopPath = splitTopPathAndTargetName(lastMainTreeItemPath).topPath; //// 리스트 렌더링 여부 판단에 사용할 변수 let listRendering = false; //// lastMainTreeItemTopPath와 oldPath(이름 변경 전의 depth2 폴더 경로)가 같을 때 아래 코드 실행 if (lastMainTreeItemTopPath == oldPath) { //// 마지막으로 선택된 depth3 폴더의 경로 수정 및 리스트 렌더링 여부 변수 true로 변경 lastMainTreeItemPath = updatePartialPath(depth2Path, lastMainTreeItemPath); listRendering = true; } //// 마지막으로 선택된 depth3 폴더의 스타일 강조 let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${lastMainTreeItemPath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); //// 파일리스트 헤더, 바디의 resourcePath 변경 document.querySelector('.archive-main-center .list-container .list-header').dataset.resourcePath = lastMainTreeItemPath; document.querySelector('.archive-main-center .list-container .list-body').dataset.resourcePath = lastMainTreeItemPath; //// listRendering이 true일 때 아래 코드 실행 if (listRendering) { //// 리스트 렌더링 pageRanderingOption = { scope: 'list', resourcePath: lastMainTreeItemPath, userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); /// 251104 박지은 ol 소켓처리 // fileAreaMode 체크 // let isMapMode = document.querySelector('.archive-main .archive-main-left .control-box .contents-wrap .file-area-mode-btn-wrap .file-area-mode-btn.btn.map')?.classList.contains('selected'); // if(!isMapMode) { // // 일반/그리드 모드인 경우만 - 전체 리스트 렌더링 // //// 리스트 렌더링 // pageRanderingOption = { // scope: 'list', // resourcePath: lastMainTreeItemPath, // userCurPath: userCurPath // } // await preparePageRendering(pageRanderingOption); // } //// 마지막으로 선택된 depth4 파일이 있을 때 아래 코드 실행 if (vars.lastListItem) { //// 마지막으로 선택된 depth4 파일의 경로 수정 후 스타일 강조 let lastListItemPath = vars.lastListItem.dataset.resourcePath; lastListItemPath = updatePartialPath(lastMainTreeItemPath, lastListItemPath); let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`) if (listItem) changeListItemStyle(listItem); } } } } } //// depth3 폴더 이름을 변경할 때 아래 코드 실행 if (depth == 3) { //// 마지막으로 선택된 depth1 폴더 경로와 변경하려는 depth3 폴더를 포함하고 있는 depth1 폴더 경로가 동일할 때 아래 코드 실행 //// -> 다른 depth1 폴더를 보고 있는 사용자는 코드 실행 안됨 if (lastHeaderBtnPath == depth1Path) { //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 let pageRanderingOption = { scope: 'tree', resourcePath: depth1Path, userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth3 폴더가 있을 때 아래 코드 실행 if (vars.lastMainTreeItem) { //// 마지막으로 선택된 depth3 폴더의 경로 let lastMainTreeItemPath = vars.lastMainTreeItem.dataset.resourcePath; //// 리스트 렌더링 여부 판단에 사용할 변수 let listRendering = false; //// lastMainTreeItemPath와 oldPath(이름 변경 전의 depth3 폴더 경로)가 같을 때 아래 코드 실행 // console.log(lastMainTreeItemPath); // console.log(oldPath); if (lastMainTreeItemPath == oldPath) { //// 마지막으로 선택된 depth3 폴더의 경로 수정 및 리스트 렌더링 여부 변수 true로 변경 lastMainTreeItemPath = updatePartialPath(depth3Path, lastMainTreeItemPath); listRendering = true; } //// 마지막으로 선택된 depth3 폴더의 스타일 강조 let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${lastMainTreeItemPath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); //// 파일리스트 헤더, 바디의 resourcePath 변경 document.querySelector('.archive-main-center .list-container .list-header').dataset.resourcePath = lastMainTreeItemPath; document.querySelector('.archive-main-center .list-container .list-body').dataset.resourcePath = lastMainTreeItemPath; //// listRendering이 true일 때 아래 코드 실행 if (listRendering) { //// 리스트 렌더링 pageRanderingOption = { scope: 'list', resourcePath: lastMainTreeItemPath, userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); /// 251104 박지은 ol 소켓처리 // fileAreaMode 체크 // let isMapMode = document.querySelector('.archive-main .archive-main-left .control-box .contents-wrap .file-area-mode-btn-wrap .file-area-mode-btn.btn.map')?.classList.contains('selected'); // if(!isMapMode) { // //// 리스트 렌더링 // pageRanderingOption = { // scope: 'list', // resourcePath: lastMainTreeItemPath, // userCurPath: userCurPath // } // await preparePageRendering(pageRanderingOption); // } //// 마지막으로 선택된 depth4 파일이 있을 때 아래 코드 실행 if (vars.lastListItem) { //// 마지막으로 선택된 depth4 파일의 경로 수정 후 스타일 강조 let lastListItemPath = vars.lastListItem.dataset.resourcePath; lastListItemPath = updatePartialPath(lastMainTreeItemPath, lastListItemPath); let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`) if (listItem) changeListItemStyle(listItem); } } } } } //// depth4 파일 및 추가 파일 이름을 변경할 때 아래 코드 실행 if (depth >= 4) { if(vars.tempMemo[oldPath]) { vars.tempMemo[newPath] = vars.tempMemo[oldPath]; // delete vars.tempMemo[oldPath] } //// 마지막으로 선택된 depth1 폴더 경로와 변경하려는 depth4 파일을 포함하고 있는 depth1 폴더 경로가 동일할 때 아래 코드 실행 //// -> 다른 depth1 폴더를 보고 있는 사용자는 코드 실행 안됨 if (lastHeaderBtnPath == depth1Path) { //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 let pageRanderingOption = { scope: 'tree', resourcePath: depth1Path, userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth3 폴더의 경로 let lastMainTreeItemPath = vars.lastMainTreeItem.dataset.resourcePath; //// lastMainTreeItemPath와 oldPath(이름 변경 전의 depth4 파일 경로)의 상위 폴더 경로가 같을 때 아래 코드 실행 if (lastMainTreeItemPath == splitTopPathAndTargetName(oldPath).topPath) { //// lastMainTreeItemPath 갱신 lastMainTreeItemPath = updatePartialPath(depth3Path, lastMainTreeItemPath); } //// 마지막으로 선택된 depth3 폴더의 스타일 강조 let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${lastMainTreeItemPath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); //// 마지막으로 선택된 depth3 폴더 경로와 변경하려는 depth4 파일을 포함하고 있는 depth3 폴더 경로가 동일할 때 아래 코드 실행 //// -> 다른 depth3 폴더를 보고 있는 사용자는 코드 실행 안됨 if (lastMainTreeItemPath == depth3Path) { //// 파일리스트 헤더, 바디의 resourcePath 변경 document.querySelector('.archive-main-center .list-container .list-header').dataset.resourcePath = depth3Path; document.querySelector('.archive-main-center .list-container .list-body').dataset.resourcePath = depth3Path; //// 리스트 렌더링 pageRanderingOption = { scope: 'list', resourcePath: depth3Path, userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); /// 251104 박지은 ol 소켓처리 // // fileAreaMode 체크 // let isMapMode = document.querySelector('.archive-main .archive-main-left .control-box .contents-wrap .file-area-mode-btn-wrap .file-area-mode-btn.btn.map')?.classList.contains('selected'); // if(!isMapMode) { // //// 리스트 렌더링 // pageRanderingOption = { // scope: 'list', // resourcePath: depth3Path, // userCurPath: userCurPath // } // await preparePageRendering(pageRanderingOption); // } //// 마지막으로 선택된 depth4 파일이 있을 때 아래 코드 실행 if (vars.lastListItem) { //// 마지막으로 선택된 depth4 파일의 경로 let lastListItemPath = vars.lastListItem.dataset.resourcePath; //// 마지막으로 선택된 depth4 파일 이름 let lastListItemFileName = splitTopPathAndTargetName(lastListItemPath).targetName; //// 이름 변경 전 파일 이름 let oldPathFileName = splitTopPathAndTargetName(oldPath).targetName; //// lastListItemFileName과 oldPathFileName이 같을 때 아래 코드 실행 if (lastListItemFileName == oldPathFileName) { lastListItemPath = updatePartialPath(newPath, lastListItemPath); } //// 마지막으로 선택된 depth4 파일의 스타일 강조 let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`) if (listItem) changeListItemStyle(listItem); } } } } }) //// 다운로드 완료 // 로그 작성 socket.on('downloadTarget_success', async (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; renderLog(); // console.log(resultData); }) //// 이동 // 로그 작성 socket.on('relocateTarget_success', async (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; renderLog(); let userCurPath = vars.users[socket.id].curPath; let fromDepth1Path = extractPathByLength(resultData.resourcePathArr[0].from, 1); let toDepth1Path = extractPathByLength(resultData.resourcePathArr[0].to, 1); let fromDepth3Path = extractPathByLength(resultData.resourcePathArr[0].from, 3); let toDepth3Path = extractPathByLength(resultData.resourcePathArr[0].to, 3); //// vars.allTreeObject에서 depth1, depth2 폴더 데이터에 filesCount 갱신을 위해 헤더 버튼 렌더링 필요 (getTreeObject: false) let pageRanderingOption = { scope: 'headerBtn', pushState: false, getTreeObject: false } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth1 폴더의 경로 let lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; let lastHeaderBtn = document.querySelector(`body > .header .center .menu-tab .btn[data-resource-path="${lastHeaderBtnPath}"]`); //// 마지막으로 선택된 depth1 폴더의 스타일 강조 if (lastHeaderBtn) changeHeaderBtnStyle(lastHeaderBtn); lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; let depth1Path; if (fromDepth1Path == lastHeaderBtnPath) depth1Path = fromDepth1Path; if (toDepth1Path == lastHeaderBtnPath) depth1Path = toDepth1Path; // 251114 김아름 if (lastHeaderBtnPath == undefined) return; //// depth3 폴더명 몇 파일 개수 표시 업데이트를 위해 트리 렌더링 필요 //// 이동 전 depth1 폴더 경로 또는 이동 후 depth1 폴더 경로와 treeContainer의 dataset.resourcePath가 같을 때 트리 렌더링 if (depth1Path == lastHeaderBtnPath) { //// 마지막으로 선택된 depth3 폴더의 경로 let lastMainTreeItemPath = vars.lastMainTreeItem?vars.lastMainTreeItem.dataset.resourcePath:undefined; let depth3Path; if (fromDepth3Path == lastMainTreeItemPath) depth3Path = fromDepth3Path; if (toDepth3Path == lastMainTreeItemPath) depth3Path = toDepth3Path; //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 let pageRanderingOption = { scope: 'tree', resourcePath: depth1Path, userCurPath: depth3Path?depth3Path:userCurPath, pushState: false, } await preparePageRendering(pageRanderingOption); if (lastMainTreeItemPath) { let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${lastMainTreeItemPath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); } //// depth3 폴더가 선택된 상태인 경우 depth3 폴더 경로로 리스트 렌더링 if (treeContainer.dataset.resourcePath == depth1Path && vars.lastMainTreeItem) { let pageRanderingOption = { scope: 'list', resourcePath: vars.lastMainTreeItem.dataset.resourcePath, pushState: false, } await preparePageRendering(pageRanderingOption); /// 251104 박지은 ol 소켓처리 // fileAreaMode 체크 // let isMapMode = document.querySelector('.archive-main .archive-main-left .control-box .contents-wrap .file-area-mode-btn-wrap .file-area-mode-btn.btn.map')?.classList.contains('selected'); // if(!isMapMode) { // let pageRanderingOption = { // scope: 'list', // resourcePath: vars.lastMainTreeItem.dataset.resourcePath, // pushState: false, // } // await preparePageRendering(pageRanderingOption); // } else { // await createNewMapItems(resultData.resourcePathArr); // } //// depth4 파일이 선택된 상태인 경우 depth4 파일 경로로 스타일 강조 if (vars.lastListItem) { let lastListItemPath = vars.lastListItem.dataset.resourcePath; let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`) if (listItem) { changeListItemStyle(listItem); //// 보고있는 파일이 리스트에서 벗어난 경우 포커스 targetFocus(listItem); } else { //// 보고있는 파일이 이동한 경우 미리보기 종료 resetViewer(); renderMemo(); //// vars 아이템 관련 변수 초기화 // vars.lastListItem = undefined; // vars.lastSelectTarget = undefined; } } } } }) //// 삭제 완료 // 로그 작성 socket.on('removeTarget_success', async (resultData) => { // console.log('//////// 삭제'); // console.log(resultData); let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; let myId = JSON.parse(vars.userInfoString).user_id; let userInfo = JSON.parse(resultData.userInfoString); let removedUserId = userInfo.user_id; // console.log('-------- removeTarget socket error'); // console.log(resultData); renderLog(); renderSizeBar(); removeCountdownTooltip(); let userCurPath; if (vars.users[socket.id] && vars.users[socket.id].curPath) userCurPath = vars.users[socket.id].curPath; let resourcePath = resultData.resourcePathArr[0]; let userCurPathSplit = userCurPath.split('/'); let depth1Path, depth2Path, depth3Path; if (userCurPathSplit[1]) depth1Path = `${userCurPathSplit[0]}/${userCurPathSplit[1]}`; if (userCurPathSplit[2]) depth2Path = `${depth1Path}/${userCurPathSplit[2]}`; if (userCurPathSplit[3]) depth3Path = `${depth2Path}/${userCurPathSplit[3]}`; let depth = getDepth(userCurPath); //// depth1 폴더 영역 렌더링 let pageRanderingOption = { scope: 'headerBtn', resourcePath: userCurPath, pushState: false // userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth1 폴더의 경로 let lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; let lastHeaderBtn = document.querySelector(`body > .header .center .menu-tab .btn[data-resource-path="${lastHeaderBtnPath}"]`); //// lastHeaderBtn이 있는 경우 -> 마지막으로 선택된 depth1 폴더와 다른 폴더를 삭제한 경우 //// 마지막으로 선택된 depth1 폴더의 스타일 강조 if (lastHeaderBtn) changeHeaderBtnStyle(lastHeaderBtn); lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; if (!lastHeaderBtn) { //// lastHeaderBtn이 없는 경우 -> 마지막으로 선택된 depth1 폴더를 삭제한 경우 //// 변수 초기화 vars.lastHeaderBtn = undefined; lastHeaderBtnPath = undefined; lastHeaderBtn = undefined; //// 메인 영역 숨기고 안내문구 표시 if (treeContainer.dataset.resourcePath == resourcePath && userCurPath != '/') { // 251114 김아름, && userCurPath != '/' 추가 archiveMain.style.display = 'none'; mainNotice.style.display = 'flex'; userCurPath = '/'; // 251111 김아름 if (myId != removedUserId) { let toggleParams = { text: `폴더가 삭제되었습니다.${resourcePath}`, type: 'alertModal' }; toggleModal(true, toggleParams); } vars.lastSelectTarget = undefined; delete treeContainer.dataset.resourcePath; // 251112 김아름, 브라우저 경로 수정 let pageRanderingOption = { resourcePath: userCurPath, pushState: true, } await preparePageRendering(pageRanderingOption); } // 현재 경로 갱신 let pageRanderingOption = { scope: 'headerBtn', resourcePath: userCurPath, pushState: false // userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); } // 251114 김아름 if (lastHeaderBtnPath == undefined) return; //// 폴더가 자동 삭제되었고, 현재 선택되어 있는 depth1 경로와 자동 삭제된 폴더의 depth1 폴더 경로가 동일할 때 아래 코드 실행 let extractedDepth1Path = extractPathByLength(resourcePath, 1); if (resultData.isExpiredFolder && lastHeaderBtnPath == extractedDepth1Path) { let toggleParams = { text: `다음 폴더는 파일 개수 미달 및 만료 기간 경과로 인해 자동으로 삭제되었습니다.${resourcePath}`, type: 'alertModal' }; toggleModal(true, toggleParams); } //// 마지막으로 선택된 depth1 폴더 경로와 삭제하려는 depth2/depth3 폴더를 포함하고 있는 depth1 폴더 경로가 동일할 때 아래 코드 실행 if (lastHeaderBtnPath == depth1Path) { //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 let pageRanderingOption = { scope: 'tree', resourcePath: depth1Path, userCurPath: userCurPath, } await preparePageRendering(pageRanderingOption); //// 현재 표시되어 있는 파일 리스트가 삭제한 depth2/depth3 폴더 안에 포함되어 있는 경우 let listWrapBodyPath = listWrapBody.dataset.resourcePath; let listPath; if (depth == 2) listPath = splitTopPathAndTargetName(listWrapBodyPath).topPath; if (depth == 3) listPath = listWrapBodyPath; // 251107 김아름, depth2 필터링을 위한 || listPath?.startsWith(resourcePath + '/') 추가 if (resourcePath == listPath || listPath?.startsWith(resourcePath + '/')) { //// 현재 위치 수정, 리스트 영역, 뷰어 영역 숨기고 안내문구 표시 // listWrapBody.querySelector('.list-item-wrap').innerHTML = ''; // console.log('폴더 삭제했을 때 / 권한 수정해서 권한 해당 안될 때 -> 해당 폴더에 들어와있던 유저 경로 수정 필요'); userCurPath = extractPathByLength(resourcePath, 1); // listContainer.style.display = 'none'; // listNotice.style.display = 'flex'; // resetViewer(); // 251111 김아름 if (myId != removedUserId) { let toggleParams = { text: `폴더가 삭제되었습니다.${resourcePath}`, type: 'alertModal' }; toggleModal(true, toggleParams); // 251112 김아름, 브라우저 경로 수정 let pageRanderingOption = { resourcePath: userCurPath, pushState: true, } await preparePageRendering(pageRanderingOption); } lastHeaderBtn?.click(); vars.lastSelectTarget = undefined; } //// 마지막으로 선택된 depth3 폴더가 있을 때 아래 코드 실행 let lastMainTreeItemPath; if (vars.lastMainTreeItem) { //// 마지막으로 선택된 depth3 폴더의 스타일 강조 let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${vars.lastMainTreeItem.dataset.resourcePath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); lastMainTreeItemPath = vars.lastMainTreeItem.dataset.resourcePath; } //// 마지막으로 선택된 depth3 폴더 경로와 삭제하려는 depth4 파일을 포함하고 있는 depth3 폴더 경로가 동일할 때 아래 코드 실행 //// -> 다른 depth3 폴더를 보고 있는 사용자는 코드 실행 안됨 if (lastMainTreeItemPath == depth3Path && lastMainTreeItemPath != undefined && depth3Path != undefined) { let lastTreeItemWrap = document.querySelector(`.tree-item-wrap[data-resource-path="${lastMainTreeItemPath}"]`); if (lastTreeItemWrap) { //// 마지막으로 보고 있던 depth3 폴더가 그대로 있는 경우 아래 코드 실행 //// 리스트 렌더링 pageRanderingOption = { scope: 'list', resourcePath: depth3Path, userCurPath: userCurPath, } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth4 파일이 있을 때 아래 코드 실행 if (vars.lastListItem) { let lastListItemPath = vars.lastListItem.dataset.resourcePath; let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`) if (listItem) { //// 마지막으로 선택된 depth4 파일의 스타일 강조 changeListItemStyle(listItem); } else { //// 현재 위치 수정, 마지막으로 선택된 depth4 파일이 없으면 뷰어 영역 숨기고 안내문구 표시 // console.log('폴더 삭제했을 때 / 권한 수정해서 권한 해당 안될 때 -> 해당 폴더에 들어와있던 유저 경로 수정 필요'); userCurPath = extractPathByLength(resourcePath, 1); resetViewer(); } } } else { //// 마지막으로 보고 있던 depth3 폴더가 없어진 경우(null) 아래 코드 실행 vars.multiSelectListItemArr = []; vars.lastListItem = undefined; vars.lastSelectTarget = undefined; vars.lastListGroupTarget = undefined; toggleArchiveMainRight(false); } } else { //// depth3가 선택되어 있지 않은 경우 아래 코드 실행 vars.multiSelectListItemArr = []; vars.lastListItem = undefined; vars.lastSelectTarget = undefined; vars.lastListGroupTarget = undefined; toggleArchiveMainRight(false); } } //// 유저 위치 업데이트 // console.log('폴더 삭제했을 때 / 권한 수정해서 권한 해당 안될 때 -> 해당 폴더에 들어와있던 유저 경로 수정 필요'); // console.log(userCurPath); pageRanderingOption = { userCurPath: userCurPath, pushState: false, } await preparePageRendering(pageRanderingOption); }) /// 251104 박지은 ol 소켓처리 // socket.on('removeTarget_success', async (resultData) => { // let currProjectId = JSON.parse(vars.userInfoString).project_id; // if (currProjectId != resultData.projectId) return; // renderLog(); // renderSizeBar(); // let userCurPath; // if (vars.users[socket.id] && vars.users[socket.id].curPath) userCurPath = vars.users[socket.id].curPath; // let resourcePath = resultData.resourcePathArr[0]; // let userCurPathSplit = userCurPath.split('/'); // let depth1Path, depth2Path, depth3Path, depth4Path; // if (userCurPathSplit[1]) depth1Path = `${userCurPathSplit[0]}/${userCurPathSplit[1]}`; // if (userCurPathSplit[2]) depth2Path = `${depth1Path}/${userCurPathSplit[2]}`; // if (userCurPathSplit[3]) depth3Path = `${depth2Path}/${userCurPathSplit[3]}`; // if (userCurPathSplit[4]) depth4Path = `${depth3Path}/${userCurPathSplit[4]}`; // let depth = getDepth(userCurPath); // //// depth1 폴더 영역 렌더링 // let pageRanderingOption = { // scope: 'headerBtn', // resourcePath: userCurPath, // pushState: false // // userCurPath: userCurPath // } // await preparePageRendering(pageRanderingOption); // //// 마지막으로 선택된 depth1 폴더의 경로 // let lastHeaderBtnPath = vars.lastHeaderBtn? vars.lastHeaderBtn.dataset.resourcePath : undefined; // let lastHeaderBtn = document.querySelector(`body > .header .center .menu-tab .btn[data-resource-path="${lastHeaderBtnPath}"]`); // //// lastHeaderBtn이 있는 경우 -> 마지막으로 선택된 depth1 폴더와 다른 폴더를 삭제한 경우 // //// 마지막으로 선택된 detph1 폴더의 스타일 강조 // if (lastHeaderBtn) changeHeaderBtnStyle(lastHeaderBtn); // lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; // if (!lastHeaderBtn) { // //// lastHeaderBtn이 없는 경우 -> 마지막으로 선택된 depth1 폴더를 삭제한 경우 // //// 변수 초기화 // vars.lastHeaderBtn = undefined; // lastHeaderBtnPath = undefined; // lastHeaderBtn = undefined; // //// 메인 영역 숨기고 안내문구 표시 // if (treeContainer.dataset.resourcePath == resourcePath) { // archiveMain.style.display = 'none'; // mainNotice.style.display = 'flex'; // userCurPath = '/'; // } // // 현재 경로 갱신 // let pageRanderingOption = { // scope: 'headerBtn', // resourcePath: userCurPath, // pushState: false // // userCurPath: userCurPath // } // await preparePageRendering(pageRanderingOption); // } // //// 마지막으로 선택된 depth1 폴더 경로와 삭제하려는 depth2/depth3 폴더를 포함하고 있는 depth1 폴더 경로가 동일할 때 아래 코드 실행 // if (lastHeaderBtnPath == depth1Path) { // //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 // let pageRanderingOption = { // scope: 'tree', // resourcePath: depth1Path, // userCurPath: userCurPath, // } // await preparePageRendering(pageRanderingOption); // //// 현재 표시되어 있는 파일 리스트가 삭제한 depth2/depth3 폴더 안에 포함되어 있는 경우 // let listWrapBodyPath = listWrapBody.dataset.resourcePath; // let listPath; // if (depth == 2) listPath = splitTopPathAndTargetName(listWrapBodyPath).topPath; // if (depth == 3) listPath = listWrapBodyPath; // if (resourcePath == listPath) { // //// 현재 위치 수정, 리스트 영역, 뷰어 영역 숨기고 안내문구 표시 // // listWrapBody.querySelector('.list-item-wrap').innerHTML = ''; // // console.log('폴더 삭제했을 때 / 권한 수정해서 권한 해당 안될 때 -> 해당 폴더에 들어와있던 유저 경로 수정 필요'); // userCurPath = extractPathByLength(resourcePath, 1); // listContainer.style.display = 'none'; // listNotice.style.display = 'flex'; // resetViewer(); // } // //// 마지막으로 선택된 depth3 폴더가 있을 때 아래 코드 실행 // let lastMainTreeItemPath; // if (vars.lastMainTreeItem) { // //// 마지막으로 선택된 depth3 폴더의 스타일 강조 // let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${vars.lastMainTreeItem.dataset.resourcePath}"]`) // if (mainTreeItem) changeTreeItemStyle(mainTreeItem); // lastMainTreeItemPath = vars.lastMainTreeItem.dataset.resourcePath; // } // //// 마지막으로 선택된 depth3 폴더 경로와 삭제하려는 depth4 파일을 포함하고 있는 depth3 폴더 경로가 동일할 때 아래 코드 실행 // //// -> 다른 depth3 폴더를 보고 있는 사용자는 코드 실행 안됨 // // if (lastMainTreeItemPath == depth3Path && lastMainTreeItemPath != undefined && depth3Path != undefined) { // if (resourcePath == depth1Path) { // //// 리스트 렌더링 // pageRanderingOption = { // scope: 'list', // resourcePath: depth3Path, // userCurPath: userCurPath, // } // await preparePageRendering(pageRanderingOption); // //// 마지막으로 선택된 depth4 파일이 있을 때 아래 코드 실행 // if (vars.lastListItem) { // let lastListItemPath = vars.lastListItem.dataset.resourcePath; // let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`) // if (listItem) { // //// 마지막으로 선택된 depth4 파일의 스타일 강조 // changeListItemStyle(listItem); // } else { // //// 현재 위치 수정, 마지막으로 선택된 depth4 파일이 없으면 뷰어 영역 숨기고 안내문구 표시 // // console.log('폴더 삭제했을 때 / 권한 수정해서 권한 해당 안될 때 -> 해당 폴더에 들어와있던 유저 경로 수정 필요'); // userCurPath = extractPathByLength(resourcePath, 1); // resetViewer(); // } // } // } // } // //// 유저 위치 업데이트 // // console.log('폴더 삭제했을 때 / 권한 수정해서 권한 해당 안될 때 -> 해당 폴더에 들어와있던 유저 경로 수정 필요'); // // console.log(userCurPath); // pageRanderingOption = { // userCurPath: userCurPath, // pushState: false // } // await preparePageRendering(pageRanderingOption); // vars.multiSelectListItemArr = []; // }) socket.on('deleteTarget_success', async (resultData) => { // console.log('@@@@@@@@@'); // console.log(resultData); let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; // renderLog(); renderSizeBar(); let isRecycleBinModal = document.querySelector('.recycle-bin-modal').style.display == 'flex'; if (isRecycleBinModal) await prepareRecycleBinRendering(); }) //// 메모 데이터 저장 socket.on('saveMemo_success', async (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; let userCurPath; if (vars.users[socket.id] && vars.users[socket.id].curPath) userCurPath = vars.users[socket.id].curPath; // 메모가 생성된 파일의 depth3 path와 유저 현재위치 비교 후 화면에 반영 let memoDepth3Path = extractPathByLength(resultData.resourcePath, 3); if (memoDepth3Path == userCurPath) { let pageRanderingOption = { scope: 'list', resourcePath: memoDepth3Path, } await preparePageRendering(pageRanderingOption); } // renderLog(); let data; if(vars.lastListItem) { // console.log(resultData) // data = vars.currentTreeObject data = getDataFromTreeObject(resultData.resourcePath, 'file', vars.allTreeObject).data; data.memo = resultData.memo; if(resultData.resourcePath == vars.lastListItem.dataset.resourcePath) { let resourcePath = splitTopPathAndTargetName(data.resourcePath).topPath; // 추가 파일에 메모 저장하는 경우 위의 resourcePath는 depth1/depth2/depth3/파일명.txt_version 과 같은 형태로 가공된 상태 // list 렌더를 위해 필요한 resourcePath의 형태는 depth1/depth2/depth3 // 따라서 resourcePath를 접두어(_version, _attachment 등)로 split 후 배열 0번째를 구한 뒤, // 이것을 splitTopPathAndTargetName함수를 통해 topPath를 구하면 depth1/depth2/depth3 형태로 가공됨 if (resourcePath.includes('_version')) resourcePath = splitTopPathAndTargetName(resourcePath.split('_version')[0]).topPath; if (resourcePath.includes('_attachment')) resourcePath = splitTopPathAndTargetName(resourcePath.split('_attachment')[0]).topPath; let pageRanderingOption = { scope: 'list', resourcePath: resourcePath } await preparePageRendering(pageRanderingOption); } } }) //// 권한 설정 socket.on('setDataPermission_success', async (resultData) => { // console.log('-------- setDataPermission socket error'); // console.log(resultData); let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; renderLog(); let userCurPath, userCurPermission; if (vars.users[socket.id] && vars.users[socket.id].curPath) userCurPath = vars.users[socket.id].curPath; if (vars.users[socket.id] && vars.users[socket.id].permission) userCurPermission = vars.users[socket.id].permission; // 251107 김아름 let extractedPath = extractPathByLength(userCurPath, 1); // 251107 김아름 let myId = JSON.parse(vars.userInfoString).user_id; let userInfo = JSON.parse(resultData.userInfoString); let permissionChangeUserId = userInfo.user_id; let permissionChangedFolderPath = resultData.resourcePath; let permissionChangedFolderDepth = getDepth(permissionChangedFolderPath); let pathSplit = permissionChangedFolderPath.split('/'); let permissionChangedFolderDepth1Path, permissionChangedFolderDepth2Path, permissionChangedFolderDepth3Path; if (pathSplit[1]) permissionChangedFolderDepth1Path = `${pathSplit[0]}/${pathSplit[1]}`; if (pathSplit[2]) permissionChangedFolderDepth2Path = `${permissionChangedFolderDepth1Path}/${pathSplit[2]}`; if (pathSplit[3]) permissionChangedFolderDepth3Path = `${permissionChangedFolderDepth2Path}/${pathSplit[3]}`; let beforePermission = (resultData.beforePermission == 0) ? 99999 : resultData.beforePermission; let newPermission = (resultData.newPermission == 0) ? 99999 : resultData.newPermission; //// 마지막으로 선택된 depth1 폴더의 경로 let lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; let lastHeaderBtn = document.querySelector(`body > .header .center .menu-tab .btn[data-resource-path="${lastHeaderBtnPath}"]`); //// 마지막으로 선택된 depth1 폴더의 스타일 강조 if (lastHeaderBtn) changeHeaderBtnStyle(lastHeaderBtn); lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; // 251107 김아름, 내가 지금 있는 폴더와 상대방이 권한을 바꾼 폴더 비교 // 권한 변경에 영향이 있는 조건 const isAffected = myId != permissionChangeUserId && // 권한 바꾼 사람이 내가 아닐 때 beforePermission < newPermission && // 이전 폴더 권한보다 바꾼 폴더 권한이 클때(참관자->참관자일때도 alert떠서 방지용) userCurPermission < newPermission; // 나의 권한보다 바꾼 폴더 권한이 클때 if (isAffected) { if (permissionChangedFolderDepth === 1 && extractedPath == permissionChangedFolderDepth1Path) { // 권한 바뀐 폴더가 depth1인 경우 && 내 현재 위치의 depth1 폴더명이 권한 바뀐 폴더명과 같을 때 let toggleParams = { text: `폴더의 권한이 변경되었습니다.${permissionChangedFolderDepth1Path}`, type: 'alertModal' }; toggleModal(true, toggleParams); document.querySelector('.archive-main.main').style.display = 'none'; document.querySelector('.main-notice.notice').style.display = 'flex'; vars.lastMainTreeItem = undefined; } if (permissionChangedFolderDepth === 2 && userCurPath.startsWith(permissionChangedFolderDepth2Path + '/')) { // 권한 바뀐 폴더가 depth2인 경우 && 내 현재 위치가 권한 바뀐 폴더의 depth2 path로 시작될 때 let toggleParams = { text: `폴더의 권한이 변경되었습니다.${permissionChangedFolderDepth2Path}`, type: 'alertModal' }; toggleModal(true, toggleParams); lastHeaderBtn?.click(); vars.lastMainTreeItem = undefined; } if (permissionChangedFolderDepth === 3 && userCurPath == permissionChangedFolderDepth3Path) { // 권한 바뀐 폴더가 depth3인 경우 && 내 현재 위치가 권한 바뀐 폴더와 같을 때 let toggleParams = { text: `폴더의 권한이 변경되었습니다.${permissionChangedFolderDepth3Path}`, type: 'alertModal' }; toggleModal(true, toggleParams); lastHeaderBtn?.click(); vars.lastMainTreeItem = undefined; } // 251112 김아름, 브라우저 경로 수정 if (permissionChangedFolderDepth == 1) { let pageRanderingOption = { resourcePath: '/', pushState: true, } await preparePageRendering(pageRanderingOption); } if (permissionChangedFolderDepth == 2 || permissionChangedFolderDepth == 3) { let pageRanderingOption = { resourcePath: extractedPath, pushState: true, } await preparePageRendering(pageRanderingOption); } } //// depth1 폴더 영역 렌더링 let pageRanderingOption = { scope: 'headerBtn', pushState: false } await preparePageRendering(pageRanderingOption); // 251114 김아름 if (vars.lastHeaderBtn == undefined) return; //// depth2, depth3 폴더 생성 //// 마지막으로 선택된 depth1 폴더 안에 depth2, depth3 폴더의 권한을 설정할 때 아래 코드 실행 //// -> 다른 depth1 폴더를 보고 있는 사용자는 해당 안됨 if (extractedPath == lastHeaderBtnPath) { //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 let pageRanderingOption = { scope: 'tree', resourcePath: extractedPath, userCurPath: userCurPath, pushState: false } await preparePageRendering(pageRanderingOption); if (vars.lastMainTreeItem) { let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${vars.lastMainTreeItem.dataset.resourcePath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); } } // console.log('폴더 삭제했을 때 / 권한 수정해서 권한 해당 안될 때 -> 해당 폴더에 들어와있던 유저 경로 수정 필요'); //// depth3 폴더가 선택된 상태이고, depth3 폴더 경로의 데이터가 존재할 때 리스트 렌더링 // if (treeContainer.dataset.resourcePath == extractedPath && vars.lastMainTreeItem) { // let lastTreePath = vars.lastMainTreeItem.dataset.resourcePath // let data = getDataFromTreeObject(lastTreePath, 'folder').data; // if (data) { // let pageRanderingOption = { // scope: 'list', // resourcePath: lastTreePath, // pushState: false, // debug: '업로드완료 - list' // } // await preparePageRendering(pageRanderingOption); // //// depth4 파일이 선택된 상태인 경우 depth4 파일 경로로 스타일 강조 // if (vars.lastListItem) { // let lastListItemPath = vars.lastListItem.dataset.resourcePath; // let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-resource-path="${lastListItemPath}"]`) // if (listItem) changeListItemStyle(listItem); // } // } // } }) //// 만료 기간 갱신 socket.on('renewExpiryDate_success', async (resultData) => { // console.log('//////// 만료 기간 갱신'); // console.log(resultData); let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; let userCurPath; if (vars.users[socket.id] && vars.users[socket.id].curPath) userCurPath = vars.users[socket.id].curPath; let lastHeaderBtnPath = vars.lastHeaderBtn?vars.lastHeaderBtn.dataset.resourcePath:undefined; let pathSplit = resultData.resourcePath.split('/'); let depth1Path, depth2Path, depth3Path; if (pathSplit[1]) depth1Path = `${pathSplit[0]}/${pathSplit[1]}`; if (pathSplit[2]) depth2Path = `${depth1Path}/${pathSplit[2]}`; if (pathSplit[3]) depth3Path = `${depth2Path}/${pathSplit[3]}`; //// 마지막으로 선택된 depth1 폴더 경로와 변경하려는 depth3 폴더를 포함하고 있는 depth1 폴더 경로가 동일할 때 아래 코드 실행 //// -> 다른 depth1 폴더를 보고 있는 사용자는 코드 실행 안됨 if (lastHeaderBtnPath == depth1Path) { //// 마지막으로 선택된 depth1 폴더의 하위 트리 폴더 렌더링 let pageRanderingOption = { scope: 'tree', pushState: false, resourcePath: depth1Path, userCurPath: userCurPath } await preparePageRendering(pageRanderingOption); //// 마지막으로 선택된 depth3 폴더가 있을 때 아래 코드 실행 if (vars.lastMainTreeItem) { //// 마지막으로 선택된 depth3 폴더의 경로 let lastMainTreeItemPath = vars.lastMainTreeItem.dataset.resourcePath; //// 마지막으로 선택된 depth3 폴더의 스타일 강조 let mainTreeItem = document.querySelector(`.archive-main-left .tree-container .tree-wrap .tree-item-wrap[data-resource-path="${lastMainTreeItemPath}"]`) if (mainTreeItem) changeTreeItemStyle(mainTreeItem); } } }) //// 작성자 변경 socket.on('editAuthor_success', async (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; renderLog(); // vars.allTreeObject만 갱신 let pageRanderingOption = { scope: 'updateTreeObject', pushState: false, resourcePath: JSON.parse(vars.userInfoString).curPath } await preparePageRendering(pageRanderingOption); let extractedPath = extractPathByLength(resultData.originalResourcePathArr[0], 3); if (listWrapBody.dataset.resourcePath == extractedPath) { for (let dataId of resultData.dataIdArr) { let listItem = document.querySelector(`.archive-main-center .list-container .list-body .list-item[data-id="${dataId}"]`) if (listItem) { let authorText = listItem.querySelector('.author .text'); authorText.innerText = resultData.newAuthorNm; } if (viewerContainer.dataset.dataId == dataId) { let viewerAuthorText = viewerContainer.querySelector('.info-wrap .metadata .author .value'); viewerAuthorText.innerText = resultData.newAuthorNm; } } // 작성자 정렬을 위한 리스트 렌더링 let pageRanderingOption = { scope: 'list', pushState: false, resourcePath: JSON.parse(vars.userInfoString).curPath } await preparePageRendering(pageRanderingOption); } }) //// viewer 리셋 socket.on('requestResetViewer', async (resultData) => { let resourcePath = resultData.resourcePath; let depth = getDepth(resourcePath); let compPath = extractPathByLength(listWrapBody.dataset.resourcePath, depth); if (listContainer.style.display == 'flex' && compPath == resourcePath) resetViewer(); }) //// 현재 내 정보 받아오기 socket.on('returnMe', (data)=>{ let me = data; vars.userInfoString = JSON.stringify(me); vars.users[socket.id] = me; }) //// 동일 프로젝트 접속자 확인 => 추후 동일 프로젝트 접속자 알림으로 사용 socket.on('connected_user', (data) => { let {users} = data; vars.users = users; // console.log(data); // console.log(users); let connectedUsers = document.querySelector('body > .header .right .connected-users'); let connectedUsersCount = connectedUsers.querySelector('.count'); connectedUsersCount.innerHTML = ''; // let keys = Object.keys(users); let values = Object.values(users); connectedUsersCount.innerHTML = `${addCommasToNumber(values.length)} 명`; // connectedUsersCount.innerHTML = `${addCommasToNumber(9806)} 명`; let modalHeaderUsersCount = document.querySelector('.archive-modal .modal-header > .title .left-wrap .title-wrap .users-count'); modalHeaderUsersCount.innerHTML = ''; modalHeaderUsersCount.innerHTML = `${addCommasToNumber(values.length)} 명`; let connectedUsersWrap = document.querySelector('.archive-modal .modal-body .connected-users-wrap'); let userItemWrap = connectedUsersWrap.querySelector('.user-item-wrap'); userItemWrap.innerHTML = ''; let docFragment = document.createDocumentFragment(); let userInfo = JSON.parse(vars.userInfoString); for(let i = 0; i < values.length; i++){ let user = values[i]; let userId = user.user_id; let userName = `${user.user_nm} ${user.position}`; userName = userName.trim(); let userColor = user.userColor; let userPermission = user.permission; let userCurPath = user.curPath; let userItem = document.createElement('div'); userItem.classList.add('user-item'); userItem.dataset.userId = userId; let wrap = document.createElement('div'); wrap.classList.add('wrap'); let topWrap = document.createElement('div'); topWrap.classList.add('top-wrap'); let bottomWrap = document.createElement('div'); bottomWrap.classList.add('bottom-wrap'); let profileImage = document.createElement('img'); profileImage.classList.add('profile-image'); profileImage.style.outline = `2px solid ${userColor}`; let defaultImageUrl = '/main/img/archive/empty-profile.svg'; let profileImageUrl = defaultImageUrl; if (/^[a-zA-Z]{1}\d{5}$/.test(userId)) profileImageUrl = `http://erp.hanmaceng.co.kr/erpphoto/${userId}.jpg`; profileImage.src = profileImageUrl; // onerror 핸들러 바인딩 (한번만 동작하도록) profileImage.onerror = function() { this.onerror = null; // 무한루프 방지 this.src = defaultImageUrl; }; let name = document.createElement('div'); name.classList.add('name'); name.innerHTML = userName; let addPermissionBadge = false, permissionBadge, permissionEng, permissionKor; // if (userPermission == 191) { if (vars.permission.permissionDef[user.permission] == '관리자') { addPermissionBadge = true; permissionEng = 'master'; permissionKor = '관리자'; } if (vars.permission.permissionDef[user.permission] == '부관리자') { addPermissionBadge = true; permissionEng = 'sub-master'; permissionKor = '부관리자'; } if (vars.permission.permissionDef[user.permission] == '보안참여자') { addPermissionBadge = true; permissionEng = 'security-worker'; permissionKor = '보안참여자'; } if (vars.permission.permissionDef[user.permission] == '일반참여자') { addPermissionBadge = true; permissionEng = 'worker'; permissionKor = '일반참여자'; } if (vars.permission.permissionDef[user.permission] == '참관자') { addPermissionBadge = true; permissionEng = 'viewer'; permissionKor = '참관자'; } if (addPermissionBadge) { permissionBadge = document.createElement('div'); permissionBadge.classList.add(`user-permission-${permissionEng}`); let h6 = document.createElement('h6'); h6.innerText = permissionKor; permissionBadge.appendChild(h6); } let curPath = document.createElement('div'); curPath.classList.add('cur-path'); curPath.innerHTML = `현재 위치: ${userCurPath}`; topWrap.appendChild(name); if (permissionBadge) topWrap.appendChild(permissionBadge); bottomWrap.appendChild(curPath); wrap.appendChild(topWrap); // 프로젝트에 포함된 사용자인 경우에만 접속 인원 모달창에서 현재 위치 표시 if (userInfo.permission != null && typeof userInfo.permission == 'number') wrap.appendChild(bottomWrap); userItem.appendChild(profileImage); userItem.appendChild(wrap); docFragment.appendChild(userItem); } userItemWrap.appendChild(docFragment); addMeBadge(); function addMeBadge() { let myId = JSON.parse(vars.userInfoString).user_id; let userItemWrap = document.querySelector('.archive-modal .modal-body .connected-users-wrap .user-item-wrap'); let myUserItem = userItemWrap.querySelector(`.user-item[data-user-id="${myId}"]`); myUserItem.classList.add('me'); userItemWrap.insertBefore(myUserItem, userItemWrap.firstElementChild); if (!myUserItem.querySelector('.wrap .top-wrap .me-badge')) { let meBadge = document.createElement('div'); meBadge.classList.add('me-badge'); let h6 = document.createElement('h6'); h6.innerText = '나'; meBadge.appendChild(h6); myUserItem.querySelector('.wrap .top-wrap').appendChild(meBadge); } } }) //// 현재 파일선택한 사람들 확인 // socket.on('fileSelected', (data)=>{ // let {users} = data; // Object.assign(vars.users, users); // console.log(users); // }) //folder download 준비 완료 socket.on('zip-prepared', (data)=>{ // 다운로드창 new 표시 if(document.querySelector('.download-btn .download-reddot')){ document.querySelector('.download-btn .download-reddot').style.display = 'block'; } // console.log('다운로드 준비 완료', data); // alert(`${data.resourcePath}의 다운로드가 준비되었습니다.`); }) // 폴더 압축 프로그레스 socket.on('zip-progress', (data)=>{ console.log(data); }) //// AI 요약 시작 socket.on('summarize_start', (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; let datas = resultData.summarizeAiDataArr; datas.forEach(data => { const { dataId, type } = data; // 해당 파일의 버튼만 로딩 상태로 변경 updateAiButtonState(dataId, 'loading', type); }) }); //// AI 요약 로그 기록 완료 socket.on('addSummarizeAiLog_success', async (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; const { text, dataId, type } = resultData; renderMemo(text, dataId); updateAiButtonState(dataId, 'initial', type); renderLog(); let userCurPath; if (vars.users[socket.id] && vars.users[socket.id].curPath) userCurPath = vars.users[socket.id].curPath; // 메모가 생성된 파일의 depth3 path와 유저 현재위치 비교 후 화면에 반영 let memoDepth3Path = extractPathByLength(resultData.resourcePath, 3); if (memoDepth3Path == userCurPath) { let pageRanderingOption = { scope: 'list', resourcePath: memoDepth3Path, } await preparePageRendering(pageRanderingOption); } }) //// AI 요약 실패 socket.on('summarize_failed', async (resultData) => { const { resourcePath, dataId, text, type } = resultData; renderMemo(text, dataId); updateAiButtonState(dataId, 'initial', type); let userInfoString = vars.userInfoString; let params = { resourcePath: resourcePath, memo: text, }; let res = await axios.post(`${vars.path_name}/updateMemoInfo`, { userInfoString, params }); let addSummarizeAiLogParams = { dataId: dataId, isState: false }; await axios.post(`${vars.path_name}/addSummarizeAiLog`, { addSummarizeAiLogParams}); }); // 유저권한 추가/삭제 로그 기록 완료 socket.on('addPermissionLog_success', async (resultData) => { let currProjectId = JSON.parse(vars.userInfoString).project_id; if (currProjectId != resultData.projectId) return; renderLog(); });