| @@ -40,7 +40,7 @@ class WBCollectionFields extends Component { | |||
| [ 'Description', wbFormatSpecialValue(item.description) ], | |||
| [ 'Properties', ( | |||
| <WBAccordion names={ ['Properties'] } cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ item.properties } /> | |||
| <WBJsonViewer app={ app } value={ item.properties } /> | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Portable Data Hash', item.portable_data_hash ], | |||
| @@ -39,38 +39,38 @@ class WBContainerFields extends Component { | |||
| [ 'Environment', ( | |||
| <WBAccordion names={ ['Environment'] } | |||
| cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ item.environment } /> | |||
| <WBJsonViewer app={ app } value={ item.environment } /> | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Working Directory', item.cwd ], | |||
| [ 'Command', ( | |||
| <WBJsonViewer value={ item.command } /> | |||
| <WBJsonViewer app={ app } value={ item.command } /> | |||
| ) ], | |||
| [ 'Output Path', item.output_path ], | |||
| [ 'Mounts', ( | |||
| <WBAccordion names={ Object.keys(item.mounts) } | |||
| cardHeaderClass="card-header-sm"> | |||
| { Object.keys(item.mounts).map(k => ( | |||
| <WBJsonViewer value={ item.mounts[k] } /> | |||
| <WBJsonViewer app={ app } value={ item.mounts[k] } /> | |||
| )) } | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Runtime Constraints', ( | |||
| <WBAccordion names={ ['Runtime Constraints'] } | |||
| cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ item.runtime_constraints } /> | |||
| <WBJsonViewer app={ app } value={ item.runtime_constraints } /> | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Runtime Status', ( | |||
| <WBAccordion names={ ['Runtime Status'] } | |||
| cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ item.runtime_status } /> | |||
| <WBJsonViewer app={ app } value={ item.runtime_status } /> | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Scheduling Parameters', ( | |||
| <WBAccordion names={ ['Scheduling Parameters'] } | |||
| cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ item.scheduling_parameters } /> | |||
| <WBJsonViewer app={ app } value={ item.scheduling_parameters } /> | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Output', item.output ? ( | |||
| @@ -34,7 +34,7 @@ class WBContainerRequestFields extends Component { | |||
| [ 'Description', item.description || (<i>{ String(item.description) }</i>) ], | |||
| [ 'Properties', ( | |||
| <WBAccordion names={ ['Properties'] } cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ item.properties } /> | |||
| <WBJsonViewer app={ app } value={ item.properties } /> | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'State', item.state ], | |||
| @@ -49,20 +49,20 @@ class WBContainerRequestFields extends Component { | |||
| <WBAccordion names={ Object.keys(item.mounts) } | |||
| cardHeaderClass="card-header-sm"> | |||
| { Object.keys(item.mounts).map(k => ( | |||
| <WBJsonViewer value={ item.mounts[k] } /> | |||
| <WBJsonViewer app={ app } value={ item.mounts[k] } /> | |||
| )) } | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Runtime Constraints', ( | |||
| <WBAccordion names={ ['Runtime Constraints'] } | |||
| cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ item.runtime_constraints } /> | |||
| <WBJsonViewer app={ app } value={ item.runtime_constraints } /> | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Scheduling Parameters', ( | |||
| <WBAccordion names={ ['Scheduling Parameters'] } | |||
| cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ item.scheduling_parameters } /> | |||
| <WBJsonViewer app={ app } value={ item.scheduling_parameters } /> | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Container Image', ( | |||
| @@ -71,12 +71,12 @@ class WBContainerRequestFields extends Component { | |||
| [ 'Environment', ( | |||
| <WBAccordion names={ ['Environment'] } | |||
| cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ item.environment } /> | |||
| <WBJsonViewer app={ app } value={ item.environment } /> | |||
| </WBAccordion> | |||
| ) ], | |||
| [ 'Working Directory', item.cwd ], | |||
| [ 'Command', ( | |||
| <WBJsonViewer value={ item.command } /> | |||
| <WBJsonViewer app={ app } value={ item.command } /> | |||
| ) ], | |||
| [ 'Output Path', item.output_path ], | |||
| [ 'Output Name', item.output_name ], | |||
| @@ -91,7 +91,7 @@ class WBContainerRequestFields extends Component { | |||
| <WBNameAndUuid app={ app } uuid={ item.output_uuid } /> | |||
| ) ], | |||
| [ 'Filters', ( | |||
| item.filters ? (<WBJsonViewer value={ item.filters } />) : (<i>{ String(item.filters) }</i>) | |||
| item.filters ? (<WBJsonViewer app={ app } value={ item.filters } />) : (<i>{ String(item.filters) }</i>) | |||
| ) ], | |||
| [ 'Runtime Token', item.runtime_token || (<i>{ String(item.runtime_token) }</i>) ], | |||
| [ 'Runtime User', ( | |||
| @@ -99,7 +99,7 @@ class WBContainerRequestFields extends Component { | |||
| ) ], | |||
| [ 'Runtime Auth Scopes', ( | |||
| item.runtime_auth_scopes ? ( | |||
| <WBJsonViewer value={ item.runtime_auth_scopes } /> | |||
| <WBJsonViewer app={ app } value={ item.runtime_auth_scopes } /> | |||
| ) : ( | |||
| <i>{ String(item.runtime_auth_scopes) }</i> | |||
| ) | |||
| @@ -1,8 +1,56 @@ | |||
| import { h, Component } from 'preact'; | |||
| import WBIdTools from 'wb-id-tools'; | |||
| import urlForObject from 'url-for-object'; | |||
| import makeArvadosRequest from 'make-arvados-request'; | |||
| import arvadosObjectName from 'arvados-object-name'; | |||
| function detectIds(value) { | |||
| class WBLazyInlineName extends Component { | |||
| fetchData() { | |||
| const { app, identifier } = this.props; | |||
| const { arvHost, arvToken } = app.state; | |||
| const typeName = WBIdTools.typeName(identifier); | |||
| if (WBIdTools.isPDH(identifier)) { | |||
| const filters = [ | |||
| [ 'portable_data_hash', '=', identifier ] | |||
| ]; | |||
| let prom = makeArvadosRequest(arvHost, arvToken, | |||
| '/arvados/v1/collections?filters=' + encodeURIComponent(JSON.stringify(filters))); | |||
| prom = prom.then(xhr => this.setState({ item: { | |||
| uuid: xhr.response.items.length > 0 ? xhr.response.items[0].uuid : '', | |||
| name: xhr.response.items.length > 0 ? xhr.response.items[0].name : 'Not Found' + | |||
| ( xhr.response.items_available > 1 ? ' (+' + (xhr.response.items_available - 1) + ' others)' : '' ) | |||
| }})); | |||
| return; | |||
| } | |||
| let prom = makeArvadosRequest(arvHost, arvToken, | |||
| '/arvados/v1/' + typeName + 's/' + identifier); | |||
| prom = prom.then(xhr => this.setState({ item: xhr.response })); | |||
| prom = prom.catch(() => this.setState({ item: { name: 'Not Found' }})); | |||
| } | |||
| render({ identifier }, { item }) { | |||
| if (item) { | |||
| return ( | |||
| <a href={ urlForObject(item) }>{ arvadosObjectName(item) }</a> | |||
| ); | |||
| } | |||
| const typeName = WBIdTools.typeName(identifier); | |||
| const url = (typeName === 'group' ? '/browse/' + identifier : | |||
| typeName === 'collection' ? '/collection-browse/' + identifier : | |||
| urlForObject({ uuid: identifier })); | |||
| return ( | |||
| <span> | |||
| <a href={ url }>{ identifier }</a> <a href="#" title="Look up" | |||
| onclick={ e => { e.preventDefault(); this.fetchData(); } }> | |||
| <i class="fas fa-search"></i> | |||
| </a> | |||
| </span> | |||
| ); | |||
| } | |||
| } | |||
| function detectIds(value, app) { | |||
| const matches = WBIdTools.detectIdentifiers(value); | |||
| matches.sort((a, b) => (a.index - b.index)); | |||
| const res = []; | |||
| @@ -15,7 +63,7 @@ function detectIds(value) { | |||
| typeName === 'collection' ? '/collection-browse/' + id : | |||
| urlForObject({ uuid: id })); | |||
| res.push(value.substring(ofs, index)); | |||
| res.push(h('a', { href: url }, id)); | |||
| res.push(h(WBLazyInlineName, { identifier: id, app }, id)); | |||
| ofs = index + id.length; | |||
| } | |||
| res.push(value.substring(ofs)); | |||
| @@ -23,11 +71,11 @@ function detectIds(value) { | |||
| } | |||
| class WBJsonViewer extends Component { | |||
| render({ value, stringify }) { | |||
| render({ value, stringify, app }) { | |||
| if (stringify) | |||
| value = JSON.stringify(value, null, 2); | |||
| return ( | |||
| <div class="wb-json-viewer">{ detectIds(value) }</div> | |||
| <div class="wb-json-viewer">{ detectIds(value, app) }</div> | |||
| ); | |||
| } | |||
| } | |||
| @@ -52,9 +52,9 @@ class WBWorkflowFields extends Component { | |||
| <WBAccordion names={ [ 'Inputs', 'Outputs', 'Rest' ] } | |||
| cardHeaderClass="card-header-sm"> | |||
| <WBJsonViewer value={ it.inputs } /> | |||
| <WBJsonViewer app={ app } value={ it.inputs } /> | |||
| <WBJsonViewer value={ it.outputs } /> | |||
| <WBJsonViewer app={ app } value={ it.outputs } /> | |||
| { (() => { | |||
| delete it['inputs']; | |||
| @@ -64,7 +64,7 @@ class WBWorkflowFields extends Component { | |||
| delete it['doc']; | |||
| delete it['id']; | |||
| return ( | |||
| <WBJsonViewer value={ it } /> | |||
| <WBJsonViewer app={ app } value={ it } /> | |||
| ); | |||
| })() } | |||
| @@ -78,7 +78,7 @@ class WBWorkflowFields extends Component { | |||
| cardHeaderClass="card-header-sm"> | |||
| { graph.map(it => ( | |||
| <WBJsonViewer value={ it } /> | |||
| <WBJsonViewer app={ app } value={ it } /> | |||
| )) } | |||
| </WBAccordion> | |||