From: Daniel Kos Date: Mon, 12 Nov 2018 23:43:47 +0000 (+0100) Subject: Update redux form types, make getFilters keywords aware X-Git-Tag: 1.4.0~95^2~14 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/34399d176adae18bd42d70129c0a51f740afeb8e Update redux form types, make getFilters keywords aware Arvados-DCO-1.1-Signed-off-by: Daniel Kos --- diff --git a/package.json b/package.json index 89458046..90fca4f2 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@types/react-dnd": "3.0.2", "@types/react-dropzone": "4.2.2", "@types/react-highlight-words": "0.12.0", - "@types/redux-form": "7.4.5", + "@types/redux-form": "7.4.12", "@types/reselect": "2.2.0", "@types/shell-quote": "1.6.0", "axios": "0.18.0", @@ -48,6 +48,7 @@ "start": "react-scripts-ts start", "build": "REACT_APP_BUILD_NUMBER=$BUILD_NUMBER REACT_APP_GIT_COMMIT=$GIT_COMMIT react-scripts-ts build", "test": "CI=true react-scripts-ts test --env=jsdom", + "test:watch": "react-scripts-ts test --env=jsdom", "eject": "react-scripts-ts eject", "lint": "tslint src/** -t verbose", "build-css": "node-sass-chokidar src/ -o src/", diff --git a/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts b/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts index e441959c..e25f0713 100644 --- a/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts +++ b/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts @@ -11,7 +11,7 @@ import { snackbarActions } from "../../snackbar/snackbar-actions"; import { dialogActions } from '../../dialog/dialog-actions'; import { getNodeValue } from "~/models/tree"; import { filterCollectionFilesBySelection } from './collection-panel-files-state'; -import { startSubmit, stopSubmit, reset, initialize } from 'redux-form'; +import { startSubmit, stopSubmit, reset, initialize, FormErrors } from 'redux-form'; import { getDialog } from "~/store/dialog/dialog-reducer"; import { getFileFullPath } from "~/services/collection-service/collection-service-files-response"; import { resourcesDataActions } from "~/store/resources-data/resources-data-actions"; @@ -116,7 +116,10 @@ export const renameFile = (newName: string) => dispatch(dialogActions.CLOSE_DIALOG({ id: RENAME_FILE_DIALOG })); dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'File name changed.', hideDuration: 2000 })); } catch (e) { - dispatch(stopSubmit(RENAME_FILE_DIALOG, { name: 'Could not rename the file' })); + const errors: FormErrors = { + name: 'Could not rename the file' + }; + dispatch(stopSubmit(RENAME_FILE_DIALOG, errors)); } } } diff --git a/src/store/collections/collection-copy-actions.ts b/src/store/collections/collection-copy-actions.ts index d0387609..3afda604 100644 --- a/src/store/collections/collection-copy-actions.ts +++ b/src/store/collections/collection-copy-actions.ts @@ -4,7 +4,7 @@ import { Dispatch } from "redux"; import { dialogActions } from "~/store/dialog/dialog-actions"; -import { initialize, startSubmit, stopSubmit } from 'redux-form'; +import { FormErrors, initialize, startSubmit, stopSubmit } from 'redux-form'; import { resetPickerProjectTree } from '~/store/project-tree-picker/project-tree-picker-actions'; import { RootState } from '~/store/store'; import { ServiceRepository } from '~/services/services'; @@ -37,7 +37,10 @@ export const copyCollection = (resource: CopyFormDialogData) => } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(COLLECTION_COPY_FORM_NAME, { ownerUuid: 'A collection with the same name already exists in the target project.' })); + dispatch(stopSubmit( + COLLECTION_COPY_FORM_NAME, + { ownerUuid: 'A collection with the same name already exists in the target project.' } as FormErrors + )); } else { dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_COPY_FORM_NAME })); throw new Error('Could not copy the collection.'); diff --git a/src/store/collections/collection-create-actions.ts b/src/store/collections/collection-create-actions.ts index b05945c1..c61e8da2 100644 --- a/src/store/collections/collection-create-actions.ts +++ b/src/store/collections/collection-create-actions.ts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0 import { Dispatch } from "redux"; -import { reset, startSubmit, stopSubmit, initialize } from 'redux-form'; +import { reset, startSubmit, stopSubmit, initialize, FormErrors } from 'redux-form'; import { RootState } from '~/store/store'; import { dialogActions } from "~/store/dialog/dialog-actions"; import { ServiceRepository } from '~/services/services'; @@ -49,7 +49,7 @@ export const createCollection = (data: CollectionCreateFormDialogData) => } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(COLLECTION_CREATE_FORM_NAME, { name: 'Collection with the same name already exists.' })); + dispatch(stopSubmit(COLLECTION_CREATE_FORM_NAME, { name: 'Collection with the same name already exists.' } as FormErrors)); } dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_CREATE_FORM_NAME)); return; diff --git a/src/store/collections/collection-move-actions.ts b/src/store/collections/collection-move-actions.ts index 54508e13..d767efee 100644 --- a/src/store/collections/collection-move-actions.ts +++ b/src/store/collections/collection-move-actions.ts @@ -4,7 +4,7 @@ import { Dispatch } from "redux"; import { dialogActions } from "~/store/dialog/dialog-actions"; -import { startSubmit, stopSubmit, initialize } from 'redux-form'; +import { startSubmit, stopSubmit, initialize, FormErrors } from 'redux-form'; import { ServiceRepository } from '~/services/services'; import { RootState } from '~/store/store'; import { getCommonResourceServiceError, CommonResourceServiceError } from "~/services/common-service/common-resource-service"; @@ -37,7 +37,7 @@ export const moveCollection = (resource: MoveToFormDialogData) => } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(COLLECTION_MOVE_FORM_NAME, { ownerUuid: 'A collection with the same name already exists in the target project.' })); + dispatch(stopSubmit(COLLECTION_MOVE_FORM_NAME, { ownerUuid: 'A collection with the same name already exists in the target project.' } as FormErrors)); } else { dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_MOVE_FORM_NAME })); dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not move the collection.', hideDuration: 2000 })); diff --git a/src/store/collections/collection-partial-copy-actions.ts b/src/store/collections/collection-partial-copy-actions.ts index 4dac9c7d..b4b22e26 100644 --- a/src/store/collections/collection-partial-copy-actions.ts +++ b/src/store/collections/collection-partial-copy-actions.ts @@ -4,7 +4,7 @@ import { Dispatch } from 'redux'; import { RootState } from '~/store/store'; -import { initialize, startSubmit, stopSubmit } from 'redux-form'; +import { FormErrors, initialize, startSubmit, stopSubmit } from 'redux-form'; import { resetPickerProjectTree } from '~/store/project-tree-picker/project-tree-picker-actions'; import { dialogActions } from '~/store/dialog/dialog-actions'; import { ServiceRepository } from '~/services/services'; @@ -65,7 +65,7 @@ export const copyCollectionPartial = ({ name, description, projectUuid }: Collec } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(COLLECTION_PARTIAL_COPY_FORM_NAME, { name: 'Collection with this name already exists.' })); + dispatch(stopSubmit(COLLECTION_PARTIAL_COPY_FORM_NAME, { name: 'Collection with this name already exists.' } as FormErrors)); } else if (error === CommonResourceServiceError.UNKNOWN) { dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_COPY_FORM_NAME })); dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not create a copy of collection', hideDuration: 2000 })); diff --git a/src/store/collections/collection-update-actions.ts b/src/store/collections/collection-update-actions.ts index 9c859234..02ec8bb5 100644 --- a/src/store/collections/collection-update-actions.ts +++ b/src/store/collections/collection-update-actions.ts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0 import { Dispatch } from "redux"; -import { initialize, startSubmit, stopSubmit } from 'redux-form'; +import { FormErrors, initialize, startSubmit, stopSubmit } from 'redux-form'; import { RootState } from "~/store/store"; import { collectionPanelActions } from "~/store/collection-panel/collection-panel-action"; import { dialogActions } from "~/store/dialog/dialog-actions"; @@ -41,7 +41,7 @@ export const updateCollection = (collection: Partial) => } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(COLLECTION_UPDATE_FORM_NAME, { name: 'Collection with the same name already exists.' })); + dispatch(stopSubmit(COLLECTION_UPDATE_FORM_NAME, { name: 'Collection with the same name already exists.' } as FormErrors)); } dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_UPDATE_FORM_NAME)); return; diff --git a/src/store/processes/process-move-actions.ts b/src/store/processes/process-move-actions.ts index 6df82699..89dc0efe 100644 --- a/src/store/processes/process-move-actions.ts +++ b/src/store/processes/process-move-actions.ts @@ -4,7 +4,7 @@ import { Dispatch } from "redux"; import { dialogActions } from "~/store/dialog/dialog-actions"; -import { startSubmit, stopSubmit, initialize } from 'redux-form'; +import { startSubmit, stopSubmit, initialize, FormErrors } from 'redux-form'; import { ServiceRepository } from '~/services/services'; import { RootState } from '~/store/store'; import { getCommonResourceServiceError, CommonResourceServiceError } from "~/services/common-service/common-resource-service"; @@ -45,13 +45,13 @@ export const moveProcess = (resource: MoveToFormDialogData) => } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(PROCESS_MOVE_FORM_NAME, { ownerUuid: 'A process with the same name already exists in the target project.' })); + dispatch(stopSubmit(PROCESS_MOVE_FORM_NAME, { ownerUuid: 'A process with the same name already exists in the target project.' } as FormErrors)); } else if (error === CommonResourceServiceError.MODIFYING_CONTAINER_REQUEST_FINAL_STATE) { - dispatch(stopSubmit(PROCESS_MOVE_FORM_NAME, { ownerUuid: 'You can move only draft processes.' })); + dispatch(stopSubmit(PROCESS_MOVE_FORM_NAME, { ownerUuid: 'You can move only draft processes.' } as FormErrors)); } else { dispatch(dialogActions.CLOSE_DIALOG({ id: PROCESS_MOVE_FORM_NAME })); dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not move the process.', hideDuration: 2000 })); } return; } - }; \ No newline at end of file + }; diff --git a/src/store/processes/process-update-actions.ts b/src/store/processes/process-update-actions.ts index 92cf032f..dfd548b0 100644 --- a/src/store/processes/process-update-actions.ts +++ b/src/store/processes/process-update-actions.ts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0 import { Dispatch } from "redux"; -import { initialize, startSubmit, stopSubmit } from 'redux-form'; +import { FormErrors, initialize, startSubmit, stopSubmit } from 'redux-form'; import { RootState } from "~/store/store"; import { dialogActions } from "~/store/dialog/dialog-actions"; import { getCommonResourceServiceError, CommonResourceServiceError } from "~/services/common-service/common-resource-service"; @@ -42,13 +42,13 @@ export const updateProcess = (resource: ProcessUpdateFormDialogData) => } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(PROCESS_UPDATE_FORM_NAME, { name: 'Process with the same name already exists.' })); + dispatch(stopSubmit(PROCESS_UPDATE_FORM_NAME, { name: 'Process with the same name already exists.' } as FormErrors)); } else if (error === CommonResourceServiceError.MODIFYING_CONTAINER_REQUEST_FINAL_STATE) { - dispatch(stopSubmit(PROCESS_UPDATE_FORM_NAME, { name: 'You cannot modified in "Final" state.' })); + dispatch(stopSubmit(PROCESS_UPDATE_FORM_NAME, { name: 'You cannot modified in "Final" state.' } as FormErrors)); } else { dispatch(dialogActions.CLOSE_DIALOG({ id: PROCESS_UPDATE_FORM_NAME })); dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not update the process.', hideDuration: 2000 })); } return; } - }; \ No newline at end of file + }; diff --git a/src/store/projects/project-create-actions.ts b/src/store/projects/project-create-actions.ts index 1fd1be0c..d226048b 100644 --- a/src/store/projects/project-create-actions.ts +++ b/src/store/projects/project-create-actions.ts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0 import { Dispatch } from "redux"; -import { reset, startSubmit, stopSubmit, initialize } from 'redux-form'; +import { reset, startSubmit, stopSubmit, initialize, FormErrors } from 'redux-form'; import { RootState } from '~/store/store'; import { dialogActions } from "~/store/dialog/dialog-actions"; import { getCommonResourceServiceError, CommonResourceServiceError } from '~/services/common-service/common-resource-service'; @@ -43,7 +43,7 @@ export const openProjectCreateDialog = (ownerUuid: string) => dispatch(initialize(PROJECT_CREATE_FORM_NAME, { userUuid })); } else { dispatch(initialize(PROJECT_CREATE_FORM_NAME, { ownerUuid })); - } + } dispatch(dialogActions.OPEN_DIALOG({ id: PROJECT_CREATE_FORM_NAME, data: {} })); }; @@ -58,7 +58,7 @@ export const createProject = (project: Partial) => } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(PROJECT_CREATE_FORM_NAME, { name: 'Project with the same name already exists.' })); + dispatch(stopSubmit(PROJECT_CREATE_FORM_NAME, { name: 'Project with the same name already exists.' } as FormErrors)); } return undefined; } diff --git a/src/store/projects/project-move-actions.ts b/src/store/projects/project-move-actions.ts index c251bdf8..1e8aff5c 100644 --- a/src/store/projects/project-move-actions.ts +++ b/src/store/projects/project-move-actions.ts @@ -4,7 +4,7 @@ import { Dispatch } from "redux"; import { dialogActions } from "~/store/dialog/dialog-actions"; -import { startSubmit, stopSubmit, initialize } from 'redux-form'; +import { startSubmit, stopSubmit, initialize, FormErrors } from 'redux-form'; import { ServiceRepository } from '~/services/services'; import { RootState } from '~/store/store'; import { getCommonResourceServiceError, CommonResourceServiceError } from "~/services/common-service/common-resource-service"; @@ -31,9 +31,9 @@ export const moveProject = (resource: MoveToFormDialogData) => } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: 'A project with the same name already exists in the target project.' })); + dispatch(stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: 'A project with the same name already exists in the target project.' } as FormErrors)); } else if (error === CommonResourceServiceError.OWNERSHIP_CYCLE) { - dispatch(stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: 'Cannot move a project into itself.' })); + dispatch(stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: 'Cannot move a project into itself.' } as FormErrors)); } else { dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_MOVE_FORM_NAME })); throw new Error('Could not move the project.'); diff --git a/src/store/projects/project-update-actions.ts b/src/store/projects/project-update-actions.ts index 34ea42f5..321b8554 100644 --- a/src/store/projects/project-update-actions.ts +++ b/src/store/projects/project-update-actions.ts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0 import { Dispatch } from "redux"; -import { initialize, startSubmit, stopSubmit } from 'redux-form'; +import { FormErrors, initialize, startSubmit, stopSubmit } from 'redux-form'; import { RootState } from "~/store/store"; import { dialogActions } from "~/store/dialog/dialog-actions"; import { getCommonResourceServiceError, CommonResourceServiceError } from "~/services/common-service/common-resource-service"; @@ -38,7 +38,7 @@ export const updateProject = (project: Partial) => } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(PROJECT_UPDATE_FORM_NAME, { name: 'Project with the same name already exists.' })); + dispatch(stopSubmit(PROJECT_UPDATE_FORM_NAME, { name: 'Project with the same name already exists.' } as FormErrors)); } return ; } diff --git a/src/store/search-bar/search-bar-actions.test.ts b/src/store/search-bar/search-bar-actions.test.ts new file mode 100644 index 00000000..30b05157 --- /dev/null +++ b/src/store/search-bar/search-bar-actions.test.ts @@ -0,0 +1,48 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { parseQuery } from "~/store/search-bar/search-bar-actions"; + +describe('search-bar-actions', () => { + it('should correctly parse query #1', () => { + const q = 'val0 is:trashed val1'; + const r = parseQuery(q); + expect(r.hasKeywords).toBeTruthy(); + expect(r.values).toEqual(['val0', 'val1']); + expect(r.properties).toEqual({ + is: 'trashed' + }); + }); + + it('should correctly parse query #2 (value with keyword should be ignored)', () => { + const q = 'val0 is:from:trashed val1'; + const r = parseQuery(q); + expect(r.hasKeywords).toBeTruthy(); + expect(r.values).toEqual(['val0', 'val1']); + expect(r.properties).toEqual({ + from: 'trashed' + }); + }); + + it('should correctly parse query #3 (many keywords)', () => { + const q = 'val0 is:trashed val2 from:2017-04-01 val1'; + const r = parseQuery(q); + expect(r.hasKeywords).toBeTruthy(); + expect(r.values).toEqual(['val0', 'val2', 'val1']); + expect(r.properties).toEqual({ + is: 'trashed', + from: '2017-04-01' + }); + }); + + it('should correctly parse query #4 (no duplicated values)', () => { + const q = 'val0 is:trashed val2 val2 val0'; + const r = parseQuery(q); + expect(r.hasKeywords).toBeTruthy(); + expect(r.values).toEqual(['val0', 'val2']); + expect(r.properties).toEqual({ + is: 'trashed' + }); + }); +}); diff --git a/src/store/search-bar/search-bar-actions.ts b/src/store/search-bar/search-bar-actions.ts index 165392c6..c4fb727d 100644 --- a/src/store/search-bar/search-bar-actions.ts +++ b/src/store/search-bar/search-bar-actions.ts @@ -16,8 +16,9 @@ import { SearchView } from '~/store/search-bar/search-bar-reducer'; import { navigateToSearchResults, navigateTo } from '~/store/navigation/navigation-action'; import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions'; import { initialize } from 'redux-form'; -import { SearchBarAdvanceFormData, PropertyValues } from '~/models/search-bar'; +import { SearchBarAdvanceFormData, PropertyValues, ClusterObjectType } from '~/models/search-bar'; import { debounce } from 'debounce'; +import * as _ from "lodash"; export const searchBarActions = unionize({ SET_CURRENT_VIEW: ofType(), @@ -61,7 +62,7 @@ export const searchData = (searchValue: string) => const currentView = getState().searchBar.currentView; dispatch(searchBarActions.SET_SEARCH_VALUE(searchValue)); if (searchValue.length > 0) { - dispatch(searchGroups(searchValue, 5, {})); + dispatch(searchGroups(searchValue, 5)); if (currentView === SearchView.BASIC) { dispatch(searchBarActions.CLOSE_SEARCH_VIEW()); dispatch(navigateToSearchResults); @@ -77,6 +78,31 @@ export const searchAdvanceData = (data: SearchBarAdvanceFormData) => dispatch(navigateToSearchResults); }; +export const setSearchValueFromAdvancedData = (data: SearchBarAdvanceFormData, prevData: SearchBarAdvanceFormData) => + (dispatch: Dispatch) => { + let value = ''; + if (data.type) { + value += ` type:${data.type}`; + } + if (data.cluster) { + value += ` cluster:${data.cluster}`; + } + if (data.projectUuid) { + value += ` project:${data.projectUuid}`; + } + if (data.inTrash) { + value += ` is:trashed`; + } + if (data.dateFrom) { + value += ` from:${data.dateFrom}`; + } + if (data.dateTo) { + value += ` from:${data.dateTo}`; + } + value = value.substr(1) + data.searchQuery; + dispatch(searchBarActions.SET_SEARCH_VALUE(value)); + }; + const saveQuery = (data: SearchBarAdvanceFormData) => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { const savedQueries = services.searchService.getSavedQueries(); @@ -176,12 +202,12 @@ const startSearch = () => dispatch(searchData(searchValue)); }; -const searchGroups = (searchValue: string, limit: number, {...props}) => +const searchGroups = (searchValue: string, limit: number) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { const currentView = getState().searchBar.currentView; if (searchValue || currentView === SearchView.ADVANCED) { - const filters = getFilters('name', searchValue, props); + const filters = getFilters('name', searchValue); const { items } = await services.groupsService.contents('', { filters, limit, @@ -191,15 +217,118 @@ const searchGroups = (searchValue: string, limit: number, {...props}) => } }; -export const getFilters = (filterName: string, searchValue: string, props: any): string => { - const { resourceKind, dateTo, dateFrom } = props; - return new FilterBuilder() - .addIsA("uuid", buildUuidFilter(resourceKind)) - .addILike(filterName, searchValue, GroupContentsResourcePrefix.COLLECTION) - .addILike(filterName, searchValue, GroupContentsResourcePrefix.PROCESS) - .addILike(filterName, searchValue, GroupContentsResourcePrefix.PROJECT) - .addLte('modified_at', buildDateFilter(dateTo)) - .addGte('modified_at', buildDateFilter(dateFrom)) +export const parseQuery: (searchValue: string) => { hasKeywords: boolean; values: string[]; properties: any } = (searchValue: string) => { + const keywords = [ + 'type:', + 'cluster:', + 'project:', + 'is:', + 'from:', + 'to:' + ]; + + const hasKeywords = (search: string) => keywords.reduce((acc, keyword) => acc + search.indexOf(keyword) >= 0 ? 1 : 0, 0); + let keywordsCnt = 0; + + const properties = {}; + + keywords.forEach(k => { + const p = searchValue.indexOf(k); + const l = searchValue.length; + if (p >= 0) { + keywordsCnt += 1; + + let v = ''; + let i = p + k.length; + while (i < l && searchValue[i] === ' ') { + ++i; + } + const vp = i; + while (i < l && searchValue[i] !== ' ') { + v += searchValue[i]; + ++i; + } + + if (hasKeywords(v)) { + searchValue = searchValue.substr(0, p) + searchValue.substr(vp); + } else { + if (v !== '') { + properties[k.substr(0, k.length - 1)] = v; + } + searchValue = searchValue.substr(0, p) + searchValue.substr(i); + } + } + }); + + const values = _.uniq(searchValue.split(' ').filter(v => v.length > 0)); + + return { hasKeywords: keywordsCnt > 0, values, properties }; +}; + +export const getFilters = (filterName: string, searchValue: string): string => { + const filter = new FilterBuilder(); + + const pq = parseQuery(searchValue); + + if (!pq.hasKeywords) { + filter + .addILike(filterName, searchValue, GroupContentsResourcePrefix.COLLECTION) + .addILike(filterName, searchValue, GroupContentsResourcePrefix.PROCESS) + .addILike(filterName, searchValue, GroupContentsResourcePrefix.PROJECT); + } else { + + if (pq.properties.type) { + pq.values.forEach(v => { + let prefix = ''; + switch (ResourceKind[pq.properties.type]) { + case ResourceKind.PROJECT: + prefix = GroupContentsResourcePrefix.PROJECT; + break; + case ResourceKind.COLLECTION: + prefix = GroupContentsResourcePrefix.COLLECTION; + break; + case ResourceKind.PROCESS: + prefix = GroupContentsResourcePrefix.PROCESS; + break; + } + if (prefix !== '') { + filter.addILike(filterName, v, prefix); + } + }); + } else { + pq.values.forEach(v => { + filter + .addILike(filterName, v, GroupContentsResourcePrefix.COLLECTION) + .addILike(filterName, v, GroupContentsResourcePrefix.PROCESS) + .addILike(filterName, v, GroupContentsResourcePrefix.PROJECT); + }); + } + + if (pq.properties.is && pq.properties.is === 'trashed') { + } + + if (pq.properties.project) { + filter.addEqual('owner_uuid', pq.properties.project, GroupContentsResourcePrefix.PROJECT); + } + + if (pq.properties.from) { + filter.addGte('modified_at', buildDateFilter(pq.properties.from)); + } + + if (pq.properties.to) { + filter.addLte('modified_at', buildDateFilter(pq.properties.to)); + } + // filter + // .addIsA("uuid", buildUuidFilter(resourceKind)) + // .addILike(filterName, searchValue, GroupContentsResourcePrefix.COLLECTION) + // .addILike(filterName, searchValue, GroupContentsResourcePrefix.PROCESS) + // .addILike(filterName, searchValue, GroupContentsResourcePrefix.PROJECT) + // .addLte('modified_at', buildDateFilter(dateTo)) + // .addGte('modified_at', buildDateFilter(dateFrom)) + // .addEqual('groupClass', GroupClass.PROJECT, GroupContentsResourcePrefix.PROJECT) + } + + return filter .addEqual('groupClass', GroupClass.PROJECT, GroupContentsResourcePrefix.PROJECT) .getFilters(); }; 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 e8097e98..38067653 100644 --- a/src/store/search-results-panel/search-results-middleware-service.ts +++ b/src/store/search-results-panel/search-results-middleware-service.ts @@ -39,7 +39,7 @@ export class SearchResultsMiddlewareService extends DataExplorerMiddlewareServic export const getParams = (dataExplorer: DataExplorer, searchValue: string) => ({ ...dataExplorerToListParams(dataExplorer), - filters: getFilters('name', searchValue, {}), + filters: getFilters('name', searchValue), order: getOrder(dataExplorer) }); diff --git a/src/views-components/search-bar/search-bar-advanced-view.tsx b/src/views-components/search-bar/search-bar-advanced-view.tsx index c7573501..66ef6512 100644 --- a/src/views-components/search-bar/search-bar-advanced-view.tsx +++ b/src/views-components/search-bar/search-bar-advanced-view.tsx @@ -6,7 +6,11 @@ import * as React from 'react'; import { reduxForm, InjectedFormProps, reset } from 'redux-form'; import { compose, Dispatch } from 'redux'; import { Paper, StyleRulesCallback, withStyles, WithStyles, Button, Grid, IconButton, CircularProgress } from '@material-ui/core'; -import { SEARCH_BAR_ADVANCE_FORM_NAME, searchAdvanceData } from '~/store/search-bar/search-bar-actions'; +import { + SEARCH_BAR_ADVANCE_FORM_NAME, + searchAdvanceData, + setSearchValueFromAdvancedData +} from '~/store/search-bar/search-bar-actions'; import { ArvadosTheme } from '~/common/custom-theme'; import { CloseIcon } from '~/components/icon/icon'; import { SearchBarAdvanceFormData } from '~/models/search-bar'; @@ -99,6 +103,9 @@ export const SearchBarAdvancedView = compose( onSubmit: (data: SearchBarAdvanceFormData, dispatch: Dispatch) => { dispatch(searchAdvanceData(data)); dispatch(reset(SEARCH_BAR_ADVANCE_FORM_NAME)); + }, + onChange: (data: SearchBarAdvanceFormData, dispatch: Dispatch, props: any, prevData: SearchBarAdvanceFormData) => { + dispatch(setSearchValueFromAdvancedData(data, prevData)); } }), withStyles(styles))( diff --git a/src/views-components/search-bar/search-bar-basic-view.tsx b/src/views-components/search-bar/search-bar-basic-view.tsx index 76d46b36..f62e146d 100644 --- a/src/views-components/search-bar/search-bar-basic-view.tsx +++ b/src/views-components/search-bar/search-bar-basic-view.tsx @@ -32,10 +32,12 @@ const styles: StyleRulesCallback = theme => { color: theme.palette.primary.main }, label: { - fontSize: '0.875rem', + fontSize: '0.775rem', padding: `${theme.spacing.unit}px ${theme.spacing.unit}px `, color: theme.palette.grey["900"], - background: theme.palette.grey["200"] + background: 'white', + textAlign: 'right', + fontWeight: 'bold' } }; }; @@ -52,12 +54,12 @@ type SearchBarBasicViewProps = SearchBarBasicViewDataProps & SearchBarBasicViewA export const SearchBarBasicView = withStyles(styles)( ({ classes, onSetView, loadRecentQueries, deleteSavedQuery, savedQueries, onSearch, editSavedQuery, selectedItem }: SearchBarBasicViewProps) => -
Recent search queries
+
{"Recent queries"}
-
Saved search queries
+
{"Saved queries"}
= theme => ({ } }); const PermissionManagementRow = withStyles(permissionManagementRowStyles)( - ({ field, index, fields, classes }: { field: string, index: number, fields: FieldsProps<{ email: string }> } & WithStyles<'root'>) => + ({ field, index, fields, classes }: { field: string, index: number, fields: FieldArrayFieldsProps<{ email: string }> } & WithStyles<'root'>) => <> diff --git a/yarn.lock b/yarn.lock index 1eaa15f8..e4d50aae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -252,10 +252,10 @@ "@types/react" "*" redux "^3.6.0" -"@types/redux-form@7.4.5": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@types/redux-form/-/redux-form-7.4.5.tgz#fae0fa6cfbc613867093d1e0f6a84db17177305e" - integrity sha512-PY74tuDamNhStB+87TQJXAKoa7uf5Ue/MJvnIrQowgjyRUo2Ky/THUfDec9U7IKRGzLnX7vWVTsoN1EvLnwAEQ== +"@types/redux-form@7.4.12": + version "7.4.12" + resolved "https://registry.yarnpkg.com/@types/redux-form/-/redux-form-7.4.12.tgz#2afb0615e3b7417d460ab14a4802ede4a98f9c79" + integrity sha512-qHRkJcgdc5MntQHrkYCg5o6oySh+OdVKA90yELTdi9XlNvSGRxd6K230aTckVrwdUjdxtwZ31UqFgLoU5SiWYQ== dependencies: "@types/react" "*" redux "^3.6.0 || ^4.0.0"