Allow to edit active smart filter
This commit is contained in:
parent
a391eb2f92
commit
6d380bf8a8
5 changed files with 167 additions and 61 deletions
|
@ -22,7 +22,7 @@ const EditFilter: React.FC<EditFilterProps> = ({
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<S.FilterTitle>Edit saved filter</S.FilterTitle>
|
<S.FilterTitle>Edit filter</S.FilterTitle>
|
||||||
<AddEditFilterContainer
|
<AddEditFilterContainer
|
||||||
cancelBtnHandler={() => toggleEditModal()}
|
cancelBtnHandler={() => toggleEditModal()}
|
||||||
submitBtnText="Save"
|
submitBtnText="Save"
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as S from 'components/Topics/Topic/Messages/Filters/Filters.styled';
|
import * as S from 'components/Topics/Topic/Messages/Filters/Filters.styled';
|
||||||
import { MessageFilters } from 'components/Topics/Topic/Messages/Filters/Filters';
|
import { ActiveMessageFilter, MessageFilters } from 'components/Topics/Topic/Messages/Filters/Filters';
|
||||||
import AddFilter from 'components/Topics/Topic/Messages/Filters/AddFilter';
|
import AddFilter from 'components/Topics/Topic/Messages/Filters/AddFilter';
|
||||||
import EditFilter from 'components/Topics/Topic/Messages/Filters/EditFilter';
|
import EditFilter from 'components/Topics/Topic/Messages/Filters/EditFilter';
|
||||||
|
|
||||||
export interface FilterModalProps {
|
export interface FilterModalProps {
|
||||||
toggleIsOpen(): void;
|
toggleIsOpen(): void;
|
||||||
filters: MessageFilters[];
|
filters?: MessageFilters[];
|
||||||
addFilter(values: MessageFilters): void;
|
addFilter?(values: MessageFilters): void;
|
||||||
deleteFilter(index: number): void;
|
deleteFilter?(index: number): void;
|
||||||
activeFilterHandler(activeFilter: MessageFilters, index: number): void;
|
activeFilterHandler?(activeFilter: MessageFilters, index: number): void;
|
||||||
editSavedFilter(filter: FilterEdit): void;
|
editSavedFilter(filter: FilterEdit): void;
|
||||||
activeFilter?: MessageFilters;
|
activeFilter?: ActiveMessageFilter;
|
||||||
|
quickEditMode?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FilterEdit {
|
export interface FilterEdit {
|
||||||
|
@ -27,45 +28,48 @@ const FilterModal: React.FC<FilterModalProps> = ({
|
||||||
activeFilterHandler,
|
activeFilterHandler,
|
||||||
editSavedFilter,
|
editSavedFilter,
|
||||||
activeFilter,
|
activeFilter,
|
||||||
|
quickEditMode = false,
|
||||||
}) => {
|
}) => {
|
||||||
const [addFilterModal, setAddFilterModal] = React.useState<boolean>(true);
|
const [isInEditMode, setIsInEditMode] = React.useState<boolean>(quickEditMode);
|
||||||
const [isSavedFiltersOpen, setIsSavedFiltersOpen] =
|
const [isSavedFiltersOpen, setIsSavedFiltersOpen] =
|
||||||
React.useState<boolean>(false);
|
React.useState<boolean>(false);
|
||||||
|
|
||||||
const toggleEditModal = () => {
|
const toggleEditModal = () => {
|
||||||
setAddFilterModal(!addFilterModal);
|
setIsInEditMode(!isInEditMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
const [editFilter, setEditFilter] = React.useState<FilterEdit>({
|
const [editFilter, setEditFilter] = React.useState<FilterEdit>( () => {
|
||||||
index: -1,
|
const {index, name, code} = activeFilter!;
|
||||||
filter: { name: '', code: '' },
|
return quickEditMode ? { index, filter: { name, code } } : { index: -1, filter: { name: "", code: "" } };
|
||||||
});
|
});
|
||||||
const editFilterHandler = (value: FilterEdit) => {
|
const editFilterHandler = (value: FilterEdit) => {
|
||||||
setEditFilter(value);
|
setEditFilter(value);
|
||||||
setAddFilterModal(!addFilterModal);
|
setIsInEditMode(!isInEditMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleEditModalHandler = quickEditMode ? toggleIsOpen : toggleEditModal;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<S.MessageFilterModal data-testid="messageFilterModal">
|
<S.MessageFilterModal data-testid="messageFilterModal">
|
||||||
{addFilterModal ? (
|
{isInEditMode ? (
|
||||||
|
<EditFilter
|
||||||
|
editFilter={editFilter}
|
||||||
|
toggleEditModal={toggleEditModalHandler}
|
||||||
|
editSavedFilter={editSavedFilter}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<AddFilter
|
<AddFilter
|
||||||
toggleIsOpen={toggleIsOpen}
|
toggleIsOpen={toggleIsOpen}
|
||||||
filters={filters}
|
filters={filters!}
|
||||||
addFilter={addFilter}
|
addFilter={addFilter!}
|
||||||
deleteFilter={deleteFilter}
|
deleteFilter={deleteFilter!}
|
||||||
activeFilterHandler={activeFilterHandler}
|
activeFilterHandler={activeFilterHandler!}
|
||||||
toggleEditModal={toggleEditModal}
|
toggleEditModal={toggleEditModal}
|
||||||
editFilter={editFilterHandler}
|
editFilter={editFilterHandler}
|
||||||
isSavedFiltersOpen={isSavedFiltersOpen}
|
isSavedFiltersOpen={isSavedFiltersOpen}
|
||||||
onClickSavedFilters={() => setIsSavedFiltersOpen(!isSavedFiltersOpen)}
|
onClickSavedFilters={() => setIsSavedFiltersOpen(!isSavedFiltersOpen)}
|
||||||
activeFilter={activeFilter}
|
activeFilter={activeFilter}
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<EditFilter
|
|
||||||
editFilter={editFilter}
|
|
||||||
toggleEditModal={toggleEditModal}
|
|
||||||
editSavedFilter={editSavedFilter}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</S.MessageFilterModal>
|
</S.MessageFilterModal>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,8 @@ import Input from 'components/common/Input/Input';
|
||||||
import Select from 'components/common/Select/Select';
|
import Select from 'components/common/Select/Select';
|
||||||
import styled, { css } from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
import DatePicker from 'react-datepicker';
|
import DatePicker from 'react-datepicker';
|
||||||
|
import EditIcon from 'components/common/Icons/EditIcon';
|
||||||
|
import closeIcon from 'components/common/Icons/CloseIcon';
|
||||||
|
|
||||||
interface SavedFilterProps {
|
interface SavedFilterProps {
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
|
@ -280,28 +282,73 @@ export const SavedFilter = styled.div.attrs({
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ActiveSmartFilter = styled.div`
|
export const ActiveSmartFilter = styled.div`
|
||||||
border-radius: 4px;
|
|
||||||
min-width: 115px;
|
|
||||||
height: 24px;
|
|
||||||
background: ${({ theme }) => theme.savedFilter.backgroundColor};
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 20px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
color: ${({ theme }) => theme.savedFilter.color};
|
height: 32px;
|
||||||
padding: 16px 8px;
|
color: ${({ theme }) => theme.activeFilter.color};
|
||||||
|
background: ${({ theme }) => theme.activeFilter.backgroundColor};
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const DeleteSavedFilterIcon = styled.div`
|
|
||||||
color: ${({ theme }) => theme.icons.closeIcon};
|
export const EditSmartFilterIcon = styled.div(
|
||||||
|
({ theme: { icons } }) => css`
|
||||||
|
color: ${({ theme }) => theme.icons.editIcon.normal};
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-left: 6px;
|
justify-content: center;
|
||||||
height: 24px;
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-left: 4px;
|
border-left: 1px solid ${icons.editIcon.border};
|
||||||
`;
|
|
||||||
|
&:hover {
|
||||||
|
${EditIcon} {
|
||||||
|
fill: ${icons.editIcon.hover};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
${EditIcon} {
|
||||||
|
fill: ${icons.editIcon.active};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
export const SmartFilterName = styled.div(
|
||||||
|
({ theme: { icons } }) => css`
|
||||||
|
padding: 0 8px;
|
||||||
|
min-width: 32px;
|
||||||
|
`);
|
||||||
|
|
||||||
|
export const DeleteSmartFilterIcon = styled.div(
|
||||||
|
({ theme: { icons } }) => css`
|
||||||
|
color: ${({ theme }) => theme.icons.closeIcon.normal};
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-left: 1px solid ${icons.closeIcon.border};
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
${closeIcon} {
|
||||||
|
fill: ${icons.closeIcon.hover};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
${closeIcon} {
|
||||||
|
fill: ${icons.closeIcon.active};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
export const MessageLoading = styled.div.attrs({
|
export const MessageLoading = styled.div.attrs({
|
||||||
role: 'contentLoader',
|
role: 'contentLoader',
|
||||||
|
|
|
@ -30,6 +30,7 @@ import useBoolean from 'lib/hooks/useBoolean';
|
||||||
import { RouteParamsClusterTopic } from 'lib/paths';
|
import { RouteParamsClusterTopic } from 'lib/paths';
|
||||||
import useAppParams from 'lib/hooks/useAppParams';
|
import useAppParams from 'lib/hooks/useAppParams';
|
||||||
import PlusIcon from 'components/common/Icons/PlusIcon';
|
import PlusIcon from 'components/common/Icons/PlusIcon';
|
||||||
|
import EditIcon from 'components/common/Icons/EditIcon';
|
||||||
import CloseIcon from 'components/common/Icons/CloseIcon';
|
import CloseIcon from 'components/common/Icons/CloseIcon';
|
||||||
import ClockIcon from 'components/common/Icons/ClockIcon';
|
import ClockIcon from 'components/common/Icons/ClockIcon';
|
||||||
import ArrowDownIcon from 'components/common/Icons/ArrowDownIcon';
|
import ArrowDownIcon from 'components/common/Icons/ArrowDownIcon';
|
||||||
|
@ -67,7 +68,7 @@ export interface MessageFilters {
|
||||||
code: string;
|
code: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActiveMessageFilter {
|
export interface ActiveMessageFilter {
|
||||||
index: number;
|
index: number;
|
||||||
name: string;
|
name: string;
|
||||||
code: string;
|
code: string;
|
||||||
|
@ -108,6 +109,8 @@ const Filters: React.FC<FiltersProps> = ({
|
||||||
|
|
||||||
const { value: isOpen, toggle } = useBoolean();
|
const { value: isOpen, toggle } = useBoolean();
|
||||||
|
|
||||||
|
const { value: isQuickEditOpen, toggle: toggleQuickEdit } = useBoolean();
|
||||||
|
|
||||||
const source = React.useRef<EventSource | null>(null);
|
const source = React.useRef<EventSource | null>(null);
|
||||||
|
|
||||||
const [selectedPartitions, setSelectedPartitions] = React.useState<Option[]>(
|
const [selectedPartitions, setSelectedPartitions] = React.useState<Option[]>(
|
||||||
|
@ -307,27 +310,37 @@ const Filters: React.FC<FiltersProps> = ({
|
||||||
setActiveFilter({ index, ...newActiveFilter });
|
setActiveFilter({ index, ...newActiveFilter });
|
||||||
setQueryType(MessageFilterType.GROOVY_SCRIPT);
|
setQueryType(MessageFilterType.GROOVY_SCRIPT);
|
||||||
};
|
};
|
||||||
const editSavedFilter = (filter: FilterEdit) => {
|
|
||||||
const filters = [...savedFilters];
|
const composeMessageFilter = (filter: FilterEdit) : ActiveMessageFilter => ({
|
||||||
filters[filter.index] = filter.filter;
|
|
||||||
if (activeFilter.name && activeFilter.index === filter.index) {
|
|
||||||
setActiveFilter({
|
|
||||||
index: filter.index,
|
index: filter.index,
|
||||||
name: filter.filter.name,
|
name: filter.filter.name,
|
||||||
code: filter.filter.code,
|
code: filter.filter.code,
|
||||||
});
|
});
|
||||||
localStorage.setItem(
|
|
||||||
'activeFilter',
|
const storeAsActiveFilter = (filter: FilterEdit) => {
|
||||||
JSON.stringify({
|
const messageFilter = JSON.stringify(composeMessageFilter(filter));
|
||||||
index: filter.index,
|
localStorage.setItem('activeFilter', messageFilter);
|
||||||
name: filter.filter.name,
|
}
|
||||||
code: filter.filter.code,
|
|
||||||
})
|
const editSavedFilter = (filter: FilterEdit) => {
|
||||||
);
|
const filters = [...savedFilters];
|
||||||
|
filters[filter.index] = filter.filter;
|
||||||
|
if (activeFilter.name && activeFilter.index === filter.index) {
|
||||||
|
setActiveFilter(composeMessageFilter(filter));
|
||||||
|
storeAsActiveFilter(filter);
|
||||||
}
|
}
|
||||||
localStorage.setItem('savedFilters', JSON.stringify(filters));
|
localStorage.setItem('savedFilters', JSON.stringify(filters));
|
||||||
setSavedFilters(filters);
|
setSavedFilters(filters);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const editCurrentFilter = (filter: FilterEdit) => {
|
||||||
|
if (filter.index < 0) {
|
||||||
|
setActiveFilter(composeMessageFilter(filter));
|
||||||
|
storeAsActiveFilter(filter);
|
||||||
|
} else {
|
||||||
|
editSavedFilter(filter);
|
||||||
|
}
|
||||||
|
};
|
||||||
// eslint-disable-next-line consistent-return
|
// eslint-disable-next-line consistent-return
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (location.search?.length !== 0) {
|
if (location.search?.length !== 0) {
|
||||||
|
@ -542,13 +555,27 @@ const Filters: React.FC<FiltersProps> = ({
|
||||||
</Button>
|
</Button>
|
||||||
{activeFilter.name && (
|
{activeFilter.name && (
|
||||||
<S.ActiveSmartFilter data-testid="activeSmartFilter">
|
<S.ActiveSmartFilter data-testid="activeSmartFilter">
|
||||||
|
<S.SmartFilterName>
|
||||||
{activeFilter.name}
|
{activeFilter.name}
|
||||||
<S.DeleteSavedFilterIcon onClick={deleteActiveFilter}>
|
</S.SmartFilterName>
|
||||||
|
<S.EditSmartFilterIcon onClick={toggleQuickEdit}>
|
||||||
|
<EditIcon />
|
||||||
|
</S.EditSmartFilterIcon>
|
||||||
|
<S.DeleteSmartFilterIcon onClick={deleteActiveFilter}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</S.DeleteSavedFilterIcon>
|
</S.DeleteSmartFilterIcon>
|
||||||
</S.ActiveSmartFilter>
|
</S.ActiveSmartFilter>
|
||||||
)}
|
)}
|
||||||
</S.ActiveSmartFilterWrapper>
|
</S.ActiveSmartFilterWrapper>
|
||||||
|
{isQuickEditOpen &&
|
||||||
|
<FilterModal
|
||||||
|
quickEditMode
|
||||||
|
activeFilter={activeFilter}
|
||||||
|
toggleIsOpen={toggleQuickEdit}
|
||||||
|
editSavedFilter={editCurrentFilter}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<FilterModal
|
<FilterModal
|
||||||
toggleIsOpen={toggle}
|
toggleIsOpen={toggle}
|
||||||
|
|
|
@ -161,7 +161,18 @@ const baseTheme = {
|
||||||
},
|
},
|
||||||
icons: {
|
icons: {
|
||||||
chevronDownIcon: Colors.neutral[0],
|
chevronDownIcon: Colors.neutral[0],
|
||||||
editIcon: Colors.neutral[30],
|
editIcon: {
|
||||||
|
normal: Colors.neutral[30],
|
||||||
|
hover: Colors.neutral[90],
|
||||||
|
active: Colors.neutral[100],
|
||||||
|
border: Colors.neutral[10]
|
||||||
|
},
|
||||||
|
closeIcon: {
|
||||||
|
normal: Colors.neutral[30],
|
||||||
|
hover: Colors.neutral[90],
|
||||||
|
active: Colors.neutral[100],
|
||||||
|
border: Colors.neutral[10]
|
||||||
|
},
|
||||||
cancelIcon: Colors.neutral[30],
|
cancelIcon: Colors.neutral[30],
|
||||||
autoIcon: Colors.neutral[95],
|
autoIcon: Colors.neutral[95],
|
||||||
fileIcon: Colors.neutral[90],
|
fileIcon: Colors.neutral[90],
|
||||||
|
@ -170,7 +181,7 @@ const baseTheme = {
|
||||||
moonIcon: Colors.neutral[95],
|
moonIcon: Colors.neutral[95],
|
||||||
sunIcon: Colors.neutral[95],
|
sunIcon: Colors.neutral[95],
|
||||||
infoIcon: Colors.neutral[30],
|
infoIcon: Colors.neutral[30],
|
||||||
closeIcon: Colors.neutral[30],
|
closeCircleIcon: Colors.neutral[30],
|
||||||
deleteIcon: Colors.red[20],
|
deleteIcon: Colors.red[20],
|
||||||
warningIcon: Colors.yellow[20],
|
warningIcon: Colors.yellow[20],
|
||||||
warningRedIcon: {
|
warningRedIcon: {
|
||||||
|
@ -678,10 +689,13 @@ export const theme = {
|
||||||
color: Colors.neutral[80],
|
color: Colors.neutral[80],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
activeFilter: {
|
||||||
|
color: Colors.neutral[70],
|
||||||
|
backgroundColor: Colors.neutral[5],
|
||||||
|
},
|
||||||
savedFilter: {
|
savedFilter: {
|
||||||
filterName: Colors.neutral[90],
|
filterName: Colors.neutral[90],
|
||||||
color: Colors.neutral[30],
|
color: Colors.neutral[30],
|
||||||
backgroundColor: Colors.neutral[5],
|
|
||||||
},
|
},
|
||||||
editFilter: {
|
editFilter: {
|
||||||
textColor: Colors.brand[50],
|
textColor: Colors.brand[50],
|
||||||
|
@ -1073,10 +1087,13 @@ export const darkTheme: ThemeType = {
|
||||||
color: Colors.neutral[0],
|
color: Colors.neutral[0],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
activeFilter: {
|
||||||
|
color: Colors.neutral[0],
|
||||||
|
backgroundColor: Colors.neutral[80],
|
||||||
|
},
|
||||||
savedFilter: {
|
savedFilter: {
|
||||||
filterName: Colors.neutral[0],
|
filterName: Colors.neutral[0],
|
||||||
color: Colors.neutral[70],
|
color: Colors.neutral[70],
|
||||||
backgroundColor: Colors.neutral[80],
|
|
||||||
},
|
},
|
||||||
editFilter: {
|
editFilter: {
|
||||||
textColor: Colors.brand[30],
|
textColor: Colors.brand[30],
|
||||||
|
@ -1102,7 +1119,18 @@ export const darkTheme: ThemeType = {
|
||||||
},
|
},
|
||||||
icons: {
|
icons: {
|
||||||
...baseTheme.icons,
|
...baseTheme.icons,
|
||||||
editIcon: Colors.neutral[0],
|
editIcon: {
|
||||||
|
normal: Colors.neutral[50],
|
||||||
|
hover: Colors.neutral[30],
|
||||||
|
active: Colors.neutral[40],
|
||||||
|
border: Colors.neutral[70]
|
||||||
|
},
|
||||||
|
closeIcon: {
|
||||||
|
normal: Colors.neutral[50],
|
||||||
|
hover: Colors.neutral[30],
|
||||||
|
active: Colors.neutral[40],
|
||||||
|
border: Colors.neutral[70]
|
||||||
|
},
|
||||||
cancelIcon: Colors.neutral[0],
|
cancelIcon: Colors.neutral[0],
|
||||||
autoIcon: Colors.neutral[0],
|
autoIcon: Colors.neutral[0],
|
||||||
fileIcon: Colors.neutral[0],
|
fileIcon: Colors.neutral[0],
|
||||||
|
|
Loading…
Add table
Reference in a new issue