@@ -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> | ||||
); | ); | ||||
} | } | ||||