From c6e6a6ecd005bbe181e4889a4f323ca84aba3663 Mon Sep 17 00:00:00 2001 From: Stanislaw Adaszewski Date: Wed, 15 Apr 2020 12:52:33 +0200 Subject: [PATCH] Add project properties view. --- .../src/js/arvados/base/url-for-object.js | 9 ++- frontend/src/js/component/wb-json-viewer.js | 53 +-------------- .../src/js/component/wb-lazy-inline-name.js | 59 +++++++++++++++++ .../src/js/component/wb-project-fields.js | 65 +++++++++++++++++++ .../src/js/component/wb-project-listing.js | 5 ++ frontend/src/js/page/wb-app.js | 3 + frontend/src/js/page/wb-project-view.js | 29 +++++++++ 7 files changed, 168 insertions(+), 55 deletions(-) create mode 100644 frontend/src/js/component/wb-lazy-inline-name.js create mode 100644 frontend/src/js/component/wb-project-fields.js create mode 100644 frontend/src/js/page/wb-project-view.js diff --git a/frontend/src/js/arvados/base/url-for-object.js b/frontend/src/js/arvados/base/url-for-object.js index 8a3e4a9..fce5424 100644 --- a/frontend/src/js/arvados/base/url-for-object.js +++ b/frontend/src/js/arvados/base/url-for-object.js @@ -4,9 +4,12 @@ function urlForObject(item, mode='primary') { let objectType = arvadosTypeName(item.uuid.split('-')[1]); if (objectType === 'user') 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); else if (objectType === 'workflow') { if (mode === 'launch') diff --git a/frontend/src/js/component/wb-json-viewer.js b/frontend/src/js/component/wb-json-viewer.js index d3940d5..abbf696 100644 --- a/frontend/src/js/component/wb-json-viewer.js +++ b/frontend/src/js/component/wb-json-viewer.js @@ -3,58 +3,7 @@ import WBIdTools from 'wb-id-tools'; import urlForObject from 'url-for-object'; import makeArvadosRequest from 'make-arvados-request'; 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 ( - { arvadosObjectName(item) } - ); - } - - const typeName = WBIdTools.typeName(identifier); - const url = (typeName === 'group' ? '/browse/' + identifier : - typeName === 'collection' ? '/collection-browse/' + identifier : - urlForObject({ uuid: identifier })); - return ( - - { identifier } { e.preventDefault(); this.fetchData(); } }> - - - - ); - } -} +import WBLazyInlineName from 'wb-lazy-inline-name'; function detectIds(value, app) { const matches = WBIdTools.detectIdentifiers(value); diff --git a/frontend/src/js/component/wb-lazy-inline-name.js b/frontend/src/js/component/wb-lazy-inline-name.js new file mode 100644 index 0000000..3b5ec47 --- /dev/null +++ b/frontend/src/js/component/wb-lazy-inline-name.js @@ -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 ( + { arvadosObjectName(item) } + ); + } + + const typeName = WBIdTools.typeName(identifier); + const url = (typeName === 'group' ? '/browse/' + identifier : + typeName === 'collection' ? '/collection-browse/' + identifier : + urlForObject({ uuid: identifier })); + return ( + + { identifier } { e.preventDefault(); this.fetchData(); } }> + + + + ); + } +} + +export default WBLazyInlineName; diff --git a/frontend/src/js/component/wb-project-fields.js b/frontend/src/js/component/wb-project-fields.js new file mode 100644 index 0000000..f859fcf --- /dev/null +++ b/frontend/src/js/component/wb-project-fields.js @@ -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', ( + + + + ) ], + [ 'Writable by', item.writable_by + .map(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 ? ( + + ) : ( +
Loading...
+ ) + ); + } +} + +export default WBProjectFields; diff --git a/frontend/src/js/component/wb-project-listing.js b/frontend/src/js/component/wb-project-listing.js index 0d2eb52..83bc254 100644 --- a/frontend/src/js/component/wb-project-listing.js +++ b/frontend/src/js/component/wb-project-listing.js @@ -4,6 +4,7 @@ import makeArvadosRequest from 'make-arvados-request'; import WBTable from 'wb-table'; import WBPagination from 'wb-pagination'; import WBNameAndUuid from 'wb-name-and-uuid'; +import urlForObject from 'url-for-object'; class WBProjectListing extends Component { @@ -37,6 +38,10 @@ class WBProjectListing extends Component { ), ( ), (
+ + + { renderDeleteButton(item, () => this.fetchItems()) } { renderSharingButton(item) }
) diff --git a/frontend/src/js/page/wb-app.js b/frontend/src/js/page/wb-app.js index 22c07f2..14aeb76 100644 --- a/frontend/src/js/page/wb-app.js +++ b/frontend/src/js/page/wb-app.js @@ -14,6 +14,7 @@ import WBLaunchWorkflowPage from 'wb-launch-workflow-page'; import WBDownloadPage from 'wb-download-page'; import WBImageViewerPage from 'wb-image-viewer-page'; import WBSharingPage from 'wb-sharing-page'; +import WBProjectView from 'wb-project-view'; import arvadosTypeName from 'arvados-type-name'; class WBApp extends Component { @@ -100,6 +101,8 @@ class WBApp extends Component { + + ); } diff --git a/frontend/src/js/page/wb-project-view.js b/frontend/src/js/page/wb-project-view.js new file mode 100644 index 0000000..44695ad --- /dev/null +++ b/frontend/src/js/page/wb-project-view.js @@ -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 ( +
+ + + + +
+ This is the project view for { uuid } +
+ +

Common Fields

+ + +

Project Fields

+ +
+ ); + } +} + +export default WBProjectView;