ソースを参照

update 2024-05-08

junggilpark 1 年間 前
コミット
e7ad894ccc
5 ファイル変更239 行追加119 行削除
  1. 74 9
      src/app.js
  2. 1 1
      src/auth/AuthProvider.js
  3. 1 1
      src/static/scripts/teamsapp.js
  4. 19 0
      src/static/styles/custom.css
  5. 144 108
      src/views/hello.html

+ 74 - 9
src/app.js

@@ -171,10 +171,11 @@ serverApp.post("/api-post", authProvider.acquireToken({
 }));
 
 serverApp.post("/getGroupList", authProvider.acquireToken({
-  scopes: ['.default'],
-  redirectUri: 'https://localhost:53000/redirect',
-  successRedirect: '/group-redirect'
+        scopes: ['.default'],
+        redirectUri: 'https://localhost:53000/redirect',
+        successRedirect: '/group-redirect'
 }));
+  
 
 serverApp.get("/group-redirect", 
   isAuthenticated,
@@ -271,14 +272,14 @@ serverApp.post('/makeFolder',
       }
 })
 
-serverApp.post('/uploadItems', upload.array('file'),
+serverApp.post('/api/upload', upload.array('file'),
   isAuthenticated,
   (req, res, next)=>{
     if (!req.session.accessToken) {
       return authProvider.acquireToken({
         scopes: ['.default'],
         redirectUri: 'https://localhost:53000/redirect',
-        successRedirect: '/uploadItems' 
+        successRedirect: '/api/upload'
       })(req, res, next);
     }
     next();
@@ -396,7 +397,9 @@ serverApp.post('/uploadItems', upload.array('file'),
         console.log('시작 시간 :', startTime, '종료 시간 :', endTime);
         res.json({success:'S', message: '요청하신 파일 업로드가 정상적으로 처리 되었습니다.'});
       }
-})
+});
+
+
 serverApp.post('/api/download',
   isAuthenticated,
   (req, res, next)=>{
@@ -506,7 +509,7 @@ serverApp.post('/api/download',
       }
     }
   }
-)
+);
 
 function createZipFile(obj, zip) {
   
@@ -561,21 +564,23 @@ async function getFolderItems(url, array, options) {
       }
     }
   }
+
   const resultObj = {
     folder : folder,
     files : files,
   };
+
   return resultObj;
 }
 
-serverApp.post('/deleteItems', 
+serverApp.post('/api/delete', 
   isAuthenticated,
   (req, res, next)=>{
     if (!req.session.accessToken) {
       return authProvider.acquireToken({
         scopes: ['.default'],
         redirectUri: 'https://localhost:53000/redirect',
-        successRedirect: '/deleteItems'
+        successRedirect: '/api/delete'
       })(req, res, next);
     }
     next();
@@ -660,3 +665,63 @@ serverApp.post('/api/update-name',
         return res.json(resultObj);
       }
   })
+
+
+  
+serverApp.post('/api/move-item', 
+  isAuthenticated,
+  (req, res, next)=>{
+    if (!req.session.accessToken) {
+      return authProvider.acquireToken({
+        scopes: ['.default'],
+        redirectUri: 'https://localhost:53000/redirect',
+        successRedirect: '/api/move-item'
+      })(req, res, next);
+    }
+    next();
+  },
+  async (req, res, next)=>{
+    if (req.body) {
+      const {id, name, itemId, siteId} = req.body;
+      const resultObj = {message:'', successItems : [], failItems : []};
+      if (name && isNaN(name)) {
+        const nameArray = JSON.parse(name);
+        const options = {
+          headers: {
+            Authorization: `Bearer ${req.session.accessToken}`,
+            ContentType: "application/json",
+          },
+        };
+
+        if (nameArray && nameArray.length > 0) {
+          for (let moveItem of nameArray) {
+            if (moveItem) {
+              const param = {
+                parentReference: {
+                  id: id
+                },
+                name: moveItem.name
+              };
+              try {
+                const result = await axios.patch(`${endPoint}/sites/${siteId}/drive/items/${moveItem.id}`, param, options);
+                // const remove = await axios.delete(`${endPoint}/sites/${siteId}/drive/items/${moveItem.id}`, options);
+                console.log(result.data);
+                if (result.data) {
+                  resultObj.successItems.push(moveItem.name);
+                }
+              }
+              catch (error) {
+                // console.log(error);
+                console.log(error.message);
+                console.log(error.name);
+                console.log(error.errors);
+                resultObj.failItems.push(moveName.name);
+              }
+            }
+          }
+          resultObj.message = `요청 하신 ${nameArray.length} 개 파일 중 ${ resultObj.successItems.length} 개 파일이 이동 되었습니다.`;
+        }
+      }
+      return res.json(resultObj);
+    }
+  });

+ 1 - 1
src/auth/AuthProvider.js

@@ -24,6 +24,7 @@ class AuthProvider {
                     successRedirect: options.successRedirect || '/',
                 })
             );
+            
             const authCodeUrlRequestParams = {
                 state: state,
 
@@ -77,7 +78,6 @@ class AuthProvider {
         return async (req, res, next) => {
             try {
                 const msalInstance = this.getMsalInstance(this.msalConfig);
-
                 /**
                  * If a token cache exists in the session, deserialize it and set it as the 
                  * cache for the new MSAL CCA instance. For more, see: 

+ 1 - 1
src/static/scripts/teamsapp.js

@@ -12,7 +12,7 @@
 
   function updateHubState(hubName) {
     if (hubName) {
-      // document.getElementById("hubState").innerHTML = "in " + hubName;
+      document.getElementById("hubState").innerHTML = "in " + hubName;
     }
   }
 })();

+ 19 - 0
src/static/styles/custom.css

@@ -726,4 +726,23 @@ html, body {
 
 .menu-button:hover{
   cursor: pointer;
+}
+
+.toggle-button {
+  position: absolute;
+  top: 100px;
+  border: 1px solid rgb(238, 238, 238);
+  width: auto;
+  z-index: 10;
+  background-color: white;
+  display: none;
+  min-width: 150px;
+}
+
+.toggle-button > div {
+  padding: 10px;
+}
+.toggle-button > div:hover {
+  cursor: pointer;
+  background-color: #eeeeee;
 }

+ 144 - 108
src/views/hello.html

@@ -3,13 +3,13 @@
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <link rel="icon" href="/favicon.ico" />
-    <link rel="stylesheet" type="text/css" href="/static/styles/custom.css?v=05" />
+    <link rel="stylesheet" type="text/css" href="/static/styles/custom.css?v=06" />
     <script
       src="https://res.cdn.office.net/teams-js/2.17.0/js/MicrosoftTeams.min.js"
       integrity="sha384-xp55t/129OsN192JZYLP0rGhzjCF9aYtjY0LVtXvolkDrBe4Jchylp56NrUYJ4S2"
       crossorigin="anonymous"
     ></script>
-    <script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.2.1/js/msal.js"></script>
+    <!-- <script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.2.1/js/msal.js"></script> -->
     <script src="/static/scripts/teamsapp.js"></script>
     <script src="https://code.jquery.com/jquery-latest.min.js"></script>
     <title>Microsoft Teams Tab</title>
@@ -55,6 +55,7 @@
                     <div class="one-drive-button">OneDrive에서 열기</div>
                     <input type="file" style="display: none;" id="folder-upload" name="folder" onchange="uploadFolders(event)" webkitdirectory multiple >
                     <input type="file" style="display: none;" id="file-upload" name="file" onchange="uploadFiles(event)" multiple >
+                    <div id="hubState" style="display: none;"></div>
                 </div>
                 <div class="panel"></div>
                 <div class="file-title">
@@ -88,7 +89,6 @@
   $(()=>{
     microsoftTeams.appInitialization.notifySuccess();
     getGroupList();
-    moveItem();
     window.oncontextmenu = function () {
         return false;
     };
@@ -103,6 +103,8 @@
       }
     })
   });
+
+
   function openFolder(event) {
     $('.upload-items').css('display', 'none');
     if (!$('.panel-item.on')[0]) return alertMessage('폴더 업로드', '업로드할 그룹을 선택해 주세요.');
@@ -276,29 +278,24 @@
 
               const {clientX, clientY} = e;
               const array = $('.file-content input[type="checkbox"]');
-              let str = `<div>편집</div>
-                  <div>탭으로 설정</div>
-                  <div onclick="download()">다운로드</div>
-                  <div onclick="deleteItem()">삭제</div>
-                  <div onclick="moveItem()">이동</div>
-                  <div>복사</div>
-                  <div onclick="nameChange()">이름 바꾸기</div>`;
+              let checkCnt = 0;
               if (array && array.length > 0) {
-                let checkCnt = 0;
                 for (let ii = 0; ii < array.length; ii++) {
-                  if(array.eq(ii).is(':checked')) {
+                  if (array.eq(ii).is(':checked')) {
                     checkCnt++;
                   }
                 }
-
-                if (checkCnt > 1) {
-                  str = `<div>편집</div>
-                  <div>탭으로 설정</div>
-                  <div onclick="download()">다운로드</div>
-                  <div onclick="deleteItem()">삭제</div>
-                  <div>이동</div>
-                  <div>복사</div>`;
-                }
+              }
+              
+              let str = `<div>편집</div>
+                <div>탭으로 설정</div>
+                <div onclick="download()">다운로드</div>
+                <div onclick="deleteItem()">삭제</div>
+                <div onclick="moveItem()">이동</div>
+                <div>복사</div>`;
+              console.log(checkCnt);
+              if (checkCnt === 1) {
+                str += `<div onclick="nameChange()">이름 바꾸기</div>`;
               }
               const toggleBox = $(`<div class="toggle-box" style="position:absolute; top:${clientY}; left: ${clientX}">
                   ${str}
@@ -414,7 +411,12 @@
     }
 
     function moveItem() {
+      
       const moveArr = $('.file-content div.on input[type="checkbox"]');
+      if (moveArr.length === 0) {
+        return alertMessage('파일 이동', '선택 된 파일 정보가 없습니다.');
+      }
+
       $.ajax({
           method: 'post',
           url : "/getGroupList",
@@ -441,11 +443,7 @@
                                           const jTeam = joinedTeams.teams;
                                           jTeam.forEach((obj, idx)=>{
                                             const share = obj.sharePoint;
-                                            let classNm = '';
-                                            if (idx === 0) {
-                                              classNm = 'on';
-                                            }
-                                            str += `<div id="move_${share.siteId}" class="${classNm}" onclick="setContent('${share.siteId}', event)">
+                                            str += `<div id="move_${share.siteId}" onclick="setContent('${share.siteId}', event)">
                                                       <div>
                                                         <img width="25" height="25" src="${share.siteUrl}${groupImageUrl}" alt="아이콘">
                                                         <div>${obj.displayName}</div>
@@ -484,13 +482,16 @@
                                   </div>
                                   <div class="button-box">
                                       <div id="move-btn" onclick="moveUpdate()">여기로 이동</div>
-                                      <div onclick="$('.modal').remove()">취소</div>
+                                      <div onclick="modalClose('move')">취소</div>
                                   </div>
                               </div>
                           </div>
                       </div>`;
             $('body').append($(str));
-            $('.access-box div.on').click();
+            if (res.joinedTeams && res.joinedTeams.teams.length > 0) {
+              const firstId = "move_" + res.joinedTeams.teams[0].sharePoint.siteId;
+              $('#'+firstId).click();
+            }
           },
           error: (error)=> {
             console.log(error);
@@ -500,53 +501,96 @@
 
     function moveUpdate() {
 
+      const selectedDrive = $('.modal-move-box .left-box div.on');
+      const siteId = selectedDrive.attr('id');
+      const pathArr = $('.modal-move-box .right-box .panel .panel-item');
+      
+      if (selectedDrive[0] && siteId) {
+        let path = getDrivePath(true);
+        const currentId = $('section .panel-item').eq(0).attr('id');
+        const selectId = siteId.replace('move_', '');
+
+        if (selectId === currentId && path === getDrivePath()) {
+          return alertMessage('파일 이동', '대상 경로는 원본 개체와 같을 수 없습니다.');
+        }
+        callApi('get', '/sites/'+ currentId + getDrivePath(), (itemData)=>{
+          if (itemData && itemData.id){
+            const itemId = itemData.id;
+            callApi('get', '/sites/'+ selectId + path, (jsonData)=>{
+              const $selectedItems = $('.file-content div.on');
+              const name = [];
+              for (let ii = 0; ii < $selectedItems.length; ii++) {
+                const selectCheck =  $selectedItems.eq(ii).find('input[type="checkbox"]');
+                const selectName = $selectedItems.eq(ii).find('.sp-name');
+                if ($selectedItems.eq(ii) && selectCheck.length && selectName.length) {
+                    name.push({
+                      id : selectCheck.val(),
+                      name : selectName.text(),
+                    });
+                }
+              }
+              if (jsonData && jsonData.id) {
+                $.ajax({
+                  method : 'post',
+                  url : '/api/move-item',
+                  data : {
+                    siteId : currentId,
+                    itemId : itemId,
+                    id : jsonData.id,
+                    name : JSON.stringify(name),
+                  },
+                  success : (res) => {
+                    // console.log(res);
+                    if (res){
+                      let message = res.message;
+                      if (res.failItems.length > 0) {
+                        message += '<br>이동 되지 않은 파일 : ';
+                        res.failItems.forEach((fail, idx)=>{
+                          message += fail;
+                          if (res.failItems.length - 1 !== idx) {
+                            message += ',';
+                          }
+                        })
+                      }
+                      alertMessage('파일 이동', message);
+                      drawMoveItems(selectId, getDrivePath(true));
+                      const selected = $('section .panel-item.on');
+                      selected.removeClass('on');
+                      selected.click();
+                    }
+                  },
+                  error : (error) => {
+                    console.log(error);
+                  }
+                })
+              }
+              else {
+                alertMessage('파일 이동', '선택된 그룹 정보를 찾을 수 없습니다.');
+              }
+            });
+          }
+          else {
+            alertMessage('파일 이동', '선택된 그룹 정보를 찾을 수 없습니다.');
+          }
+        });
+      }
+      else {
+        alertMessage('파일 이동', '선택된 그룹 정보를 찾을 수 없습니다.');
+      }
     }
 
+
     function setContent(siteId, event) {
-      const selectEl = $('#move_' + siteId);
-      if (selectEl === $('.access-box .on')) {
+      const $selectEl = $('#move_' + siteId);
+      const $selectedEl = $('.modal-move-box .left-box div.on');
+      const selectTitle = $('.modal-move-box .panel-item.on').text().trim();
+      if ($selectEl.text().trim() === selectTitle) {
         return;
       }
 
-      $('.access-box .on').removeClass('on');
-      selectEl.addClass('on');
-
-      callApi('get', '/sites/' + siteId +'/drive/root/children', (jsonData)=>{
-        const panel = $('.modal-move-box .right-box .panel');
-        const content = $('.modal-move .right-box .content');
-        const imgSrc = $('#move_' + siteId+ ' img').attr('src');
-        const text = $('#move_' + siteId).text().trim();
-        
-        let str = `<div class="panel-item on">`
-          if (text !== '내 파일') {
-            str +=`<img width="24" height="24" src="${imgSrc}" alt="아이콘">&nbsp;&nbsp;`
-          }
-            str +=`${text}</div>`;
-        const $list = $('.modal-move-box .right-box .content .list');
-        panel.html(str);
-        $list.empty();
-        //하위 파일들이 있는지 먼저 체크
-        if (jsonData && jsonData.value && jsonData.value.length > 0) {
-          const itemArray = jsonData.value;
-          if (itemArray.length > 0) {
-            let listStr = '';
-            itemArray.forEach((obj, idx)=>{
-              let path = '/drive/root';
-              if (obj.parentReference && obj.parentReference.path) {
-                path = obj.parentReference.path + '/' + obj.name;
-              }
-              listStr += getListStr(obj, idx, siteId, path);
-            })
-            $list.html(listStr);
-          }
-          else {
-            $list.html(getEmptyBox());
-          }
-        }
-        else {
-          $list.html(getEmptyBox());
-        }
-      });
+      $selectedEl.removeClass('on');
+      $selectEl.addClass('on');
+      drawMoveItems(siteId, '/drive/root');
     }
 
     function drawMoveItems(siteId, path) {
@@ -569,14 +613,18 @@
           let pathArr = itemPath.split('/');
           if (pathArr && pathArr.length > 0) {
             let directoryRoot = '';
+            let id = "";
             pathArr.forEach((directory, idx)=>{
               if (directory) {
                 onOff = '';
+                directoryRoot += `/${directory}`;
+                let method = `drawMoveItems('${siteId}', '/drive/root:${directoryRoot}')`;
                 if (idx === pathArr.length - 1) {
                   onOff = 'on'
+                  method = '';
                 }
-                directoryRoot += `/${directory}`;
-                str += `<div> > </div><div class="panel-item ${onOff}" onclick="drawMoveItems('${siteId}', '/drive/root:${directoryRoot}')">${directory}</div>`
+                
+                str += `<div> > </div><div class="panel-item ${onOff}" onclick="${method}">${directory}</div>`
               }
             })
           }
@@ -592,11 +640,10 @@
         $panel.html(str);
         const menuWidth =  $('.modal .modal-move-box .right-box').width() - 40;
         const menuArr = $panel.children();
-        console.log(menuArr);
+        
         let totalWidth = 0;
         for (let ii = 0; ii < menuArr.length; ii++) {
           const menu = menuArr.eq(ii);
-          console.log('width:', menu.width() + 10, ', text:', menu.text().trim());
           let gap = 10;
           if ( menuArr.length-1 === ii) {
             gap = 0;
@@ -604,7 +651,7 @@
           totalWidth += menu.width() + gap;
         }
         if (menuWidth < totalWidth) {
-          let div = '<div class="toggle-button" style="display:none; position:absolute; top:100px; padding:10px; border:1px solid #eeeeee; width:auto;">';
+          let div = '<div class="toggle-button">';
           for (let ii = 0; ii < menuArr.length; ii++) {
             const menu = menuArr.eq(ii);
             
@@ -615,9 +662,6 @@
             menu.css('display', 'none');
 
             if (menuWidth - 30 >= totalWidth && !menu.attr('class')) {
-              console.log(menu.attr('class') !== 'panel-item');
-              console.log('마지막 메뉴 :',menu.text());
-              console.log('마지막 class :',menu.attr('class'));
               div += '</div>';
               break;
             }
@@ -760,7 +804,7 @@
           confirmMessage('파일 삭제', '선택된 파일을 삭제하시겠습니까?', ()=>{
             $.ajax({
                 method:'post',
-                url : "/deleteItems",
+                url : "/api/delete",
                 data: {
                   siteId: siteId,
                   itemIds : JSON.stringify(checkedArr),
@@ -784,16 +828,19 @@
     }
 
 
-    //
-    function getDrivePath() {
+    //폴더 경로 가져오기
+    function getDrivePath(isMove) {
       let path = '/drive/root';
-      if ($('.panel-item').length > 1) {
+      let $pathArr = $('section .panel-item');
+      if (isMove) {
+        $pathArr = $('.modal-move-box .panel-item');
+      }
+      if ($pathArr.length > 1) {
         path += ':';
-        for (let ii = 1; ii < $('.panel-item').length; ii++) {
-            path += '/' + $('.panel-item').eq(ii).text();
+        for (let ii = 1; ii <  $pathArr.length; ii++) {
+            path += '/' + $pathArr.eq(ii).text();
         }
       }
-
       return path;
     }
 
@@ -894,12 +941,6 @@
       return panelStr;
     }
 
-    // function nameChange() {
-    //     if ($('.file-content > .on .file_name')[0]) {
-    //     }
-    // }
-
-    
     function dragAndDrop() {
       const $fileContent = $('.file-content');
       $fileContent.off('dragover');
@@ -962,7 +1003,7 @@
             processData : false,
             contentType : false,
             data : formData,
-            url : '/uploadItems',
+            url : '/api/upload',
             success: (res) => {
               let str = res.message;
               console.log(res.error);
@@ -984,19 +1025,19 @@
     }
 
     function alertMessage(title, message, color) {
-      $('body').append($(`<div class="modal" style="display:flex;">
+      $('body').append($(`<div class="modal alert" style="display:flex;">
           <div class="modal-box">
             <div class="header">
                   <div class="title">${title}</div>
                   <div class="x-button">
-                    <span><img src="/static/images/x-button.png" width="15" height="15" alt="닫기 버튼" onclick="modalClose()"></span>
+                    <span><img src="/static/images/x-button.png" width="15" height="15" alt="닫기 버튼" onclick="modalClose('alert')"></span>
                   </div>
                 </div>
                 <div class="modal-content">
                   ${message}
                 </div>
                 <div class="button-box">
-                    <div class="name-btn" onclick="modalClose()">확인</div>
+                    <div class="name-btn" onclick="modalClose('alert')">확인</div>
                 </div>
             </div>
           </div>
@@ -1004,12 +1045,12 @@
     }
 
     function confirmMessage(title, message, method) {
-      $('body').append($(`<div class="modal" style="display:flex;">
+      $('body').append($(`<div class="modal confirm" style="display:flex;">
           <div class="modal-box">
             <div class="header">
                   <div class="title">${title}</div>
                   <div class="x-button">
-                    <span><img src="/static/images/x-button.png" width="15" height="15" alt="닫기 버튼" onclick="modalClose()"></span>
+                    <span><img src="/static/images/x-button.png" width="15" height="15" alt="닫기 버튼" onclick="modalClose('confirm')"></span>
                   </div>
                 </div>
                 <div class="modal-content">
@@ -1017,7 +1058,7 @@
                 </div>
                 <div class="button-box">
                     <div class="success-button" >확인</div>
-                    <div class="name-btn" onclick="modalClose()">취소</div>
+                    <div class="name-btn" onclick="modalClose('confirm')">취소</div>
                 </div>
             </div>
           </div>
@@ -1128,7 +1169,7 @@
                             <div style="display:flex; border:1px solid red; flex-direction: column; padding:20px;justify-content:center;width:400px;height:120px; background-color:white;">
                                 <div style='width:100%;margin-bottom:10px; height:40px;display:flex;justify-content:space-between; align-items:center; font-weight: bold; font-size: 18px;'>
                                   <div style="">파일 형식 오류</div>
-                                  <div onclick="modalClose()" style="cursor:pointer; user-select:none;">x</div>
+                                  <div onclick="modalClose('error')" style="cursor:pointer; user-select:none;">x</div>
                                 </div>
                                 <div>
                                   암호화 할수 없는 형식의 파일입니다.<br>
@@ -1143,11 +1184,6 @@
       }
     }
 
-    function modalClose() {
-      if ($('.modal.error')[0]){
-        $('.modal.error').remove();
-      }
-    }
 
 
     function callApi(type, uri, callBackMethod, args, params) {
@@ -1445,12 +1481,12 @@
   //새폴더 생성
   function mkdir() {
     const modalContainer = $(
-      `<div class="modal" style="display: flex;">
+      `<div class="modal folder" style="display: flex;">
           <div class="modal-box">
               <div class="header">
                 <div class="title">폴더 생성</div>
                 <div class="x-button">
-                  <span><img src="/static/images/x-button.png" width="15" height="15" alt="닫기 버튼" onclick="modalClose()"></span>
+                  <span><img src="/static/images/x-button.png" width="15" height="15" alt="닫기 버튼" onclick="modalClose('folder')"></span>
                 </div>
               </div>
               <div class="modal-content">
@@ -1459,7 +1495,7 @@
               </div>
               <div class="button-box">
                   <div class="name-btn" onclick="makeFolder()">만들기</div>
-                  <div class="name-btn" onclick="modalClose()">취소</div>
+                  <div class="name-btn" onclick="modalClose('folder')">취소</div>
               </div>
           </div>
       </div>`);
@@ -1467,8 +1503,8 @@
     
   }
 
-  function modalClose(){
-      $('.modal').remove();
+  function modalClose(className){
+      $('.modal.' + className).remove();
   }
 
   function getSitesId() {