513 lines
18 KiB
JavaScript
513 lines
18 KiB
JavaScript
import { vars } from './variable.js';
|
|
|
|
// 파일 사이즈 변환
|
|
export function formatBytes(bytes) {
|
|
const abs = Math.abs(bytes);
|
|
let size, unit;
|
|
|
|
if (abs < 1024) {
|
|
size = addCommasToNumber(bytes);
|
|
unit = ' Bytes';
|
|
} else if (abs < 1048576) {
|
|
size = addCommasToNumber((bytes / 1024).toFixed(2));
|
|
unit = ' KB';
|
|
} else if (abs < 1073741824) {
|
|
size = addCommasToNumber((bytes / 1048576).toFixed(2));
|
|
unit = ' MB';
|
|
} else if (abs < 1099511627776) {
|
|
size = addCommasToNumber((bytes / 1073741824).toFixed(2));
|
|
unit = ' GB';
|
|
} else {
|
|
size = addCommasToNumber((bytes / 1099511627776).toFixed(2));
|
|
unit = ' TB';
|
|
}
|
|
|
|
if (size != 0) {
|
|
let decimalPointNum = size.split('.')[1];
|
|
if (decimalPointNum) {
|
|
// 소수점 아래 숫자가 00인 경우
|
|
if (decimalPointNum == '00') size = size.split('.')[0];
|
|
// 소수점 아래 두번째 숫자가 0인 경우
|
|
else if (decimalPointNum[1] == '0') size = `${size.split('.')[0]}.${decimalPointNum[0]}`;
|
|
}
|
|
}
|
|
|
|
return size + unit;
|
|
}
|
|
|
|
// 1000 단위 콤마 추가
|
|
// export function addCommasToNumber(num) {
|
|
// return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
// }
|
|
|
|
export function addCommasToNumber(num) {
|
|
const isNegative = Number(num) < 0;
|
|
const parts = Math.abs(Number(num)).toString().split('.');
|
|
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
|
|
const formatted = parts.join('.');
|
|
return isNegative ? `-${formatted}` : formatted;
|
|
}
|
|
|
|
export function getDepth(path) {
|
|
path = path.startsWith('/') ? path.slice(1) : path;
|
|
let pathSplit = path.split('/');
|
|
let result = pathSplit.length;
|
|
return result;
|
|
}
|
|
|
|
export function updatePartialPath(sourcePath, targetPath) {
|
|
let sourcePathSplit = sourcePath.split('/');
|
|
let targetPathSplit = targetPath.split('/');
|
|
for (let i = 0; i < sourcePathSplit.length; i++) {
|
|
targetPathSplit[i] = sourcePathSplit[i];
|
|
}
|
|
|
|
return targetPathSplit.join('/');
|
|
}
|
|
|
|
// 파일명, 확장자 분리
|
|
export function splitBaseAndExt(target, isLowerExt) {
|
|
let targetSplit = target.split('.');
|
|
let ext = targetSplit.pop();
|
|
if (isLowerExt) ext = ext.toLowerCase();
|
|
let base = targetSplit.join('.');
|
|
return { ext: ext, base: base }
|
|
}
|
|
|
|
// 선택한 대상이 포함된 상위 폴더 경로 추출
|
|
export function splitTopPathAndTargetName(resourcePath) {
|
|
let resourcePathSplit = resourcePath.split('/');
|
|
let targetName = resourcePathSplit.pop();
|
|
let topPath = resourcePathSplit.join('/');
|
|
if (!topPath || topPath == '' || topPath == null) topPath = '/';
|
|
return { targetName: targetName, topPath: topPath };
|
|
}
|
|
|
|
export function extractPathByLength(target, count) {
|
|
if (!Array.isArray(target)) {
|
|
target = target.split('/');
|
|
}
|
|
const parts = target.filter(Boolean).slice(0, count);
|
|
return '/' + parts.join('/');
|
|
}
|
|
|
|
// 특수문자를 체크하는 정규표현식
|
|
export function hasSpecialChar(target) {
|
|
// const pattern = /[\/\\;:?`'"<>|#%&*]/;
|
|
const pattern = /[\/\\:*?'"`<>|#]/;
|
|
return pattern.test(target);
|
|
}
|
|
|
|
// 동일한 폴더명/파일명 존재 여부 확인
|
|
export function existEqualName(type, comparisonPath, targetName) {
|
|
let result;
|
|
if (comparisonPath != '' && comparisonPath != undefined) {
|
|
result = getTypeDataFromFolderData(type, comparisonPath)[targetName];
|
|
} else {
|
|
// result = vars.currentTreeObject[type][targetName];
|
|
result = vars.allTreeObject[type][targetName];
|
|
}
|
|
|
|
// 헤더 버튼 이름 변경 시 페이지 버튼과 이름 같은 경우 변경 불가
|
|
let pageBtnNameArr = ['과업개요', '공문'];
|
|
if (comparisonPath == '/' && result == undefined) result = pageBtnNameArr.includes(targetName);
|
|
|
|
return result;
|
|
|
|
// folderData에서 타입(폴더/파일)과 경로를 사용해서 해당 경로의 타입별 데이터 가져오기
|
|
function getTypeDataFromFolderData(type, path) {
|
|
let data;
|
|
if (type == 'folder') data = vars.allTreeObject[type];
|
|
if (type == 'file') data = vars.currentTreeObject[type];
|
|
|
|
let pathSplit = path.split('/');
|
|
pathSplit.shift();
|
|
// if (pathSplit[0] == '') return data;
|
|
|
|
for (let i = 0; i < pathSplit.length; i++) {
|
|
if (data[pathSplit[i]]) {
|
|
if (type == 'folder') data = data[pathSplit[i]]['child'][type];
|
|
if (type == 'file') data = data;
|
|
} else {
|
|
data = data;
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
}
|
|
|
|
export function getNextFileName(nameArr, newName) {
|
|
const dotIdx = newName.lastIndexOf('.');
|
|
const base = dotIdx !== -1 ? newName.slice(0, dotIdx) : newName;
|
|
const ext = dotIdx !== -1 ? newName.slice(dotIdx) : '';
|
|
const set = new Set(nameArr);
|
|
|
|
let maxNum = 0;
|
|
const regex = new RegExp(`^${escapeRegExp(base)}(?: \\((\\d+)\\))?${escapeRegExp(ext)}$`);
|
|
for (const name of set) {
|
|
const match = name.match(regex);
|
|
if (match) {
|
|
const num = match[1] ? parseInt(match[1], 10) : 0;
|
|
if (num > maxNum) maxNum = num;
|
|
}
|
|
}
|
|
|
|
if (maxNum === 0 && !set.has(newName)) return newName;
|
|
return `${base} (${maxNum + 1})${ext}`;
|
|
|
|
function escapeRegExp(str) {
|
|
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
}
|
|
}
|
|
|
|
export function getDataFromTreeObject(path, type, data) {
|
|
let parentData;
|
|
if (!data) data = vars.allTreeObject;
|
|
let pathSplit = path.split('/');
|
|
pathSplit.shift();
|
|
|
|
for (let i = 0; i < pathSplit.length; i++) {
|
|
if (i != pathSplit.length - 1) {
|
|
if (data['folder'][pathSplit[i]]) {
|
|
data = data['folder'][pathSplit[i]]['child'];
|
|
}
|
|
} else {
|
|
if (type == 'folder') {
|
|
parentData = data;
|
|
data = data['folder'][pathSplit[i]];
|
|
}
|
|
if (type == 'file') {
|
|
if (data['file'][pathSplit[i]]) {
|
|
parentData = data;
|
|
data = data['file'][pathSplit[i]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return { parentData: parentData, data: data };
|
|
}
|
|
|
|
export function getCurrentTreeObject(path) {
|
|
let data = vars.allTreeObject;
|
|
let pathSplit = path.split('/');
|
|
pathSplit.shift();
|
|
for (let i = 0; i < pathSplit.length; i++) {
|
|
if (i != pathSplit.length - 1) {
|
|
if (data['folder'][pathSplit[i]]) {
|
|
data = data['folder'][pathSplit[i]]['child'];
|
|
}
|
|
} else {
|
|
if (data['folder'][pathSplit[i]]) data = data['folder'][pathSplit[i]]['child'];
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
|
|
export function targetFocus(target, behavior = 'smooth') {
|
|
target.scrollIntoView({
|
|
behavior: behavior, // 부드럽게
|
|
block: 'center', // 화면 중앙에 위치하도록 (start, end, nearest 도 가능)
|
|
inline: 'center'
|
|
});
|
|
target.focus();
|
|
}
|
|
|
|
export function pxToRem(px) {
|
|
let remPx = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
return px / remPx;
|
|
}
|
|
|
|
export function buildResourcePathFromSegments(rows) {
|
|
if (!Array.isArray(rows)) rows = [rows];
|
|
let result = [];
|
|
rows.map(row => {
|
|
let resourcePath = '/';
|
|
let maxDepth = 8;
|
|
let arr = [];
|
|
for (let i = 0; i < maxDepth; i++) {
|
|
let num = i+1;
|
|
let segment = row[`path${num}`];
|
|
if (segment) arr.push(segment);
|
|
}
|
|
if (arr.length != 0) resourcePath += arr.join('/');
|
|
result.push(resourcePath);
|
|
})
|
|
|
|
return result;
|
|
}
|
|
|
|
export function headerBtnForceClick(headerBtn) {
|
|
headerBtn.click();
|
|
}
|
|
|
|
export function treeBtnForceClick(treeBtn) {
|
|
treeBtn.click();
|
|
}
|
|
|
|
export function closeInitProgress() {
|
|
document.querySelector('.init-progress').style.display = 'none';
|
|
}
|
|
|
|
export async function getMyDownloadList(){
|
|
let res = await axios.get(`${vars.path_name}/getMyDownloadList`, {params : {user_id : JSON.parse(vars.userInfoString).user_id}});
|
|
// console.log(res.data);
|
|
if(res.data.length > 0){
|
|
if(document.querySelector('.download-btn .download-reddot')){
|
|
document.querySelector('.download-btn .download-reddot').style.display = 'block';
|
|
}
|
|
}else{
|
|
if(document.querySelector('.download-btn .download-reddot')){
|
|
document.querySelector('.download-btn .download-reddot').style.display = 'none';
|
|
}
|
|
}
|
|
|
|
let ul = document.querySelector('.download-modal__body_list');
|
|
ul.innerHTML = '';
|
|
for(let i = 0; i < res.data.length; i++){
|
|
let li = document.createElement('li');
|
|
li.classList.add('download-modal__body_list_item');
|
|
|
|
let expireDate = new Date(res.data[i].expire_date);
|
|
let now = new Date();
|
|
let yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
|
|
|
let state = (expireDate < yesterday)? `<img class="--button__xsmall-icon --disable" src="/main/img/archive/icon__download--111.svg" alt="/" />`: (!res.data[i].made)?`준비중`:`<img class="--button__xsmall-icon downloadFolder__btn__icon" src="/main/img/archive/icon__download--111.svg" alt="/" />`
|
|
let expire =(state == '준비중')?state :(expireDate < yesterday)? '만료됨': formatDateTime(expireDate);
|
|
|
|
li.innerHTML = `
|
|
<img class="--icon" src="/main/img/header/header-folder-icon.svg" alt="/" />
|
|
<div class="download-modal__body_list_item_text">
|
|
<h4 class="download-modal__body_list_item_text_title">
|
|
${res.data[i].name}
|
|
</h4>
|
|
<p class="download-modal__body_list_item_text_subtitle">
|
|
${res.data[i].project_nm}${res.data[i].path}
|
|
</p>
|
|
</div>
|
|
<h6 class="download-modal__body_list_item_time">
|
|
${expire}
|
|
</h6>
|
|
<div class="download-modal__body_list_item_status">${state}</div>
|
|
`;
|
|
|
|
ul.appendChild(li);
|
|
|
|
li.querySelector('.downloadFolder__btn__icon')?.addEventListener('click', () => {
|
|
window.location.href = res.data[i].url;
|
|
})
|
|
}
|
|
|
|
function formatDateTime(date) {
|
|
const padZero = (num) => String(num).padStart(2, '0');
|
|
|
|
const year = date.getFullYear();
|
|
const month = padZero(date.getMonth() + 1); // getMonth()는 0부터 시작하므로 +1
|
|
const day = padZero(date.getDate());
|
|
const hours = padZero(date.getHours());
|
|
const minutes = padZero(date.getMinutes());
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
|
}
|
|
}
|
|
|
|
export async function openNewWindowViewer() {
|
|
let isRecycleBinModal = document.querySelector('.recycle-bin-modal').style.display == 'flex';
|
|
let lastListItem = (isRecycleBinModal) ? vars.lastListItem_bin : vars.lastListItem;
|
|
|
|
let resourcePath = lastListItem.dataset.resourcePath;
|
|
let dataId = lastListItem.dataset.id;
|
|
let isLowerExt = true, ext = splitBaseAndExt(resourcePath, isLowerExt).ext;
|
|
|
|
let thumbnail_key = getDataFromTreeObject(resourcePath, 'file', vars.currentTreeObject).data?.thumbnailKey;
|
|
|
|
//Presigned URL
|
|
let PresignedUrl = undefined;
|
|
let getDataInfoParams = {
|
|
userInfoString: vars.userInfoString,
|
|
storageType: vars.storageType,
|
|
dataIdArr: [dataId],
|
|
isRemoved: isRecycleBinModal,
|
|
debug: "'우측 미리보기 새 창으로 열기 버튼 클릭 이벤트'에서 실행"
|
|
}
|
|
let getDataInfoRes = await axios.post(`${vars.path_name}/getDataInfo`, { params: getDataInfoParams } );
|
|
if (getDataInfoRes.data.message == 'getDataInfo_success') {
|
|
let result = getDataInfoRes.data.result;
|
|
let directViewExtArr = ['xls', 'xlsx', 'xlsm', 'docx', 'hwp', 'hwpx'];
|
|
let objectKey = directViewExtArr.includes(ext) ? result.object_key : result.popup_key;
|
|
|
|
if(objectKey == undefined || objectKey == `` || objectKey == null){
|
|
return;
|
|
}
|
|
let generateDownloadUrlParams = {
|
|
objectKey: objectKey,
|
|
resourcePath: resourcePath
|
|
}
|
|
let generateDownloadUrlRes = await axios.post(`${vars.path_name}/generateDownloadUrl`, generateDownloadUrlParams);
|
|
if (generateDownloadUrlRes.data.message == 'generateDownloadUrl_success') {
|
|
PresignedUrl = generateDownloadUrlRes.data.url;
|
|
}
|
|
}
|
|
//Presigned URL end
|
|
|
|
|
|
thumbnail_key = encodeURIComponent(thumbnail_key);
|
|
resourcePath = encodeURIComponent(resourcePath);
|
|
let fullPath = encodeURIComponent(PresignedUrl);
|
|
|
|
// 뷰어 기본 width값은 현재 화면 width값의 절반
|
|
let denominator = 2;
|
|
// url 뷰어는 현재 화면 width값과 동일하게 설정
|
|
if (ext == 'url') denominator = 1;
|
|
|
|
let width = screen.width / denominator;
|
|
let height = screen.height;
|
|
let left = screen.width * 2 + 10;
|
|
|
|
let open_ext = `pdf`;
|
|
switch(ext){
|
|
case 'pdf' :
|
|
case 'doc' :
|
|
case 'ppt' :
|
|
case 'pptx' :
|
|
case 'dwg' :
|
|
case 'dxf' :
|
|
case 'grm' :
|
|
open_ext = 'pdf';
|
|
break;
|
|
case 'hwp' :
|
|
case 'hwpx' :
|
|
open_ext = ext;
|
|
break;
|
|
case 'xls' :
|
|
case 'xlsx' :
|
|
case 'xlsm' :
|
|
open_ext = ext;
|
|
break;
|
|
case 'docx' :
|
|
open_ext = ext;
|
|
break;
|
|
case 'gsim' :
|
|
open_ext = 'gsim';
|
|
break
|
|
case 'ifc' :
|
|
open_ext = 'ifc';
|
|
break
|
|
case 'png' :
|
|
case 'jpg' :
|
|
case 'jpeg' :
|
|
case 'webp' :
|
|
case 'gif' :
|
|
open_ext = 'png';
|
|
break
|
|
case 'mp4' :
|
|
case 'mov' :
|
|
case 'webm' :
|
|
open_ext = 'mp4';
|
|
break
|
|
case 'log' :
|
|
case 'txt' :
|
|
case 'md' :
|
|
open_ext = 'txt';
|
|
break
|
|
case 'url' :
|
|
open_ext = 'url';
|
|
break;
|
|
case 'zip' :
|
|
open_ext = 'zip';
|
|
break
|
|
case 'glb':
|
|
case 'gltf':
|
|
case 'obj':
|
|
case 'stl':
|
|
case 'fbx':
|
|
case '3dm':
|
|
open_ext = 'glb';
|
|
break;
|
|
case 'html':
|
|
open_ext = 'html';
|
|
break;
|
|
}
|
|
|
|
//presigned url은 ext를 읽을수 없엉...
|
|
const jsonData = JSON.stringify({$ext : open_ext});
|
|
const encodedData = btoa(jsonData);
|
|
|
|
// 3d모델뷰어 썸네일 생성을 위해 dataId, path_name 추가
|
|
// let popup = window.open(`/popup?path=${fullPath}&data=${encodedData}`, '', `width=${width}, height=${height}, left=${left},`);
|
|
let popup = window.open(`/popup?thumbnail_key=${thumbnail_key}&path_name=${vars.path_name}&resourcePath=${resourcePath}&dataId=${dataId}&path=${fullPath}&data=${encodedData}`, '', `width=${width}, height=${height}, left=${left},`);
|
|
}
|
|
|
|
export function initFileAreaUI(fileAreaMode) {
|
|
let listContainer = document.querySelector('.archive-main .archive-main-center .list-container');
|
|
let isRecycleBinModal = document.querySelector('.recycle-bin-modal').style.display == 'flex';
|
|
if (isRecycleBinModal) listContainer = document.querySelector('.recycle-bin-modal .recycle-bin-wrap .list-container');
|
|
|
|
let listHeader = listContainer.querySelector('.list-header');
|
|
let listBody = listContainer.querySelector('.list-body');
|
|
let listBodyItemWrap = listBody.querySelector('.list-item-wrap');
|
|
let mapContainer = listBody.querySelector('.map-container');
|
|
|
|
let archiveMainRight = document.querySelector('.archive-main-right');
|
|
let viewerHeader = archiveMainRight.querySelector('.viewer-header');
|
|
|
|
if (fileAreaMode == 'map') {
|
|
listHeader.style.display = 'none';
|
|
listBody.style.height = '100%';
|
|
listBody.style.overflowY = 'hidden';
|
|
listBodyItemWrap.style.display = 'none';
|
|
if (mapContainer) mapContainer.style.display = 'flex';
|
|
|
|
archiveMainRight.style.minWidth = '36rem';
|
|
archiveMainRight.style.maxWidth = '36rem';
|
|
archiveMainRight.style.height = 'calc(100% - 2.75rem)';
|
|
archiveMainRight.style.position = 'absolute';
|
|
archiveMainRight.style.right = '0.625rem';
|
|
archiveMainRight.style.top = '0.5rem';
|
|
archiveMainRight.style.background = '#fffa';
|
|
archiveMainRight.style.backdropFilter = 'blur(0.2rem)';
|
|
archiveMainRight.style.webkitBackdropFilter = 'blur(0.2rem)';
|
|
archiveMainRight.style.borderRadius = '0.25rem';
|
|
archiveMainRight.style.boxShadow = '#ccc 0 0 0rem 0.0625rem, #0c0c0db3 0rem 0.5rem 1rem -0.25rem';
|
|
viewerHeader.style.borderRadius = '0.25rem 0.25rem 0 0';
|
|
} else {
|
|
listHeader.style.display = 'flex';
|
|
listBody.style.height = 'calc(100% - 2.25rem)';
|
|
listBody.style.overflowY = 'scroll';
|
|
listBodyItemWrap.style.display = 'flex';
|
|
if (mapContainer) mapContainer.style.display = 'none';
|
|
|
|
archiveMainRight.style.minWidth = '41rem';
|
|
archiveMainRight.style.maxWidth = '41rem';
|
|
archiveMainRight.style.height = '100%';
|
|
archiveMainRight.style.position = 'relative';
|
|
archiveMainRight.style.right = 'unset';
|
|
archiveMainRight.style.top = 'unset';
|
|
archiveMainRight.style.background = '#fff';
|
|
archiveMainRight.style.backdropFilter = 'none';
|
|
archiveMainRight.style.webkitBackdropFilter = 'none';
|
|
archiveMainRight.style.borderRadius = 'unset';
|
|
archiveMainRight.style.boxShadow = 'none';
|
|
viewerHeader.style.borderRadius = 'unset';
|
|
}
|
|
}
|
|
|
|
export function syncGroupStyle() {
|
|
let listContainer = document.querySelector('.archive-main .archive-main-center .list-container');
|
|
let isRecycleBinModal = document.querySelector('.recycle-bin-modal').style.display == 'flex';
|
|
if (isRecycleBinModal) listContainer = document.querySelector('.recycle-bin-modal .recycle-bin-wrap .list-container');
|
|
|
|
listContainer.querySelectorAll('.main-list-item').forEach(item => {
|
|
if (listContainer.querySelectorAll(`.list-item.selected[data-main-file-name="${item.dataset.mainFileName}"]`).length > 0) {
|
|
listContainer.querySelectorAll(`.list-item[data-main-file-name="${item.dataset.mainFileName}"]`).forEach(item => {
|
|
item.classList.add('group-style');
|
|
item.classList.remove('non-selected');
|
|
})
|
|
} else {
|
|
listContainer.querySelectorAll(`.list-item[data-main-file-name="${item.dataset.mainFileName}"]`).forEach(item => {
|
|
item.classList.remove('group-style');
|
|
})
|
|
}
|
|
})
|
|
} |