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