diff --git a/frontend/src/js/misc/wb-copy-collection.js b/frontend/src/js/misc/wb-copy-collection.js
new file mode 100644
index 0000000..df53f13
--- /dev/null
+++ b/frontend/src/js/misc/wb-copy-collection.js
@@ -0,0 +1,25 @@
+import makeArvadosRequest from 'make-arvados-request';
+import arvadosTypeName from 'arvados-type-name';
+
+function wbCopyCollection(arvHost, arvToken, uuid, newOwnerUuid) {
+ const typeName = arvadosTypeName(uuid);
+ if (typeName !== 'collection')
+ throw Error('Specified UUID does not refer to a collection');
+ let prom = makeArvadosRequest(arvHost, arvToken,
+ '/arvados/v1/collections/' + uuid);
+ prom = prom.then(xhr => {
+ const { name, description, properties, portable_data_hash,
+ manifest_text } = xhr.response;
+ const dup = { name: name + ' (Copied at ' + new Date().toISOString() + ')',
+ description, properties, portable_data_hash, manifest_text,
+ owner_uuid: newOwnerUuid };
+ return makeArvadosRequest(arvHost, arvToken,
+ '/arvados/v1/collections', {
+ 'method': 'POST',
+ 'data': JSON.stringify(dup)
+ });
+ });
+ return prom;
+}
+
+export default wbCopyCollection;
diff --git a/frontend/src/js/page/wb-browse.js b/frontend/src/js/page/wb-browse.js
index d96ca11..8be72c7 100644
--- a/frontend/src/js/page/wb-browse.js
+++ b/frontend/src/js/page/wb-browse.js
@@ -12,6 +12,8 @@ import WBRenameDialog from 'wb-rename-dialog';
import WBDeleteDialog from 'wb-delete-dialog';
import WBNewProjectDialog from 'wb-new-project-dialog';
import wbMoveObject from 'wb-move-object';
+import wbCopyCollection from 'wb-copy-collection';
+import arvadosTypeName from 'arvados-type-name';
class WBBrowseProjectTabs extends Component {
render({ ownerUuid, selected, newProjectDialogRef, projectListingRef,
@@ -26,7 +28,8 @@ class WBBrowseProjectTabs extends Component {
( ownerUuid && Object.keys(selected).length > 0 ) ?
{ 'name': ( Move Here ),
'onClick': moveHere } : null,
- ( ownerUuid && Object.keys(selected).length > 0 ) ?
+ ( ownerUuid && (uuids => uuids.length > 0 && uuids.length ===
+ uuids.map(arvadosTypeName).filter(a => (a === 'collection')).length )(Object.keys(selected)) ) ?
{ 'name': ( Copy Here ),
'onClick': copyHere } : null
] } />
@@ -106,22 +109,26 @@ class WBBrowse extends Component {
);
}
- moveHere() {
+ moveOrCopyOp(op) {
const { ownerUuid, app } = this.props;
const { selected } = this.state;
const { arvHost, arvToken } = app.state;
let prom = new Promise(accept => accept());
const uuids = Object.keys(selected);
for (let i = 0; i < uuids.length; i++) {
- prom = prom.then(() => wbMoveObject(arvHost, arvToken, uuids[i], ownerUuid));
+ prom = prom.then(() => op(arvHost, arvToken, uuids[i], ownerUuid));
prom = prom.then(() => ( delete selected[uuids[i]] ));
prom = prom.catch(() => {});
}
prom = prom.then(() => this.setState({}));
}
- copyHere() {
+ moveHere() {
+ this.moveOrCopyOp(wbMoveObject);
+ }
+ copyHere() {
+ this.moveOrCopyOp(wbCopyCollection);
}
render({ mode, ownerUuid, activePage, app,