diff --git a/frontend/src/js/component/wb-collection-listing.js b/frontend/src/js/component/wb-collection-listing.js
index f0eaa27..6e01e6a 100644
--- a/frontend/src/js/component/wb-collection-listing.js
+++ b/frontend/src/js/component/wb-collection-listing.js
@@ -22,7 +22,7 @@ class WBCollectionListing extends Component {
prepareRows(items, ownerLookup) {
let { app, renderRenameLink, renderDeleteButton,
- renderSelectionCell } = this.props;
+ renderSelectionCell, renderSharingButton } = this.props;
return items.map(item => [
renderSelectionCell(item),
@@ -59,6 +59,8 @@ class WBCollectionListing extends Component {
{ renderDeleteButton(item, () => this.fetchItems()) }
+
+ { renderSharingButton(item) }
)
]);
}
diff --git a/frontend/src/js/component/wb-process-listing.js b/frontend/src/js/component/wb-process-listing.js
index 7c1f3df..3228ed1 100644
--- a/frontend/src/js/component/wb-process-listing.js
+++ b/frontend/src/js/component/wb-process-listing.js
@@ -29,7 +29,7 @@ class WBProcessListing extends Component {
prepareRows(requests, containerLookup, ownerLookup, outputLookup) {
const { app, renderRenameLink, renderDeleteButton,
- renderSelectionCell } = this.props;
+ renderSelectionCell, renderSharingButton } = this.props;
return requests.map(item => {
return ( [
renderSelectionCell(item),
@@ -47,6 +47,7 @@ class WBProcessListing extends Component {
( ),
(
{ renderDeleteButton(item, () => this.fetchItems()) }
+ { renderSharingButton(item) }
)
] );
});
diff --git a/frontend/src/js/component/wb-workflow-listing.js b/frontend/src/js/component/wb-workflow-listing.js
index dbb7fcd..4dbea55 100644
--- a/frontend/src/js/component/wb-workflow-listing.js
+++ b/frontend/src/js/component/wb-workflow-listing.js
@@ -22,7 +22,7 @@ class WBWorkflowListing extends Component {
prepareRows(items, ownerLookup) {
const { renderRenameLink, renderDeleteButton,
- renderSelectionCell } = this.props;
+ renderSelectionCell, renderSharingButton } = this.props;
return items.map(item => [
renderSelectionCell(item),
(
@@ -43,6 +43,7 @@ class WBWorkflowListing extends Component {
href={ urlForObject(item, 'launch') }>
{ renderDeleteButton(item, () => this.fetchItems()) }
+ { renderSharingButton(item) }
)
]);
}
diff --git a/frontend/src/js/page/wb-browse.js b/frontend/src/js/page/wb-browse.js
index aad22eb..eb83941 100644
--- a/frontend/src/js/page/wb-browse.js
+++ b/frontend/src/js/page/wb-browse.js
@@ -194,7 +194,8 @@ class WBBrowse extends Component {
getPageUrl={ i => this.getUrl({ 'collectionPage': i }) }
renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) }
renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) }
- renderSelectionCell={ it => this.renderSelectionCell(it) } />
+ renderSelectionCell={ it => this.renderSelectionCell(it) }
+ renderSharingButton={ it => this.renderSharingButton(it) } />
) : (objTypeTab === 'process') ? (
this.route({ 'processPage': i }) }
renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) }
renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) }
- renderSelectionCell={ it => this.renderSelectionCell(it) } />
+ renderSelectionCell={ it => this.renderSelectionCell(it) }
+ renderSharingButton={ it => this.renderSharingButton(it) } />
) : (objTypeTab === 'workflow') ? (
this.getUrl({ 'workflowPage': i }) }
renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) }
renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) }
- renderSelectionCell={ it => this.renderSelectionCell(it) } />
+ renderSelectionCell={ it => this.renderSelectionCell(it) }
+ renderSharingButton={ it => this.renderSharingButton(it) } />
) : null
}
diff --git a/frontend/src/js/page/wb-sharing-page.js b/frontend/src/js/page/wb-sharing-page.js
index 3ef7193..4a4562d 100644
--- a/frontend/src/js/page/wb-sharing-page.js
+++ b/frontend/src/js/page/wb-sharing-page.js
@@ -22,37 +22,116 @@ class WBSharingPage extends Component {
const { app, uuid } = this.props;
const { arvHost, arvToken } = app.state;
let prom = makeArvadosRequest(arvHost, arvToken,
- '/arvados/v1/permissions/' + encodeURIComponent(uuid));
+ '/arvados/v1/permissions/' + encodeURIComponent(uuid) +
+ '?limit=100000');
prom = prom.then(xhr => this.setState({
+ 'entries': xhr.response.items,
'rows': this.prepareRows(xhr.response.items)
}));
}
- deletePermission(uuid) {
- throw Error('Not implemented');
+ deleteEntry(it) {
+ it._delete = true;
+ this.setState({ rows: this.prepareRows(this.state.entries) });
}
prepareRows(items) {
const { app } = this.props;
- return items.map(it => [
+ return items.filter(it => (!it._delete)).map(it => [
( ),
- ( ),
+ ( this.modifyEntry(it, e.target.value) } /> ),
( )
]);
}
- addEntry(it) {
- throw Error('Not implemented');
+ modifyEntry(it, newPermissionName) {
+ it.name = newPermissionName;
+ it._dirty = true;
+ // this.setState({ rows: this.prepareRows(this.state.entries) });
+ }
+
+ addEntry(it, permissionName='can_read') {
+ // throw Error('Not implemented');
+ const { uuid } = this.props;
+ let { entries } = this.state;
+ if (entries.filter(e => (e.tail_uuid === it.uuid)).length > 0)
+ return; // already in the list
+ const e = {
+ //_dirty: true,
+ link_class: 'permission',
+ head_uuid: uuid,
+ tail_uuid: it.uuid,
+ name: permissionName
+ };
+ entries = entries.concat([e]);
+ this.setState({
+ entries,
+ rows: this.prepareRows(entries)
+ });
+ }
+
+ disableControls() {
+ $('input, select, button').attr('disabled', 'disabled');
+ $('a').each(function() { $(this).data('old_href', $(this).attr('href')); });
+ $('a').attr('href', null);
+ }
+
+ enableControls() {
+ $('input, select, button').attr('disabled', null);
+ $('a').each(function() { $(this).attr('href', $(this).data('old_href')); });
}
save() {
- throw Error('Not implemented');
+ const { entries } = this.state;
+ const { arvHost, arvToken } = this.props.app.state;
+ let prom = new Promise(accept => accept());
+ this.disableControls();
+ this.setState({ working: true });
+ for (let i = 0; i < entries.length; i++) {
+ const e = entries[i];
+
+ //if (!e._dirty && !e._delete)
+ //continue;
+
+ if (!e.uuid) {
+ prom = prom.then(() => makeArvadosRequest(arvHost, arvToken,
+ '/arvados/v1/links',
+ { 'method': 'POST',
+ 'data': JSON.stringify({
+ 'link_class': 'permission',
+ 'head_uuid': e.head_uuid,
+ 'tail_uuid': e.tail_uuid,
+ 'name': e.name
+ }) }));
+
+ } else if (e._delete) {
+ prom = prom.then(() => makeArvadosRequest(arvHost, arvToken,
+ '/arvados/v1/links/' + e.uuid,
+ { 'method': 'DELETE' }));
+
+ } else if (e._dirty) {
+ prom = prom.then(() => makeArvadosRequest(arvHost, arvToken,
+ '/arvados/v1/links/' + e.uuid,
+ { 'method': 'PUT',
+ 'data': JSON.stringify({
+ 'name': e.name
+ }) }));
+ }
+ prom = prom.catch(() => {});
+ }
+ prom = prom.then(() => {
+ this.enableControls();
+ this.fetchData();
+ this.setState({ working: false });
+ });
}
- render({ app, uuid }, { rows }) {
+ render({ app, uuid }, { rows, working }) {
return (
@@ -70,6 +149,12 @@ class WBSharingPage extends Component {
+ { working ? (
) : null }
+