| @@ -68,13 +68,16 @@ class WBCollectionListing extends Component { | |||||
| fetchItems() { | fetchItems() { | ||||
| let { arvHost, arvToken } = this.props.app.state; | let { arvHost, arvToken } = this.props.app.state; | ||||
| let { activePage, itemsPerPage, ownerUuid } = this.props; | |||||
| let { activePage, itemsPerPage, ownerUuid, textSearch } = this.props; | |||||
| let filters = []; | let filters = []; | ||||
| if (ownerUuid) | if (ownerUuid) | ||||
| filters.push([ 'owner_uuid', '=', ownerUuid ]); | filters.push([ 'owner_uuid', '=', ownerUuid ]); | ||||
| if (textSearch) | |||||
| filters.push([ 'any', 'ilike', '%' + textSearch + '%' ]); | |||||
| let prom = makeArvadosRequest(arvHost, arvToken, | let prom = makeArvadosRequest(arvHost, arvToken, | ||||
| '/arvados/v1/collections?filters=' + encodeURIComponent(JSON.stringify(filters)) + | '/arvados/v1/collections?filters=' + encodeURIComponent(JSON.stringify(filters)) + | ||||
| '&limit=' + encodeURIComponent(itemsPerPage) + | '&limit=' + encodeURIComponent(itemsPerPage) + | ||||
| @@ -1,12 +1,13 @@ | |||||
| import { h, Component } from 'preact'; | import { h, Component } from 'preact'; | ||||
| class WBInlineSearch extends Component { | class WBInlineSearch extends Component { | ||||
| render() { | |||||
| render({ textSearch, navigate }) { | |||||
| return ( | return ( | ||||
| <form class="form-inline my-2 my-lg-0"> | |||||
| <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" /> | |||||
| <div class="form-inline my-2 my-lg-0"> | |||||
| <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" | |||||
| value={ textSearch } onchange={ navigate ? (e => navigate(e.target.value)) : null } /> | |||||
| <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> | <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> | ||||
| </form> | |||||
| </div> | |||||
| ); | ); | ||||
| } | } | ||||
| } | } | ||||
| @@ -3,7 +3,7 @@ import WBNavbar from 'wb-navbar'; | |||||
| import WBInlineSearch from 'wb-inline-search'; | import WBInlineSearch from 'wb-inline-search'; | ||||
| class WBNavbarCommon extends Component { | class WBNavbarCommon extends Component { | ||||
| render({ app, items, activeItem }) { | |||||
| render({ app, items, activeItem, textSearch, textSearchNavigate }) { | |||||
| return ( | return ( | ||||
| <WBNavbar | <WBNavbar | ||||
| items={ [ | items={ [ | ||||
| @@ -13,9 +13,9 @@ class WBNavbarCommon extends Component { | |||||
| { 'name': 'Shared with Me', 'id': 'shared-with-me' }, | { 'name': 'Shared with Me', 'id': 'shared-with-me' }, | ||||
| { 'name': 'Current User', 'dropdown': [ { 'id': 'sign-out', 'name': 'Sign Out' } ]} | { 'name': 'Current User', 'dropdown': [ { 'id': 'sign-out', 'name': 'Sign Out' } ]} | ||||
| ].concat(items) } | ].concat(items) } | ||||
| rhs={ ( | |||||
| <WBInlineSearch /> | |||||
| ) } | |||||
| rhs={ textSearchNavigate ? ( | |||||
| <WBInlineSearch textSearch={ textSearch } navigate={ textSearchNavigate } /> | |||||
| ) : null } | |||||
| titleUrl = { '/browse/' + app.state.currentUser.uuid } | titleUrl = { '/browse/' + app.state.currentUser.uuid } | ||||
| getItemUrl={ item => app.navbarItemUrl(item) } | getItemUrl={ item => app.navbarItemUrl(item) } | ||||
| activeItem={ activeItem } /> | activeItem={ activeItem } /> | ||||
| @@ -57,7 +57,8 @@ class WBProcessListing extends Component { | |||||
| const { arvHost, arvToken } = this.props.appState; | const { arvHost, arvToken } = this.props.appState; | ||||
| const { requestStates, reqStateMask } = this.state; | const { requestStates, reqStateMask } = this.state; | ||||
| const { activePage, itemsPerPage, ownerUuid, | const { activePage, itemsPerPage, ownerUuid, | ||||
| requestingContainerUuid, waitForNextProps } = this.props; | |||||
| requestingContainerUuid, waitForNextProps, | |||||
| textSearch } = this.props; | |||||
| if (waitForNextProps) | if (waitForNextProps) | ||||
| return; | return; | ||||
| @@ -69,6 +70,8 @@ class WBProcessListing extends Component { | |||||
| filters.push([ 'state', 'in', requestStates.filter((_, idx) => reqStateMask[idx]) ]); | filters.push([ 'state', 'in', requestStates.filter((_, idx) => reqStateMask[idx]) ]); | ||||
| if (ownerUuid) | if (ownerUuid) | ||||
| filters.push([ 'owner_uuid', '=', ownerUuid ]); | filters.push([ 'owner_uuid', '=', ownerUuid ]); | ||||
| if (textSearch) | |||||
| filters.push([ 'any', 'ilike', '%' + textSearch + '%' ]) | |||||
| let prom = makeArvadosRequest(arvHost, arvToken, | let prom = makeArvadosRequest(arvHost, arvToken, | ||||
| '/arvados/v1/container_requests?filters=' + encodeURIComponent(JSON.stringify(filters)) + | '/arvados/v1/container_requests?filters=' + encodeURIComponent(JSON.stringify(filters)) + | ||||
| @@ -24,8 +24,7 @@ class WBProjectListing extends Component { | |||||
| renderSelectionCell(item), | renderSelectionCell(item), | ||||
| (<div> | (<div> | ||||
| <div> | <div> | ||||
| <a href="#" | |||||
| onclick={ e => { e.preventDefault(); route('/browse/' + item['uuid']) }}> | |||||
| <a href={ '/browse/' + item.uuid }> | |||||
| { item['name'] } | { item['name'] } | ||||
| </a> { renderRenameLink(item, () => this.fetchItems()) } | </a> { renderRenameLink(item, () => this.fetchItems()) } | ||||
| </div> | </div> | ||||
| @@ -45,13 +44,15 @@ class WBProjectListing extends Component { | |||||
| } | } | ||||
| fetchItems() { | fetchItems() { | ||||
| let { activePage, mode, itemsPerPage, ownerUuid, app } = this.props; | |||||
| let { activePage, mode, itemsPerPage, ownerUuid, app, textSearch } = this.props; | |||||
| let { arvHost, arvToken } = app.state; | let { arvHost, arvToken } = app.state; | ||||
| let filters = [ | let filters = [ | ||||
| [ 'group_class', '=', 'project' ] | [ 'group_class', '=', 'project' ] | ||||
| ]; | ]; | ||||
| if (ownerUuid) | if (ownerUuid) | ||||
| filters.push([ 'owner_uuid', '=', ownerUuid ]); | filters.push([ 'owner_uuid', '=', ownerUuid ]); | ||||
| if (textSearch) | |||||
| filters.push([ 'any', 'ilike', '%' + textSearch + '%' ]); | |||||
| let prom = makeArvadosRequest(arvHost, arvToken, | let prom = makeArvadosRequest(arvHost, arvToken, | ||||
| '/arvados/v1/groups' + (mode === 'shared-with-me' ? '/shared' : '') + | '/arvados/v1/groups' + (mode === 'shared-with-me' ? '/shared' : '') + | ||||
| '?filters=' + encodeURIComponent(JSON.stringify(filters)) + | '?filters=' + encodeURIComponent(JSON.stringify(filters)) + | ||||
| @@ -15,12 +15,17 @@ class WBUserListing extends Component { | |||||
| preparePage() { | preparePage() { | ||||
| const { arvHost, arvToken } = this.props.app.state; | const { arvHost, arvToken } = this.props.app.state; | ||||
| const { itemsPerPage, page } = this.props; | |||||
| const { itemsPerPage, page, textSearch } = this.props; | |||||
| const order = ['last_name asc']; | const order = ['last_name asc']; | ||||
| const filters = []; | |||||
| if (textSearch) | |||||
| filters.push([ 'any', 'ilike', '%' + textSearch + '%' ]); | |||||
| let prom = makeArvadosRequest(arvHost, arvToken, | let prom = makeArvadosRequest(arvHost, arvToken, | ||||
| '/arvados/v1/users?order=' + encodeURIComponent(JSON.stringify(order)) + | '/arvados/v1/users?order=' + encodeURIComponent(JSON.stringify(order)) + | ||||
| '&filters=' + encodeURIComponent(JSON.stringify(filters)) + | |||||
| '&limit=' + itemsPerPage + '&offset=' + (itemsPerPage * page)); | '&limit=' + itemsPerPage + '&offset=' + (itemsPerPage * page)); | ||||
| prom = prom.then(xhr => { | prom = prom.then(xhr => { | ||||
| this.setState({ | this.setState({ | ||||
| @@ -50,10 +50,12 @@ class WBWorkflowListing extends Component { | |||||
| fetchItems() { | fetchItems() { | ||||
| const { arvHost, arvToken } = this.props.app.state; | const { arvHost, arvToken } = this.props.app.state; | ||||
| const { page, itemsPerPage, ownerUuid } = this.props; | |||||
| const { page, itemsPerPage, ownerUuid, textSearch } = this.props; | |||||
| const filters = []; | const filters = []; | ||||
| if (ownerUuid) | if (ownerUuid) | ||||
| filters.push([ 'owner_uuid', '=', ownerUuid ]); | filters.push([ 'owner_uuid', '=', ownerUuid ]); | ||||
| if (textSearch) | |||||
| filters.push([ 'any', 'ilike', '%' + textSearch + '%' ]); | |||||
| const select = ['uuid', 'name', 'description', 'owner_uuid', 'created_at']; | const select = ['uuid', 'name', 'description', 'owner_uuid', 'created_at']; | ||||
| let prom = makeArvadosRequest(arvHost, arvToken, | let prom = makeArvadosRequest(arvHost, arvToken, | ||||
| '/arvados/v1/workflows?filters=' + encodeURIComponent(JSON.stringify(filters)) + | '/arvados/v1/workflows?filters=' + encodeURIComponent(JSON.stringify(filters)) + | ||||
| @@ -75,10 +75,10 @@ class WBApp extends Component { | |||||
| <WBSignOut path='/sign-out' app={ this } /> | <WBSignOut path='/sign-out' app={ this } /> | ||||
| <WBBrowse path="/browse/:ownerUuid?/:activePage?/:objTypeTab?/:collectionPage?/:processPage?/:workflowPage?" | |||||
| <WBBrowse path="/browse/:ownerUuid?/:activePage?/:objTypeTab?/:collectionPage?/:processPage?/:workflowPage?/:textSearch?" | |||||
| app={ this } mode="browse" /> | app={ this } mode="browse" /> | ||||
| <WBBrowse path="/shared-with-me/:activePage?" | |||||
| <WBBrowse path="/shared-with-me/:activePage?/:textSearch?" | |||||
| app={ this } mode="shared-with-me" /> | app={ this } mode="shared-with-me" /> | ||||
| <WBProcessView path="/process/:uuid/:page?" app={ this } /> | <WBProcessView path="/process/:uuid/:page?" app={ this } /> | ||||
| @@ -89,7 +89,7 @@ class WBApp extends Component { | |||||
| <WBCollectionBrowse path='/collection-browse/:uuid/:collectionPath?/:page?' app={ this } /> | <WBCollectionBrowse path='/collection-browse/:uuid/:collectionPath?/:page?' app={ this } /> | ||||
| <WBUsersPage path='/users/:page?' app={ this } /> | |||||
| <WBUsersPage path='/users/:page?/:textSearch?' app={ this } /> | |||||
| <WBWorkflowView path="/workflow/:uuid" app={ this } /> | <WBWorkflowView path="/workflow/:uuid" app={ this } /> | ||||
| @@ -52,8 +52,9 @@ class WBBrowse extends Component { | |||||
| const mode = ('mode' in params ? params.mode : this.props.mode); | const mode = ('mode' in params ? params.mode : this.props.mode); | ||||
| if (mode === 'shared-with-me') | if (mode === 'shared-with-me') | ||||
| return '/shared-with-me/' + ('activePage' in params ? params.activePage : | |||||
| (this.props.activePage || '')); | |||||
| return '/shared-with-me/' + | |||||
| ('activePage' in params ? params.activePage : (this.props.activePage || '')) + '/' + | |||||
| ('textSearch' in params ? params.textSearch : (this.props.textSearch || '')); | |||||
| let res = '/browse/' + | let res = '/browse/' + | ||||
| ('ownerUuid' in params ? params.ownerUuid : (this.props.ownerUuid || '')) + '/' + | ('ownerUuid' in params ? params.ownerUuid : (this.props.ownerUuid || '')) + '/' + | ||||
| @@ -61,7 +62,8 @@ class WBBrowse extends Component { | |||||
| ('objTypeTab' in params ? params.objTypeTab : (this.props.objTypeTab || '')) + '/' + | ('objTypeTab' in params ? params.objTypeTab : (this.props.objTypeTab || '')) + '/' + | ||||
| ('collectionPage' in params ? params.collectionPage : (this.props.collectionPage || '')) + '/' + | ('collectionPage' in params ? params.collectionPage : (this.props.collectionPage || '')) + '/' + | ||||
| ('processPage' in params ? params.processPage : (this.props.processPage || '')) + '/' + | ('processPage' in params ? params.processPage : (this.props.processPage || '')) + '/' + | ||||
| ('workflowPage' in params ? params.workflowPage : (this.props.workflowPage || '')); | |||||
| ('workflowPage' in params ? params.workflowPage : (this.props.workflowPage || '')) + '/' + | |||||
| encodeURIComponent('textSearch' in params ? params.textSearch : (this.props.textSearch || '')); | |||||
| return res; | return res; | ||||
| } | } | ||||
| @@ -141,7 +143,8 @@ class WBBrowse extends Component { | |||||
| } | } | ||||
| render({ mode, ownerUuid, activePage, app, | render({ mode, ownerUuid, activePage, app, | ||||
| objTypeTab, collectionPage, processPage, workflowPage }, { selected }) { | |||||
| objTypeTab, collectionPage, processPage, workflowPage, | |||||
| textSearch }, { selected }) { | |||||
| return ( | return ( | ||||
| <div> | <div> | ||||
| @@ -151,9 +154,13 @@ class WBBrowse extends Component { | |||||
| <WBNewProjectDialog app={ app } ref={ this.newProjectDialogRef } /> | <WBNewProjectDialog app={ app } ref={ this.newProjectDialogRef } /> | ||||
| <WBNavbarCommon app={ app } activeItem={ mode === 'shared-with-me' ? 'shared-with-me' : | |||||
| (!ownerUuid) ? 'all-projects' : | |||||
| (ownerUuid === app.state.currentUser.uuid) ? 'home' : null } /> | |||||
| <WBNavbarCommon app={ app } | |||||
| activeItem={ mode === 'shared-with-me' ? 'shared-with-me' : | |||||
| (!ownerUuid) ? 'all-projects' : | |||||
| (ownerUuid === app.state.currentUser.uuid) ? 'home' : null } | |||||
| textSearch={ textSearch } | |||||
| textSearchNavigate={ textSearch => route(this.getUrl({ textSearch, | |||||
| activePage: 0, collectionPage: 0, processPage: 0, workflowPage: 0 })) } /> | |||||
| <WBArvadosCrumbs mode={ mode } uuid={ ownerUuid } app={ app } /> | <WBArvadosCrumbs mode={ mode } uuid={ ownerUuid } app={ app } /> | ||||
| @@ -174,7 +181,8 @@ class WBBrowse extends Component { | |||||
| renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) } | renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) } | ||||
| renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } | renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } | ||||
| renderSelectionCell={ it => this.renderSelectionCell(it) } | renderSelectionCell={ it => this.renderSelectionCell(it) } | ||||
| renderSharingButton={ it => this.renderSharingButton(it) } /> | |||||
| renderSharingButton={ it => this.renderSharingButton(it) } | |||||
| textSearch={ textSearch } /> | |||||
| { (mode !== 'browse') ? null : ( | { (mode !== 'browse') ? null : ( | ||||
| <WBTabs tabs={ [ | <WBTabs tabs={ [ | ||||
| @@ -195,7 +203,8 @@ class WBBrowse extends Component { | |||||
| renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) } | renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) } | ||||
| renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } | renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } | ||||
| renderSelectionCell={ it => this.renderSelectionCell(it) } | renderSelectionCell={ it => this.renderSelectionCell(it) } | ||||
| renderSharingButton={ it => this.renderSharingButton(it) } /> | |||||
| renderSharingButton={ it => this.renderSharingButton(it) } | |||||
| textSearch={ textSearch } /> | |||||
| ) : (objTypeTab === 'process') ? ( | ) : (objTypeTab === 'process') ? ( | ||||
| <WBProcessListing app={ app } | <WBProcessListing app={ app } | ||||
| @@ -207,7 +216,8 @@ class WBBrowse extends Component { | |||||
| renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) } | renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) } | ||||
| renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } | renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } | ||||
| renderSelectionCell={ it => this.renderSelectionCell(it) } | renderSelectionCell={ it => this.renderSelectionCell(it) } | ||||
| renderSharingButton={ it => this.renderSharingButton(it) } /> | |||||
| renderSharingButton={ it => this.renderSharingButton(it) } | |||||
| textSearch={ textSearch } /> | |||||
| ) : (objTypeTab === 'workflow') ? ( | ) : (objTypeTab === 'workflow') ? ( | ||||
| <WBWorkflowListing app={ app } | <WBWorkflowListing app={ app } | ||||
| @@ -218,7 +228,8 @@ class WBBrowse extends Component { | |||||
| renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) } | renderRenameLink={ (it, cb) => this.renderRenameLink(it, cb) } | ||||
| renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } | renderDeleteButton={ (it, cb) => this.renderDeleteButton(it, cb) } | ||||
| renderSelectionCell={ it => this.renderSelectionCell(it) } | renderSelectionCell={ it => this.renderSelectionCell(it) } | ||||
| renderSharingButton={ it => this.renderSharingButton(it) } /> | |||||
| renderSharingButton={ it => this.renderSharingButton(it) } | |||||
| textSearch={ textSearch } /> | |||||
| ) : null | ) : null | ||||
| } | } | ||||
| @@ -1,19 +1,27 @@ | |||||
| import { h, Component } from 'preact'; | import { h, Component } from 'preact'; | ||||
| import { route } from 'preact-router'; | |||||
| import WBNavbarCommon from 'wb-navbar-common'; | import WBNavbarCommon from 'wb-navbar-common'; | ||||
| import WBUserListing from 'wb-user-listing'; | import WBUserListing from 'wb-user-listing'; | ||||
| class WBUsersPage extends Component { | class WBUsersPage extends Component { | ||||
| getUrl(page) { | |||||
| return ('/users/' + page); | |||||
| getUrl(params) { | |||||
| const url = '/users/' + | |||||
| Number('page' in params ? params.page : (this.props.page || 0)) + '/' + | |||||
| encodeURIComponent('textSearch' in params ? params.textSearch : (this.props.textSearch || '')); | |||||
| return url; | |||||
| // return ('/users/' + page); | |||||
| } | } | ||||
| render({ app, page }) { | |||||
| render({ app, page, textSearch }) { | |||||
| return ( | return ( | ||||
| <div> | <div> | ||||
| <WBNavbarCommon app={ app } activeItem="all-users" /> | |||||
| <WBNavbarCommon app={ app } activeItem="all-users" | |||||
| textSearch={ textSearch } | |||||
| textSearchNavigate={ textSearch => route(this.getUrl({ textSearch, page: 0 })) } /> | |||||
| <WBUserListing app={ app } page={ Number(page || 0) } | <WBUserListing app={ app } page={ Number(page || 0) } | ||||
| getPageUrl={ page => this.getUrl(page) } /> | |||||
| textSearch={ textSearch } | |||||
| getPageUrl={ page => this.getUrl({ page }) } /> | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| } | } | ||||