Bladeren bron

分享功能结构调整

zhongzewei 7 jaren geleden
bovenliggende
commit
73172b3d97

+ 4 - 1
config/gulpConfig.js

@@ -35,6 +35,7 @@ module.exports = {
         'lib/jquery-contextmenu/jquery.contextMenu.css'
     ],
     pm_jspaths:[
+        'public/web/uuid.js',
         'public/web/date_util.js',
         'public/web/id_tree.js',
         'public/web/tree_sheet/tree_sheet_helper.js',
@@ -215,7 +216,9 @@ module.exports = {
         'web/building_saas/complementary_ration_lib/js/ration_glj.js',
         'web/building_saas/complementary_ration_lib/js/ration_coe.js',
         'web/building_saas/complementary_ration_lib/js/ration_assist.js',
-        'web/building_saas/complementary_ration_lib/js/ration_installation.js.js'
+        'web/building_saas/complementary_ration_lib/js/ration_installation.js.js',
+        'public/web/slideResize.js',
+        'web/building_saas/complementary_ration_lib/js/coe.js'
     ],
     compleRation_glj_css: [
     ],

+ 5 - 11
modules/pm/controllers/pm_controller.js

@@ -47,21 +47,15 @@ module.exports = {
         }
     },
     checkProjectRight: function (userId, projectId, callback) {
-        ProjectsData.getProject(projectId).then(function (result) {
+        ProjectsData.getProject(projectId).then(async function (result) {
             /**
              * result._doc.userID(Number): MongoDB
              * userId(String): Session.userID
              */
-            //result._doc.userID == userId &&
             let isShare = false;
+            //判断是否是打开分享的项目
             if(userId !== result.userID){
-                //判断是否是打开分享的项目
-                for(let shareData of result.shareInfo){
-                    if(shareData.userID === userId){
-                        isShare = true;
-                        break;
-                    }
-                }
+                isShare = await pm_facade.isShare(userId, result);
             }
             if ((userId === result.userID || isShare) && result._doc.projType === projType.tender) {
                 callback(true);
@@ -521,8 +515,8 @@ module.exports = {
         try{
             let data = JSON.parse(req.body.data);
             //添加分享
-            let shareData = {userID: data.userID, allowCopy: data.allowCopy, shareDate: moment(Date.now()).format('YYYY-MM-DD HH:mm:ss')};
             if(data.type === 'create'){
+                let shareData = {userID: data.userID, allowCopy: data.allowCopy, shareDate: moment(Date.now()).format('YYYY-MM-DD HH:mm:ss')};
                 //覆盖
                 await projectModel.update({ID: data.projectID, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]}, {$pull: {shareInfo: {userID: data.userID}}});
                 //新增
@@ -544,7 +538,7 @@ module.exports = {
             let rst = {grouped: [], ungrouped: []}
             let userID = req.session.sessionUser.id;
             let receiveProjects = await projectModel.find({
-                $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], compilation: req.session.sessionCompilation._id, 'shareInfo.userID': userID});
+                $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], compilation: req.session.sessionCompilation._id, 'shareInfo.userID': userID}, '-_id -property');
             //设置原项目用户信息
             if(receiveProjects.length > 0){
                 let orgUserIDs = [];

+ 15 - 0
modules/pm/facade/pm_facade.js

@@ -48,6 +48,7 @@ module.exports={
     getProjectFeature:getProjectFeature,
     projectType: projectType,
     getPosterityProjects: getPosterityProjects,
+    isShare: isShare,
 };
 
 async function copyProject(userID, compilationID,data) {
@@ -741,4 +742,18 @@ async function getPosterityProjects(projectIDs) {
     }
     await getProjects(projectIDs);
     return rst;
+}
+
+//打开的单位工程是否是被分享的
+async function isShare(userId, project){
+    //判断是否是打开分享的项目,属于分享文件的子项也算
+    while (project) {
+        for(let shareData of project.shareInfo){
+            if(shareData.userID === userId){
+                return true;
+            }
+        }
+        project = await projectModel.findOne({ID: project.ParentID}, '-_id shareInfo ID ParentID');
+    }
+    return false;
 }

+ 1 - 1
web/building_saas/complementary_ration_lib/html/dinge.html

@@ -75,7 +75,7 @@
     <div class="content" style="margin-left: 0px">
         <div class="container-fluid">
             <div class="row" id="dataRow">
-                <div class="main-side p-0" style="width: 25%; height: 100%; overflow: hidden" id="leftContent">
+                <div class="main-side p-0" style="width: 25%; height: 100%; overflow: hidden" id="leftContentg">
                     <div class="tab-bar">
                         <a href="javascript:void(0);" id="tree_Insert" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="插入"><i class="fa fa-plus" aria-hidden="true"></i></a>
                         <a href="javascript:void(0);" id="tree_remove" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>

+ 19 - 0
web/building_saas/pm/html/project-management-share.html

@@ -105,3 +105,22 @@
         </div>
     </div>
 </div>
+<!--取消分享-->
+<div class="modal fade" id="cancelShare" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">清除分享 </h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+            </div>
+            <div class="modal-footer">
+                <a href="javascript:void(0);" class="btn btn-primary" data-dismiss="modal" id="cancelShareConfirm">确定</a>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 1 - 0
web/building_saas/pm/html/project-management.html

@@ -676,6 +676,7 @@
 <script>GC.Spread.Sheets.LicenseKey = '<%- LicenseKey %>';</script>
 <!-- inject:js -->
 <script src="/web/building_saas/js/global.js"></script>
+<script src="/public/web/uuid.js"></script>
 <script src="/public/web/PerfectLoad.js"></script>
 <script src="/public/web/date_util.js"></script>
 <script src="/web/building_saas/pm/js/pm_tree.js"></script>

+ 5 - 3
web/building_saas/pm/js/pm_newMain.js

@@ -301,15 +301,17 @@ const projTreeObj = {
                     icon: 'fa-share',
                     disabled: function () {
                         let selectedItem = projTreeObj.tree.selected;
-                        return !(selectedItem && selectedItem.data.projType === projectType.tender);
+                        return !selectedItem;
+                        //return !(selectedItem && selectedItem.data.projType === projectType.tender);
                     },
                     callback: function (key, opt) {
                         $('#sharePhone').val('');
                         $('#share-info').hide();
                         $('#share').find('.card').hide();
                         $('#share').modal('show');
-                        $('#allowCopy').prop('checked', false);
-                        $('#allowCopyHint').hide();
+                        //默认允许拷贝
+                        $('#allowCopy').prop('checked', true);
+                        $('#allowCopyHint').show();
                         setTimeout(function () {
                             $('#sharePhone').focus();
                         }, 200);

+ 163 - 64
web/building_saas/pm/js/pm_share.js

@@ -13,6 +13,8 @@ const pmShare = (function () {
     let spreadObj = {workBook: null, sheet: null};
     //项目分享类型,由别人分享给自己的,和自己分享给别人的
     const shareType = {receive: 'receive', shareTo: 'shareTo'};
+    //操作类型
+    const oprType = {copy: 'copy', cancel: 'cancel'};
     let tree = null;
     const treeSetting = {
         tree: {
@@ -27,7 +29,8 @@ const pmShare = (function () {
         {name: '工程列表', dataCode: 'name', width: 0.55, rateWidth: 0.55, vAlign: 'center', hAlign: 'left'},
         {name: '由...分享', dataCode: 'from', width: 0.15, rateWidth: 0.15, vAlign: 'center', hAlign: 'left'},
         {name: '分享给...', dataCode: 'to', width: 0.15, rateWidth: 0.15, vAlign: 'center', hAlign: 'left'},
-        {name: '操作', dataCode: 'operation', width: 0.15, rateWidth: 0.15, vAlign: 'center', hAlign: 'left'},
+        {name: '拷贝工程', dataCode: 'copy', width: 0.075, rateWidth: 0.075, vAlign: 'center', hAlign: 'left'},
+        {name: '清除', dataCode: 'cancel', width: 0.075, rateWidth: 0.075, vAlign: 'center', hAlign: 'left'},
     ];
     const spreadOpts = {
         workBook: {
@@ -106,11 +109,20 @@ const pmShare = (function () {
             sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
             let spreadWidth = getWorkBookWidth();
             for(let i = 0, len = headers.length; i < len; i++){
-                sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
                 sheet.setColumnWidth(i, spreadWidth * headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
                 if(headers[i].formatter){
                     sheet.setFormatter(-1, i, headers[i].formatter);
                 }
+                if(headers[i].dataCode === oprType.copy){
+                    //合并列
+                    sheet.addSpan(0, i, 1, 2, GC.Spread.Sheets.SheetArea.colHeader);
+                    sheet.setValue(0, i, '操作', GC.Spread.Sheets.SheetArea.colHeader);
+                    continue;
+                }
+                if(headers[i].dataCode === '' || headers[i].dataCode === 'feeRateFile_delete'){
+                    continue;
+                }
+                sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
                 sheet.getRange(-1, i, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[i]['hAlign']]);
                 sheet.getRange(-1, i, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[i]['vAlign']]);
             }
@@ -315,8 +327,9 @@ const pmShare = (function () {
             //点击单位工程
             if(node.data.projType === projectType.tender && withingClickArea()){
                 let newTab = window.open('about:blank');
-                BeforeOpenProject(node.data.ID, {'fullFolder': GetFullFolder(node.parent)}, function () {
-                    let mainUrl = `/main?project=${node.data.ID}`;
+                //打开项目的实际ID
+                BeforeOpenProject(node.data.actualTreeInfo.ID, {'fullFolder': GetFullFolder(node.parent)}, function () {
+                    let mainUrl = `/main?project=${node.data.actualTreeInfo.ID}`;
                     CommonAjax.get(mainUrl, [], function () {
                         newTab.location.href = mainUrl;
                     });
@@ -374,8 +387,7 @@ const pmShare = (function () {
         }
         return new TreeNodeCellType();
     }
-    //
-    //
+    //互动单元格
     function getInteractionCell() {
         let InteractionCell = function () {
         };
@@ -421,8 +433,8 @@ const pmShare = (function () {
                     }
                 }
                 //操作
-                else if(dataCode === 'operation'){
-                    if(node.data.operation === '添加分享'){
+                else if(dataCode === oprType.copy){
+                   /* if(node.data.copy === '添加分享'){
                         $('#sharePhone').val('');
                         $('#share-info').hide();
                         $('#share').find('.card').hide();
@@ -430,32 +442,18 @@ const pmShare = (function () {
                         $('#allowCopy').prop('checked', false);
                         $('#allowCopyHint').hide();
                     }
-                    else if(node.data.operation === '拷贝工程'){
+                    else*/
+                    if(node.data.copy === '拷贝工程'){
                         $('#copyShare').modal('show');
                     }
-                    else {
-                        return;
-                    }
-                }
-                //清除
-                else if(dataCode === 'delete'){
-                    gcTreeObj.oprProj('#delPoj', node)
-                }
-                //恢复单价文件
-                else if(dataCode === 'unitPriceFile'){
-                    gcTreeObj.recoveryUnitPrc(node);
-                }
-                //清除单价文件
-                else if(dataCode === 'unitPriceFile_delete'){
-                    gcTreeObj.deleteUnitPrc(node);
-                }
-                //恢复费率文件
-                else if(dataCode === 'feeRateFile'){
-                    gcTreeObj.recoveryFeeRate(node);
                 }
-                //清除费率文件
-                else if(dataCode === 'feeRateFile_delete'){
-                    gcTreeObj.deleteFeeRate(node);
+                else if (dataCode === oprType.cancel) {
+                    if (node.data.cancel === '清除') {
+                        let $p = $('<p>').text(`点“确定”按钮,确认清除分享文件 “${node.data.name}”。`);
+                        $('#cancelShare').find('.modal-body').empty();
+                        $('#cancelShare').find('.modal-body').append($p);
+                        $('#cancelShare').modal('show');
+                    }
                 }
             }
         };
@@ -552,6 +550,7 @@ const pmShare = (function () {
         });
     }
     const foreColor = '#007bff';
+    const cancelForeColor = 'red';
     //显示树结构数据
     //@param {Array}nodes {Array}headers @return {void}
     function showTreeData(nodes, headers){
@@ -565,12 +564,18 @@ const pmShare = (function () {
                     sheet.getRange(-1, j, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[j]['hAlign']]);
                     sheet.getRange(-1, j, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[j]['vAlign']]);
                     let dataCode = headers[j].dataCode;
-                    if(dataCode === 'operation'){
+                    if(dataCode === oprType.copy){
                         let style = new GC.Spread.Sheets.Style();
                         style.foreColor = foreColor;
                         sheet.setStyle(i, j, style);
                         sheet.getCell(i, j).cellType(getInteractionCell());
                     }
+                    else if (dataCode === oprType.cancel) {
+                        let style = new GC.Spread.Sheets.Style();
+                        style.foreColor = cancelForeColor;
+                        sheet.setStyle(i, j, style);
+                        sheet.getCell(i, j).cellType(getInteractionCell());
+                    }
                     else if(dataCode === 'from'){
                         if(nodes[i].data.shareType && nodes[i].data.shareType === shareType.receive){
                             let style = new GC.Spread.Sheets.Style();
@@ -587,51 +592,122 @@ const pmShare = (function () {
                             sheet.getCell(i, j).cellType(getInteractionCell());
                         }
                     }
-                   /* else if(dataCode === 'delete' || dataCode === 'unitPriceFile_delete' || dataCode === 'feeRateFile_delete'){
-                        let style = new GC.Spread.Sheets.Style();
-                        style.foreColor = me.setting.style.delForeColor;
-                        sheet.setStyle(-1, j, style);
-                    }*/
                     sheet.setValue(i, j, nodes[i].data[dataCode] ? nodes[i].data[dataCode] : '');
-                    //me.setCellValue({row: i, col: j}, nodes[i]);
                 }
             }
         };
         renderSheetFunc(sheet, fuc);
     }
-    //将数据转换为可成树的数据,因为获取的数据不来自同一棵树
+    //同一棵树,可能存在相同数据显示多条的问题(传入的datas中不存在相同数据),将真实树结构数据存在actualTreeInfo中,外部树结构数据用uuid重置。
     //@param {Array}datas
-    function buildTreeDatas(datas){
-        let IDMap = {};
-        for(let i = 0; i < datas.length; i++){
-            let data = datas[i];
-            let nextData = datas[i + 1];
+    function setTreeInfo(datas) {
+        let IDMapping = {};
+        for (let data of datas) {
+            IDMapping[data.ID] = uuid.v1();
+        }
+        for (let data of datas) {
+            data.actualTreeInfo = {ID: data.ID, ParentID: data.ParentID, NextSiblingID: data.NextSiblingID};
+            data.ID = IDMapping[data.ID];
+            data.NextSiblingID = IDMapping[data.NextSiblingID] ? IDMapping[data.NextSiblingID] : -1;
+            data.ParentID = IDMapping[data.ParentID] ? IDMapping[data.ParentID] : -1;
+        }
+    }
+    //整理同层数据的NextSiblingID,ParentID
+    //@param {Array}datas {Number || String}pid @return {void}
+    function sortSameDepthData(datas, pid) {
+        for (let i = 0; i < datas.length; i++) {
+            let data = datas[i],
+                nextData = datas[i + 1];
             data.NextSiblingID = nextData ? nextData.ID : -1;
-            data.ParentID = -1;
-            IDMap[data.ID] = data;
-            if(data.shareType === shareType.receive){
-                if(data.userInfo){
-                    data.from = `由 ${data.userInfo.name} 分享`;
-                    data.to = '分享给 我';
-                    data.operation = isAllowCopy(userID, data) ? '拷贝工程' : '';
+            data.ParentID = pid;
+        }
+    }
+    //给项目设置分享信息:由xx分享、分享给我、可进行的操作,含有userInfo信息的文件为他人直接分享的文件,他人分享父级文件,子文件不含有userInfo信息
+    //@param {Array}datas @return {void}
+    function setShareInfo(datas) {
+        for (let data of datas) {
+            if (data.userInfo) {
+                data.from = `由 ${data.userInfo.name} 分享`;
+                data.to = '分享给 我';
+                data.cancel = '清除'
+
+                //拷贝操作只允许到单位工程级
+                let tendersCanCopy = isAllowCopy(userID, data);
+                let tenders = data.projType === projectType.tender ? [data] : _.filter(data.children, {projType: projectType.tender});
+                for (let tender of tenders) {
+                    tender.copy = tendersCanCopy ? '拷贝工程' : '';
                 }
             }
-            else {
-                data.from = '由 我 分享';
-                data.to = '分享给...';
-                data.operation = '添加分享';
+        }
+    }
+    //获取可成树的数据
+    //@param {Array}datas @return {Array}
+    function getTreeDatas(groupedDatas, ungroupedDatas){
+        //设置新的树结构数据
+        for (let data of groupedDatas) {
+            setTreeInfo([data].concat(data.children));
+        }
+        let engs = _.filter(ungroupedDatas, {projType: projectType.engineering}),
+            tenders = _.filter(ungroupedDatas, {projType: projectType.tender});
+        for (let data of engs) {
+            setTreeInfo([data].concat(data.children));
+        }
+        setTreeInfo(tenders);
+        let rst = [];
+        //整理树结构
+        sortSameDepthData(groupedDatas, -1);
+        //新建未分类建设项目及单项工程
+        let ungroupedProj = {ID: uuid.v1(), ParentID: -1, NextSiblingID: -1, name: '未分类建设项目', projType: projectType.project};
+        let ungroupedEng = {ID: uuid.v1(), ParentID: ungroupedProj.ID, NextSiblingID: -1, name: '未分类单项工程', projType: projectType.engineering};
+        if (groupedDatas.length > 0) {
+            groupedDatas[groupedDatas.length - 1].NextSiblingID = ungroupedProj.ID;
+        }
+        //将未分类的数据归类
+        sortSameDepthData(engs, ungroupedProj.ID);
+        sortSameDepthData(tenders, ungroupedEng.ID);
+        //未分类单项工程处于同层第一个节点
+        ungroupedEng.NextSiblingID = engs[0] ? engs[0].ID : ungroupedEng.NextSiblingID;
+        let allDatas = groupedDatas.concat(ungroupedDatas);
+        //设置分享信息及操作信息
+        setShareInfo(allDatas);
+        for (let data of allDatas) {
+            rst.push(data);
+            if (data.children) {
+                rst = rst.concat(data.children);
             }
         }
+        rst.push(ungroupedProj);
+        rst.push(ungroupedEng);
+        return rst;
+    }
+    //按照时间排序
+    //@param {Array}datas @return {void}
+    function sortByDate(datas){
+        datas.sort(function (a, b) {
+            let shareInfoA = _.find(a.shareInfo, {userID}),
+                shareInfoB = _.find(b.shareInfo, {userID});
+            let aV = shareInfoA ? Date.parse(shareInfoA.shareDate) : 0,
+                bV = shareInfoB ? Date.parse(shareInfoB.shareDate) : 0;
+            //时间越晚越靠前
+            if (aV > bV) {
+                return -1;
+            } else if (aV < bV) {
+                return 1;
+            }
+            return 0;
+        });
     }
     //建立树
     //@return void
     function initShareTree(){
         $.bootstrapLoading.start();
         //获取分享数据
-        CommonAjax.post('/pm/api/receiveProjects', {user_id: userID}, function (projDatas) {
-            return;
-            buildTreeDatas(projDatas);
-            tree = pmTree.createNew(treeSetting, projDatas);
+        CommonAjax.post('/pm/api/receiveProjects', {user_id: userID}, function (rstData) {
+            // 排序 --分享的文件按照时间先后顺序排序,分享文件下的子文件,按照原本树结构显示,不需要排序
+            sortByDate(rstData.grouped);
+            sortByDate(rstData.ungrouped);
+            let treeDatas = getTreeDatas(rstData.grouped, rstData.ungrouped);
+            tree = pmTree.createNew(treeSetting, treeDatas);
             console.log(tree);
             tree.selected = tree.items[0];
             showTreeData(tree.items, headers);
@@ -718,7 +794,7 @@ const pmShare = (function () {
             return;
         }
         let copyMap = {copy: null, update: null};
-        let newName = `${selected.data.name} (${selected.data.userInfo.name}分享拷贝)`;
+        let newName = getCopyName(selected);
         //获取单项工程的单位工程
         let tenderQuery = {$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], userID: userID, ParentID: engID};
         CommonAjax.post('/pm/api/getProjectsByQuery', {user_id: userID, query: tenderQuery, options: '-_id -property'}, function (rstData) {
@@ -740,7 +816,7 @@ const pmShare = (function () {
             //拷贝
             let copyData = {
                 userID: userID,
-                ID: selected.data.ID,
+                ID: selected.data.actualTreeInfo.ID,
                 NextSiblingID: -1,
                 ParentID: engID,
                 name: newName,
@@ -765,6 +841,18 @@ const pmShare = (function () {
         });
 
     }
+    //获取拷贝后的名称
+    //@param {Object}node @return {String}
+    function getCopyName(node) {
+        //当前单位工程可能没有分享的用户信息,可能他人分享的是父级文件,userInfo在父级文件中
+        let orgName = node.data.name,
+            userInfo = node.data.userInfo;
+        while (node && !userInfo) {
+            node = node.parent;
+            userInfo = node.data.userInfo;
+        }
+        return `${orgName} (${userInfo.name}分享拷贝)`;
+    }
     //事件监听器
     //@return void
     function eventListener(){
@@ -794,14 +882,14 @@ const pmShare = (function () {
         $('#copyShare').on('shown.bs.modal', function () {
             setCopyModal();
             //更改显示名称
-            let newName = `${shareSeleted.data.name} (${shareSeleted.data.userInfo.name}分享拷贝)`;
+            let newName = getCopyName(shareSeleted);
             $('#copyShare_name').html(`拷贝后,工程将重命名为 "<b>${newName}</b>"`);
             $('#copyShare_name').removeClass('text-danger');
         });
         //拷贝工程改变选择建设项目
         $('#copyShare_selectProj').change(function () {
             //更改显示名称
-            let newName = `${shareSeleted.data.name} (${shareSeleted.data.userInfo.name}分享拷贝)`;
+            let newName = getCopyName(shareSeleted);
             $('#copyShare_name').html(`拷贝后,工程将重命名为 "<b>${newName}</b>"`);
             $('#copyShare_name').removeClass('text-danger');
             $('#copyShareProj-info').hide();
@@ -812,7 +900,7 @@ const pmShare = (function () {
         //拷贝工程改变选择单项工程
         $('#copyShare_selectEng').change(function () {
             //更改显示名称
-            let newName = `${shareSeleted.data.name} (${shareSeleted.data.userInfo.name}分享拷贝)`;
+            let newName = getCopyName(shareSeleted);
             $('#copyShare_name').html(`拷贝后,工程将重命名为 "<b>${newName}</b>"`);
             $('#copyShare_name').removeClass('text-danger');
         });
@@ -834,6 +922,17 @@ const pmShare = (function () {
         $('#shareToConfirm').click(function () {
             updateShareInfo(tree.selected);
         });
+        //清除分享
+        $('#cancelShareConfirm').click(function () {
+            $.bootstrapLoading.start();
+            CommonAjax.post('/pm/api/share', {user_id: userID, type: oprType.cancel,  projectID: tree.selected.data.actualTreeInfo.ID, userID: userID}, function (rstData) {
+                $.bootstrapLoading.end();
+                tree.removeNode(tree.selected);
+                showTreeData(tree.items, headers);
+            }, function () {
+                $.bootstrapLoading.end();
+            });
+        });
     }
 
     return {spreadObj, headers, initView, eventListener}