@@ -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> | |||
); | |||
}) } | |||