| 
				
				
					
				
				
				 | 
			
			 | 
			@@ -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 => [
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      ( <WBNameAndUuid app={ app } uuid={ it.tail_uuid } /> ),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      ( <WBSelect value={ it.name } options={ ['can_read', 'can_write', 'can_manage'] } /> ),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      ( <WBSelect value={ it.name }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          options={ ['can_read', 'can_write', 'can_manage'] }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          onChange={ e => this.modifyEntry(it, e.target.value) } /> ),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      ( <button class="btn btn-outline-danger m-1" title="Delete"
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        onclick={ () => this.deletePermission(it.uuid) }>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        onclick={ () => this.deleteEntry(it) }>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        <i class="fas fa-trash"></i>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      </button> )
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    ]);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  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 (
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      <div>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        <WBNavbarCommon app={ app } />
 | 
		
		
	
	
		
			
				| 
				
				
				
					
				
				 | 
			
			 | 
			@@ -70,6 +149,12 @@ class WBSharingPage extends Component { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          <WBPickObjectDialog app={ app } ref={ this.dialogRef } />
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          { working ? (<div class="progress my-2">
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            <div class={ 'progress-bar progress-bar-striped progress-bar-animated' }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              role="progressbar" aria-valuenow="100" aria-valuemin="0"
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              aria-valuemax="100" style="width: 100%"></div>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          </div>) : null }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          <button class="btn btn-outline-secondary mr-2"
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            onclick={ () => this.dialogRef.current.show('Select User', 'user', it => this.addEntry(it)) }>Add User...</button>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          <button class="btn btn-outline-secondary mr-2"
 | 
		
		
	
	
		
			
				| 
				
					
				
				
				
				 | 
			
			 | 
			
  |