@@ -40,7 +40,7 @@ class WBCollectionFields extends Component { | |||||
[ 'Description', wbFormatSpecialValue(item.description) ], | [ 'Description', wbFormatSpecialValue(item.description) ], | ||||
[ 'Properties', ( | [ 'Properties', ( | ||||
<WBAccordion names={ ['Properties'] } cardHeaderClass="card-header-sm"> | <WBAccordion names={ ['Properties'] } cardHeaderClass="card-header-sm"> | ||||
<WBJsonViewer value={ item.properties } /> | |||||
<WBJsonViewer app={ app } value={ item.properties } /> | |||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Portable Data Hash', item.portable_data_hash ], | [ 'Portable Data Hash', item.portable_data_hash ], | ||||
@@ -39,38 +39,38 @@ class WBContainerFields extends Component { | |||||
[ 'Environment', ( | [ 'Environment', ( | ||||
<WBAccordion names={ ['Environment'] } | <WBAccordion names={ ['Environment'] } | ||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
<WBJsonViewer value={ item.environment } /> | |||||
<WBJsonViewer app={ app } value={ item.environment } /> | |||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Working Directory', item.cwd ], | [ 'Working Directory', item.cwd ], | ||||
[ 'Command', ( | [ 'Command', ( | ||||
<WBJsonViewer value={ item.command } /> | |||||
<WBJsonViewer app={ app } value={ item.command } /> | |||||
) ], | ) ], | ||||
[ 'Output Path', item.output_path ], | [ 'Output Path', item.output_path ], | ||||
[ 'Mounts', ( | [ 'Mounts', ( | ||||
<WBAccordion names={ Object.keys(item.mounts) } | <WBAccordion names={ Object.keys(item.mounts) } | ||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
{ Object.keys(item.mounts).map(k => ( | { Object.keys(item.mounts).map(k => ( | ||||
<WBJsonViewer value={ item.mounts[k] } /> | |||||
<WBJsonViewer app={ app } value={ item.mounts[k] } /> | |||||
)) } | )) } | ||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Runtime Constraints', ( | [ 'Runtime Constraints', ( | ||||
<WBAccordion names={ ['Runtime Constraints'] } | <WBAccordion names={ ['Runtime Constraints'] } | ||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
<WBJsonViewer value={ item.runtime_constraints } /> | |||||
<WBJsonViewer app={ app } value={ item.runtime_constraints } /> | |||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Runtime Status', ( | [ 'Runtime Status', ( | ||||
<WBAccordion names={ ['Runtime Status'] } | <WBAccordion names={ ['Runtime Status'] } | ||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
<WBJsonViewer value={ item.runtime_status } /> | |||||
<WBJsonViewer app={ app } value={ item.runtime_status } /> | |||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Scheduling Parameters', ( | [ 'Scheduling Parameters', ( | ||||
<WBAccordion names={ ['Scheduling Parameters'] } | <WBAccordion names={ ['Scheduling Parameters'] } | ||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
<WBJsonViewer value={ item.scheduling_parameters } /> | |||||
<WBJsonViewer app={ app } value={ item.scheduling_parameters } /> | |||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Output', item.output ? ( | [ 'Output', item.output ? ( | ||||
@@ -34,7 +34,7 @@ class WBContainerRequestFields extends Component { | |||||
[ 'Description', item.description || (<i>{ String(item.description) }</i>) ], | [ 'Description', item.description || (<i>{ String(item.description) }</i>) ], | ||||
[ 'Properties', ( | [ 'Properties', ( | ||||
<WBAccordion names={ ['Properties'] } cardHeaderClass="card-header-sm"> | <WBAccordion names={ ['Properties'] } cardHeaderClass="card-header-sm"> | ||||
<WBJsonViewer value={ item.properties } /> | |||||
<WBJsonViewer app={ app } value={ item.properties } /> | |||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'State', item.state ], | [ 'State', item.state ], | ||||
@@ -49,20 +49,20 @@ class WBContainerRequestFields extends Component { | |||||
<WBAccordion names={ Object.keys(item.mounts) } | <WBAccordion names={ Object.keys(item.mounts) } | ||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
{ Object.keys(item.mounts).map(k => ( | { Object.keys(item.mounts).map(k => ( | ||||
<WBJsonViewer value={ item.mounts[k] } /> | |||||
<WBJsonViewer app={ app } value={ item.mounts[k] } /> | |||||
)) } | )) } | ||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Runtime Constraints', ( | [ 'Runtime Constraints', ( | ||||
<WBAccordion names={ ['Runtime Constraints'] } | <WBAccordion names={ ['Runtime Constraints'] } | ||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
<WBJsonViewer value={ item.runtime_constraints } /> | |||||
<WBJsonViewer app={ app } value={ item.runtime_constraints } /> | |||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Scheduling Parameters', ( | [ 'Scheduling Parameters', ( | ||||
<WBAccordion names={ ['Scheduling Parameters'] } | <WBAccordion names={ ['Scheduling Parameters'] } | ||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
<WBJsonViewer value={ item.scheduling_parameters } /> | |||||
<WBJsonViewer app={ app } value={ item.scheduling_parameters } /> | |||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Container Image', ( | [ 'Container Image', ( | ||||
@@ -71,12 +71,12 @@ class WBContainerRequestFields extends Component { | |||||
[ 'Environment', ( | [ 'Environment', ( | ||||
<WBAccordion names={ ['Environment'] } | <WBAccordion names={ ['Environment'] } | ||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
<WBJsonViewer value={ item.environment } /> | |||||
<WBJsonViewer app={ app } value={ item.environment } /> | |||||
</WBAccordion> | </WBAccordion> | ||||
) ], | ) ], | ||||
[ 'Working Directory', item.cwd ], | [ 'Working Directory', item.cwd ], | ||||
[ 'Command', ( | [ 'Command', ( | ||||
<WBJsonViewer value={ item.command } /> | |||||
<WBJsonViewer app={ app } value={ item.command } /> | |||||
) ], | ) ], | ||||
[ 'Output Path', item.output_path ], | [ 'Output Path', item.output_path ], | ||||
[ 'Output Name', item.output_name ], | [ 'Output Name', item.output_name ], | ||||
@@ -91,7 +91,7 @@ class WBContainerRequestFields extends Component { | |||||
<WBNameAndUuid app={ app } uuid={ item.output_uuid } /> | <WBNameAndUuid app={ app } uuid={ item.output_uuid } /> | ||||
) ], | ) ], | ||||
[ 'Filters', ( | [ '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 Token', item.runtime_token || (<i>{ String(item.runtime_token) }</i>) ], | ||||
[ 'Runtime User', ( | [ 'Runtime User', ( | ||||
@@ -99,7 +99,7 @@ class WBContainerRequestFields extends Component { | |||||
) ], | ) ], | ||||
[ 'Runtime Auth Scopes', ( | [ 'Runtime Auth Scopes', ( | ||||
item.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> | <i>{ String(item.runtime_auth_scopes) }</i> | ||||
) | ) | ||||
@@ -1,8 +1,56 @@ | |||||
import { h, Component } from 'preact'; | import { h, Component } from 'preact'; | ||||
import WBIdTools from 'wb-id-tools'; | import WBIdTools from 'wb-id-tools'; | ||||
import urlForObject from 'url-for-object'; | 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); | const matches = WBIdTools.detectIdentifiers(value); | ||||
matches.sort((a, b) => (a.index - b.index)); | matches.sort((a, b) => (a.index - b.index)); | ||||
const res = []; | const res = []; | ||||
@@ -15,7 +63,7 @@ function detectIds(value) { | |||||
typeName === 'collection' ? '/collection-browse/' + id : | typeName === 'collection' ? '/collection-browse/' + id : | ||||
urlForObject({ uuid: id })); | urlForObject({ uuid: id })); | ||||
res.push(value.substring(ofs, index)); | 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; | ofs = index + id.length; | ||||
} | } | ||||
res.push(value.substring(ofs)); | res.push(value.substring(ofs)); | ||||
@@ -23,11 +71,11 @@ function detectIds(value) { | |||||
} | } | ||||
class WBJsonViewer extends Component { | class WBJsonViewer extends Component { | ||||
render({ value, stringify }) { | |||||
render({ value, stringify, app }) { | |||||
if (stringify) | if (stringify) | ||||
value = JSON.stringify(value, null, 2); | value = JSON.stringify(value, null, 2); | ||||
return ( | 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' ] } | <WBAccordion names={ [ 'Inputs', 'Outputs', 'Rest' ] } | ||||
cardHeaderClass="card-header-sm"> | 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']; | delete it['inputs']; | ||||
@@ -64,7 +64,7 @@ class WBWorkflowFields extends Component { | |||||
delete it['doc']; | delete it['doc']; | ||||
delete it['id']; | delete it['id']; | ||||
return ( | return ( | ||||
<WBJsonViewer value={ it } /> | |||||
<WBJsonViewer app={ app } value={ it } /> | |||||
); | ); | ||||
})() } | })() } | ||||
@@ -78,7 +78,7 @@ class WBWorkflowFields extends Component { | |||||
cardHeaderClass="card-header-sm"> | cardHeaderClass="card-header-sm"> | ||||
{ graph.map(it => ( | { graph.map(it => ( | ||||
<WBJsonViewer value={ it } /> | |||||
<WBJsonViewer app={ app } value={ it } /> | |||||
)) } | )) } | ||||
</WBAccordion> | </WBAccordion> | ||||