Commit 0341cfd6 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

UI: added methods for copying nodes and handles copy/move of multiple nodes at the same time

parent 2b1dfb56
Loading
Loading
Loading
Loading
+5 −4
Original line number Original line Diff line number Diff line
@@ -199,8 +199,9 @@ export default {
      data
      data
    }, true, true);
    }, true, true);
  },
  },
  getNodesForMove(data) {
  getNodesForMoveOrCopy(data) {
    let url = BASE_API_URL + 'nodesForMove?path=' + escapePath(data.path) + '&nodeToMove=' + data.nodeToMove;
    let url = BASE_API_URL + 'nodesForMoveOrCopy?path=' + escapePath(data.path) +
      '&' + data.targets.map(t => 'target=' + escapePath(t)).join('&');
    return apiRequest({
    return apiRequest({
      method: 'GET',
      method: 'GET',
      url: url,
      url: url,
@@ -210,8 +211,8 @@ export default {
      }
      }
    }, true, true);
    }, true, true);
  },
  },
  moveNode(data) {
  moveOrCopyNodes(data) {
    let url = BASE_API_URL + 'move';
    let url = BASE_API_URL + 'moveOrCopy';
    return apiRequest({
    return apiRequest({
      method: 'POST',
      method: 'POST',
      url: url,
      url: url,
+47 −3
Original line number Original line Diff line number Diff line
@@ -12,6 +12,8 @@
    <b-dropdown variant="primary" text="Actions" v-if="actionsEnabled">
    <b-dropdown variant="primary" text="Actions" v-if="actionsEnabled">
      <b-dropdown-item :disabled="!asyncButtonEnabled" @click="startAsyncRecallJob">Async recall</b-dropdown-item>
      <b-dropdown-item :disabled="!asyncButtonEnabled" @click="startAsyncRecallJob">Async recall</b-dropdown-item>
      <b-dropdown-item :disabled="!deleteButtonEnabled" @click="deleteNodes">Delete</b-dropdown-item>
      <b-dropdown-item :disabled="!deleteButtonEnabled" @click="deleteNodes">Delete</b-dropdown-item>
      <b-dropdown-item :disabled="!moveButtonEnabled" @click="moveNodes">Move</b-dropdown-item>
      <b-dropdown-item :disabled="!copyButtonEnabled" @click="copyNodes">Copy</b-dropdown-item>
      <b-dropdown-item :disabled="!archiveButtonEnabled" @click="createArchive('zip')">Create zip archive</b-dropdown-item>
      <b-dropdown-item :disabled="!archiveButtonEnabled" @click="createArchive('zip')">Create zip archive</b-dropdown-item>
      <b-dropdown-item :disabled="!archiveButtonEnabled" @click="createArchive('tar')">Create tar archive</b-dropdown-item>
      <b-dropdown-item :disabled="!archiveButtonEnabled" @click="createArchive('tar')">Create tar archive</b-dropdown-item>
    </b-dropdown>
    </b-dropdown>
@@ -44,7 +46,7 @@
  <ConfirmDeleteModal />
  <ConfirmDeleteModal />
  <ShareModal />
  <ShareModal />
  <RenameModal />
  <RenameModal />
  <MoveModal />
  <MoveOrCopyModal />
  <ConfirmArchiveModal />
  <ConfirmArchiveModal />
</div>
</div>
</template>
</template>
@@ -56,7 +58,7 @@ import UploadFilesModal from './modal/UploadFilesModal.vue'
import ConfirmDeleteModal from './modal/ConfirmDeleteModal.vue'
import ConfirmDeleteModal from './modal/ConfirmDeleteModal.vue'
import ShareModal from './modal/ShareModal.vue'
import ShareModal from './modal/ShareModal.vue'
import RenameModal from './modal/RenameModal.vue'
import RenameModal from './modal/RenameModal.vue'
import MoveModal from './modal/MoveModal.vue'
import MoveOrCopyModal from './modal/MoveOrCopyModal.vue'
import ConfirmArchiveModal from './modal/ConfirmArchiveModal.vue'
import ConfirmArchiveModal from './modal/ConfirmArchiveModal.vue'


export default {
export default {
@@ -68,7 +70,7 @@ export default {
    ConfirmDeleteModal,
    ConfirmDeleteModal,
    ShareModal,
    ShareModal,
    RenameModal,
    RenameModal,
    MoveModal,
    MoveOrCopyModal,
    ConfirmArchiveModal
    ConfirmArchiveModal
  },
  },
  computed: {
  computed: {
@@ -98,9 +100,15 @@ export default {
    deleteButtonEnabled() {
    deleteButtonEnabled() {
      return this.$store.state.deleteButtonEnabled;
      return this.$store.state.deleteButtonEnabled;
    },
    },
    moveButtonEnabled() {
      return this.$store.state.moveButtonEnabled;
    },
    archiveButtonEnabled() {
    archiveButtonEnabled() {
      return this.$store.state.archiveButtonEnabled;
      return this.$store.state.archiveButtonEnabled;
    },
    },
    copyButtonEnabled() {
      return this.$store.state.copyButtonEnabled;
    },
    writable() {
    writable() {
      return this.$store.state.writable;
      return this.$store.state.writable;
    }
    }
@@ -147,6 +155,42 @@ export default {
      this.$store.commit('setSelectedUndeletableNodes', unDeletablePaths);
      this.$store.commit('setSelectedUndeletableNodes', unDeletablePaths);
      this.$bvModal.show('confirm-delete-modal');
      this.$bvModal.show('confirm-delete-modal');
    },
    },
    moveNodes() {
      let selectedNodesCheckboxes = document.querySelectorAll('#nodes input:checked');
      let paths = [];
      let unDeletablePaths = [];
      for (let i = 0; i < selectedNodesCheckboxes.length; i++) {
        let checkbox = selectedNodesCheckboxes[i];
        let dataNode = checkbox.getAttribute('data-node');
        if (checkbox.classList.contains('deletable')) {
          paths.push(dataNode);
        } else {
          unDeletablePaths.push(dataNode);
        }
      }
      this.$store.commit('setNodesToMoveOrCopy', paths);
      this.$store.commit('setMoveOrCopy', 'move');
      this.$store.commit('setSelectedNotMovableNodes', unDeletablePaths);
      this.$bvModal.show('move-or-copy-modal');
    },
    copyNodes() {
      let selectedNodesCheckboxes = document.querySelectorAll('#nodes input:checked');
      let paths = [];
      let unCopiablePaths = [];
      for (let i = 0; i < selectedNodesCheckboxes.length; i++) {
        let checkbox = selectedNodesCheckboxes[i];
        let dataNode = checkbox.getAttribute('data-node');
        if (checkbox.classList.contains('async')) {
          unCopiablePaths.push(dataNode);
        } else {
          paths.push(dataNode);
        }
      }
      this.$store.commit('setNodesToMoveOrCopy', paths);
      this.$store.commit('setMoveOrCopy', 'copy');
      this.$store.commit('setSelectedNotCopiableNodes', unCopiablePaths);
      this.$bvModal.show('move-or-copy-modal');
    },
    createArchive(type) {
    createArchive(type) {
      let selectedNodesCheckboxes = document.querySelectorAll('#nodes input:checked');
      let selectedNodesCheckboxes = document.querySelectorAll('#nodes input:checked');
      let nodesToArchive = [];
      let nodesToArchive = [];
+111 −0
Original line number Original line Diff line number Diff line
@@ -4,26 +4,56 @@
  SPDX-License-Identifier: GPL-3.0-or-later
  SPDX-License-Identifier: GPL-3.0-or-later
-->
-->
<template>
<template>
<b-modal id="move-modal" :title="'Move ' + nodeToMove + ' to ' + destinationPath" okTitle="Move node" @show="afterShow" @ok.prevent="moveNode" :ok-disabled="!writable" size="lg">
<b-modal id="move-or-copy-modal" :title="title" :okTitle="okTitle" @show="afterShow" @ok.prevent="moveOrCopyNodes" :ok-disabled="!writable" size="lg">
  <ol class="breadcrumb">
  <ol class="breadcrumb">
    <li class="breadcrumb-item" v-for="(item, i) in breadcrumbs" :key="i" :class="{ 'active' : item.active }">
    <li class="breadcrumb-item" v-for="(item, i) in breadcrumbs" :key="i" :class="{ 'active' : item.active }">
      <a href="#" @click.stop.prevent="breadcrumbClick(i)" v-if="!item.active">{{item.text}}</a>
      <a href="#" @click.stop.prevent="breadcrumbClick(i)" v-if="!item.active">{{item.text}}</a>
      <span v-if="item.active">{{item.text}}</span>
      <span v-if="item.active">{{item.text}}</span>
    </li>
    </li>
  </ol>
  </ol>
  <div id="move-nodes-wrapper">
  <div id="move-or-copy-nodes-wrapper">
    <div id="move-nodes"></div>
    <div id="move-or-copy-nodes"></div>
  </div>
  <div v-if="selectedNotCopiableNodes.length > 0" class="mt-3">
    <p><strong>Warning</strong>: following selected nodes can't be copied and will be ignored:</p>
    <p>
    <ul>
      <li v-for="node in selectedNotCopiableNodes" :key="node">{{node}}</li>
    </ul>
    </p>
  </div>
  <div v-if="selectedNotMovableNodes.length > 0" class="mt-3">
    <p><strong>Warning</strong>: following selected nodes can't be moved and will be ignored:</p>
    <p>
    <ul>
      <li v-for="node in selectedNotMovableNodes" :key="node">{{node}}</li>
    </ul>
    </p>
  </div>
  </div>
</b-modal>
</b-modal>
</template>
</template>


<script>
<script>
export default {
export default {
  name: 'MoveModal',
  name: 'MoveOrCopyModal',
  computed: {
  computed: {
    nodeToMove() { return this.$store.state.nodeToMove },
    nodesToMoveOrCopy() { return this.$store.state.nodesToMoveOrCopy },
    destinationPath() { return this.$store.state.nodeToMoveDestination },
    destinationPath() { return this.$store.state.moveOrCopyDestination },
    writable() { return this.$store.state.nodeToMoveDestinationWritable },
    writable() { return this.$store.state.moveOrCopyDestinationWritable },
    moveOrCopy() { return this.$store.state.moveOrCopy },
    selectedNotMovableNodes() { return this.$store.state.selectedNotMovableNodes },
    selectedNotCopiableNodes() { return this.$store.state.selectedNotCopiableNodes },
    title() {
      let text = this.moveOrCopy === 'move' ? 'Move ' : 'Copy ';
      if (this.nodesToMoveOrCopy.length === 1) {
        text += this.nodesToMoveOrCopy[0];
      } else {
        text += this.nodesToMoveOrCopy.length + ' nodes';
      }
      text += ' to ' + this.destinationPath;
      return text;
    },
    okTitle() { return (this.moveOrCopy === 'move' ? 'Move nodes' : 'Copy nodes') },
    breadcrumbs() {
    breadcrumbs() {
      let items = [];
      let items = [];
      if (this.destinationPath !== null) {
      if (this.destinationPath !== null) {
@@ -41,7 +71,8 @@ export default {
  methods: {
  methods: {
    afterShow() {
    afterShow() {
      // starts from parent path
      // starts from parent path
      this.$store.dispatch('openNodeInMoveModal', this.nodeToMove.substring(0, this.nodeToMove.lastIndexOf('/')));
      let firstSelectedNode = this.nodesToMoveOrCopy[0];
      this.$store.dispatch('openNodeInMoveOrCopyModal', firstSelectedNode.substring(0, firstSelectedNode.lastIndexOf('/')));
    },
    },
    breadcrumbClick(i) {
    breadcrumbClick(i) {
      let pathSplit = this.destinationPath.split('/');
      let pathSplit = this.destinationPath.split('/');
@@ -49,16 +80,17 @@ export default {
      if (path === '') {
      if (path === '') {
        path = '/';
        path = '/';
      }
      }
      this.$store.commit('setNodeToMoveDestination', path);
      this.$store.commit('setMoveOrCopyDestination', path);
      window.openNodeInMoveModal(event, path);
      window.openNodeInMoveOrCopyModal(event, path);
    },
    },
    moveNode() {
    moveOrCopyNodes() {
      this.$store.dispatch('moveNode', {
      this.$store.dispatch('moveOrCopyNodes', {
          target: this.nodeToMove,
          targets: this.nodesToMoveOrCopy,
          direction: this.destinationPath
          direction: this.destinationPath,
          keepBytes: this.moveOrCopy === 'copy'
        })
        })
        .then(() => {
        .then(() => {
          this.$bvModal.hide('move-modal');
          this.$bvModal.hide('move-or-copy-modal');
        })
        })
    }
    }
  }
  }
@@ -66,13 +98,13 @@ export default {
</script>
</script>


<style>
<style>
#move-nodes .list-group-item {
#move-or-copy-nodes .list-group-item {
  /* reduced padding */
  /* reduced padding */
  padding-top: .35rem;
  padding-top: .35rem;
  padding-bottom: .35rem;
  padding-bottom: .35rem;
}
}


#move-nodes-wrapper {
#move-or-copy-nodes-wrapper {
  max-height: 300px;
  max-height: 300px;
  overflow-y: auto;
  overflow-y: auto;
}
}
+4 −3
Original line number Original line Diff line number Diff line
@@ -54,9 +54,10 @@ export default {
        this.newNameError = "Name contains an illegal character. Following characters are not allowed: < > ? \" : \\ / | ' * `";
        this.newNameError = "Name contains an illegal character. Following characters are not allowed: < > ? \" : \\ / | ' * `";
      } else {
      } else {
        let parentPath = this.nodeToRename.substring(0, this.nodeToRename.lastIndexOf('/') + 1);
        let parentPath = this.nodeToRename.substring(0, this.nodeToRename.lastIndexOf('/') + 1);
        this.$store.dispatch('moveNode', {
        this.$store.dispatch('moveOrCopyNodes', {
            target: parentPath + this.oldName,
            targets: [parentPath + this.oldName],
            direction: parentPath + this.newName
            direction: parentPath + this.newName,
            keepBytes: false
          })
          })
          .then(() => {
          .then(() => {
            this.$bvModal.hide('rename-modal');
            this.$bvModal.hide('rename-modal');
+14 −4
Original line number Original line Diff line number Diff line
@@ -36,13 +36,23 @@ window.renameNode = function(path) {
  vm.$bvModal.show('rename-modal');
  vm.$bvModal.show('rename-modal');
}
}
window.moveNode = function(path) {
window.moveNode = function(path) {
  store.commit('setNodeToMove', path);
  moveOrCopy(path, 'move');
  vm.$bvModal.show('move-modal');
}
}
window.openNodeInMoveModal = function(event, path) {
window.copyNode = function(path) {
  moveOrCopy(path, 'copy');
}
window.openNodeInMoveOrCopyModal = function(event, path) {
  event.preventDefault();
  event.preventDefault();
  event.stopPropagation();
  event.stopPropagation();
  store.dispatch('openNodeInMoveModal', path);
  store.dispatch('openNodeInMoveOrCopyModal', path);
}

function moveOrCopy(path, moveOrCopy) {
  store.commit('setNodesToMoveOrCopy', [path]);
  store.commit('setMoveOrCopy', moveOrCopy);
  store.commit('setSelectedNotMovableNodes', []);
  store.commit('setSelectedNotCopiableNodes', []);
  vm.$bvModal.show('move-or-copy-modal');
}
}


export default {
export default {
Loading