@@ -38,7 +38,7 @@ class WBDeleteDialog extends Component { | |||||
<div> | <div> | ||||
<input type="submit" class="btn btn-danger mr-2" value="Delete" | <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); } } /> | wbDeleteObject(arvHost, arvToken, item.uuid).then(callback); } } /> | ||||
<button class="btn btn-secondary mr-2" onclick={ e => { e.preventDefault(); | <button class="btn btn-secondary mr-2" onclick={ e => { e.preventDefault(); | ||||
this.hide(); } }> | 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', | 'responseType': 'json', | ||||
'useSsl': true, | 'useSsl': true, | ||||
'requireToken': true, | 'requireToken': true, | ||||
'onProgress': () => {} | |||||
'onProgress': () => {}, | |||||
'promiseOrdering': true | |||||
}; | }; | ||||
Object.keys(defaultParams).map(k => (params[k] = | Object.keys(defaultParams).map(k => (params[k] = | ||||
(k in params ? params[k] : defaultParams[k]))); | (k in params ? params[k] : defaultParams[k]))); | ||||
let { method, data, contentType, responseType, | let { method, data, contentType, responseType, | ||||
useSsl, requireToken, onProgress } = params; | |||||
useSsl, requireToken, onProgress, promiseOrdering } = params; | |||||
if (!(arvHost && (arvToken || !requireToken))) | if (!(arvHost && (arvToken || !requireToken))) | ||||
return new Promise((accept, reject) => reject()); | return new Promise((accept, reject) => reject()); | ||||
@@ -43,7 +44,8 @@ function makeArvadosRequest(arvHost, arvToken, endpoint, params={}) { | |||||
xhr.send(data); | xhr.send(data); | ||||
}); | }); | ||||
prom = wbApplyPromiseOrdering(prom, requestPromiseOrdering); | |||||
if (promiseOrdering) | |||||
prom = wbApplyPromiseOrdering(prom, requestPromiseOrdering); | |||||
return prom; | return prom; | ||||
} | } | ||||
@@ -5,7 +5,7 @@ function wbDeleteObject(arvHost, arvToken, uuid) { | |||||
const typeName = arvadosTypeName(uuid); | const typeName = arvadosTypeName(uuid); | ||||
return makeArvadosRequest(arvHost, arvToken, | return makeArvadosRequest(arvHost, arvToken, | ||||
'/arvados/v1/' + typeName + 's/' + | '/arvados/v1/' + typeName + 's/' + | ||||
uuid, { 'method': 'DELETE' }); | |||||
uuid, { 'method': 'DELETE', 'promiseOrdering': false }); | |||||
} | } | ||||
export default wbDeleteObject; | export default wbDeleteObject; |
@@ -10,12 +10,15 @@ import WBCollectionListing from 'wb-collection-listing'; | |||||
import WBWorkflowListing from 'wb-workflow-listing'; | import WBWorkflowListing from 'wb-workflow-listing'; | ||||
import WBRenameDialog from 'wb-rename-dialog'; | import WBRenameDialog from 'wb-rename-dialog'; | ||||
import WBDeleteDialog from 'wb-delete-dialog'; | import WBDeleteDialog from 'wb-delete-dialog'; | ||||
import WBNewProjectDialog from 'wb-new-project-dialog'; | |||||
class WBBrowse extends Component { | class WBBrowse extends Component { | ||||
constructor(...args) { | constructor(...args) { | ||||
super(...args); | super(...args); | ||||
this.renameDialogRef = createRef(); | this.renameDialogRef = createRef(); | ||||
this.deleteDialogRef = createRef(); | this.deleteDialogRef = createRef(); | ||||
this.newProjectDialogRef = createRef(); | |||||
this.projectListingRef = createRef(); | |||||
} | } | ||||
getUrl(params) { | getUrl(params) { | ||||
@@ -65,14 +68,22 @@ class WBBrowse extends Component { | |||||
<WBDeleteDialog app={ app } ref={ this.deleteDialogRef } /> | <WBDeleteDialog app={ app } ref={ this.deleteDialogRef } /> | ||||
<WBNewProjectDialog app={ app } ref={ this.newProjectDialogRef } /> | |||||
<WBNavbarCommon app={ app } activeItem={ !ownerUuid ? 'all-projects' : | <WBNavbarCommon app={ app } activeItem={ !ownerUuid ? 'all-projects' : | ||||
(ownerUuid === app.state.currentUser.uuid ? 'home' : null) } /> | (ownerUuid === app.state.currentUser.uuid ? 'home' : null) } /> | ||||
<WBArvadosCrumbs uuid={ ownerUuid } app={ app } /> | <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 } | arvHost={ appState.arvHost } | ||||
arvToken={ appState.arvToken } | arvToken={ appState.arvToken } | ||||
ownerUuid={ ownerUuid } | ownerUuid={ ownerUuid } | ||||
@@ -1,18 +1,22 @@ | |||||
import { h, Component } from 'preact'; | |||||
import { h, Component, VNode } from 'preact'; | |||||
class WBTabs extends Component { | class WBTabs extends Component { | ||||
render({ tabs, onTabChanged }) { | render({ tabs, onTabChanged }) { | ||||
return ( | return ( | ||||
<ul class="nav nav-tabs"> | <ul class="nav nav-tabs"> | ||||
{ tabs.map((t, idx) => { | { tabs.map((t, idx) => { | ||||
let name, isActive, isDisabled; | |||||
let name, isActive, isDisabled, onClick; | |||||
if (typeof(t) === 'object') { | if (typeof(t) === 'object') { | ||||
name = t.name; | name = t.name; | ||||
isActive = t.isActive; | isActive = t.isActive; | ||||
isDisabled = t.isDisabled; | isDisabled = t.isDisabled; | ||||
onClick = t.onClick; | |||||
} else if (typeof(t) === 'string') { | } else if (typeof(t) === 'string') { | ||||
name = t; | name = t; | ||||
} | } | ||||
let cls = ['nav-link']; | let cls = ['nav-link']; | ||||
if (isActive) | if (isActive) | ||||
cls.push('active'); | cls.push('active'); | ||||
@@ -21,7 +25,11 @@ class WBTabs extends Component { | |||||
cls = cls.join(' '); | cls = cls.join(' '); | ||||
return ( | return ( | ||||
<li class="nav-item"> | <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> | </li> | ||||
); | ); | ||||
}) } | }) } | ||||