| @@ -38,7 +38,7 @@ class WBDeleteDialog extends Component { | |||
| <div> | |||
| <input type="submit" class="btn btn-danger mr-2" value="Delete" | |||
| onclick={ e => { e.preventDefault(); | |||
| onclick={ e => { e.preventDefault(); this.hide(); | |||
| wbDeleteObject(arvHost, arvToken, item.uuid).then(callback); } } /> | |||
| <button class="btn btn-secondary mr-2" onclick={ e => { e.preventDefault(); | |||
| this.hide(); } }> | |||
| @@ -0,0 +1,54 @@ | |||
| import { h, Component, createRef } from 'preact'; | |||
| import WBDialog from 'wb-dialog'; | |||
| import linkState from 'linkstate'; | |||
| import makeArvadosRequest from 'make-arvados-request'; | |||
| class WBNewProjectDialog extends Component { | |||
| constructor(...args) { | |||
| super(...args); | |||
| this.dialogRef = createRef(); | |||
| this.state.inputId = uuid.v4(); | |||
| } | |||
| show(ownerUuid, callback) { | |||
| const { inputId } = this.state; | |||
| this.setState({ | |||
| 'ownerUuid': ownerUuid, | |||
| 'newName': null, | |||
| 'placeholderName': 'New Project (' + (new Date()).toISOString() + ')', | |||
| 'callback': callback || (() => {}) | |||
| }); | |||
| this.dialogRef.current.show(); | |||
| $('#' + inputId).focus(); | |||
| } | |||
| hide() { | |||
| this.dialogRef.current.hide(); | |||
| } | |||
| render({ app }, { ownerUuid, newName, placeholderName, callback, inputId }) { | |||
| const { arvHost, arvToken } = app.state; | |||
| return ( | |||
| <WBDialog title="New Project" ref={ this.dialogRef } accept={ () => { | |||
| const group = { | |||
| 'group_class': 'project', | |||
| 'name': newName || placeholderName, | |||
| 'owner_uuid': ownerUuid | |||
| }; | |||
| makeArvadosRequest(arvHost, arvToken, | |||
| '/arvados/v1/groups', { 'method': 'POST', | |||
| 'data': JSON.stringify(group), | |||
| 'promiseOrdering': false } | |||
| ).then(callback); | |||
| } }> | |||
| <div> | |||
| <input type="text" class="form-control" id={ inputId } | |||
| placeholder={ placeholderName } | |||
| value={ newName } onChange={ linkState(this, 'newName') } /> | |||
| </div> | |||
| </WBDialog> | |||
| ); | |||
| } | |||
| } | |||
| export default WBNewProjectDialog; | |||
| @@ -10,13 +10,14 @@ function makeArvadosRequest(arvHost, arvToken, endpoint, params={}) { | |||
| 'responseType': 'json', | |||
| 'useSsl': true, | |||
| 'requireToken': true, | |||
| 'onProgress': () => {} | |||
| 'onProgress': () => {}, | |||
| 'promiseOrdering': true | |||
| }; | |||
| Object.keys(defaultParams).map(k => (params[k] = | |||
| (k in params ? params[k] : defaultParams[k]))); | |||
| let { method, data, contentType, responseType, | |||
| useSsl, requireToken, onProgress } = params; | |||
| useSsl, requireToken, onProgress, promiseOrdering } = params; | |||
| if (!(arvHost && (arvToken || !requireToken))) | |||
| return new Promise((accept, reject) => reject()); | |||
| @@ -43,7 +44,8 @@ function makeArvadosRequest(arvHost, arvToken, endpoint, params={}) { | |||
| xhr.send(data); | |||
| }); | |||
| prom = wbApplyPromiseOrdering(prom, requestPromiseOrdering); | |||
| if (promiseOrdering) | |||
| prom = wbApplyPromiseOrdering(prom, requestPromiseOrdering); | |||
| return prom; | |||
| } | |||
| @@ -5,7 +5,7 @@ function wbDeleteObject(arvHost, arvToken, uuid) { | |||
| const typeName = arvadosTypeName(uuid); | |||
| return makeArvadosRequest(arvHost, arvToken, | |||
| '/arvados/v1/' + typeName + 's/' + | |||
| uuid, { 'method': 'DELETE' }); | |||
| uuid, { 'method': 'DELETE', 'promiseOrdering': false }); | |||
| } | |||
| export default wbDeleteObject; | |||
| @@ -10,12 +10,15 @@ import WBCollectionListing from 'wb-collection-listing'; | |||
| import WBWorkflowListing from 'wb-workflow-listing'; | |||
| import WBRenameDialog from 'wb-rename-dialog'; | |||
| import WBDeleteDialog from 'wb-delete-dialog'; | |||
| import WBNewProjectDialog from 'wb-new-project-dialog'; | |||
| class WBBrowse extends Component { | |||
| constructor(...args) { | |||
| super(...args); | |||
| this.renameDialogRef = createRef(); | |||
| this.deleteDialogRef = createRef(); | |||
| this.newProjectDialogRef = createRef(); | |||
| this.projectListingRef = createRef(); | |||
| } | |||
| getUrl(params) { | |||
| @@ -65,14 +68,22 @@ class WBBrowse extends Component { | |||
| <WBDeleteDialog app={ app } ref={ this.deleteDialogRef } /> | |||
| <WBNewProjectDialog app={ app } ref={ this.newProjectDialogRef } /> | |||
| <WBNavbarCommon app={ app } activeItem={ !ownerUuid ? 'all-projects' : | |||
| (ownerUuid === app.state.currentUser.uuid ? 'home' : null) } /> | |||
| <WBArvadosCrumbs uuid={ ownerUuid } app={ app } /> | |||
| <WBTabs tabs={ [ { 'name': 'Projects', 'isActive': true } ] } /> | |||
| <WBProjectListing app={ app } | |||
| <WBTabs tabs={ [ | |||
| { 'name': 'Projects', 'isActive': true }, | |||
| { 'name': ( <span><i class="fas fa-plus-square text-success"></i> New Project</span> ), | |||
| 'onClick': () => this.newProjectDialogRef.current.show(ownerUuid, | |||
| () => this.projectListingRef.current.fetchItems() ) } | |||
| ] } /> | |||
| <WBProjectListing ref={ this.projectListingRef } | |||
| app={ app } | |||
| arvHost={ appState.arvHost } | |||
| arvToken={ appState.arvToken } | |||
| ownerUuid={ ownerUuid } | |||
| @@ -1,18 +1,22 @@ | |||
| import { h, Component } from 'preact'; | |||
| import { h, Component, VNode } from 'preact'; | |||
| class WBTabs extends Component { | |||
| render({ tabs, onTabChanged }) { | |||
| return ( | |||
| <ul class="nav nav-tabs"> | |||
| { tabs.map((t, idx) => { | |||
| let name, isActive, isDisabled; | |||
| let name, isActive, isDisabled, onClick; | |||
| if (typeof(t) === 'object') { | |||
| name = t.name; | |||
| isActive = t.isActive; | |||
| isDisabled = t.isDisabled; | |||
| onClick = t.onClick; | |||
| } else if (typeof(t) === 'string') { | |||
| name = t; | |||
| } | |||
| let cls = ['nav-link']; | |||
| if (isActive) | |||
| cls.push('active'); | |||
| @@ -21,7 +25,11 @@ class WBTabs extends Component { | |||
| cls = cls.join(' '); | |||
| return ( | |||
| <li class="nav-item"> | |||
| <a class={ cls } href="#" onclick={ e => { e.preventDefault(); onTabChanged(t); } }>{ name }</a> | |||
| <a class={ cls } href="#" | |||
| onclick={ e => { e.preventDefault(); | |||
| onClick ? onClick() : onTabChanged(t); } }> | |||
| { name } | |||
| </a> | |||
| </li> | |||
| ); | |||
| }) } | |||