@@ -7,6 +7,11 @@ import WBCheckboxes from 'wb-checkboxes'; | |||||
import wbFormatDate from 'wb-format-date'; | import wbFormatDate from 'wb-format-date'; | ||||
import wbFetchObjects from 'wb-fetch-objects'; | import wbFetchObjects from 'wb-fetch-objects'; | ||||
import WBNameAndUuid from 'wb-name-and-uuid'; | import WBNameAndUuid from 'wb-name-and-uuid'; | ||||
import WBProcessState from 'wb-process-state'; | |||||
function maskRows(rows) { | |||||
return rows.map(r => r.map(c => '-')); | |||||
} | |||||
class WBProcessListing extends Component { | class WBProcessListing extends Component { | ||||
@@ -15,9 +20,7 @@ class WBProcessListing extends Component { | |||||
this.state.rows = []; | this.state.rows = []; | ||||
this.state.numPages = 0; | this.state.numPages = 0; | ||||
this.state.requestStates = [ 'Uncommitted', 'Committed', 'Final' ]; | this.state.requestStates = [ 'Uncommitted', 'Committed', 'Final' ]; | ||||
// this.state.containerStates = [ 'Queued', 'Locked', 'Running', 'Cancelled', 'Complete' ]; | |||||
this.state.reqStateMask = [ true, true, true ]; | this.state.reqStateMask = [ true, true, true ]; | ||||
// this.state.contStateMask = [ true, true, true, true, true ]; | |||||
} | } | ||||
componentDidMount() { | componentDidMount() { | ||||
@@ -25,14 +28,8 @@ class WBProcessListing extends Component { | |||||
} | } | ||||
prepareRows(requests, containerLookup, ownerLookup, outputLookup) { | prepareRows(requests, containerLookup, ownerLookup, outputLookup) { | ||||
const { renderRenameLink, renderDeleteButton } = this.props; | |||||
const { app, renderRenameLink, renderDeleteButton } = this.props; | |||||
return requests.map(item => { | return requests.map(item => { | ||||
const container = item.container_uuid in containerLookup ? | |||||
containerLookup[item.container_uuid] : null; | |||||
const runtimeStatus = container ? container.runtime_status : null; | |||||
const error = runtimeStatus ? runtimeStatus.error : null; | |||||
const warning = runtimeStatus ? runtimeStatus.warning : null; | |||||
return ( [ | return ( [ | ||||
(<div> | (<div> | ||||
<div> | <div> | ||||
@@ -42,22 +39,10 @@ class WBProcessListing extends Component { | |||||
</div> | </div> | ||||
<div>{ item['uuid'] }</div> | <div>{ item['uuid'] }</div> | ||||
</div>), | </div>), | ||||
( <div> | |||||
{ item['state'] } | |||||
{ item.container_uuid ? | |||||
container ? | |||||
[ " / ", container.state ] : | |||||
[ " / ", <i>Container Not Found</i> ] : | |||||
null } | |||||
{ !(error || warning) && container && container.state === 'Complete' ? " / Success" : null } | |||||
{ error ? [" / ", <a href={ '/container/' + container.uuid } | |||||
title={ error }>E</a> ] : null } | |||||
{ warning ? [ " / ", <a href={ '/container/' + container.uuid } | |||||
title={ warning }>W</a> ] : null } | |||||
</div> ), | |||||
( <WBNameAndUuid uuid={ item['owner_uuid'] } lookup={ ownerLookup } /> ), | |||||
( <WBProcessState app={ app } process={ item } /> ), | |||||
( <WBNameAndUuid app={ app } uuid={ item['owner_uuid'] } /> ), | |||||
wbFormatDate(item['created_at']), | wbFormatDate(item['created_at']), | ||||
( <WBNameAndUuid uuid={ item['output_uuid'] } lookup={ outputLookup } /> ), | |||||
( <WBNameAndUuid app={ app } uuid={ item['output_uuid'] } /> ), | |||||
(<div> | (<div> | ||||
{ renderDeleteButton(item, () => this.fetchItems()) } | { renderDeleteButton(item, () => this.fetchItems()) } | ||||
</div>) | </div>) | ||||
@@ -78,64 +63,22 @@ class WBProcessListing extends Component { | |||||
filters.push([ 'state', 'in', requestStates.filter((_, idx) => reqStateMask[idx]) ]); | filters.push([ 'state', 'in', requestStates.filter((_, idx) => reqStateMask[idx]) ]); | ||||
if (ownerUuid) | if (ownerUuid) | ||||
filters.push([ 'owner_uuid', '=', ownerUuid ]); | filters.push([ 'owner_uuid', '=', ownerUuid ]); | ||||
//if (requestingContainerUuid) | |||||
//filters.push(); | |||||
let prom = makeArvadosRequest(arvHost, arvToken, | let prom = makeArvadosRequest(arvHost, arvToken, | ||||
'/arvados/v1/container_requests?filters=' + encodeURIComponent(JSON.stringify(filters)) + | '/arvados/v1/container_requests?filters=' + encodeURIComponent(JSON.stringify(filters)) + | ||||
'&limit=' + itemsPerPage + | '&limit=' + itemsPerPage + | ||||
'&offset=' + (itemsPerPage * activePage)); | '&offset=' + (itemsPerPage * activePage)); | ||||
let requests; | |||||
let numPages; | |||||
prom = prom.then(xhr => { | |||||
requests = xhr.response.items; | |||||
numPages = Math.ceil(xhr.response['items_available'] / xhr.response['limit']); | |||||
/* container_uuids = requests.map(r => r.container_uuid); | |||||
container_uuids = container_uuids.filter(uuid => uuid); | |||||
const filters_1 = [ | |||||
[ 'uuid', 'in', container_uuids ] | |||||
]; | |||||
return makeArvadosRequest(arvHost, arvToken, | |||||
'/arvados/v1/containers?filters=' + | |||||
encodeURIComponent(JSON.stringify(filters_1)));*/ | |||||
return wbFetchObjects(arvHost, arvToken, | |||||
requests.map(r => r.container_uuid).filter(uuid => uuid)); | |||||
}); | |||||
let containerLookup; | |||||
prom = prom.then(lookup => { | |||||
containerLookup = lookup; | |||||
// const containers = xhr.response.items; | |||||
// containers.map(c => (containerLookup[c.uuid] = c)); | |||||
return wbFetchObjects(arvHost, arvToken, | |||||
requests.map(r => r.owner_uuid).filter(uuid => uuid)); | |||||
}); | |||||
let ownerLookup; | |||||
prom = prom.then(lookup => { | |||||
ownerLookup = lookup; | |||||
return wbFetchObjects(arvHost, arvToken, | |||||
requests.map(r => r.output_uuid).filter(uuid => uuid)); | |||||
}); | |||||
let outputLookup; | |||||
prom = prom.then(lookup => (outputLookup = lookup)); | |||||
// prom = prom.then(() => makeArvadosRequest(arvHost, arvToken, | |||||
// '/arvados/v1/')) | |||||
prom = prom.then(() => | |||||
prom = prom.then(xhr => | |||||
this.setState({ | this.setState({ | ||||
'numPages': numPages, | |||||
'rows': this.prepareRows(requests, containerLookup, | |||||
ownerLookup, outputLookup) | |||||
'numPages': Math.ceil(xhr.response['items_available'] / xhr.response['limit']), | |||||
'rows': this.prepareRows(xhr.response.items) | |||||
})); | })); | ||||
} | } | ||||
componentWillReceiveProps(nextProps, nextState) { | componentWillReceiveProps(nextProps, nextState) { | ||||
// this.setState({ 'rows': [] }); // .rows = []; | |||||
this.props = nextProps; | this.props = nextProps; | ||||
this.setState({ 'rows': maskRows(this.state.rows) }); | |||||
this.fetchItems(); | this.fetchItems(); | ||||
} | } | ||||
@@ -0,0 +1,47 @@ | |||||
import { h, Component } from 'preact'; | |||||
import makeArvadosRequest from 'make-arvados-request'; | |||||
class WBProcessState extends Component { | |||||
componentDidMount() { | |||||
this.fetchData(); | |||||
} | |||||
componentWillReceiveProps(nextProps) { | |||||
this.props = nextProps; | |||||
this.fetchData(); | |||||
} | |||||
fetchData() { | |||||
const { app, process } = this.props; | |||||
const { arvHost, arvToken } = app.state; | |||||
if (!process.container_uuid) | |||||
return; | |||||
let prom = makeArvadosRequest(arvHost, arvToken, | |||||
'/arvados/v1/containers/' + process.container_uuid); | |||||
prom = prom.then(xhr => this.setState({ 'container': xhr.response })); | |||||
prom = prom.catch(() => this.setState({ 'apiError': 'Failed to fetch container' })); | |||||
} | |||||
render({ process }, { container, apiError }) { | |||||
const runtimeStatus = container ? container.runtime_status : null; | |||||
const error = runtimeStatus ? runtimeStatus.error : null; | |||||
const warning = runtimeStatus ? runtimeStatus.warning : null; | |||||
return ( | |||||
<div> | |||||
{ process.state } | |||||
{ apiError ? <i>{ [ ' / ', apiError ] }</i> : null } | |||||
{ container ? [ " / ", container.state ] : null } | |||||
{ !(error || warning) && container && container.state === 'Complete' ? " / Success" : null } | |||||
{ error ? [" / ", <a href={ '/container/' + container.uuid } | |||||
title={ error }>E</a> ] : null } | |||||
{ warning ? [ " / ", <a href={ '/container/' + container.uuid } | |||||
title={ warning }>W</a> ] : null } | |||||
</div> | |||||
); | |||||
} | |||||
} | |||||
export default WBProcessState; |
@@ -7,6 +7,10 @@ function wbFetchObjects(arvHost, arvToken, uuids) { | |||||
uuids = {}; | uuids = {}; | ||||
Object.keys(unique).map(u => { | Object.keys(unique).map(u => { | ||||
let typeName = arvadosTypeName(u); | let typeName = arvadosTypeName(u); | ||||
if (!typeName) { | |||||
console.log('Unknown type name for UUID: ' + u); | |||||
return; | |||||
} | |||||
if (!(typeName in uuids)) | if (!(typeName in uuids)) | ||||
uuids[typeName] = []; | uuids[typeName] = []; | ||||
uuids[typeName].push(u); | uuids[typeName].push(u); | ||||
@@ -23,6 +27,7 @@ function wbFetchObjects(arvHost, arvToken, uuids) { | |||||
encodeURIComponent(JSON.stringify(filters)))); | encodeURIComponent(JSON.stringify(filters)))); | ||||
prom = prom.then(xhr => xhr.response.items.map(it => ( | prom = prom.then(xhr => xhr.response.items.map(it => ( | ||||
lookup[it.uuid] = it))); | lookup[it.uuid] = it))); | ||||
prom = prom.catch(xhr => console.log(xhr.responseURL + ': ' + xhr.statusText)); | |||||
} | } | ||||
prom = prom.then(() => lookup); | prom = prom.then(() => lookup); | ||||
@@ -121,7 +121,8 @@ class WBBrowse extends Component { | |||||
renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } /> | renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } /> | ||||
) : (objTypeTab === 'process') ? ( | ) : (objTypeTab === 'process') ? ( | ||||
<WBProcessListing appState={ app.state } | |||||
<WBProcessListing app={ app } | |||||
appState={ app.state } | |||||
ownerUuid={ ownerUuid } | ownerUuid={ ownerUuid } | ||||
itemsPerPage="20" | itemsPerPage="20" | ||||
activePage={ Number(processPage || 0) } | activePage={ Number(processPage || 0) } | ||||
@@ -9,6 +9,7 @@ import detectHashes from 'detect-hashes'; | |||||
import WBCommonFields from 'wb-common-fields'; | import WBCommonFields from 'wb-common-fields'; | ||||
import WBContainerRequestFields from 'wb-container-request-fields'; | import WBContainerRequestFields from 'wb-container-request-fields'; | ||||
import WBProcessListing from 'wb-process-listing'; | import WBProcessListing from 'wb-process-listing'; | ||||
import wbFetchObjects from 'wb-fetch-objects'; | |||||
class WBProcessView extends Component { | class WBProcessView extends Component { | ||||
constructor(...args) { | constructor(...args) { | ||||
@@ -55,9 +56,12 @@ class WBProcessView extends Component { | |||||
uuids.map(u => (dict[u] = true)); | uuids.map(u => (dict[u] = true)); | ||||
return Object.keys(dict); | return Object.keys(dict); | ||||
}); | }); | ||||
prom = prom.then(uuids => { | |||||
prom = prom.then(uuids => wbFetchObjects(arvHost, arvToken, uuids)); | |||||
/* prom = prom.then(() => { | |||||
// let uuids = detectUuids([ req, cont ]); | // let uuids = detectUuids([ req, cont ]); | ||||
let objectTypes = uuids.map(u => arvadosTypeName(u.split('-')[1]) + 's'); | |||||
let objectTypes = uuids.map(u => arvadosTypeName(u) + 's'); | |||||
//objectTypes = objectTypes.filter(ot => ot); | |||||
//objectTypes = objectTypes.map(ot => ot + 's'); | |||||
let objQueries = {}; | let objQueries = {}; | ||||
objectTypes.map(t => (objQueries[t] = [])); | objectTypes.map(t => (objQueries[t] = [])); | ||||
uuids.map((u, idx) => (objQueries[objectTypes[idx]].push(u))); | uuids.map((u, idx) => (objQueries[objectTypes[idx]].push(u))); | ||||
@@ -76,11 +80,11 @@ class WBProcessView extends Component { | |||||
} | } | ||||
prom_1 = prom_1.then(() => objects); | prom_1 = prom_1.then(() => objects); | ||||
return prom_1; | return prom_1; | ||||
}); | |||||
}); */ | |||||
prom = prom.then(objects => { | prom = prom.then(objects => { | ||||
let objDict = {}; | |||||
objects.map(o => (objDict[o['uuid']] = o)); | |||||
let urls = objects.map(o => urlForObject(o)); | |||||
// let objDict = {}; | |||||
// objects.map(o => (objDict[o['uuid']] = o)); | |||||
let urls = Object.values(objects).map(o => urlForObject(o)); | |||||
this.setState({ | this.setState({ | ||||
'objectUrls': urls, | 'objectUrls': urls, | ||||
'request': req, | 'request': req, | ||||
@@ -95,7 +99,7 @@ class WBProcessView extends Component { | |||||
componentWillReceiveProps(nextProps) { | componentWillReceiveProps(nextProps) { | ||||
this.props = nextProps; | this.props = nextProps; | ||||
this.setState({ 'objectUrls': [], 'request': null, 'container': null }); | |||||
// this.setState({ 'objectUrls': [], 'request': null, 'container': null }); | |||||
this.fetchData(); | this.fetchData(); | ||||
} | } | ||||
@@ -118,7 +122,8 @@ class WBProcessView extends Component { | |||||
{ container ? ([ | { container ? ([ | ||||
<h2>Children</h2>, | <h2>Children</h2>, | ||||
<WBProcessListing appState={ app.state } | |||||
<WBProcessListing app={ app } | |||||
appState={ app.state } | |||||
requestingContainerUuid={ container.uuid } | requestingContainerUuid={ container.uuid } | ||||
itemsPerPage="20" | itemsPerPage="20" | ||||
activePage={ Number(page || 0) } | activePage={ Number(page || 0) } | ||||