[ARVADOS-WORKBENCH2] updated: 1.3.1-400-ga5cc3b71

Git user git at public.curoverse.com
Tue Mar 12 08:05:06 EDT 2019


Summary of changes:
 src/components/data-explorer/data-explorer.tsx     | 14 ++--
 src/services/api/filter-builder.test.ts            |  8 +++
 src/services/api/filter-builder.ts                 |  7 ++
 src/store/search-bar/search-bar-actions.ts         | 39 ++++++++++-
 .../search-results-middleware-service.ts           | 76 +++++++++-------------
 .../search-results-panel-view.tsx                  |  3 +-
 6 files changed, 92 insertions(+), 55 deletions(-)

       via  a5cc3b71b39f304f15c03b175e541b5adf4541f7 (commit)
       via  29059cd958303cc1a984231155547746a98c3ef3 (commit)
       via  ea0fe5f2c5ff25dd7fcac9edf970e04a653f90ef (commit)
       via  fb09f3b8554460f678b32bfa76c409feccd9c2c3 (commit)
       via  f6af447a642cf3c9692f0ffda156321201d7471c (commit)
       via  f903d0b6f04bade95c139a9c64a1327eee1aae2b (commit)
      from  1e5181ff623fd92942bc7bbaf5110e38dd7fdd9e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit a5cc3b71b39f304f15c03b175e541b5adf4541f7
Merge: 1e5181ff 29059cd9
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Tue Mar 12 13:04:48 2019 +0100

    Merge branch '14917-searching-by-properties'
    
    refs #14917
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>


commit 29059cd958303cc1a984231155547746a98c3ef3
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Tue Mar 12 12:49:45 2019 +0100

    Hide search-input in search-results-panel
    
    Feature #14917
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --git a/src/views/search-results-panel/search-results-panel-view.tsx b/src/views/search-results-panel/search-results-panel-view.tsx
index b0037a41..368a0d64 100644
--- a/src/views/search-results-panel/search-results-panel-view.tsx
+++ b/src/views/search-results-panel/search-results-panel-view.tsx
@@ -117,5 +117,6 @@ export const SearchResultsPanelView = (props: SearchResultsPanelProps) => {
         onRowClick={props.onItemClick}
         onRowDoubleClick={props.onItemDoubleClick}
         onContextMenu={props.onContextMenu}
-        contextMenuColumn={true} />;
+        contextMenuColumn={true}
+        hideSearchInput />;
 };

commit ea0fe5f2c5ff25dd7fcac9edf970e04a653f90ef
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Tue Mar 12 12:49:21 2019 +0100

    Fix data-explorer layout when search input is hidden
    
    Feature #14917
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --git a/src/components/data-explorer/data-explorer.tsx b/src/components/data-explorer/data-explorer.tsx
index 2e3e1a34..7c1f9045 100644
--- a/src/components/data-explorer/data-explorer.tsx
+++ b/src/components/data-explorer/data-explorer.tsx
@@ -89,11 +89,11 @@ export const DataExplorer = withStyles(styles)(
             return <Paper className={classes.root} {...paperProps} key={paperKey}>
                 {(!hideColumnSelector || !hideSearchInput) && <Toolbar className={classes.toolbar}>
                     <Grid container justify="space-between" wrap="nowrap" alignItems="center">
-                        {!hideSearchInput && <div className={classes.searchBox}>
-                            <SearchInput
+                        <div className={classes.searchBox}>
+                            {!hideSearchInput && <SearchInput
                                 value={searchValue}
-                                onSearch={onSearch} />
-                        </div>}
+                                onSearch={onSearch} />}
+                        </div>
                         {actions}
                         {!hideColumnSelector && <ColumnSelector
                             columns={columns}
@@ -110,8 +110,8 @@ export const DataExplorer = withStyles(styles)(
                     onSortToggle={onSortToggle}
                     extractKey={extractKey}
                     working={working}
-                    defaultView={dataTableDefaultView} 
-                    currentItemUuid={currentItemUuid} 
+                    defaultView={dataTableDefaultView}
+                    currentItemUuid={currentItemUuid}
                     currentRoute={paperKey} />
                 <Toolbar className={classes.footer}>
                     <Grid container justify="flex-end">
@@ -126,7 +126,7 @@ export const DataExplorer = withStyles(styles)(
                                 variant="text"
                                 size="medium"
                                 onClick={this.loadMore}
-                                >Load more</Button>}
+                            >Load more</Button>}
                     </Grid>
                 </Toolbar>
             </Paper>;

commit fb09f3b8554460f678b32bfa76c409feccd9c2c3
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Tue Mar 12 12:45:14 2019 +0100

    Update search implementations to use searchQueryToFilters instead of getFilters
    
    Feature #14917
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --git a/src/store/search-bar/search-bar-actions.ts b/src/store/search-bar/search-bar-actions.ts
index 9bb75750..b2b19a48 100644
--- a/src/store/search-bar/search-bar-actions.ts
+++ b/src/store/search-bar/search-bar-actions.ts
@@ -214,7 +214,7 @@ const searchGroups = (searchValue: string, limit: number) =>
             const clusterId = getSearchQueryFirstProp(sq, 'cluster');
             const sessions = getSearchSessions(clusterId, getState().auth.sessions);
             const lists: ListResults<GroupContentsResource>[] = await Promise.all(sessions.map(session => {
-                const filters = getFilters('name', searchValue, sq);
+                const filters = searchQueryToFilters(sq);
                 return services.groupsService.contents('', {
                     filters,
                     limit,
@@ -404,7 +404,7 @@ export const getSearchSessions = (clusterId: string | undefined, sessions: Sessi
 export const getFilters = (filterName: string, searchValue: string, sq: ParseSearchQuery): string => {
     const filter = new FilterBuilder();
     const isSearchQueryUuid = isResourceUuid(sq.values[0]);
-    const resourceKind = getSearchQueryFirstProp(sq, 'type') as ResourceKind; 
+    const resourceKind = getSearchQueryFirstProp(sq, 'type') as ResourceKind;
 
     let prefix = '';
     switch (resourceKind) {
diff --git a/src/store/search-results-panel/search-results-middleware-service.ts b/src/store/search-results-panel/search-results-middleware-service.ts
index efe62f23..a855dc46 100644
--- a/src/store/search-results-panel/search-results-middleware-service.ts
+++ b/src/store/search-results-panel/search-results-middleware-service.ts
@@ -16,10 +16,11 @@ import { GroupContentsResource, GroupContentsResourcePrefix } from "~/services/g
 import { ListResults } from '~/services/common-service/common-service';
 import { searchResultsPanelActions } from '~/store/search-results-panel/search-results-panel-actions';
 import {
-    getFilters,
     getSearchQueryFirstProp,
     getSearchSessions, ParseSearchQuery,
-    parseSearchQuery
+    parseSearchQuery,
+    searchQueryToFilters,
+    getSearchQueryPropValue
 } from '~/store/search-bar/search-bar-actions';
 import { getSortColumn } from "~/store/data-explorer/data-explorer-reducer";
 import { joinFilters } from '~/services/api/filter-builder';
@@ -27,6 +28,7 @@ import { DataColumns } from '~/components/data-table/data-table';
 import { serializeResourceTypeFilters } from '~/store//resource-type-filters/resource-type-filters';
 import { ProjectPanelColumnNames } from '~/views/project-panel/project-panel';
 import * as _ from 'lodash';
+import { Resource } from '~/models/resource';
 
 export class SearchResultsMiddlewareService extends DataExplorerMiddlewareService {
     constructor(private services: ServiceRepository, id: string) {
@@ -35,7 +37,6 @@ export class SearchResultsMiddlewareService extends DataExplorerMiddlewareServic
 
     async requestItems(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean) {
         const state = api.getState();
-        const userUuid = state.auth.user!.uuid;
         const dataExplorer = getDataExplorer(state.dataExplorer, this.getId());
         const searchValue = state.searchBar.searchValue;
         const sq = parseSearchQuery(searchValue);
@@ -47,46 +48,31 @@ export class SearchResultsMiddlewareService extends DataExplorerMiddlewareServic
         }
 
         try {
-            const nameParams = getParams(dataExplorer, searchValue, sq, 'name');
+            const params = getParams(dataExplorer, sq);
 
-            const nameLists: ListResults<GroupContentsResource>[] = await Promise.all(sessions.map(session =>
-                this.services.groupsService.contents('', nameParams, session)
+            const responses = await Promise.all(sessions.map(session =>
+                this.services.groupsService.contents('', params, session)
             ));
 
-            const nameItems = nameLists
-                .reduce((items, list) => items.concat(list.items), [] as GroupContentsResource[]);
-
-            const nameItemsAvailable = nameLists
-                .reduce((itemsAvailable, list) => itemsAvailable + list.itemsAvailable, 0);
-
-            const descriptionParams = getParams(dataExplorer, searchValue, sq, 'description');
-
-            const descriptionLists: ListResults<GroupContentsResource>[] = await Promise.all(sessions.map(session =>
-                this.services.groupsService.contents('', descriptionParams, session)
-            ));
-
-            const descriptionItems = descriptionLists
-                .reduce((items, list) => items.concat(list.items), [] as GroupContentsResource[]);
-
-            const descriptionItemsAvailable = descriptionLists
-                .reduce((itemsAvailable, list) => itemsAvailable + list.itemsAvailable, 0);
-
-            const items = nameItems.concat(descriptionItems);
-
-            const uniqueItems = _.uniqBy(items, 'uuid');
-
-            const mainList: ListResults<GroupContentsResource> = {
-                ...nameParams,
+            const initial = {
+                itemsAvailable: 0,
+                items: [] as GroupContentsResource[],
                 kind: '',
-                items: uniqueItems,
-                itemsAvailable: nameItemsAvailable + descriptionItemsAvailable
+                offset: 0,
+                limit: 10
             };
 
-            api.dispatch(updateResources(mainList.items));
+            const mergedResponse = responses.reduce((merged, current) => ({
+                ...merged,
+                itemsAvailable: merged.itemsAvailable + current.itemsAvailable,
+                items: merged.items.concat(current.items)
+            }), initial);
+
+            api.dispatch(updateResources(mergedResponse.items));
 
             api.dispatch(criteriaChanged
-                ? setItems(mainList)
-                : appendItems(mainList));
+                ? setItems(mergedResponse)
+                : appendItems(mergedResponse));
 
         } catch {
             api.dispatch(couldNotFetchSearchResults());
@@ -96,16 +82,17 @@ export class SearchResultsMiddlewareService extends DataExplorerMiddlewareServic
 
 const typeFilters = (columns: DataColumns<string>) => serializeResourceTypeFilters(getDataExplorerColumnFilters(columns, ProjectPanelColumnNames.TYPE));
 
-export const getParams = (dataExplorer: DataExplorer, searchValue: string, sq: ParseSearchQuery, filter: string) => ({
+export const getParams = (dataExplorer: DataExplorer, sq: ParseSearchQuery) => ({
     ...dataExplorerToListParams(dataExplorer),
     filters: joinFilters(
-        getFilters(filter, searchValue, sq),
-        typeFilters(dataExplorer.columns)),
-    order: getOrder(dataExplorer, filter),
-    includeTrash: true
+        searchQueryToFilters(sq),
+        typeFilters(dataExplorer.columns)
+    ),
+    order: getOrder(dataExplorer),
+    includeTrash: (!!getSearchQueryPropValue(sq, 'is', 'trashed')) || false
 });
 
-const getOrder = (dataExplorer: DataExplorer, orderBy: any) => {
+const getOrder = (dataExplorer: DataExplorer) => {
     const sortColumn = getSortColumn(dataExplorer);
     const order = new OrderBuilder<GroupContentsResource>();
     if (sortColumn) {
@@ -113,11 +100,10 @@ const getOrder = (dataExplorer: DataExplorer, orderBy: any) => {
             ? OrderDirection.ASC
             : OrderDirection.DESC;
 
-        const columnName = sortColumn && sortColumn.name === SearchResultsPanelColumnNames.NAME ? orderBy : "modifiedAt";
         return order
-            .addOrder(sortDirection, columnName, GroupContentsResourcePrefix.COLLECTION)
-            .addOrder(sortDirection, columnName, GroupContentsResourcePrefix.PROCESS)
-            .addOrder(sortDirection, columnName, GroupContentsResourcePrefix.PROJECT)
+            .addOrder(sortDirection, sortColumn.name as keyof Resource, GroupContentsResourcePrefix.COLLECTION)
+            .addOrder(sortDirection, sortColumn.name as keyof Resource, GroupContentsResourcePrefix.PROCESS)
+            .addOrder(sortDirection, sortColumn.name as keyof Resource, GroupContentsResourcePrefix.PROJECT)
             .getOrder();
     } else {
         return order.getOrder();

commit f6af447a642cf3c9692f0ffda156321201d7471c
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Tue Mar 12 12:44:44 2019 +0100

    Create searchQueryToFilters function
    
    Feature #14917
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --git a/src/store/search-bar/search-bar-actions.ts b/src/store/search-bar/search-bar-actions.ts
index 01a0311e..9bb75750 100644
--- a/src/store/search-bar/search-bar-actions.ts
+++ b/src/store/search-bar/search-bar-actions.ts
@@ -506,6 +506,41 @@ export const getFilters = (filterName: string, searchValue: string, sq: ParseSea
         .getFilters();
 };
 
+export const searchQueryToFilters = (sq: ParseSearchQuery): string => {
+    const filter = new FilterBuilder();
+    const resourceKind = getSearchQueryFirstProp(sq, 'type') as ResourceKind;
+
+    const projectUuid = getSearchQueryFirstProp(sq, 'project');
+    if (projectUuid) {
+        filter.addEqual('ownerUuid', projectUuid);
+    }
+
+    const dateFrom = getSearchQueryFirstProp(sq, 'from');
+    if (dateFrom) {
+        filter.addGte('modified_at', buildDateFilter(dateFrom));
+    }
+
+    const dateTo = getSearchQueryFirstProp(sq, 'to');
+    if (dateTo) {
+        filter.addLte('modified_at', buildDateFilter(dateTo));
+    }
+
+    const props = getSearchQueryProperties(sq);
+    props.forEach(p => {
+        if (p.value) {
+            filter
+                .addILike(`properties.${p.key}`, p.value, GroupContentsResourcePrefix.PROJECT)
+                .addILike(`properties.${p.key}`, p.value, GroupContentsResourcePrefix.COLLECTION);
+        }
+        filter.addExists(p.key);
+    });
+
+    return filter
+        .addIsA("uuid", buildUuidFilter(resourceKind))
+        .addFullTextSearch(sq.values.join(' '))
+        .getFilters();
+};
+
 const buildUuidFilter = (type?: ResourceKind): ResourceKind[] => {
     return type ? [type] : [ResourceKind.PROJECT, ResourceKind.COLLECTION, ResourceKind.PROCESS];
 };

commit f903d0b6f04bade95c139a9c64a1327eee1aae2b
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Tue Mar 12 10:54:06 2019 +0100

    Create addFullTextSearch of FilterBuilder
    
    Feature #14917
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --git a/src/services/api/filter-builder.test.ts b/src/services/api/filter-builder.test.ts
index 2ddd6bf0..d9b76b1e 100644
--- a/src/services/api/filter-builder.test.ts
+++ b/src/services/api/filter-builder.test.ts
@@ -81,4 +81,12 @@ describe("FilterBuilder", () => {
             .getFilters())
             .toEqual(`["myPrefix.etag","in",["etagValue1","etagValue2"]]`);
     });
+
+    it('should add full text search', () => {
+        expect(
+            new FilterBuilder()
+                .addFullTextSearch('my custom search')
+                .getFilters()
+        ).toEqual(`["any","@@","my:*&custom:*&search"]`);
+    });
 });
diff --git a/src/services/api/filter-builder.ts b/src/services/api/filter-builder.ts
index 4b3db9fa..e8992341 100644
--- a/src/services/api/filter-builder.ts
+++ b/src/services/api/filter-builder.ts
@@ -55,6 +55,13 @@ export class FilterBuilder {
         return this.addCondition("properties", "exists", value, "", "", resourcePrefix);
     }
 
+    public addFullTextSearch(value: string) {
+        // Filter construction implementation taken from 
+        // https://dev.arvados.org/projects/arvados/repository/entry/apps/workbench/app/assets/javascripts/filterable.js
+        // https://dev.arvados.org/projects/arvados/repository/entry/apps/workbench/app/assets/javascripts/to_tsquery.js
+        return this.addCondition('any', '@@', value.replace(/[^-\w\.\/]+/g, ' ').trim().replace(/ /g, ':*&'));
+    }
+
     public getFilters() {
         return this.filters;
     }

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list