mirror of
https://github.com/twentyhq/twenty.git
synced 2025-01-07 09:17:31 +03:00
Move filter and sort compoenets in a separate lib (#612)
* Move filter and sort compoenets in a separate lib * Add SortAndFilterBar to the filter lib * Abstract hotkeys scopes * Fix hotkeys on filters --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
parent
e8d77833a7
commit
b5de2abd48
@ -1,10 +1,10 @@
|
|||||||
|
import { FilterDropdownEntitySearchSelect } from '@/lib/filters-and-sorts/components/FilterDropdownEntitySearchSelect';
|
||||||
import { filterDropdownSearchInputScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSearchInputScopedState';
|
import { filterDropdownSearchInputScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSearchInputScopedState';
|
||||||
import { filterDropdownSelectedEntityIdScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSelectedEntityIdScopedState';
|
import { filterDropdownSelectedEntityIdScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSelectedEntityIdScopedState';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { useRecoilScopedValue } from '@/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import { useFilteredSearchEntityQuery } from '@/relation-picker/hooks/useFilteredSearchEntityQuery';
|
import { useFilteredSearchEntityQuery } from '@/relation-picker/hooks/useFilteredSearchEntityQuery';
|
||||||
import { Entity } from '@/relation-picker/types/EntityTypeForSelect';
|
import { Entity } from '@/relation-picker/types/EntityTypeForSelect';
|
||||||
import { FilterDropdownEntitySearchSelect } from '@/ui/components/table/table-header/FilterDropdownEntitySearchSelect';
|
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
import { TableContext } from '@/ui/tables/states/TableContext';
|
||||||
import { getLogoUrlFromDomainName } from '@/utils/utils';
|
import { getLogoUrlFromDomainName } from '@/utils/utils';
|
||||||
import { useSearchCompanyQuery } from '~/generated/graphql';
|
import { useSearchCompanyQuery } from '~/generated/graphql';
|
||||||
@ -38,6 +38,9 @@ export function FilterDropdownCompanySearchSelect() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FilterDropdownEntitySearchSelect entitiesForSelect={usersForSelect} />
|
<FilterDropdownEntitySearchSelect
|
||||||
|
entitiesForSelect={usersForSelect}
|
||||||
|
context={TableContext}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,10 @@ import { Key } from 'ts-key-enum';
|
|||||||
|
|
||||||
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
||||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||||
|
import { useOutsideAlerter } from '@/ui/hooks/useOutsideAlerter';
|
||||||
import { IconChevronDown } from '@/ui/icons/index';
|
import { IconChevronDown } from '@/ui/icons/index';
|
||||||
import { overlayBackground, textInputStyle } from '@/ui/themes/effects';
|
import { overlayBackground, textInputStyle } from '@/ui/themes/effects';
|
||||||
|
|
||||||
import { useOutsideAlerter } from '../../../hooks/useOutsideAlerter';
|
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
label: string;
|
label: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
@ -16,6 +15,7 @@ type OwnProps = {
|
|||||||
isUnfolded?: boolean;
|
isUnfolded?: boolean;
|
||||||
onIsUnfoldedChange?: (newIsUnfolded: boolean) => void;
|
onIsUnfoldedChange?: (newIsUnfolded: boolean) => void;
|
||||||
resetState?: () => void;
|
resetState?: () => void;
|
||||||
|
hotkeysScope: InternalHotkeysScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledDropdownButtonContainer = styled.div`
|
const StyledDropdownButtonContainer = styled.div`
|
||||||
@ -160,13 +160,14 @@ function DropdownButton({
|
|||||||
children,
|
children,
|
||||||
isUnfolded = false,
|
isUnfolded = false,
|
||||||
onIsUnfoldedChange,
|
onIsUnfoldedChange,
|
||||||
|
hotkeysScope,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
[Key.Enter, Key.Escape],
|
[Key.Enter, Key.Escape],
|
||||||
() => {
|
() => {
|
||||||
onIsUnfoldedChange?.(false);
|
onIsUnfoldedChange?.(false);
|
||||||
},
|
},
|
||||||
InternalHotkeysScope.TableHeaderDropdownButton,
|
hotkeysScope,
|
||||||
[onIsUnfoldedChange],
|
[onIsUnfoldedChange],
|
||||||
);
|
);
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { Context, useCallback, useState } from 'react';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
||||||
@ -10,7 +10,6 @@ import { filtersScopedState } from '@/lib/filters-and-sorts/states/filtersScoped
|
|||||||
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '@/lib/filters-and-sorts/states/isFilterDropdownOperandSelectUnfoldedScopedState';
|
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '@/lib/filters-and-sorts/states/isFilterDropdownOperandSelectUnfoldedScopedState';
|
||||||
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
|
||||||
|
|
||||||
import DropdownButton from './DropdownButton';
|
import DropdownButton from './DropdownButton';
|
||||||
import { FilterDropdownDateSearchInput } from './FilterDropdownDateSearchInput';
|
import { FilterDropdownDateSearchInput } from './FilterDropdownDateSearchInput';
|
||||||
@ -22,7 +21,13 @@ import { FilterDropdownOperandButton } from './FilterDropdownOperandButton';
|
|||||||
import { FilterDropdownOperandSelect } from './FilterDropdownOperandSelect';
|
import { FilterDropdownOperandSelect } from './FilterDropdownOperandSelect';
|
||||||
import { FilterDropdownTextSearchInput } from './FilterDropdownTextSearchInput';
|
import { FilterDropdownTextSearchInput } from './FilterDropdownTextSearchInput';
|
||||||
|
|
||||||
export function FilterDropdownButton() {
|
export function FilterDropdownButton({
|
||||||
|
context,
|
||||||
|
hotkeysScope,
|
||||||
|
}: {
|
||||||
|
context: Context<string | null>;
|
||||||
|
hotkeysScope: InternalHotkeysScope;
|
||||||
|
}) {
|
||||||
const [isUnfolded, setIsUnfolded] = useState(false);
|
const [isUnfolded, setIsUnfolded] = useState(false);
|
||||||
|
|
||||||
const [
|
const [
|
||||||
@ -30,52 +35,45 @@ export function FilterDropdownButton() {
|
|||||||
setIsFilterDropdownOperandSelectUnfolded,
|
setIsFilterDropdownOperandSelectUnfolded,
|
||||||
] = useRecoilScopedState(
|
] = useRecoilScopedState(
|
||||||
isFilterDropdownOperandSelectUnfoldedScopedState,
|
isFilterDropdownOperandSelectUnfoldedScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [
|
const [filterDefinitionUsedInDropdown, setFilterDefinitionUsedInDropdown] =
|
||||||
tableFilterDefinitionUsedInDropdown,
|
useRecoilScopedState(filterDefinitionUsedInDropdownScopedState, context);
|
||||||
setTableFilterDefinitionUsedInDropdown,
|
|
||||||
] = useRecoilScopedState(
|
|
||||||
filterDefinitionUsedInDropdownScopedState,
|
|
||||||
TableContext,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [, setFilterDropdownSearchInput] = useRecoilScopedState(
|
const [, setFilterDropdownSearchInput] = useRecoilScopedState(
|
||||||
filterDropdownSearchInputScopedState,
|
filterDropdownSearchInputScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [activeTableFilters] = useRecoilScopedState(
|
const [filters] = useRecoilScopedState(filtersScopedState, context);
|
||||||
filtersScopedState,
|
|
||||||
TableContext,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [selectedOperandInDropdown, setSelectedOperandInDropdown] =
|
const [selectedOperandInDropdown, setSelectedOperandInDropdown] =
|
||||||
useRecoilScopedState(selectedOperandInDropdownScopedState, TableContext);
|
useRecoilScopedState(selectedOperandInDropdownScopedState, context);
|
||||||
|
|
||||||
const resetState = useCallback(() => {
|
const resetState = useCallback(() => {
|
||||||
setIsFilterDropdownOperandSelectUnfolded(false);
|
setIsFilterDropdownOperandSelectUnfolded(false);
|
||||||
setTableFilterDefinitionUsedInDropdown(null);
|
setFilterDefinitionUsedInDropdown(null);
|
||||||
setSelectedOperandInDropdown(null);
|
setSelectedOperandInDropdown(null);
|
||||||
setFilterDropdownSearchInput('');
|
setFilterDropdownSearchInput('');
|
||||||
}, [
|
}, [
|
||||||
setTableFilterDefinitionUsedInDropdown,
|
setFilterDefinitionUsedInDropdown,
|
||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
setFilterDropdownSearchInput,
|
setFilterDropdownSearchInput,
|
||||||
setIsFilterDropdownOperandSelectUnfolded,
|
setIsFilterDropdownOperandSelectUnfolded,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const isFilterSelected = (activeTableFilters?.length ?? 0) > 0;
|
const isFilterSelected = (filters?.length ?? 0) > 0;
|
||||||
|
|
||||||
const setHotkeysScope = useSetHotkeysScope();
|
const setHotkeysScope = useSetHotkeysScope();
|
||||||
|
|
||||||
function handleIsUnfoldedChange(newIsUnfolded: boolean) {
|
function handleIsUnfoldedChange(newIsUnfolded: boolean) {
|
||||||
if (newIsUnfolded) {
|
if (newIsUnfolded) {
|
||||||
|
setHotkeysScope(hotkeysScope);
|
||||||
setIsUnfolded(true);
|
setIsUnfolded(true);
|
||||||
} else {
|
} else {
|
||||||
if (tableFilterDefinitionUsedInDropdown?.type === 'entity') {
|
if (filterDefinitionUsedInDropdown?.type === 'entity') {
|
||||||
setHotkeysScope(InternalHotkeysScope.Table);
|
setHotkeysScope(hotkeysScope);
|
||||||
}
|
}
|
||||||
setIsUnfolded(false);
|
setIsUnfolded(false);
|
||||||
resetState();
|
resetState();
|
||||||
@ -97,31 +95,32 @@ export function FilterDropdownButton() {
|
|||||||
isActive={isFilterSelected}
|
isActive={isFilterSelected}
|
||||||
isUnfolded={isUnfolded}
|
isUnfolded={isUnfolded}
|
||||||
onIsUnfoldedChange={handleIsUnfoldedChange}
|
onIsUnfoldedChange={handleIsUnfoldedChange}
|
||||||
|
hotkeysScope={hotkeysScope}
|
||||||
>
|
>
|
||||||
{!tableFilterDefinitionUsedInDropdown ? (
|
{!filterDefinitionUsedInDropdown ? (
|
||||||
<FilterDropdownFilterSelect />
|
<FilterDropdownFilterSelect context={context} />
|
||||||
) : isFilterDropdownOperandSelectUnfolded ? (
|
) : isFilterDropdownOperandSelectUnfolded ? (
|
||||||
<FilterDropdownOperandSelect />
|
<FilterDropdownOperandSelect context={context} />
|
||||||
) : (
|
) : (
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<>
|
<>
|
||||||
<FilterDropdownOperandButton />
|
<FilterDropdownOperandButton context={context} />
|
||||||
<DropdownButton.StyledSearchField autoFocus key={'search-filter'}>
|
<DropdownButton.StyledSearchField autoFocus key={'search-filter'}>
|
||||||
{tableFilterDefinitionUsedInDropdown.type === 'text' && (
|
{filterDefinitionUsedInDropdown.type === 'text' && (
|
||||||
<FilterDropdownTextSearchInput />
|
<FilterDropdownTextSearchInput context={context} />
|
||||||
)}
|
)}
|
||||||
{tableFilterDefinitionUsedInDropdown.type === 'number' && (
|
{filterDefinitionUsedInDropdown.type === 'number' && (
|
||||||
<FilterDropdownNumberSearchInput />
|
<FilterDropdownNumberSearchInput context={context} />
|
||||||
)}
|
)}
|
||||||
{tableFilterDefinitionUsedInDropdown.type === 'date' && (
|
{filterDefinitionUsedInDropdown.type === 'date' && (
|
||||||
<FilterDropdownDateSearchInput />
|
<FilterDropdownDateSearchInput context={context} />
|
||||||
)}
|
)}
|
||||||
{tableFilterDefinitionUsedInDropdown.type === 'entity' && (
|
{filterDefinitionUsedInDropdown.type === 'entity' && (
|
||||||
<FilterDropdownEntitySearchInput />
|
<FilterDropdownEntitySearchInput context={context} />
|
||||||
)}
|
)}
|
||||||
</DropdownButton.StyledSearchField>
|
</DropdownButton.StyledSearchField>
|
||||||
{tableFilterDefinitionUsedInDropdown.type === 'entity' && (
|
{filterDefinitionUsedInDropdown.type === 'entity' && (
|
||||||
<FilterDropdownEntitySelect />
|
<FilterDropdownEntitySelect context={context} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
@ -1,33 +1,35 @@
|
|||||||
|
import { Context } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { useUpsertFilter } from '@/lib/filters-and-sorts/hooks/useUpsertFilter';
|
import { useUpsertFilter } from '@/lib/filters-and-sorts/hooks/useUpsertFilter';
|
||||||
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
||||||
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
import DatePicker from '@/ui/components/form/DatePicker';
|
||||||
|
|
||||||
import DatePicker from '../../form/DatePicker';
|
export function FilterDropdownDateSearchInput({
|
||||||
|
context,
|
||||||
export function FilterDropdownDateSearchInput() {
|
}: {
|
||||||
const [tableFilterDefinitionUsedInDropdown] = useRecoilScopedState(
|
context: Context<string | null>;
|
||||||
|
}) {
|
||||||
|
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
|
||||||
filterDefinitionUsedInDropdownScopedState,
|
filterDefinitionUsedInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [selectedOperandInDropdown] = useRecoilScopedState(
|
const [selectedOperandInDropdown] = useRecoilScopedState(
|
||||||
selectedOperandInDropdownScopedState,
|
selectedOperandInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const upsertActiveTableFilter = useUpsertFilter(TableContext);
|
const upsertFilter = useUpsertFilter(context);
|
||||||
|
|
||||||
function handleChange(date: Date) {
|
function handleChange(date: Date) {
|
||||||
if (!tableFilterDefinitionUsedInDropdown || !selectedOperandInDropdown)
|
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;
|
||||||
return;
|
|
||||||
|
|
||||||
upsertActiveTableFilter({
|
upsertFilter({
|
||||||
field: tableFilterDefinitionUsedInDropdown.field,
|
field: filterDefinitionUsedInDropdown.field,
|
||||||
type: tableFilterDefinitionUsedInDropdown.type,
|
type: filterDefinitionUsedInDropdown.type,
|
||||||
value: date.toISOString(),
|
value: date.toISOString(),
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: date.toLocaleDateString(),
|
displayValue: date.toLocaleDateString(),
|
@ -1,32 +1,35 @@
|
|||||||
import { ChangeEvent } from 'react';
|
import { ChangeEvent, Context } from 'react';
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
||||||
import { filterDropdownSearchInputScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSearchInputScopedState';
|
import { filterDropdownSearchInputScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSearchInputScopedState';
|
||||||
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
|
||||||
|
|
||||||
export function FilterDropdownEntitySearchInput() {
|
export function FilterDropdownEntitySearchInput({
|
||||||
const [tableFilterDefinitionUsedInDropdown] = useRecoilScopedState(
|
context,
|
||||||
|
}: {
|
||||||
|
context: Context<string | null>;
|
||||||
|
}) {
|
||||||
|
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
|
||||||
filterDefinitionUsedInDropdownScopedState,
|
filterDefinitionUsedInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [selectedOperandInDropdown] = useRecoilScopedState(
|
const [selectedOperandInDropdown] = useRecoilScopedState(
|
||||||
selectedOperandInDropdownScopedState,
|
selectedOperandInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [filterDropdownSearchInput, setFilterDropdownSearchInput] =
|
const [filterDropdownSearchInput, setFilterDropdownSearchInput] =
|
||||||
useRecoilScopedState(filterDropdownSearchInputScopedState, TableContext);
|
useRecoilScopedState(filterDropdownSearchInputScopedState, context);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
tableFilterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={filterDropdownSearchInput}
|
value={filterDropdownSearchInput}
|
||||||
placeholder={tableFilterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilterDropdownSearchInput(event.target.value);
|
setFilterDropdownSearchInput(event.target.value);
|
||||||
}}
|
}}
|
@ -10,36 +10,34 @@ import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState'
|
|||||||
import { EntitiesForMultipleEntitySelect } from '@/relation-picker/components/MultipleEntitySelect';
|
import { EntitiesForMultipleEntitySelect } from '@/relation-picker/components/MultipleEntitySelect';
|
||||||
import { SingleEntitySelectBase } from '@/relation-picker/components/SingleEntitySelectBase';
|
import { SingleEntitySelectBase } from '@/relation-picker/components/SingleEntitySelectBase';
|
||||||
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
|
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
|
||||||
|
|
||||||
export function FilterDropdownEntitySearchSelect({
|
export function FilterDropdownEntitySearchSelect({
|
||||||
entitiesForSelect,
|
entitiesForSelect,
|
||||||
|
context,
|
||||||
}: {
|
}: {
|
||||||
entitiesForSelect: EntitiesForMultipleEntitySelect<EntityForSelect>;
|
entitiesForSelect: EntitiesForMultipleEntitySelect<EntityForSelect>;
|
||||||
|
context: React.Context<string | null>;
|
||||||
}) {
|
}) {
|
||||||
const [filterDropdownSelectedEntityId, setFilterDropdownSelectedEntityId] =
|
const [filterDropdownSelectedEntityId, setFilterDropdownSelectedEntityId] =
|
||||||
useRecoilScopedState(
|
useRecoilScopedState(filterDropdownSelectedEntityIdScopedState, context);
|
||||||
filterDropdownSelectedEntityIdScopedState,
|
|
||||||
TableContext,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [selectedOperandInDropdown] = useRecoilScopedState(
|
const [selectedOperandInDropdown] = useRecoilScopedState(
|
||||||
selectedOperandInDropdownScopedState,
|
selectedOperandInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [tableFilterDefinitionUsedInDropdown] = useRecoilScopedState(
|
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
|
||||||
filterDefinitionUsedInDropdownScopedState,
|
filterDefinitionUsedInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const upsertActiveTableFilter = useUpsertFilter(TableContext);
|
const upsertFilter = useUpsertFilter(context);
|
||||||
const removeActiveTableFilter = useRemoveFilter(TableContext);
|
const removeFilter = useRemoveFilter(context);
|
||||||
|
|
||||||
const filterCurrentlyEdited = useFilterCurrentlyEdited(TableContext);
|
const filterCurrentlyEdited = useFilterCurrentlyEdited(context);
|
||||||
|
|
||||||
function handleUserSelected(selectedEntity: EntityForSelect) {
|
function handleUserSelected(selectedEntity: EntityForSelect) {
|
||||||
if (!tableFilterDefinitionUsedInDropdown || !selectedOperandInDropdown) {
|
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,16 +45,16 @@ export function FilterDropdownEntitySearchSelect({
|
|||||||
selectedEntity.id === filterDropdownSelectedEntityId;
|
selectedEntity.id === filterDropdownSelectedEntityId;
|
||||||
|
|
||||||
if (clickedOnAlreadySelectedEntity) {
|
if (clickedOnAlreadySelectedEntity) {
|
||||||
removeActiveTableFilter(tableFilterDefinitionUsedInDropdown.field);
|
removeFilter(filterDefinitionUsedInDropdown.field);
|
||||||
setFilterDropdownSelectedEntityId(null);
|
setFilterDropdownSelectedEntityId(null);
|
||||||
} else {
|
} else {
|
||||||
setFilterDropdownSelectedEntityId(selectedEntity.id);
|
setFilterDropdownSelectedEntityId(selectedEntity.id);
|
||||||
|
|
||||||
upsertActiveTableFilter({
|
upsertFilter({
|
||||||
displayValue: selectedEntity.name,
|
displayValue: selectedEntity.name,
|
||||||
field: tableFilterDefinitionUsedInDropdown.field,
|
field: filterDefinitionUsedInDropdown.field,
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
type: tableFilterDefinitionUsedInDropdown.type,
|
type: filterDefinitionUsedInDropdown.type,
|
||||||
value: selectedEntity.id,
|
value: selectedEntity.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -1,17 +1,21 @@
|
|||||||
|
import { Context } from 'react';
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
||||||
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
import { DropdownMenuSeparator } from '@/ui/components/menu/DropdownMenuSeparator';
|
||||||
|
|
||||||
import { DropdownMenuSeparator } from '../../menu/DropdownMenuSeparator';
|
export function FilterDropdownEntitySelect({
|
||||||
|
context,
|
||||||
export function FilterDropdownEntitySelect() {
|
}: {
|
||||||
const [tableFilterDefinitionUsedInDropdown] = useRecoilScopedState(
|
context: Context<string | null>;
|
||||||
|
}) {
|
||||||
|
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
|
||||||
filterDefinitionUsedInDropdownScopedState,
|
filterDefinitionUsedInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (tableFilterDefinitionUsedInDropdown?.type !== 'entity') {
|
if (filterDefinitionUsedInDropdown?.type !== 'entity') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +23,7 @@ export function FilterDropdownEntitySelect() {
|
|||||||
<>
|
<>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<RecoilScope>
|
<RecoilScope>
|
||||||
{tableFilterDefinitionUsedInDropdown.entitySelectComponent}
|
{filterDefinitionUsedInDropdown.entitySelectComponent}
|
||||||
</RecoilScope>
|
</RecoilScope>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
@ -1,3 +1,5 @@
|
|||||||
|
import { Context } from 'react';
|
||||||
|
|
||||||
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
||||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||||
import { availableFiltersScopedState } from '@/lib/filters-and-sorts/states/availableFiltersScopedState';
|
import { availableFiltersScopedState } from '@/lib/filters-and-sorts/states/availableFiltersScopedState';
|
||||||
@ -7,59 +9,61 @@ import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/st
|
|||||||
import { getOperandsForFilterType } from '@/lib/filters-and-sorts/utils/getOperandsForFilterType';
|
import { getOperandsForFilterType } from '@/lib/filters-and-sorts/utils/getOperandsForFilterType';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { useRecoilScopedValue } from '@/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
import { DropdownMenuItemContainer } from '@/ui/components/menu/DropdownMenuItemContainer';
|
||||||
|
import { DropdownMenuSelectableItem } from '@/ui/components/menu/DropdownMenuSelectableItem';
|
||||||
import { DropdownMenuItemContainer } from '../../menu/DropdownMenuItemContainer';
|
|
||||||
import { DropdownMenuSelectableItem } from '../../menu/DropdownMenuSelectableItem';
|
|
||||||
|
|
||||||
import DropdownButton from './DropdownButton';
|
import DropdownButton from './DropdownButton';
|
||||||
|
|
||||||
export function FilterDropdownFilterSelect() {
|
export function FilterDropdownFilterSelect({
|
||||||
const [, setTableFilterDefinitionUsedInDropdown] = useRecoilScopedState(
|
context,
|
||||||
|
}: {
|
||||||
|
context: Context<string | null>;
|
||||||
|
}) {
|
||||||
|
const [, setFilterDefinitionUsedInDropdown] = useRecoilScopedState(
|
||||||
filterDefinitionUsedInDropdownScopedState,
|
filterDefinitionUsedInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [, setSelectedOperandInDropdown] = useRecoilScopedState(
|
const [, setSelectedOperandInDropdown] = useRecoilScopedState(
|
||||||
selectedOperandInDropdownScopedState,
|
selectedOperandInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [, setFilterDropdownSearchInput] = useRecoilScopedState(
|
const [, setFilterDropdownSearchInput] = useRecoilScopedState(
|
||||||
filterDropdownSearchInputScopedState,
|
filterDropdownSearchInputScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const availableTableFilters = useRecoilScopedValue(
|
const availableFilters = useRecoilScopedValue(
|
||||||
availableFiltersScopedState,
|
availableFiltersScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const setHotkeysScope = useSetHotkeysScope();
|
const setHotkeysScope = useSetHotkeysScope();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenuItemContainer style={{ maxHeight: '300px' }}>
|
<DropdownMenuItemContainer style={{ maxHeight: '300px' }}>
|
||||||
{availableTableFilters.map((availableTableFilter, index) => (
|
{availableFilters.map((availableFilter, index) => (
|
||||||
<DropdownMenuSelectableItem
|
<DropdownMenuSelectableItem
|
||||||
key={`select-filter-${index}`}
|
key={`select-filter-${index}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTableFilterDefinitionUsedInDropdown(availableTableFilter);
|
setFilterDefinitionUsedInDropdown(availableFilter);
|
||||||
|
|
||||||
if (availableTableFilter.type === 'entity') {
|
if (availableFilter.type === 'entity') {
|
||||||
setHotkeysScope(InternalHotkeysScope.RelationPicker);
|
setHotkeysScope(InternalHotkeysScope.RelationPicker);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedOperandInDropdown(
|
setSelectedOperandInDropdown(
|
||||||
getOperandsForFilterType(availableTableFilter.type)?.[0],
|
getOperandsForFilterType(availableFilter.type)?.[0],
|
||||||
);
|
);
|
||||||
|
|
||||||
setFilterDropdownSearchInput('');
|
setFilterDropdownSearchInput('');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DropdownButton.StyledIcon>
|
<DropdownButton.StyledIcon>
|
||||||
{availableTableFilter.icon}
|
{availableFilter.icon}
|
||||||
</DropdownButton.StyledIcon>
|
</DropdownButton.StyledIcon>
|
||||||
{availableTableFilter.label}
|
{availableFilter.label}
|
||||||
</DropdownMenuSelectableItem>
|
</DropdownMenuSelectableItem>
|
||||||
))}
|
))}
|
||||||
</DropdownMenuItemContainer>
|
</DropdownMenuItemContainer>
|
@ -1,39 +1,42 @@
|
|||||||
import { ChangeEvent } from 'react';
|
import { ChangeEvent, Context } from 'react';
|
||||||
|
|
||||||
import { useRemoveFilter } from '@/lib/filters-and-sorts/hooks/useRemoveFilter';
|
import { useRemoveFilter } from '@/lib/filters-and-sorts/hooks/useRemoveFilter';
|
||||||
import { useUpsertFilter } from '@/lib/filters-and-sorts/hooks/useUpsertFilter';
|
import { useUpsertFilter } from '@/lib/filters-and-sorts/hooks/useUpsertFilter';
|
||||||
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
||||||
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
|
||||||
|
|
||||||
export function FilterDropdownNumberSearchInput() {
|
export function FilterDropdownNumberSearchInput({
|
||||||
const [tableFilterDefinitionUsedInDropdown] = useRecoilScopedState(
|
context,
|
||||||
|
}: {
|
||||||
|
context: Context<string | null>;
|
||||||
|
}) {
|
||||||
|
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
|
||||||
filterDefinitionUsedInDropdownScopedState,
|
filterDefinitionUsedInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [selectedOperandInDropdown] = useRecoilScopedState(
|
const [selectedOperandInDropdown] = useRecoilScopedState(
|
||||||
selectedOperandInDropdownScopedState,
|
selectedOperandInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const upsertActiveTableFilter = useUpsertFilter(TableContext);
|
const upsertFilter = useUpsertFilter(context);
|
||||||
const removeActiveTableFilter = useRemoveFilter(TableContext);
|
const removeFilter = useRemoveFilter(context);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
tableFilterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder={tableFilterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
if (event.target.value === '') {
|
if (event.target.value === '') {
|
||||||
removeActiveTableFilter(tableFilterDefinitionUsedInDropdown.field);
|
removeFilter(filterDefinitionUsedInDropdown.field);
|
||||||
} else {
|
} else {
|
||||||
upsertActiveTableFilter({
|
upsertFilter({
|
||||||
field: tableFilterDefinitionUsedInDropdown.field,
|
field: filterDefinitionUsedInDropdown.field,
|
||||||
type: tableFilterDefinitionUsedInDropdown.type,
|
type: filterDefinitionUsedInDropdown.type,
|
||||||
value: event.target.value,
|
value: event.target.value,
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: event.target.value,
|
displayValue: event.target.value,
|
@ -1,21 +1,26 @@
|
|||||||
|
import { Context } from 'react';
|
||||||
|
|
||||||
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '@/lib/filters-and-sorts/states/isFilterDropdownOperandSelectUnfoldedScopedState';
|
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '@/lib/filters-and-sorts/states/isFilterDropdownOperandSelectUnfoldedScopedState';
|
||||||
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
||||||
import { getOperandLabel } from '@/lib/filters-and-sorts/utils/getOperandLabel';
|
import { getOperandLabel } from '@/lib/filters-and-sorts/utils/getOperandLabel';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
|
||||||
|
|
||||||
import DropdownButton from './DropdownButton';
|
import DropdownButton from './DropdownButton';
|
||||||
|
|
||||||
export function FilterDropdownOperandButton() {
|
export function FilterDropdownOperandButton({
|
||||||
|
context,
|
||||||
|
}: {
|
||||||
|
context: Context<string | null>;
|
||||||
|
}) {
|
||||||
const [selectedOperandInDropdown] = useRecoilScopedState(
|
const [selectedOperandInDropdown] = useRecoilScopedState(
|
||||||
selectedOperandInDropdownScopedState,
|
selectedOperandInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [isOperandSelectionUnfolded, setIsOperandSelectionUnfolded] =
|
const [isOperandSelectionUnfolded, setIsOperandSelectionUnfolded] =
|
||||||
useRecoilScopedState(
|
useRecoilScopedState(
|
||||||
isFilterDropdownOperandSelectUnfoldedScopedState,
|
isFilterDropdownOperandSelectUnfoldedScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isOperandSelectionUnfolded) {
|
if (isOperandSelectionUnfolded) {
|
@ -1,3 +1,5 @@
|
|||||||
|
import { Context } from 'react';
|
||||||
|
|
||||||
import { useFilterCurrentlyEdited } from '@/lib/filters-and-sorts/hooks/useFilterCurrentlyEdited';
|
import { useFilterCurrentlyEdited } from '@/lib/filters-and-sorts/hooks/useFilterCurrentlyEdited';
|
||||||
import { useUpsertFilter } from '@/lib/filters-and-sorts/hooks/useUpsertFilter';
|
import { useUpsertFilter } from '@/lib/filters-and-sorts/hooks/useUpsertFilter';
|
||||||
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sorts/states/filterDefinitionUsedInDropdownScopedState';
|
||||||
@ -7,52 +9,50 @@ import { FilterOperand } from '@/lib/filters-and-sorts/types/FilterOperand';
|
|||||||
import { getOperandLabel } from '@/lib/filters-and-sorts/utils/getOperandLabel';
|
import { getOperandLabel } from '@/lib/filters-and-sorts/utils/getOperandLabel';
|
||||||
import { getOperandsForFilterType } from '@/lib/filters-and-sorts/utils/getOperandsForFilterType';
|
import { getOperandsForFilterType } from '@/lib/filters-and-sorts/utils/getOperandsForFilterType';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
import { DropdownMenuItemContainer } from '@/ui/components/menu/DropdownMenuItemContainer';
|
||||||
|
|
||||||
import { DropdownMenuItemContainer } from '../../menu/DropdownMenuItemContainer';
|
|
||||||
|
|
||||||
import DropdownButton from './DropdownButton';
|
import DropdownButton from './DropdownButton';
|
||||||
|
|
||||||
export function FilterDropdownOperandSelect() {
|
export function FilterDropdownOperandSelect({
|
||||||
const [tableFilterDefinitionUsedInDropdown] = useRecoilScopedState(
|
context,
|
||||||
|
}: {
|
||||||
|
context: Context<string | null>;
|
||||||
|
}) {
|
||||||
|
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
|
||||||
filterDefinitionUsedInDropdownScopedState,
|
filterDefinitionUsedInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [, setSelectedOperandInDropdown] = useRecoilScopedState(
|
const [, setSelectedOperandInDropdown] = useRecoilScopedState(
|
||||||
selectedOperandInDropdownScopedState,
|
selectedOperandInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const operandsForFilterType = getOperandsForFilterType(
|
const operandsForFilterType = getOperandsForFilterType(
|
||||||
tableFilterDefinitionUsedInDropdown?.type,
|
filterDefinitionUsedInDropdown?.type,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [isOperandSelectionUnfolded, setIsOperandSelectionUnfolded] =
|
const [isOperandSelectionUnfolded, setIsOperandSelectionUnfolded] =
|
||||||
useRecoilScopedState(
|
useRecoilScopedState(
|
||||||
isFilterDropdownOperandSelectUnfoldedScopedState,
|
isFilterDropdownOperandSelectUnfoldedScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const activeTableFilterCurrentlyEdited =
|
const filterCurrentlyEdited = useFilterCurrentlyEdited(context);
|
||||||
useFilterCurrentlyEdited(TableContext);
|
|
||||||
|
|
||||||
const upsertActiveTableFilter = useUpsertFilter(TableContext);
|
const upsertFilter = useUpsertFilter(context);
|
||||||
|
|
||||||
function handleOperangeChange(newOperand: FilterOperand) {
|
function handleOperangeChange(newOperand: FilterOperand) {
|
||||||
setSelectedOperandInDropdown(newOperand);
|
setSelectedOperandInDropdown(newOperand);
|
||||||
setIsOperandSelectionUnfolded(false);
|
setIsOperandSelectionUnfolded(false);
|
||||||
|
|
||||||
if (
|
if (filterDefinitionUsedInDropdown && filterCurrentlyEdited) {
|
||||||
tableFilterDefinitionUsedInDropdown &&
|
upsertFilter({
|
||||||
activeTableFilterCurrentlyEdited
|
field: filterCurrentlyEdited.field,
|
||||||
) {
|
displayValue: filterCurrentlyEdited.displayValue,
|
||||||
upsertActiveTableFilter({
|
|
||||||
field: activeTableFilterCurrentlyEdited.field,
|
|
||||||
displayValue: activeTableFilterCurrentlyEdited.displayValue,
|
|
||||||
operand: newOperand,
|
operand: newOperand,
|
||||||
type: activeTableFilterCurrentlyEdited.type,
|
type: filterCurrentlyEdited.type,
|
||||||
value: activeTableFilterCurrentlyEdited.value,
|
value: filterCurrentlyEdited.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { ChangeEvent } from 'react';
|
import { ChangeEvent, Context } from 'react';
|
||||||
|
|
||||||
import { useFilterCurrentlyEdited } from '@/lib/filters-and-sorts/hooks/useFilterCurrentlyEdited';
|
import { useFilterCurrentlyEdited } from '@/lib/filters-and-sorts/hooks/useFilterCurrentlyEdited';
|
||||||
import { useRemoveFilter } from '@/lib/filters-and-sorts/hooks/useRemoveFilter';
|
import { useRemoveFilter } from '@/lib/filters-and-sorts/hooks/useRemoveFilter';
|
||||||
@ -7,43 +7,46 @@ import { filterDefinitionUsedInDropdownScopedState } from '@/lib/filters-and-sor
|
|||||||
import { filterDropdownSearchInputScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSearchInputScopedState';
|
import { filterDropdownSearchInputScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSearchInputScopedState';
|
||||||
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
import { selectedOperandInDropdownScopedState } from '@/lib/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
|
||||||
|
|
||||||
export function FilterDropdownTextSearchInput() {
|
export function FilterDropdownTextSearchInput({
|
||||||
const [tableFilterDefinitionUsedInDropdown] = useRecoilScopedState(
|
context,
|
||||||
|
}: {
|
||||||
|
context: Context<string | null>;
|
||||||
|
}) {
|
||||||
|
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
|
||||||
filterDefinitionUsedInDropdownScopedState,
|
filterDefinitionUsedInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [selectedOperandInDropdown] = useRecoilScopedState(
|
const [selectedOperandInDropdown] = useRecoilScopedState(
|
||||||
selectedOperandInDropdownScopedState,
|
selectedOperandInDropdownScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [filterDropdownSearchInput, setFilterDropdownSearchInput] =
|
const [filterDropdownSearchInput, setFilterDropdownSearchInput] =
|
||||||
useRecoilScopedState(filterDropdownSearchInputScopedState, TableContext);
|
useRecoilScopedState(filterDropdownSearchInputScopedState, context);
|
||||||
|
|
||||||
const upsertActiveTableFilter = useUpsertFilter(TableContext);
|
const upsertFilter = useUpsertFilter(context);
|
||||||
const removeActiveTableFilter = useRemoveFilter(TableContext);
|
const removeFilter = useRemoveFilter(context);
|
||||||
|
|
||||||
const filterCurrentlyEdited = useFilterCurrentlyEdited(TableContext);
|
const filterCurrentlyEdited = useFilterCurrentlyEdited(context);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
tableFilterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={tableFilterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
value={filterCurrentlyEdited?.value ?? filterDropdownSearchInput}
|
value={filterCurrentlyEdited?.value ?? filterDropdownSearchInput}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilterDropdownSearchInput(event.target.value);
|
setFilterDropdownSearchInput(event.target.value);
|
||||||
|
|
||||||
if (event.target.value === '') {
|
if (event.target.value === '') {
|
||||||
removeActiveTableFilter(tableFilterDefinitionUsedInDropdown.field);
|
removeFilter(filterDefinitionUsedInDropdown.field);
|
||||||
} else {
|
} else {
|
||||||
upsertActiveTableFilter({
|
upsertFilter({
|
||||||
field: tableFilterDefinitionUsedInDropdown.field,
|
field: filterDefinitionUsedInDropdown.field,
|
||||||
type: tableFilterDefinitionUsedInDropdown.type,
|
type: filterDefinitionUsedInDropdown.type,
|
||||||
value: event.target.value,
|
value: event.target.value,
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: event.target.value,
|
displayValue: event.target.value,
|
@ -1,6 +1,8 @@
|
|||||||
|
import { Context } from 'react';
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import SortOrFilterChip from '@/lib/filters-and-sorts/components/SortOrFilterChip';
|
||||||
import { useRemoveFilter } from '@/lib/filters-and-sorts/hooks/useRemoveFilter';
|
import { useRemoveFilter } from '@/lib/filters-and-sorts/hooks/useRemoveFilter';
|
||||||
import { SelectedSortType } from '@/lib/filters-and-sorts/interfaces/sorts/interface';
|
import { SelectedSortType } from '@/lib/filters-and-sorts/interfaces/sorts/interface';
|
||||||
import { availableFiltersScopedState } from '@/lib/filters-and-sorts/states/availableFiltersScopedState';
|
import { availableFiltersScopedState } from '@/lib/filters-and-sorts/states/availableFiltersScopedState';
|
||||||
@ -8,11 +10,9 @@ import { filtersScopedState } from '@/lib/filters-and-sorts/states/filtersScoped
|
|||||||
import { getOperandLabel } from '@/lib/filters-and-sorts/utils/getOperandLabel';
|
import { getOperandLabel } from '@/lib/filters-and-sorts/utils/getOperandLabel';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { IconArrowNarrowDown, IconArrowNarrowUp } from '@/ui/icons/index';
|
import { IconArrowNarrowDown, IconArrowNarrowUp } from '@/ui/icons/index';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
|
||||||
|
|
||||||
import SortOrFilterChip from './SortOrFilterChip';
|
|
||||||
|
|
||||||
type OwnProps<SortField> = {
|
type OwnProps<SortField> = {
|
||||||
|
context: Context<string | null>;
|
||||||
sorts: Array<SelectedSortType<SortField>>;
|
sorts: Array<SelectedSortType<SortField>>;
|
||||||
onRemoveSort: (sortId: SelectedSortType<SortField>['key']) => void;
|
onRemoveSort: (sortId: SelectedSortType<SortField>['key']) => void;
|
||||||
onCancelClick: () => void;
|
onCancelClick: () => void;
|
||||||
@ -60,6 +60,7 @@ const StyledCancelButton = styled.button`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
function SortAndFilterBar<SortField>({
|
function SortAndFilterBar<SortField>({
|
||||||
|
context,
|
||||||
sorts,
|
sorts,
|
||||||
onRemoveSort,
|
onRemoveSort,
|
||||||
onCancelClick,
|
onCancelClick,
|
||||||
@ -68,26 +69,26 @@ function SortAndFilterBar<SortField>({
|
|||||||
|
|
||||||
const [filters, setFilters] = useRecoilScopedState(
|
const [filters, setFilters] = useRecoilScopedState(
|
||||||
filtersScopedState,
|
filtersScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [availableFilters] = useRecoilScopedState(
|
const [availableFilters] = useRecoilScopedState(
|
||||||
availableFiltersScopedState,
|
availableFiltersScopedState,
|
||||||
TableContext,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filtersWithDefinition = filters.map((filter) => {
|
const filtersWithDefinition = filters.map((filter) => {
|
||||||
const tableFilterDefinition = availableFilters.find((availableFilter) => {
|
const filterDefinition = availableFilters.find((availableFilter) => {
|
||||||
return availableFilter.field === filter.field;
|
return availableFilter.field === filter.field;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...filter,
|
...filter,
|
||||||
...tableFilterDefinition,
|
...filterDefinition,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const removeFilter = useRemoveFilter(TableContext);
|
const removeFilter = useRemoveFilter(context);
|
||||||
|
|
||||||
function handleCancelClick() {
|
function handleCancelClick() {
|
||||||
setFilters([]);
|
setFilters([]);
|
@ -1,5 +1,6 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
|
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||||
import {
|
import {
|
||||||
SelectedSortType,
|
SelectedSortType,
|
||||||
SortType,
|
SortType,
|
||||||
@ -11,6 +12,7 @@ type OwnProps<SortField> = {
|
|||||||
isSortSelected: boolean;
|
isSortSelected: boolean;
|
||||||
onSortSelect: (sort: SelectedSortType<SortField>) => void;
|
onSortSelect: (sort: SelectedSortType<SortField>) => void;
|
||||||
availableSorts: SortType<SortField>[];
|
availableSorts: SortType<SortField>[];
|
||||||
|
hotkeysScope: InternalHotkeysScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
const options: Array<SelectedSortType<any>['order']> = ['asc', 'desc'];
|
const options: Array<SelectedSortType<any>['order']> = ['asc', 'desc'];
|
||||||
@ -19,6 +21,7 @@ export function SortDropdownButton<SortField>({
|
|||||||
isSortSelected,
|
isSortSelected,
|
||||||
availableSorts,
|
availableSorts,
|
||||||
onSortSelect,
|
onSortSelect,
|
||||||
|
hotkeysScope,
|
||||||
}: OwnProps<SortField>) {
|
}: OwnProps<SortField>) {
|
||||||
const [isUnfolded, setIsUnfolded] = useState(false);
|
const [isUnfolded, setIsUnfolded] = useState(false);
|
||||||
|
|
||||||
@ -54,6 +57,7 @@ export function SortDropdownButton<SortField>({
|
|||||||
isActive={isSortSelected}
|
isActive={isSortSelected}
|
||||||
isUnfolded={isUnfolded}
|
isUnfolded={isUnfolded}
|
||||||
onIsUnfoldedChange={handleIsUnfoldedChange}
|
onIsUnfoldedChange={handleIsUnfoldedChange}
|
||||||
|
hotkeysScope={hotkeysScope}
|
||||||
>
|
>
|
||||||
{isOptionUnfolded
|
{isOptionUnfolded
|
||||||
? options.map((option, index) => (
|
? options.map((option, index) => (
|
@ -1,14 +1,15 @@
|
|||||||
import { ReactNode, useCallback, useState } from 'react';
|
import { ReactNode, useCallback, useState } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||||
|
import { FilterDropdownButton } from '@/lib/filters-and-sorts/components/FilterDropdownButton';
|
||||||
|
import SortAndFilterBar from '@/lib/filters-and-sorts/components/SortAndFilterBar';
|
||||||
|
import { SortDropdownButton } from '@/lib/filters-and-sorts/components/SortDropdownButton';
|
||||||
import {
|
import {
|
||||||
SelectedSortType,
|
SelectedSortType,
|
||||||
SortType,
|
SortType,
|
||||||
} from '@/lib/filters-and-sorts/interfaces/sorts/interface';
|
} from '@/lib/filters-and-sorts/interfaces/sorts/interface';
|
||||||
|
import { TableContext } from '@/ui/tables/states/TableContext';
|
||||||
import { FilterDropdownButton } from './FilterDropdownButton';
|
|
||||||
import SortAndFilterBar from './SortAndFilterBar';
|
|
||||||
import { SortDropdownButton } from './SortDropdownButton';
|
|
||||||
|
|
||||||
type OwnProps<SortField> = {
|
type OwnProps<SortField> = {
|
||||||
viewName: string;
|
viewName: string;
|
||||||
@ -89,15 +90,20 @@ export function TableHeader<SortField>({
|
|||||||
{viewName}
|
{viewName}
|
||||||
</StyledViewSection>
|
</StyledViewSection>
|
||||||
<StyledFilters>
|
<StyledFilters>
|
||||||
<FilterDropdownButton />
|
<FilterDropdownButton
|
||||||
|
context={TableContext}
|
||||||
|
hotkeysScope={InternalHotkeysScope.TableHeaderDropdownButton}
|
||||||
|
/>
|
||||||
<SortDropdownButton<SortField>
|
<SortDropdownButton<SortField>
|
||||||
isSortSelected={sorts.length > 0}
|
isSortSelected={sorts.length > 0}
|
||||||
availableSorts={availableSorts || []}
|
availableSorts={availableSorts || []}
|
||||||
onSortSelect={sortSelect}
|
onSortSelect={sortSelect}
|
||||||
|
hotkeysScope={InternalHotkeysScope.TableHeaderDropdownButton}
|
||||||
/>
|
/>
|
||||||
</StyledFilters>
|
</StyledFilters>
|
||||||
</StyledTableHeader>
|
</StyledTableHeader>
|
||||||
<SortAndFilterBar
|
<SortAndFilterBar
|
||||||
|
context={TableContext}
|
||||||
sorts={sorts}
|
sorts={sorts}
|
||||||
onRemoveSort={sortUnselect}
|
onRemoveSort={sortUnselect}
|
||||||
onCancelClick={() => {
|
onCancelClick={() => {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
import { FilterDropdownEntitySearchSelect } from '@/lib/filters-and-sorts/components/FilterDropdownEntitySearchSelect';
|
||||||
import { filterDropdownSearchInputScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSearchInputScopedState';
|
import { filterDropdownSearchInputScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSearchInputScopedState';
|
||||||
import { filterDropdownSelectedEntityIdScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSelectedEntityIdScopedState';
|
import { filterDropdownSelectedEntityIdScopedState } from '@/lib/filters-and-sorts/states/filterDropdownSelectedEntityIdScopedState';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { useRecoilScopedValue } from '@/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import { useFilteredSearchEntityQuery } from '@/relation-picker/hooks/useFilteredSearchEntityQuery';
|
import { useFilteredSearchEntityQuery } from '@/relation-picker/hooks/useFilteredSearchEntityQuery';
|
||||||
import { Entity } from '@/relation-picker/types/EntityTypeForSelect';
|
import { Entity } from '@/relation-picker/types/EntityTypeForSelect';
|
||||||
import { FilterDropdownEntitySearchSelect } from '@/ui/components/table/table-header/FilterDropdownEntitySearchSelect';
|
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
import { TableContext } from '@/ui/tables/states/TableContext';
|
||||||
import { useSearchUserQuery } from '~/generated/graphql';
|
import { useSearchUserQuery } from '~/generated/graphql';
|
||||||
|
|
||||||
@ -36,6 +36,9 @@ export function FilterDropdownUserSearchSelect() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FilterDropdownEntitySearchSelect entitiesForSelect={usersForSelect} />
|
<FilterDropdownEntitySearchSelect
|
||||||
|
entitiesForSelect={usersForSelect}
|
||||||
|
context={TableContext}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user