return undefined;
}
};
- }
+
+export const getResourceKind = (kind?: string) => {
+ switch (kind) {
+ case "arvados#collection":
+ return ResourceKind.COLLECTION;
+ case "arvados#container":
+ return ResourceKind.CONTAINER;
+ case "arvados#containerRequest":
+ return ResourceKind.CONTAINER_REQUEST;
+ case "arvados#group":
+ return ResourceKind.GROUP;
+ case "arvados#log":
+ return ResourceKind.LOG;
+ case "arvados#workflow":
+ return ResourceKind.WORKFLOW;
+ default:
+ return undefined;
+ }
++};
import { ofType, unionize, UnionOf } from '~/common/unionize';
import { Dispatch } from "redux";
- import { User } from "~/models/user";
-import { reset, stopSubmit, startSubmit } from 'redux-form';
++import { reset, stopSubmit, startSubmit, FormErrors } from 'redux-form';
+ import { AxiosInstance } from "axios";
import { RootState } from "../store";
+ import { snackbarActions } from '~/store/snackbar/snackbar-actions';
+ import { dialogActions } from '~/store/dialog/dialog-actions';
+ import { setBreadcrumbs } from '~/store/breadcrumbs/breadcrumbs-actions';
import { ServiceRepository } from "~/services/services";
- import { AxiosInstance } from "axios";
+ import { getAuthorizedKeysServiceError, AuthorizedKeysServiceError } from '~/services/authorized-keys-service/authorized-keys-service';
+ import { KeyType, SshKeyResource } from '~/models/ssh-key';
+ import { User } from "~/models/user";
export const authActions = unionize({
SAVE_API_TOKEN: ofType<string>(),
});
};
- dispatch(stopSubmit(SSH_KEY_CREATE_FORM_NAME, { publicKey: 'Public key already exists.' }));
+ export const openSshKeyCreateDialog = () => dialogActions.OPEN_DIALOG({ id: SSH_KEY_CREATE_FORM_NAME, data: {} });
+
+ export const openPublicKeyDialog = (name: string, publicKey: string) =>
+ dialogActions.OPEN_DIALOG({ id: SSH_KEY_PUBLIC_KEY_DIALOG, data: { name, publicKey } });
+
+ export const openSshKeyAttributesDialog = (index: number) =>
+ (dispatch: Dispatch, getState: () => RootState) => {
+ const sshKey = getState().auth.sshKeys[index];
+ dispatch(dialogActions.OPEN_DIALOG({ id: SSH_KEY_ATTRIBUTES_DIALOG, data: { sshKey } }));
+ };
+
+ export const openSshKeyRemoveDialog = (uuid: string) =>
+ (dispatch: Dispatch, getState: () => RootState) => {
+ dispatch(dialogActions.OPEN_DIALOG({
+ id: SSH_KEY_REMOVE_DIALOG,
+ data: {
+ title: 'Remove public key',
+ text: 'Are you sure you want to remove this public key?',
+ confirmButtonLabel: 'Remove',
+ uuid
+ }
+ }));
+ };
+
+ export const removeSshKey = (uuid: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removing ...' }));
+ await services.authorizedKeysService.delete(uuid);
+ dispatch(authActions.REMOVE_SSH_KEY(uuid));
+ dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Public Key has been successfully removed.', hideDuration: 2000 }));
+ };
+
+ export const createSshKey = (data: SshKeyCreateFormDialogData) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const userUuid = getState().auth.user!.uuid;
+ const { name, publicKey } = data;
+ dispatch(startSubmit(SSH_KEY_CREATE_FORM_NAME));
+ try {
+ const newSshKey = await services.authorizedKeysService.create({
+ name,
+ publicKey,
+ keyType: KeyType.SSH,
+ authorizedUserUuid: userUuid
+ });
+ dispatch(authActions.ADD_SSH_KEY(newSshKey));
+ dispatch(dialogActions.CLOSE_DIALOG({ id: SSH_KEY_CREATE_FORM_NAME }));
+ dispatch(reset(SSH_KEY_CREATE_FORM_NAME));
+ dispatch(snackbarActions.OPEN_SNACKBAR({
+ message: "Public key has been successfully created.",
+ hideDuration: 2000
+ }));
+ } catch (e) {
+ const error = getAuthorizedKeysServiceError(e);
+ if (error === AuthorizedKeysServiceError.UNIQUE_PUBLIC_KEY) {
- dispatch(stopSubmit(SSH_KEY_CREATE_FORM_NAME, { publicKey: 'Public key is invalid' }));
++ dispatch(stopSubmit(SSH_KEY_CREATE_FORM_NAME, { publicKey: 'Public key already exists.' } as FormErrors));
+ } else if (error === AuthorizedKeysServiceError.INVALID_PUBLIC_KEY) {
++ dispatch(stopSubmit(SSH_KEY_CREATE_FORM_NAME, { publicKey: 'Public key is invalid' } as FormErrors));
+ }
+ }
+ };
+
+ export const loadSshKeysPanel = () =>
+ async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
+ try {
+ dispatch(setBreadcrumbs([{ label: 'SSH Keys'}]));
+ const response = await services.authorizedKeysService.list();
+ dispatch(authActions.SET_SSH_KEYS(response.items));
+ } catch (e) {
+ return;
+ }
+ };
+
+
export type AuthAction = UnionOf<typeof authActions>;
export const createCollection = (data: CollectionCreateFormDialogData) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
dispatch(startSubmit(COLLECTION_CREATE_FORM_NAME));
- let newCollection: CollectionResource | null = null;
++ let newCollection: CollectionResource;
try {
dispatch(progressIndicatorActions.START_WORKING(COLLECTION_CREATE_FORM_NAME));
- const newCollection = await services.collectionService.create(data);
+ newCollection = await services.collectionService.create(data);
await dispatch<any>(uploadCollectionFiles(newCollection.uuid));
dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_CREATE_FORM_NAME }));
dispatch(reset(COLLECTION_CREATE_FORM_NAME));
} 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));
+ } else if (error === CommonResourceServiceError.NONE) {
+ dispatch(stopSubmit(COLLECTION_CREATE_FORM_NAME));
+ dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_CREATE_FORM_NAME }));
+ dispatch(snackbarActions.OPEN_SNACKBAR({
+ message: 'Collection has not been created.',
+ hideDuration: 2000,
+ kind: SnackbarKind.ERROR
+ }));
+ await services.collectionService.delete(newCollection!.uuid);
}
dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_CREATE_FORM_NAME));
return;
} 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.' } as FormErrors));
} else {
dispatch(dialogActions.CLOSE_DIALOG({ id: PROCESS_MOVE_FORM_NAME }));
dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not move the process.', hideDuration: 2000 }));
} 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.' } as FormErrors));
} else {
dispatch(dialogActions.CLOSE_DIALOG({ id: PROCESS_UPDATE_FORM_NAME }));
dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not update the process.', hideDuration: 2000 }));
--- /dev/null
-import { startSubmit, reset, stopSubmit } from "redux-form";
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+
+ import { Dispatch } from "redux";
+ import { bindDataExplorerActions } from '~/store/data-explorer/data-explorer-action';
+ import { RootState } from '~/store/store';
+ import { ServiceRepository } from "~/services/services";
+ import { navigateToRepositories } from "~/store/navigation/navigation-action";
+ import { unionize, ofType, UnionOf } from "~/common/unionize";
+ import { dialogActions } from '~/store/dialog/dialog-actions';
+ import { RepositoryResource } from "~/models/repositories";
- dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Repository has been successfully created.", hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
- dispatch<any>(loadRepositoriesData());
++import { startSubmit, reset, stopSubmit, FormErrors } from "redux-form";
+ import { getCommonResourceServiceError, CommonResourceServiceError } from "~/services/common-service/common-resource-service";
+ import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
+
+ export const repositoriesActions = unionize({
+ SET_REPOSITORIES: ofType<any>(),
+ });
+
+ export type RepositoriesActions = UnionOf<typeof repositoriesActions>;
+
+ export const REPOSITORIES_PANEL = 'repositoriesPanel';
+ export const REPOSITORIES_SAMPLE_GIT_DIALOG = 'repositoriesSampleGitDialog';
+ export const REPOSITORY_ATTRIBUTES_DIALOG = 'repositoryAttributesDialog';
+ export const REPOSITORY_CREATE_FORM_NAME = 'repositoryCreateFormName';
+ export const REPOSITORY_REMOVE_DIALOG = 'repositoryRemoveDialog';
+
+ export const openRepositoriesSampleGitDialog = () =>
+ (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const uuidPrefix = getState().properties.uuidPrefix;
+ dispatch(dialogActions.OPEN_DIALOG({ id: REPOSITORIES_SAMPLE_GIT_DIALOG, data: { uuidPrefix } }));
+ };
+
+ export const openRepositoryAttributes = (index: number) =>
+ (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const repositoryData = getState().repositories.items[index];
+ dispatch(dialogActions.OPEN_DIALOG({ id: REPOSITORY_ATTRIBUTES_DIALOG, data: { repositoryData } }));
+ };
+
+ export const openRepositoryCreateDialog = () =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const userUuid = await services.authService.getUuid();
+ const user = await services.userService.get(userUuid!);
+ dispatch(reset(REPOSITORY_CREATE_FORM_NAME));
+ dispatch(dialogActions.OPEN_DIALOG({ id: REPOSITORY_CREATE_FORM_NAME, data: { user } }));
+ };
+
+ export const createRepository = (repository: RepositoryResource) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const userUuid = await services.authService.getUuid();
+ const user = await services.userService.get(userUuid!);
+ dispatch(startSubmit(REPOSITORY_CREATE_FORM_NAME));
+ try {
+ const newRepository = await services.repositoriesService.create({ name: `${user.username}/${repository.name}` });
+ dispatch(dialogActions.CLOSE_DIALOG({ id: REPOSITORY_CREATE_FORM_NAME }));
+ dispatch(reset(REPOSITORY_CREATE_FORM_NAME));
- dispatch(stopSubmit(REPOSITORY_CREATE_FORM_NAME, { name: 'Repository with the same name already exists.' }));
++ dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Repository has been successfully created.", hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
++ dispatch<any>(loadRepositoriesData());
+ return newRepository;
+ } catch (e) {
+ const error = getCommonResourceServiceError(e);
+ if (error === CommonResourceServiceError.NAME_HAS_ALREADY_BEEN_TAKEN) {
- };
++ dispatch(stopSubmit(REPOSITORY_CREATE_FORM_NAME, { name: 'Repository with the same name already exists.' } as FormErrors));
+ }
+ return undefined;
+ }
+ };
+
+ export const openRemoveRepositoryDialog = (uuid: string) =>
+ (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ dispatch(dialogActions.OPEN_DIALOG({
+ id: REPOSITORY_REMOVE_DIALOG,
+ data: {
+ title: 'Remove repository',
+ text: 'Are you sure you want to remove this repository?',
+ confirmButtonLabel: 'Remove',
+ uuid
+ }
+ }));
+ };
+
+ export const removeRepository = (uuid: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removing ...' }));
+ await services.repositoriesService.delete(uuid);
+ dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removed.', hideDuration: 2000 }));
+ dispatch<any>(loadRepositoriesData());
+ };
+
+ const repositoriesBindedActions = bindDataExplorerActions(REPOSITORIES_PANEL);
+
+ export const openRepositoriesPanel = () =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ dispatch<any>(navigateToRepositories);
+ };
+
+ export const loadRepositoriesData = () =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const repositories = await services.repositoriesService.list();
+ dispatch(repositoriesActions.SET_REPOSITORIES(repositories.items));
+ };
+
+ export const loadRepositoriesPanel = () =>
+ (dispatch: Dispatch) => {
+ dispatch(repositoriesBindedActions.REQUEST_ITEMS());
++ };
--- /dev/null
- })
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { getAdvancedDataFromQuery, getQueryFromAdvancedData, parseQuery } from "~/store/search-bar/search-bar-actions";
+import { ResourceKind } from "~/models/resource";
+import { ClusterObjectType } from "~/models/search-bar";
+
+describe('search-bar-actions', () => {
+ describe('parseQuery', () => {
+ 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']
+ });
+ });
+
+ it('should correctly parse query #5 (properties)', () => {
+ const q = 'val0 has:filesize:100mb val2 val2 val0';
+ const r = parseQuery(q);
+ expect(r.hasKeywords).toBeTruthy();
+ expect(r.values).toEqual(['val0', 'val2']);
+ expect(r.properties).toEqual({
+ 'has': ['filesize:100mb']
+ });
+ });
+
+ it('should correctly parse query #6 (multiple properties, multiple is)', () => {
+ const q = 'val0 has:filesize:100mb val2 has:user:daniel is:starred val2 val0 is:trashed';
+ const r = parseQuery(q);
+ expect(r.hasKeywords).toBeTruthy();
+ expect(r.values).toEqual(['val0', 'val2']);
+ expect(r.properties).toEqual({
+ 'has': ['filesize:100mb', 'user:daniel'],
+ 'is': ['starred', 'trashed']
+ });
+ });
+ });
+
+ describe('getAdvancedDataFromQuery', () => {
+ it('should correctly build advanced data record from query #1', () => {
+ const r = getAdvancedDataFromQuery('val0 has:filesize:100mb val2 has:user:daniel is:starred val2 val0 is:trashed');
+ expect(r).toEqual({
+ searchValue: 'val0 val2',
+ type: undefined,
+ cluster: undefined,
+ projectUuid: undefined,
+ inTrash: true,
+ dateFrom: undefined,
+ dateTo: undefined,
+ properties: [{
+ key: 'filesize',
+ value: '100mb'
+ }, {
+ key: 'user',
+ value: 'daniel'
+ }],
+ saveQuery: false,
+ queryName: ''
- })
++ });
+ });
+
+ it('should correctly build advanced data record from query #2', () => {
+ const r = getAdvancedDataFromQuery('document from:2017-08-01 pdf has:filesize:101mb is:trashed type:arvados#collection cluster:indianapolis');
+ expect(r).toEqual({
+ searchValue: 'document pdf',
+ type: ResourceKind.COLLECTION,
+ cluster: ClusterObjectType.INDIANAPOLIS,
+ projectUuid: undefined,
+ inTrash: true,
+ dateFrom: '2017-08-01',
+ dateTo: undefined,
+ properties: [{
+ key: 'filesize',
+ value: '101mb'
+ }],
+ saveQuery: false,
+ queryName: ''
- })
++ });
+ });
+ });
+
+ describe('getQueryFromAdvancedData', () => {
+ it('should build query from advanced data', () => {
+ const q = getQueryFromAdvancedData({
+ searchValue: 'document pdf',
+ type: ResourceKind.COLLECTION,
+ cluster: ClusterObjectType.INDIANAPOLIS,
+ projectUuid: undefined,
+ inTrash: true,
+ dateFrom: '2017-08-01',
+ dateTo: '',
+ properties: [{
+ key: 'filesize',
+ value: '101mb'
+ }],
+ saveQuery: false,
+ queryName: ''
+ });
+ expect(q).toBe('document pdf type:arvados#collection cluster:indianapolis is:trashed from:2017-08-01 has:filesize:101mb');
++ });
+ });
+});
import { initUserProject } from '~/store/tree-picker/tree-picker-actions';
import { ServiceRepository } from '~/services/services';
import { FilterBuilder } from "~/services/api/filter-builder";
-import { ResourceKind } from '~/models/resource';
+import { getResourceKind, ResourceKind } from '~/models/resource';
import { GroupClass } from '~/models/group';
import { SearchView } from '~/store/search-bar/search-bar-reducer';
-import { navigateToSearchResults, navigateTo } from '~/store/navigation/navigation-action';
+import { navigateTo, navigateToSearchResults } from '~/store/navigation/navigation-action';
import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
- import { ClusterObjectType, getClusterObjectType, PropertyValues, SearchBarAdvanceFormData } from '~/models/search-bar';
-import { initialize } from 'redux-form';
-import { SearchBarAdvanceFormData, PropertyValues } from '~/models/search-bar';
++import { getClusterObjectType, PropertyValues, SearchBarAdvanceFormData } from '~/models/search-bar';
import { debounce } from 'debounce';
+import * as _ from "lodash";
+import { getModifiedKeysValues } from "~/common/objects";
export const searchBarActions = unionize({
SET_CURRENT_VIEW: ofType<string>(),
}
};
-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))
+const buildQueryFromKeyMap = (data: any, keyMap: string[][], mode: 'rebuild' | 'reuse') => {
+ let value = data.searchValue;
+
+ const addRem = (field: string, key: string) => {
+ const v = data[key];
+ if (v) {
+ const nv = v === true
+ ? `${field}`
+ : `${field}:${v}`;
+
+ if (mode === 'rebuild') {
+ value = value + ' ' + nv;
+ } else {
+ value = nv + ' ' + value;
+ }
+ } else if (data.hasOwnProperty(key) && (v === undefined || v === false)) {
+ const pattern = v === false
+ ? `${field.replace(':', '\\:\\s*')}\\s*`
+ : `${field.replace(':', '\\:\\s*')}\\:\\s*[\\w|\\#|\\-|\\/]*`;
+ value = value.replace(new RegExp(pattern), '');
+ }
+ };
+
+ keyMap.forEach(km => addRem(km[0], km[1]));
+
+ return value;
+};
+
+export const getQueryFromAdvancedData = (data: SearchBarAdvanceFormData, prevData?: SearchBarAdvanceFormData) => {
+ let value = '';
+
+ const flatData = (data: SearchBarAdvanceFormData) => {
+ const fo = {
+ searchValue: data.searchValue,
+ type: data.type,
+ cluster: data.cluster,
+ projectUuid: data.projectUuid,
+ inTrash: data.inTrash,
+ dateFrom: data.dateFrom,
+ dateTo: data.dateTo,
+ };
+ (data.properties || []).forEach(p => fo[`prop-${p.key}`] = p.value);
+ return fo;
+ };
+
+ const keyMap = [
+ ['type', 'type'],
+ ['cluster', 'cluster'],
+ ['project', 'projectUuid'],
+ ['is:trashed', 'inTrash'],
+ ['from', 'dateFrom'],
+ ['to', 'dateTo']
+ ];
+ _.union(data.properties, prevData ? prevData.properties : [])
+ .forEach(p => keyMap.push([`has:${p.key}`, `prop-${p.key}`]));
+
+ if (prevData) {
+ const obj = getModifiedKeysValues(flatData(data), flatData(prevData));
+ console.log(obj);
+ value = buildQueryFromKeyMap({
+ searchValue: data.searchValue,
+ ...obj
+ } as SearchBarAdvanceFormData, keyMap, "reuse");
+ } else {
+ value = buildQueryFromKeyMap(flatData(data), keyMap, "rebuild");
+ }
+
+ value = value.trim();
+ return value;
+};
+
+export const parseQuery: (query: string) => { hasKeywords: boolean; values: string[]; properties: any } = (searchValue: string) => {
+ const keywords = [
+ 'type:',
+ 'cluster:',
+ 'project:',
+ 'is:',
+ 'from:',
+ 'to:',
+ 'has:'
+ ];
+
+ const hasKeywords = (search: string) => keywords.reduce((acc, keyword) => acc + search.indexOf(keyword) >= 0 ? 1 : 0, 0);
+ let keywordsCnt = 0;
+
+ const properties = {};
+
+ keywords.forEach(k => {
+ let p = searchValue.indexOf(k);
+ const key = k.substr(0, k.length - 1);
+
+ while (p >= 0) {
+ const l = searchValue.length;
+ 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 !== '') {
+ if (!properties[key]) {
+ properties[key] = [];
+ }
+ properties[key].push(v);
+ }
+ searchValue = searchValue.substr(0, p) + searchValue.substr(i);
+ }
+ p = searchValue.indexOf(k);
+ }
+ });
+
+ const values = _.uniq(searchValue.split(' ').filter(v => v.length > 0));
+
+ return { hasKeywords: keywordsCnt > 0, values, properties };
+};
+
+export const getAdvancedDataFromQuery = (query: string): SearchBarAdvanceFormData => {
+ const r = parseQuery(query);
+
+ const getFirstProp = (name: string) => r.properties[name] && r.properties[name][0];
+ const getPropValue = (name: string, value: string) => r.properties[name] && r.properties[name].find((v: string) => v === value);
+ const getProperties = () => {
- if (r.properties['has']) {
- return r.properties['has'].map((value: string) => {
++ if (r.properties.has) {
++ return r.properties.has.map((value: string) => {
+ const v = value.split(':');
+ return {
+ key: v[0],
+ value: v[1]
- }
- })
++ };
++ });
+ }
+ return [];
+ };
+
+ return {
+ searchValue: r.values.join(' '),
+ type: getResourceKind(getFirstProp('type')),
+ cluster: getClusterObjectType(getFirstProp('cluster')),
+ projectUuid: getFirstProp('project'),
+ inTrash: getPropValue('is', 'trashed') !== undefined,
+ dateFrom: getFirstProp('from'),
+ dateTo: getFirstProp('to'),
+ properties: getProperties(),
+ saveQuery: false,
- queryName: '',
- }
++ queryName: ''
++ };
+};
+
+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();
};