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