@@ -4,9 +4,12 @@ function urlForObject(item, mode='primary') { | |||||
let objectType = arvadosTypeName(item.uuid.split('-')[1]); | let objectType = arvadosTypeName(item.uuid.split('-')[1]); | ||||
if (objectType === 'user') | if (objectType === 'user') | ||||
return ('/browse/' + item.uuid); | return ('/browse/' + item.uuid); | ||||
else if (objectType === 'group' && item.group_class === 'project') | |||||
return ('/browse/' + item.uuid); | |||||
else if (objectType === 'container_request') | |||||
else if (objectType === 'group' && item.group_class === 'project') { | |||||
if (mode === 'properties') | |||||
return ('/project/' + item.uuid); | |||||
else | |||||
return ('/browse/' + item.uuid); | |||||
} else if (objectType === 'container_request') | |||||
return ('/process/' + item.uuid); | return ('/process/' + item.uuid); | ||||
else if (objectType === 'workflow') { | else if (objectType === 'workflow') { | ||||
if (mode === 'launch') | if (mode === 'launch') | ||||
@@ -3,58 +3,7 @@ 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 makeArvadosRequest from 'make-arvados-request'; | ||||
import arvadosObjectName from 'arvados-object-name'; | import arvadosObjectName from 'arvados-object-name'; | ||||
class WBLazyInlineName extends Component { | |||||
componentWillReceiveProps(nextProps) { | |||||
if (nextProps.identifier === this.props.identifier) | |||||
return; | |||||
this.setState({ item: null }); | |||||
} | |||||
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> | |||||
); | |||||
} | |||||
} | |||||
import WBLazyInlineName from 'wb-lazy-inline-name'; | |||||
function detectIds(value, app) { | function detectIds(value, app) { | ||||
const matches = WBIdTools.detectIdentifiers(value); | const matches = WBIdTools.detectIdentifiers(value); | ||||
@@ -0,0 +1,59 @@ | |||||
import { h, Component } from 'preact'; | |||||
import makeArvadosRequest from 'make-arvados-request'; | |||||
import WBIdTools from 'wb-id-tools'; | |||||
import urlForObject from 'url-for-object'; | |||||
import arvadosObjectName from 'arvados-object-name'; | |||||
class WBLazyInlineName extends Component { | |||||
componentWillReceiveProps(nextProps) { | |||||
if (nextProps.identifier === this.props.identifier) | |||||
return; | |||||
this.setState({ item: null }); | |||||
} | |||||
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> | |||||
); | |||||
} | |||||
} | |||||
export default WBLazyInlineName; |
@@ -0,0 +1,65 @@ | |||||
import { h, Component } from 'preact'; | |||||
import WBTable from 'wb-table'; | |||||
import makeArvadosRequest from 'make-arvados-request'; | |||||
import WBAccordion from 'wb-accordion'; | |||||
import WBJsonViewer from 'wb-json-viewer'; | |||||
import wbFormatSpecialValue from 'wb-format-special-value'; | |||||
import WBLazyInlineName from 'wb-lazy-inline-name'; | |||||
import wbFormatDate from 'wb-format-date'; | |||||
class WBProjectFields extends Component { | |||||
componentDidMount() { | |||||
this.prepareRows(); | |||||
} | |||||
componentWillReceiveProps(nextProps) { | |||||
this.props = nextProps; | |||||
this.prepareRows(); | |||||
} | |||||
prepareRows() { | |||||
let { uuid, app } = this.props; | |||||
let { arvHost, arvToken } = app.state; | |||||
let prom = makeArvadosRequest(arvHost, arvToken, | |||||
'/arvados/v1/groups/' + uuid); | |||||
prom = prom.then(xhr => { | |||||
const item = xhr.response; | |||||
const rows = [ | |||||
[ 'Name', wbFormatSpecialValue(item.name) ], | |||||
[ 'Description', wbFormatSpecialValue(item.description) ], | |||||
[ 'Properties', ( | |||||
<WBAccordion names={[ 'Properties' ]} cardHeaderClass="card-header-sm"> | |||||
<WBJsonViewer app={ app } value={ item.properties } /> | |||||
</WBAccordion> | |||||
) ], | |||||
[ 'Writable by', item.writable_by | |||||
.map(a => (<WBLazyInlineName app={ app } identifier={ a } />)) | |||||
.reduce((a, b) => [].concat(a).concat(', ').concat(b)) | |||||
], | |||||
[ 'Trash At', wbFormatDate(item.trash_at) ], | |||||
[ 'Delete At', wbFormatDate(item.delete_at) ], | |||||
[ 'Is Trashed', wbFormatSpecialValue(item.is_trashed) ] | |||||
]; | |||||
this.setState({ 'rows': rows }); | |||||
}); | |||||
} | |||||
render({}, { rows }) { | |||||
return ( | |||||
rows ? ( | |||||
<WBTable columns={ [ "Name", "Value" ] } | |||||
headerClasses={ [ "col-sm-2", "col-sm-4" ] } | |||||
rows={ rows } | |||||
verticalHeader={ true } /> | |||||
) : ( | |||||
<div>Loading...</div> | |||||
) | |||||
); | |||||
} | |||||
} | |||||
export default WBProjectFields; |
@@ -4,6 +4,7 @@ import makeArvadosRequest from 'make-arvados-request'; | |||||
import WBTable from 'wb-table'; | import WBTable from 'wb-table'; | ||||
import WBPagination from 'wb-pagination'; | import WBPagination from 'wb-pagination'; | ||||
import WBNameAndUuid from 'wb-name-and-uuid'; | import WBNameAndUuid from 'wb-name-and-uuid'; | ||||
import urlForObject from 'url-for-object'; | |||||
class WBProjectListing extends Component { | class WBProjectListing extends Component { | ||||
@@ -37,6 +38,10 @@ class WBProjectListing extends Component { | |||||
</div>), | </div>), | ||||
( <WBNameAndUuid app={ app } uuid={ item['owner_uuid'] } lazy={ true } /> ), | ( <WBNameAndUuid app={ app } uuid={ item['owner_uuid'] } lazy={ true } /> ), | ||||
(<div> | (<div> | ||||
<a class="btn btn-outline-primary m-1" title="Properties" | |||||
href={ urlForObject(item, 'properties') }> | |||||
<i class="fas fa-list-ul"></i> | |||||
</a> | |||||
{ renderDeleteButton(item, () => this.fetchItems()) } | { renderDeleteButton(item, () => this.fetchItems()) } | ||||
{ renderSharingButton(item) } | { renderSharingButton(item) } | ||||
</div>) | </div>) | ||||
@@ -14,6 +14,7 @@ import WBLaunchWorkflowPage from 'wb-launch-workflow-page'; | |||||
import WBDownloadPage from 'wb-download-page'; | import WBDownloadPage from 'wb-download-page'; | ||||
import WBImageViewerPage from 'wb-image-viewer-page'; | import WBImageViewerPage from 'wb-image-viewer-page'; | ||||
import WBSharingPage from 'wb-sharing-page'; | import WBSharingPage from 'wb-sharing-page'; | ||||
import WBProjectView from 'wb-project-view'; | |||||
import arvadosTypeName from 'arvados-type-name'; | import arvadosTypeName from 'arvados-type-name'; | ||||
class WBApp extends Component { | class WBApp extends Component { | ||||
@@ -100,6 +101,8 @@ class WBApp extends Component { | |||||
<WBImageViewerPage path="/image-viewer/:blobUrl" app={ this } /> | <WBImageViewerPage path="/image-viewer/:blobUrl" app={ this } /> | ||||
<WBSharingPage path="/sharing/:uuid" app={ this } /> | <WBSharingPage path="/sharing/:uuid" app={ this } /> | ||||
<WBProjectView path="/project/:uuid" app={ this } /> | |||||
</Router> | </Router> | ||||
); | ); | ||||
} | } | ||||
@@ -0,0 +1,29 @@ | |||||
import { h, Component } from 'preact'; | |||||
import WBNavbarCommon from 'wb-navbar-common'; | |||||
import WBArvadosCrumbs from 'wb-arvados-crumbs'; | |||||
import WBCommonFields from 'wb-common-fields'; | |||||
import WBProjectFields from 'wb-project-fields'; | |||||
class WBProjectView extends Component { | |||||
render({ app, uuid }, {}) { | |||||
return ( | |||||
<div> | |||||
<WBNavbarCommon app={ app } /> | |||||
<WBArvadosCrumbs app={ app } uuid={ uuid } /> | |||||
<div class="my-2"> | |||||
This is the project view for { uuid } | |||||
</div> | |||||
<h2>Common Fields</h2> | |||||
<WBCommonFields app={ app } uuid={ uuid } /> | |||||
<h2>Project Fields</h2> | |||||
<WBProjectFields app={ app } uuid={ uuid } /> | |||||
</div> | |||||
); | |||||
} | |||||
} | |||||
export default WBProjectView; |