[ESLint rule]: recoil value and setter should be named after their at… (#1402)

* Override unwanted changes

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>

* Fix the tests

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>

---------

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
This commit is contained in:
gitstart-twenty
2023-09-05 11:34:11 +03:00
committed by GitHub
parent 0ec4b78aee
commit 878302dd31
52 changed files with 400 additions and 281 deletions

View File

@ -49,6 +49,7 @@ module.exports = {
'twenty/sort-css-properties-alphabetically': 'error', 'twenty/sort-css-properties-alphabetically': 'error',
'twenty/no-hardcoded-colors': 'error', 'twenty/no-hardcoded-colors': 'error',
'twenty/styled-components-prefixed-with-styled': 'error', 'twenty/styled-components-prefixed-with-styled': 'error',
'twenty/matching-state-variable': 'error',
'func-style':['error', 'declaration', { 'allowArrowFunctions': true }], 'func-style':['error', 'declaration', { 'allowArrowFunctions': true }],
"@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "off",
"no-unused-vars": "off", "no-unused-vars": "off",

View File

@ -32,7 +32,7 @@ export function ActivityAssigneePicker({
onSubmit, onSubmit,
onCancel, onCancel,
}: OwnProps) { }: OwnProps) {
const [searchFilter] = useRecoilScopedState( const [relationPickerSearchFilter] = useRecoilScopedState(
relationPickerSearchFilterScopedState, relationPickerSearchFilterScopedState,
); );
const [updateActivity] = useUpdateActivityMutation(); const [updateActivity] = useUpdateActivityMutation();
@ -40,7 +40,7 @@ export function ActivityAssigneePicker({
const users = useFilteredSearchEntityQuery({ const users = useFilteredSearchEntityQuery({
queryHook: useSearchUserQuery, queryHook: useSearchUserQuery,
selectedIds: activity?.accountOwner?.id ? [activity?.accountOwner?.id] : [], selectedIds: activity?.accountOwner?.id ? [activity?.accountOwner?.id] : [],
searchFilter: searchFilter, searchFilter: relationPickerSearchFilter,
mappingFunction: (user) => ({ mappingFunction: (user) => ({
entityType: Entity.User, entityType: Entity.User,
id: user.id, id: user.id,

View File

@ -11,7 +11,7 @@ import {
import { useOpenCreateActivityDrawer } from './useOpenCreateActivityDrawer'; import { useOpenCreateActivityDrawer } from './useOpenCreateActivityDrawer';
export function useOpenCreateActivityDrawerForSelectedRowIds() { export function useOpenCreateActivityDrawerForSelectedRowIds() {
const selectedEntityIds = useRecoilValue(selectedRowIdsSelector); const selectedRowIds = useRecoilValue(selectedRowIdsSelector);
const openCreateActivityDrawer = useOpenCreateActivityDrawer(); const openCreateActivityDrawer = useOpenCreateActivityDrawer();
@ -20,7 +20,7 @@ export function useOpenCreateActivityDrawerForSelectedRowIds() {
entityType: ActivityTargetableEntityType, entityType: ActivityTargetableEntityType,
) { ) {
const activityTargetableEntityArray: ActivityTargetableEntity[] = const activityTargetableEntityArray: ActivityTargetableEntity[] =
selectedEntityIds.map((id) => ({ selectedRowIds.map((id) => ({
type: entityType, type: entityType,
id, id,
})); }));

View File

@ -5,13 +5,13 @@ import { viewableActivityIdState } from '@/activities/states/viewableActivityIdS
import { RightDrawerActivity } from '../RightDrawerActivity'; import { RightDrawerActivity } from '../RightDrawerActivity';
export function RightDrawerCreateActivity() { export function RightDrawerCreateActivity() {
const activityId = useRecoilValue(viewableActivityIdState); const viewableActivityId = useRecoilValue(viewableActivityIdState);
return ( return (
<> <>
{activityId && ( {viewableActivityId && (
<RightDrawerActivity <RightDrawerActivity
activityId={activityId} activityId={viewableActivityId}
showComment={false} showComment={false}
autoFillTitle={true} autoFillTitle={true}
/> />

View File

@ -5,7 +5,13 @@ import { viewableActivityIdState } from '@/activities/states/viewableActivityIdS
import { RightDrawerActivity } from '../RightDrawerActivity'; import { RightDrawerActivity } from '../RightDrawerActivity';
export function RightDrawerEditActivity() { export function RightDrawerEditActivity() {
const activityId = useRecoilValue(viewableActivityIdState); const viewableActivityId = useRecoilValue(viewableActivityIdState);
return <>{activityId && <RightDrawerActivity activityId={activityId} />}</>; return (
<>
{viewableActivityId && (
<RightDrawerActivity activityId={viewableActivityId} />
)}
</>
);
} }

View File

@ -12,8 +12,8 @@ export const ClientConfigProvider: React.FC<React.PropsWithChildren> = ({
children, children,
}) => { }) => {
const [, setAuthProviders] = useRecoilState(authProvidersState); const [, setAuthProviders] = useRecoilState(authProvidersState);
const [, setDebugMode] = useRecoilState(isDebugModeState); const [, setIsDebugMode] = useRecoilState(isDebugModeState);
const [, setSignInPrefilled] = useRecoilState(isSignInPrefilledState); const [, setIsSignInPrefilled] = useRecoilState(isSignInPrefilledState);
const [, setTelemetry] = useRecoilState(telemetryState); const [, setTelemetry] = useRecoilState(telemetryState);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const setSupportChat = useSetRecoilState(supportChatState); const setSupportChat = useSetRecoilState(supportChatState);
@ -30,16 +30,16 @@ export const ClientConfigProvider: React.FC<React.PropsWithChildren> = ({
password: data?.clientConfig.authProviders.password, password: data?.clientConfig.authProviders.password,
magicLink: false, magicLink: false,
}); });
setDebugMode(data?.clientConfig.debugMode); setIsDebugMode(data?.clientConfig.debugMode);
setSignInPrefilled(data?.clientConfig.signInPrefilled); setIsSignInPrefilled(data?.clientConfig.signInPrefilled);
setTelemetry(data?.clientConfig.telemetry); setTelemetry(data?.clientConfig.telemetry);
setSupportChat(data?.clientConfig.support); setSupportChat(data?.clientConfig.support);
} }
}, [ }, [
data, data,
setAuthProviders, setAuthProviders,
setDebugMode, setIsDebugMode,
setSignInPrefilled, setIsSignInPrefilled,
setTelemetry, setTelemetry,
setIsLoading, setIsLoading,
loading, loading,

View File

@ -33,7 +33,7 @@ export function CommandMenu() {
const openActivityRightDrawer = useOpenActivityRightDrawer(); const openActivityRightDrawer = useOpenActivityRightDrawer();
const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState); const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState);
const [search, setSearch] = useState(''); const [search, setSearch] = useState('');
const commands = useRecoilValue(commandMenuCommandsState); const commandMenuCommands = useRecoilValue(commandMenuCommandsState);
useScopedHotkeys( useScopedHotkeys(
'ctrl+k,meta+k', 'ctrl+k,meta+k',
@ -80,13 +80,13 @@ export function CommandMenu() {
}); });
const activities = activityData?.searchResults ?? []; const activities = activityData?.searchResults ?? [];
const matchingNavigateCommand = commands.find( const matchingNavigateCommand = commandMenuCommands.find(
(cmd) => (cmd) =>
cmd.shortcuts?.join('') === search?.toUpperCase() && cmd.shortcuts?.join('') === search?.toUpperCase() &&
cmd.type === CommandType.Navigate, cmd.type === CommandType.Navigate,
); );
const matchingCreateCommand = commands.find( const matchingCreateCommand = commandMenuCommands.find(
(cmd) => (cmd) =>
cmd.shortcuts?.join('') === search?.toUpperCase() && cmd.shortcuts?.join('') === search?.toUpperCase() &&
cmd.type === CommandType.Create, cmd.type === CommandType.Create,
@ -112,7 +112,7 @@ export function CommandMenu() {
<StyledEmpty>No results found.</StyledEmpty> <StyledEmpty>No results found.</StyledEmpty>
{!matchingCreateCommand && ( {!matchingCreateCommand && (
<StyledGroup heading="Create"> <StyledGroup heading="Create">
{commands {commandMenuCommands
.filter((cmd) => cmd.type === CommandType.Create) .filter((cmd) => cmd.type === CommandType.Create)
.map((cmd) => ( .map((cmd) => (
<CommandMenuItem <CommandMenuItem
@ -200,7 +200,7 @@ export function CommandMenu() {
)} )}
{!matchingNavigateCommand && ( {!matchingNavigateCommand && (
<StyledGroup heading="Navigate"> <StyledGroup heading="Navigate">
{commands {commandMenuCommands
.filter( .filter(
(cmd) => (cmd) =>
(cmd.shortcuts?.join('').includes(search?.toUpperCase()) || (cmd.shortcuts?.join('').includes(search?.toUpperCase()) ||

View File

@ -9,9 +9,7 @@ import { isCommandMenuOpenedState } from '../states/isCommandMenuOpenedState';
import { Command } from '../types/Command'; import { Command } from '../types/Command';
export function useCommandMenu() { export function useCommandMenu() {
const [, setIsCommandMenuOpenedState] = useRecoilState( const [, setIsCommandMenuOpened] = useRecoilState(isCommandMenuOpenedState);
isCommandMenuOpenedState,
);
const setCommands = useSetRecoilState(commandMenuCommandsState); const setCommands = useSetRecoilState(commandMenuCommandsState);
const { const {
setHotkeyScopeAndMemorizePreviousScope, setHotkeyScopeAndMemorizePreviousScope,
@ -19,12 +17,12 @@ export function useCommandMenu() {
} = usePreviousHotkeyScope(); } = usePreviousHotkeyScope();
function openCommandMenu() { function openCommandMenu() {
setIsCommandMenuOpenedState(true); setIsCommandMenuOpened(true);
setHotkeyScopeAndMemorizePreviousScope(AppHotkeyScope.CommandMenu); setHotkeyScopeAndMemorizePreviousScope(AppHotkeyScope.CommandMenu);
} }
function closeCommandMenu() { function closeCommandMenu() {
setIsCommandMenuOpenedState(false); setIsCommandMenuOpened(false);
goBackToPreviousHotkeyScope(); goBackToPreviousHotkeyScope();
} }

View File

@ -14,12 +14,11 @@ export type OwnProps = {
}; };
export function CompanyPicker({ companyId, onSubmit, onCancel }: OwnProps) { export function CompanyPicker({ companyId, onSubmit, onCancel }: OwnProps) {
const [searchFilter, setSearchFilter] = useRecoilScopedState( const [relationPickerSearchFilter, setRelationPickerSearchFilter] =
relationPickerSearchFilterScopedState, useRecoilScopedState(relationPickerSearchFilterScopedState);
);
const companies = useFilteredSearchCompanyQuery({ const companies = useFilteredSearchCompanyQuery({
searchFilter, searchFilter: relationPickerSearchFilter,
selectedIds: companyId ? [companyId] : [], selectedIds: companyId ? [companyId] : [],
}); });
@ -30,8 +29,8 @@ export function CompanyPicker({ companyId, onSubmit, onCancel }: OwnProps) {
} }
useEffect(() => { useEffect(() => {
setSearchFilter(''); setRelationPickerSearchFilter('');
}, [setSearchFilter]); }, [setRelationPickerSearchFilter]);
return ( return (
<SingleEntitySelect <SingleEntitySelect

View File

@ -29,20 +29,20 @@ export function CompanyPickerCell({
createModeEnabled, createModeEnabled,
width, width,
}: OwnProps) { }: OwnProps) {
const [isCreating, setIsCreating] = useRecoilScopedState( const [isCreateMode, setIsCreateMode] = useRecoilScopedState(
isCreateModeScopedState, isCreateModeScopedState,
); );
const [insertCompany] = useInsertOneCompanyMutation(); const [insertCompany] = useInsertOneCompanyMutation();
const [searchFilter] = useRecoilScopedState( const [relationPickerSearchFilter] = useRecoilScopedState(
relationPickerSearchFilterScopedState, relationPickerSearchFilterScopedState,
); );
const setHotkeyScope = useSetHotkeyScope(); const setHotkeyScope = useSetHotkeyScope();
const companies = useFilteredSearchCompanyQuery({ const companies = useFilteredSearchCompanyQuery({
searchFilter, searchFilter: relationPickerSearchFilter,
selectedIds: [companyId ?? ''], selectedIds: [companyId ?? ''],
}); });
@ -53,7 +53,7 @@ export function CompanyPickerCell({
} }
function handleStartCreation() { function handleStartCreation() {
setIsCreating(true); setIsCreateMode(true);
setHotkeyScope(TableHotkeyScope.CellDoubleTextInput); setHotkeyScope(TableHotkeyScope.CellDoubleTextInput);
} }
@ -75,7 +75,7 @@ export function CompanyPickerCell({
entityType: Entity.Company, entityType: Entity.Company,
domainName: companyCreated.domainName, domainName: companyCreated.domainName,
}); });
setIsCreating(false); setIsCreateMode(false);
} }
const noCompany: CompanyPickerSelectedCompany = { const noCompany: CompanyPickerSelectedCompany = {
entityType: Entity.Company, entityType: Entity.Company,
@ -85,9 +85,9 @@ export function CompanyPickerCell({
domainName: '', domainName: '',
avatarUrl: '', avatarUrl: '',
}; };
return isCreating ? ( return isCreateMode ? (
<DoubleTextCellEdit <DoubleTextCellEdit
firstValue={searchFilter} firstValue={relationPickerSearchFilter}
secondValue={''} secondValue={''}
firstValuePlaceholder={'Name'} firstValuePlaceholder={'Name'}
secondValuePlaceholder={'Url'} secondValuePlaceholder={'Url'}

View File

@ -12,11 +12,9 @@ import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIn
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { import {
Pipeline,
PipelineProgressableType, PipelineProgressableType,
PipelineProgressOrderByWithRelationInput as PipelineProgresses_Order_By, PipelineProgressOrderByWithRelationInput as PipelineProgresses_Order_By,
} from '~/generated/graphql';
import {
Pipeline,
useGetCompaniesQuery, useGetCompaniesQuery,
useGetPipelineProgressQuery, useGetPipelineProgressQuery,
useGetPipelinesQuery, useGetPipelinesQuery,

View File

@ -53,10 +53,12 @@ export function NewCompanyProgressButton() {
setIsCreatingCard(false); setIsCreatingCard(false);
} }
const [searchFilter] = useRecoilScopedState( const [relationPickerSearchFilter] = useRecoilScopedState(
relationPickerSearchFilterScopedState, relationPickerSearchFilterScopedState,
); );
const companies = useFilteredSearchCompanyQuery({ searchFilter }); const companies = useFilteredSearchCompanyQuery({
searchFilter: relationPickerSearchFilter,
});
return ( return (
<RecoilScope> <RecoilScope>

View File

@ -17,12 +17,12 @@ export function useCreateCompanyProgress() {
], ],
}); });
const [pipeline] = useRecoilState(currentPipelineState); const [currentPipeline] = useRecoilState(currentPipelineState);
return useRecoilCallback( return useRecoilCallback(
({ set }) => ({ set }) =>
async (companyId: string, pipelineStageId: string) => { async (companyId: string, pipelineStageId: string) => {
if (!pipeline?.id) { if (!currentPipeline?.id) {
throw new Error('Pipeline not found'); throw new Error('Pipeline not found');
} }
@ -37,11 +37,11 @@ export function useCreateCompanyProgress() {
variables: { variables: {
uuid: newUuid, uuid: newUuid,
pipelineStageId: pipelineStageId, pipelineStageId: pipelineStageId,
pipelineId: pipeline?.id ?? '', pipelineId: currentPipeline?.id ?? '',
companyId: companyId, companyId: companyId,
}, },
}); });
}, },
[createOneCompanyPipelineProgress, pipeline], [createOneCompanyPipelineProgress, currentPipeline],
); );
} }

View File

@ -21,11 +21,11 @@ import { companiesFilters } from '~/pages/companies/companies-filters';
import { availableSorts } from '~/pages/companies/companies-sorts'; import { availableSorts } from '~/pages/companies/companies-sorts';
export function CompanyTable() { export function CompanyTable() {
const orderBy = useRecoilScopedValue( const sortsOrderBy = useRecoilScopedValue(
sortsOrderByScopedSelector, sortsOrderByScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const whereFilters = useRecoilScopedValue( const filtersWhere = useRecoilScopedValue(
filtersWhereScopedSelector, filtersWhereScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -55,8 +55,10 @@ export function CompanyTable() {
getRequestResultKey="companies" getRequestResultKey="companies"
useGetRequest={useGetCompaniesQuery} useGetRequest={useGetCompaniesQuery}
getRequestOptimisticEffect={getCompaniesOptimisticEffect} getRequestOptimisticEffect={getCompaniesOptimisticEffect}
orderBy={orderBy.length ? orderBy : [{ createdAt: SortOrder.Desc }]} orderBy={
whereFilters={whereFilters} sortsOrderBy.length ? sortsOrderBy : [{ createdAt: SortOrder.Desc }]
}
whereFilters={filtersWhere}
filterDefinitionArray={companiesFilters} filterDefinitionArray={companiesFilters}
setContextMenuEntries={setContextMenuEntries} setContextMenuEntries={setContextMenuEntries}
setActionBarEntries={setActionBarEntries} setActionBarEntries={setActionBarEntries}

View File

@ -10,7 +10,7 @@ import { companiesAvailableColumnDefinitions } from '../../constants/companiesAv
import { mockedCompaniesData } from './companies-mock-data'; import { mockedCompaniesData } from './companies-mock-data';
export function CompanyTableMockData() { export function CompanyTableMockData() {
const [, setColumns] = useRecoilScopedState( const [, setTableColumns] = useRecoilScopedState(
tableColumnsScopedState, tableColumnsScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -19,8 +19,8 @@ export function CompanyTableMockData() {
useEffect(() => { useEffect(() => {
setEntityTableData(mockedCompaniesData, []); setEntityTableData(mockedCompaniesData, []);
setColumns(companiesAvailableColumnDefinitions); setTableColumns(companiesAvailableColumnDefinitions);
}, [setColumns, setEntityTableData]); }, [setEntityTableData, setTableColumns]);
return <></>; return <></>;
} }

View File

@ -25,14 +25,14 @@ export function PeoplePicker({
onCreate, onCreate,
excludePersonIds, excludePersonIds,
}: OwnProps) { }: OwnProps) {
const [searchFilter] = useRecoilScopedState( const [relationPickerSearchFilter] = useRecoilScopedState(
relationPickerSearchFilterScopedState, relationPickerSearchFilterScopedState,
); );
const people = useFilteredSearchEntityQuery({ const people = useFilteredSearchEntityQuery({
queryHook: useSearchPeopleQuery, queryHook: useSearchPeopleQuery,
selectedIds: [personId ?? ''], selectedIds: [personId ?? ''],
searchFilter: searchFilter, searchFilter: relationPickerSearchFilter,
mappingFunction: (person) => ({ mappingFunction: (person) => ({
entityType: Entity.Person, entityType: Entity.Person,
id: person.id, id: person.id,

View File

@ -21,11 +21,11 @@ import { peopleFilters } from '~/pages/people/people-filters';
import { availableSorts } from '~/pages/people/people-sorts'; import { availableSorts } from '~/pages/people/people-sorts';
export function PeopleTable() { export function PeopleTable() {
const orderBy = useRecoilScopedValue( const sortsOrderBy = useRecoilScopedValue(
sortsOrderByScopedSelector, sortsOrderByScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const whereFilters = useRecoilScopedValue( const filtersWhere = useRecoilScopedValue(
filtersWhereScopedSelector, filtersWhereScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -54,8 +54,10 @@ export function PeopleTable() {
getRequestResultKey="people" getRequestResultKey="people"
useGetRequest={useGetPeopleQuery} useGetRequest={useGetPeopleQuery}
getRequestOptimisticEffect={getPeopleOptimisticEffect} getRequestOptimisticEffect={getPeopleOptimisticEffect}
orderBy={orderBy.length ? orderBy : [{ createdAt: SortOrder.Desc }]} orderBy={
whereFilters={whereFilters} sortsOrderBy.length ? sortsOrderBy : [{ createdAt: SortOrder.Desc }]
}
whereFilters={filtersWhere}
filterDefinitionArray={peopleFilters} filterDefinitionArray={peopleFilters}
setContextMenuEntries={setContextMenuEntries} setContextMenuEntries={setContextMenuEntries}
setActionBarEntries={setActionBarEntries} setActionBarEntries={setActionBarEntries}

View File

@ -10,11 +10,12 @@ type SpreadsheetImportProviderProps = React.PropsWithChildren;
export const SpreadsheetImportProvider = ( export const SpreadsheetImportProvider = (
props: SpreadsheetImportProviderProps, props: SpreadsheetImportProviderProps,
) => { ) => {
const [spreadsheetImportInternalState, setSpreadsheetImportInternalState] = const [spreadsheetImport, setSpreadsheetImport] = useRecoilState(
useRecoilState(spreadsheetImportState); spreadsheetImportState,
);
function handleClose() { function handleClose() {
setSpreadsheetImportInternalState({ setSpreadsheetImport({
isOpen: false, isOpen: false,
options: null, options: null,
}); });
@ -23,14 +24,13 @@ export const SpreadsheetImportProvider = (
return ( return (
<> <>
{props.children} {props.children}
{spreadsheetImportInternalState.isOpen && {spreadsheetImport.isOpen && spreadsheetImport.options && (
spreadsheetImportInternalState.options && ( <SpreadsheetImport
<SpreadsheetImport isOpen={true}
isOpen={true} onClose={handleClose}
onClose={handleClose} {...spreadsheetImport.options}
{...spreadsheetImportInternalState.options} />
/> )}
)}
</> </>
); );
}; };

View File

@ -33,11 +33,11 @@ const StyledContainerActionBar = styled.div`
export function ActionBar({ selectedIds }: OwnProps) { export function ActionBar({ selectedIds }: OwnProps) {
const actionBarOpen = useRecoilValue(actionBarOpenState); const actionBarOpen = useRecoilValue(actionBarOpenState);
const contextMenuOpen = useRecoilValue(contextMenuIsOpenState); const contextMenuIsOpen = useRecoilValue(contextMenuIsOpenState);
const actionBarEntries = useRecoilValue(actionBarEntriesState); const actionBarEntries = useRecoilValue(actionBarEntriesState);
const wrapperRef = useRef(null); const wrapperRef = useRef(null);
if (selectedIds.length === 0 || !actionBarOpen || contextMenuOpen) { if (selectedIds.length === 0 || !actionBarOpen || contextMenuIsOpen) {
return null; return null;
} }
return ( return (

View File

@ -106,10 +106,12 @@ export function BoardColumnMenu({
} }
setCurrentMenu(menu); setCurrentMenu(menu);
} }
const [searchFilter] = useRecoilScopedState( const [relationPickerSearchFilter] = useRecoilScopedState(
relationPickerSearchFilterScopedState, relationPickerSearchFilterScopedState,
); );
const companies = useFilteredSearchCompanyQuery({ searchFilter }); const companies = useFilteredSearchCompanyQuery({
searchFilter: relationPickerSearchFilter,
});
useListenClickOutside({ useListenClickOutside({
refs: [boardColumnMenuRef], refs: [boardColumnMenuRef],

View File

@ -6,6 +6,6 @@ import { ActionBar } from '@/ui/action-bar/components/ActionBar';
import { selectedCardIdsSelector } from '../states/selectors/selectedCardIdsSelector'; import { selectedCardIdsSelector } from '../states/selectors/selectedCardIdsSelector';
export function EntityBoardActionBar() { export function EntityBoardActionBar() {
const selectedBoardCards = useRecoilValue(selectedCardIdsSelector); const selectedCardIds = useRecoilValue(selectedCardIdsSelector);
return <ActionBar selectedIds={selectedBoardCards}></ActionBar>; return <ActionBar selectedIds={selectedCardIds}></ActionBar>;
} }

View File

@ -6,6 +6,6 @@ import { ContextMenu } from '@/ui/context-menu/components/ContextMenu';
import { selectedCardIdsSelector } from '../states/selectors/selectedCardIdsSelector'; import { selectedCardIdsSelector } from '../states/selectors/selectedCardIdsSelector';
export function EntityBoardContextMenu() { export function EntityBoardContextMenu() {
const selectedBoardCards = useRecoilValue(selectedCardIdsSelector); const selectedCardIds = useRecoilValue(selectedCardIdsSelector);
return <ContextMenu selectedIds={selectedBoardCards}></ContextMenu>; return <ContextMenu selectedIds={selectedCardIds}></ContextMenu>;
} }

View File

@ -40,8 +40,8 @@ const StyledContainerContextMenu = styled.div<StyledContainerProps>`
`; `;
export function ContextMenu({ selectedIds }: OwnProps) { export function ContextMenu({ selectedIds }: OwnProps) {
const position = useRecoilValue(contextMenuPositionState); const contextMenuPosition = useRecoilValue(contextMenuPositionState);
const contextMenuOpen = useRecoilValue(contextMenuIsOpenState); const contextMenuIsOpen = useRecoilValue(contextMenuIsOpenState);
const contextMenuEntries = useRecoilValue(contextMenuEntriesState); const contextMenuEntries = useRecoilValue(contextMenuEntriesState);
const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState); const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState);
const setActionBarOpenState = useSetRecoilState(actionBarOpenState); const setActionBarOpenState = useSetRecoilState(actionBarOpenState);
@ -55,14 +55,14 @@ export function ContextMenu({ selectedIds }: OwnProps) {
}, },
}); });
if (selectedIds.length === 0 || !contextMenuOpen) { if (selectedIds.length === 0 || !contextMenuIsOpen) {
return null; return null;
} }
return ( return (
<StyledContainerContextMenu <StyledContainerContextMenu
className="context-menu" className="context-menu"
ref={wrapperRef} ref={wrapperRef}
position={position} position={contextMenuPosition}
> >
<StyledDropdownMenu> <StyledDropdownMenu>
<StyledDropdownMenuItemsContainer> <StyledDropdownMenuItemsContainer>

View File

@ -9,7 +9,8 @@ import { DialogHotkeyScope } from '../types/DialogHotkeyScope';
import { Dialog } from './Dialog'; import { Dialog } from './Dialog';
export function DialogProvider({ children }: React.PropsWithChildren) { export function DialogProvider({ children }: React.PropsWithChildren) {
const [dialogState, setDialogState] = useRecoilState(dialogInternalState); const [dialogInternal, setDialogInternal] =
useRecoilState(dialogInternalState);
const { const {
setHotkeyScopeAndMemorizePreviousScope, setHotkeyScopeAndMemorizePreviousScope,
@ -18,7 +19,7 @@ export function DialogProvider({ children }: React.PropsWithChildren) {
// Handle dialog close event // Handle dialog close event
const handleDialogClose = (id: string) => { const handleDialogClose = (id: string) => {
setDialogState((prevState) => ({ setDialogInternal((prevState) => ({
...prevState, ...prevState,
queue: prevState.queue.filter((snackBar) => snackBar.id !== id), queue: prevState.queue.filter((snackBar) => snackBar.id !== id),
})); }));
@ -26,17 +27,17 @@ export function DialogProvider({ children }: React.PropsWithChildren) {
}; };
useEffect(() => { useEffect(() => {
if (dialogState.queue.length === 0) { if (dialogInternal.queue.length === 0) {
return; return;
} }
setHotkeyScopeAndMemorizePreviousScope(DialogHotkeyScope.Dialog); setHotkeyScopeAndMemorizePreviousScope(DialogHotkeyScope.Dialog);
}, [dialogState.queue, setHotkeyScopeAndMemorizePreviousScope]); }, [dialogInternal.queue, setHotkeyScopeAndMemorizePreviousScope]);
return ( return (
<> <>
{children} {children}
{dialogState.queue.map((dialog) => ( {dialogInternal.queue.map((dialog) => (
<Dialog <Dialog
key={dialog.id} key={dialog.id}
{...dialog} {...dialog}

View File

@ -69,9 +69,9 @@ export function DropdownButton({
setDropdownButtonCustomHotkeyScope(dropdownHotkeyScope); setDropdownButtonCustomHotkeyScope(dropdownHotkeyScope);
} }
}, [ }, [
setDropdownButtonCustomHotkeyScope,
dropdownHotkeyScope, dropdownHotkeyScope,
dropdownButtonCustomHotkeyScope, dropdownButtonCustomHotkeyScope,
setDropdownButtonCustomHotkeyScope,
]); ]);
return ( return (

View File

@ -21,13 +21,15 @@ export function FilterDropdownOperandButton({
context, context,
); );
const [isOperandSelectionUnfolded, setIsOperandSelectionUnfolded] = const [
useRecoilScopedState( isFilterDropdownOperandSelectUnfolded,
isFilterDropdownOperandSelectUnfoldedScopedState, setIsFilterDropdownOperandSelectUnfolded,
context, ] = useRecoilScopedState(
); isFilterDropdownOperandSelectUnfoldedScopedState,
context,
);
if (isOperandSelectionUnfolded) { if (isFilterDropdownOperandSelectUnfolded) {
return null; return null;
} }
@ -35,7 +37,7 @@ export function FilterDropdownOperandButton({
<DropdownMenuHeader <DropdownMenuHeader
key={'selected-filter-operand'} key={'selected-filter-operand'}
endIcon={<IconChevronDown size={theme.icon.size.md} />} endIcon={<IconChevronDown size={theme.icon.size.md} />}
onClick={() => setIsOperandSelectionUnfolded(true)} onClick={() => setIsFilterDropdownOperandSelectUnfolded(true)}
> >
{getOperandLabel(selectedOperandInDropdown)} {getOperandLabel(selectedOperandInDropdown)}
</DropdownMenuHeader> </DropdownMenuHeader>

View File

@ -32,11 +32,13 @@ export function FilterDropdownOperandSelect({
filterDefinitionUsedInDropdown?.type, filterDefinitionUsedInDropdown?.type,
); );
const [isOperandSelectionUnfolded, setIsOperandSelectionUnfolded] = const [
useRecoilScopedState( isFilterDropdownOperandSelectUnfolded,
isFilterDropdownOperandSelectUnfoldedScopedState, setIsFilterDropdownOperandSelectUnfolded,
context, ] = useRecoilScopedState(
); isFilterDropdownOperandSelectUnfoldedScopedState,
context,
);
const filterCurrentlyEdited = useFilterCurrentlyEdited(context); const filterCurrentlyEdited = useFilterCurrentlyEdited(context);
@ -44,7 +46,7 @@ export function FilterDropdownOperandSelect({
function handleOperangeChange(newOperand: FilterOperand) { function handleOperangeChange(newOperand: FilterOperand) {
setSelectedOperandInDropdown(newOperand); setSelectedOperandInDropdown(newOperand);
setIsOperandSelectionUnfolded(false); setIsFilterDropdownOperandSelectUnfolded(false);
if (filterDefinitionUsedInDropdown && filterCurrentlyEdited) { if (filterDefinitionUsedInDropdown && filterCurrentlyEdited) {
upsertFilter({ upsertFilter({
@ -57,7 +59,7 @@ export function FilterDropdownOperandSelect({
} }
} }
if (!isOperandSelectionUnfolded) { if (!isFilterDropdownOperandSelectUnfolded) {
return <></>; return <></>;
} }

View File

@ -76,12 +76,14 @@ export function MultipleFiltersDropdownButton({
const setHotkeyScope = useSetHotkeyScope(); const setHotkeyScope = useSetHotkeyScope();
const [isSortAndFilterBarOpen, setIsSortAndFilterBarOpen] = const [sortAndFilterBar, setSortAndFilterBar] = useRecoilScopedState(
useRecoilScopedState(sortAndFilterBarScopedState, context); sortAndFilterBarScopedState,
context,
);
function handleIsUnfoldedChange(unfolded: boolean) { function handleIsUnfoldedChange(unfolded: boolean) {
if (unfolded && isPrimaryButton) { if (unfolded && isPrimaryButton) {
setIsSortAndFilterBarOpen(!isSortAndFilterBarOpen); setSortAndFilterBar(!sortAndFilterBar);
} }
if ( if (

View File

@ -119,7 +119,7 @@ function SortAndFilterBar<SortField>({
context, context,
); );
const [isSortAndFilterBarOpen] = useRecoilScopedState( const [sortAndFilterBar] = useRecoilScopedState(
sortAndFilterBarScopedState, sortAndFilterBarScopedState,
context, context,
); );
@ -144,7 +144,7 @@ function SortAndFilterBar<SortField>({
if ( if (
(!canToggle && !filtersWithDefinition.length && !sorts.length) || (!canToggle && !filtersWithDefinition.length && !sorts.length) ||
!isSortAndFilterBarOpen !sortAndFilterBar
) { ) {
return null; return null;
} }

View File

@ -52,7 +52,7 @@ export function SortDropdownButton<SortField>({
setSelectedSortDirection('asc'); setSelectedSortDirection('asc');
}, []); }, []);
const [, setIsSortAndFilterBarOpen] = useRecoilScopedState( const [, setSortAndFilterBar] = useRecoilScopedState(
sortAndFilterBarScopedState, sortAndFilterBarScopedState,
context, context,
); );
@ -69,7 +69,7 @@ export function SortDropdownButton<SortField>({
function handleAddSort(sort: SortType<SortField>) { function handleAddSort(sort: SortType<SortField>) {
setIsUnfolded(false); setIsUnfolded(false);
onSortItemSelect(sort); onSortItemSelect(sort);
setIsSortAndFilterBarOpen(true); setSortAndFilterBar(true);
} }
return ( return (

View File

@ -17,12 +17,11 @@ export function useEntitySelectScroll<
entities: CustomEntityForSelect[]; entities: CustomEntityForSelect[];
containerRef: React.RefObject<HTMLDivElement>; containerRef: React.RefObject<HTMLDivElement>;
}) { }) {
const [hoveredIndex, setHoveredIndex] = useRecoilScopedState( const [relationPickerHoverIndex, setRelationPickerHoverIndex] =
relationPickerHoverIndexScopedState, useRecoilScopedState(relationPickerHoverIndexScopedState);
);
function resetScroll() { function resetScroll() {
setHoveredIndex(0); setRelationPickerHoverIndex(0);
const currentHoveredRef = containerRef.current?.children[0] as HTMLElement; const currentHoveredRef = containerRef.current?.children[0] as HTMLElement;
@ -40,12 +39,12 @@ export function useEntitySelectScroll<
useScopedHotkeys( useScopedHotkeys(
Key.ArrowUp, Key.ArrowUp,
() => { () => {
setHoveredIndex((prevSelectedIndex) => setRelationPickerHoverIndex((prevSelectedIndex) =>
Math.max(prevSelectedIndex - 1, 0), Math.max(prevSelectedIndex - 1, 0),
); );
const currentHoveredRef = containerRef.current?.children[ const currentHoveredRef = containerRef.current?.children[
hoveredIndex relationPickerHoverIndex
] as HTMLElement; ] as HTMLElement;
if (currentHoveredRef) { if (currentHoveredRef) {
@ -61,18 +60,18 @@ export function useEntitySelectScroll<
} }
}, },
RelationPickerHotkeyScope.RelationPicker, RelationPickerHotkeyScope.RelationPicker,
[setHoveredIndex, entities], [setRelationPickerHoverIndex, entities],
); );
useScopedHotkeys( useScopedHotkeys(
Key.ArrowDown, Key.ArrowDown,
() => { () => {
setHoveredIndex((prevSelectedIndex) => setRelationPickerHoverIndex((prevSelectedIndex) =>
Math.min(prevSelectedIndex + 1, (entities?.length ?? 0) - 1), Math.min(prevSelectedIndex + 1, (entities?.length ?? 0) - 1),
); );
const currentHoveredRef = containerRef.current?.children[ const currentHoveredRef = containerRef.current?.children[
hoveredIndex relationPickerHoverIndex
] as HTMLElement; ] as HTMLElement;
if (currentHoveredRef) { if (currentHoveredRef) {
@ -88,11 +87,11 @@ export function useEntitySelectScroll<
} }
}, },
RelationPickerHotkeyScope.RelationPicker, RelationPickerHotkeyScope.RelationPicker,
[setHoveredIndex, entities], [setRelationPickerHoverIndex, entities],
); );
return { return {
hoveredIndex, hoveredIndex: relationPickerHoverIndex,
resetScroll, resetScroll,
}; };
} }

View File

@ -7,31 +7,34 @@ import { relationPickerHoverIndexScopedState } from '../states/relationPickerHov
import { relationPickerSearchFilterScopedState } from '../states/relationPickerSearchFilterScopedState'; import { relationPickerSearchFilterScopedState } from '../states/relationPickerSearchFilterScopedState';
export function useEntitySelectSearch() { export function useEntitySelectSearch() {
const [, setHoveredIndex] = useRecoilScopedState( const [, setRelationPickerHoverIndex] = useRecoilScopedState(
relationPickerHoverIndexScopedState, relationPickerHoverIndexScopedState,
); );
const [searchFilter, setSearchFilter] = useRecoilScopedState( const [relationPickerSearchFilter, setRelationPickerSearchFilter] =
relationPickerSearchFilterScopedState, useRecoilScopedState(relationPickerSearchFilterScopedState);
);
const debouncedSetSearchFilter = debounce(setSearchFilter, 100, { const debouncedSetSearchFilter = debounce(
leading: true, setRelationPickerSearchFilter,
}); 100,
{
leading: true,
},
);
function handleSearchFilterChange( function handleSearchFilterChange(
event: React.ChangeEvent<HTMLInputElement>, event: React.ChangeEvent<HTMLInputElement>,
) { ) {
debouncedSetSearchFilter(event.currentTarget.value); debouncedSetSearchFilter(event.currentTarget.value);
setHoveredIndex(0); setRelationPickerHoverIndex(0);
} }
useEffect(() => { useEffect(() => {
setSearchFilter(''); setRelationPickerSearchFilter('');
}, [setSearchFilter]); }, [setRelationPickerSearchFilter]);
return { return {
searchFilter, searchFilter: relationPickerSearchFilter,
handleSearchFilterChange, handleSearchFilterChange,
}; };
} }

View File

@ -54,7 +54,8 @@ export default function NavCollapseButton({
direction = 'left', direction = 'left',
hide, hide,
}: CollapseButtonProps) { }: CollapseButtonProps) {
const [isNavOpen, setIsNavOpen] = useRecoilState(isNavbarOpenedState); const [isNavbarOpened, setIsNavbarOpened] =
useRecoilState(isNavbarOpenedState);
const iconSize = useIsMobile() const iconSize = useIsMobile()
? navbarIconSize.mobile ? navbarIconSize.mobile
@ -65,14 +66,14 @@ export default function NavCollapseButton({
{direction === 'left' ? ( {direction === 'left' ? (
<StyledCollapseButton <StyledCollapseButton
hide={hide} hide={hide}
onClick={() => setIsNavOpen(!isNavOpen)} onClick={() => setIsNavbarOpened(!isNavbarOpened)}
> >
<IconLayoutSidebarLeftCollapse size={iconSize} /> <IconLayoutSidebarLeftCollapse size={iconSize} />
</StyledCollapseButton> </StyledCollapseButton>
) : ( ) : (
<StyledCollapseButton <StyledCollapseButton
hide={hide} hide={hide}
onClick={() => setIsNavOpen(!isNavOpen)} onClick={() => setIsNavbarOpened(!isNavbarOpened)}
> >
<IconLayoutSidebarRightCollapse size={iconSize} /> <IconLayoutSidebarRightCollapse size={iconSize} />
</StyledCollapseButton> </StyledCollapseButton>

View File

@ -24,7 +24,7 @@ type NavbarProps = {
}; };
export function NavbarAnimatedContainer({ children }: NavbarProps) { export function NavbarAnimatedContainer({ children }: NavbarProps) {
const isMenuOpened = useRecoilValue(isNavbarOpenedState); const isNavbarOpened = useRecoilValue(isNavbarOpenedState);
const [, setIsNavbarSwitchingSize] = useRecoilState( const [, setIsNavbarSwitchingSize] = useRecoilState(
isNavbarSwitchingSizeState, isNavbarSwitchingSizeState,
); );
@ -47,8 +47,8 @@ export function NavbarAnimatedContainer({ children }: NavbarProps) {
setIsNavbarSwitchingSize(false); setIsNavbarSwitchingSize(false);
}} }}
animate={{ animate={{
width: isMenuOpened ? leftBarWidth : '0', width: isNavbarOpened ? leftBarWidth : '0',
opacity: isMenuOpened ? 1 : 0, opacity: isNavbarOpened ? 1 : 0,
}} }}
transition={{ transition={{
duration: theme.animation.duration.normal, duration: theme.animation.duration.normal,

View File

@ -49,37 +49,37 @@ function configureFront(chatId: string) {
export default function SupportChat() { export default function SupportChat() {
const theme = useTheme(); const theme = useTheme();
const user = useRecoilValue(currentUserState); const currentUser = useRecoilValue(currentUserState);
const supportChatConfig = useRecoilValue(supportChatState); const supportChat = useRecoilValue(supportChatState);
const [isFrontChatLoaded, setIsFrontChatLoaded] = useState(false); const [isFrontChatLoaded, setIsFrontChatLoaded] = useState(false);
useEffect(() => { useEffect(() => {
if ( if (
supportChatConfig?.supportDriver === 'front' && supportChat?.supportDriver === 'front' &&
supportChatConfig.supportFrontChatId && supportChat.supportFrontChatId &&
!isFrontChatLoaded !isFrontChatLoaded
) { ) {
configureFront(supportChatConfig.supportFrontChatId); configureFront(supportChat.supportFrontChatId);
setIsFrontChatLoaded(true); setIsFrontChatLoaded(true);
} }
if (user?.email && isFrontChatLoaded) { if (currentUser?.email && isFrontChatLoaded) {
window.FrontChat?.('identity', { window.FrontChat?.('identity', {
email: user.email, email: currentUser.email,
name: user.displayName, name: currentUser.displayName,
userHash: user?.supportUserHash, userHash: currentUser?.supportUserHash,
}); });
} }
}, [ }, [
currentUser?.displayName,
currentUser?.email,
currentUser?.supportUserHash,
isFrontChatLoaded, isFrontChatLoaded,
supportChatConfig?.supportDriver, supportChat?.supportDriver,
supportChatConfig.supportFrontChatId, supportChat.supportFrontChatId,
user?.displayName,
user?.email,
user?.supportUserHash,
]); ]);
function handleSupportClick() { function handleSupportClick() {
if (supportChatConfig?.supportDriver === 'front') { if (supportChat?.supportDriver === 'front') {
window.FrontChat?.('show'); window.FrontChat?.('show');
} }
} }

View File

@ -30,7 +30,7 @@ const StyledTopBarWrapper = styled.div`
export function RightDrawerTopBar() { export function RightDrawerTopBar() {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const activityId = useRecoilValue(viewableActivityIdState); const viewableActivityId = useRecoilValue(viewableActivityIdState);
return ( return (
<StyledRightDrawerTopBar> <StyledRightDrawerTopBar>
@ -38,7 +38,7 @@ export function RightDrawerTopBar() {
<RightDrawerTopBarCloseButton /> <RightDrawerTopBarCloseButton />
{!isMobile && <RightDrawerTopBarExpandButton />} {!isMobile && <RightDrawerTopBarExpandButton />}
</StyledTopBarWrapper> </StyledTopBarWrapper>
<ActivityActionBar activityId={activityId ?? ''} /> <ActivityActionBar activityId={viewableActivityId ?? ''} />
</StyledRightDrawerTopBar> </StyledRightDrawerTopBar>
); );
} }

View File

@ -53,13 +53,13 @@ const reducedVariants = {
export function SnackBarProvider({ children }: React.PropsWithChildren) { export function SnackBarProvider({ children }: React.PropsWithChildren) {
const reducedMotion = useReducedMotion(); const reducedMotion = useReducedMotion();
const [snackBarState, setSnackBarState] = useRecoilState( const [snackBarInternal, setSnackBarInternal] = useRecoilState(
snackBarInternalState, snackBarInternalState,
); );
// Handle snackbar close event // Handle snackbar close event
const handleSnackBarClose = (id: string) => { const handleSnackBarClose = (id: string) => {
setSnackBarState((prevState) => ({ setSnackBarInternal((prevState) => ({
...prevState, ...prevState,
queue: prevState.queue.filter((snackBar) => snackBar.id !== id), queue: prevState.queue.filter((snackBar) => snackBar.id !== id),
})); }));
@ -69,7 +69,7 @@ export function SnackBarProvider({ children }: React.PropsWithChildren) {
<> <>
{children} {children}
<StyledSnackBarContainer> <StyledSnackBarContainer>
{snackBarState.queue.map((snackBar) => ( {snackBarInternal.queue.map((snackBar) => (
<StyledSnackBarMotionContainer <StyledSnackBarMotionContainer
key={snackBar.id} key={snackBar.id}
variants={reducedMotion ? reducedVariants : variants} variants={reducedMotion ? reducedVariants : variants}

View File

@ -8,24 +8,25 @@ export type StepsOptions = {
}; };
export function useStepBar({ initialStep }: StepsOptions) { export function useStepBar({ initialStep }: StepsOptions) {
const [stepsState, setStepsState] = useRecoilState(stepBarInternalState); const [stepBarInternal, setStepBarInternal] =
useRecoilState(stepBarInternalState);
function nextStep() { function nextStep() {
setStepsState((prevState) => ({ setStepBarInternal((prevState) => ({
...prevState, ...prevState,
activeStep: prevState.activeStep + 1, activeStep: prevState.activeStep + 1,
})); }));
} }
function prevStep() { function prevStep() {
setStepsState((prevState) => ({ setStepBarInternal((prevState) => ({
...prevState, ...prevState,
activeStep: prevState.activeStep - 1, activeStep: prevState.activeStep - 1,
})); }));
} }
function reset() { function reset() {
setStepsState((prevState) => ({ setStepBarInternal((prevState) => ({
...prevState, ...prevState,
activeStep: 0, activeStep: 0,
})); }));
@ -33,12 +34,12 @@ export function useStepBar({ initialStep }: StepsOptions) {
const setStep = useCallback( const setStep = useCallback(
(step: number) => { (step: number) => {
setStepsState((prevState) => ({ setStepBarInternal((prevState) => ({
...prevState, ...prevState,
activeStep: step, activeStep: step,
})); }));
}, },
[setStepsState], [setStepBarInternal],
); );
useEffect(() => { useEffect(() => {
@ -54,6 +55,6 @@ export function useStepBar({ initialStep }: StepsOptions) {
prevStep, prevStep,
reset, reset,
setStep, setStep,
activeStep: stepsState.activeStep, activeStep: stepBarInternal.activeStep,
}; };
} }

View File

@ -25,7 +25,7 @@ const StyledSpace = styled.td<SpaceProps>`
export function EntityTableBody() { export function EntityTableBody() {
const scrollWrapperRef = useScrollWrapperScopedRef(); const scrollWrapperRef = useScrollWrapperScopedRef();
const rowIds = useRecoilValue(tableRowIdsState); const tableRowIds = useRecoilValue(tableRowIdsState);
const isNavbarSwitchingSize = useRecoilValue(isNavbarSwitchingSizeState); const isNavbarSwitchingSize = useRecoilValue(isNavbarSwitchingSizeState);
const isFetchingEntityTableData = useRecoilValue( const isFetchingEntityTableData = useRecoilValue(
@ -33,7 +33,7 @@ export function EntityTableBody() {
); );
const rowVirtualizer = useVirtual({ const rowVirtualizer = useVirtual({
size: rowIds.length, size: tableRowIds.length,
parentRef: scrollWrapperRef, parentRef: scrollWrapperRef,
overscan: 50, overscan: 50,
}); });
@ -57,7 +57,7 @@ export function EntityTableBody() {
</tr> </tr>
)} )}
{items.map((virtualItem) => { {items.map((virtualItem) => {
const rowId = rowIds[virtualItem.index]; const rowId = tableRowIds[virtualItem.index];
return ( return (
<RowIdContext.Provider value={rowId} key={rowId}> <RowIdContext.Provider value={rowId} key={rowId}>

View File

@ -33,7 +33,7 @@ export const EntityTableColumnMenu = ({
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const theme = useTheme(); const theme = useTheme();
const hiddenColumns = useRecoilScopedValue( const hiddenTableColumns = useRecoilScopedValue(
hiddenTableColumnsScopedSelector, hiddenTableColumnsScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -56,7 +56,7 @@ export const EntityTableColumnMenu = ({
return ( return (
<StyledColumnMenu {...props} ref={ref}> <StyledColumnMenu {...props} ref={ref}>
<StyledDropdownMenuItemsContainer> <StyledDropdownMenuItemsContainer>
{hiddenColumns.map((column) => ( {hiddenTableColumns.map((column) => (
<DropdownMenuItem <DropdownMenuItem
key={column.key} key={column.key}
actions={[ actions={[

View File

@ -72,24 +72,26 @@ const StyledEntityTableColumnMenu = styled(EntityTableColumnMenu)`
`; `;
export function EntityTableHeader() { export function EntityTableHeader() {
const [offset, setOffset] = useRecoilState(resizeFieldOffsetState); const [resizeFieldOffset, setResizeFieldOffset] = useRecoilState(
const [columns, setColumns] = useRecoilScopedState( resizeFieldOffsetState,
);
const [tableColumns, setTableColumns] = useRecoilScopedState(
tableColumnsScopedState, tableColumnsScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const columnsByKey = useRecoilScopedValue( const tableColumnsByKey = useRecoilScopedValue(
tableColumnsByKeyScopedSelector, tableColumnsByKeyScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const hiddenColumns = useRecoilScopedValue( const hiddenTableColumns = useRecoilScopedValue(
hiddenTableColumnsScopedSelector, hiddenTableColumnsScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const visibleColumns = useRecoilScopedValue( const visibleTableColumns = useRecoilScopedValue(
visibleTableColumnsScopedSelector, visibleTableColumnsScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const [, setIsSortAndFilterBarOpen] = useRecoilScopedState( const [, setSortAndFilterBar] = useRecoilScopedState(
sortAndFilterBarScopedState, sortAndFilterBarScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -107,9 +109,9 @@ export function EntityTableHeader() {
const handleResizeHandlerMove = useCallback( const handleResizeHandlerMove = useCallback(
(positionX: number) => { (positionX: number) => {
if (!initialPointerPositionX) return; if (!initialPointerPositionX) return;
setOffset(positionX - initialPointerPositionX); setResizeFieldOffset(positionX - initialPointerPositionX);
}, },
[setOffset, initialPointerPositionX], [setResizeFieldOffset, initialPointerPositionX],
); );
const handleResizeHandlerEnd = useRecoilCallback( const handleResizeHandlerEnd = useRecoilCallback(
@ -119,21 +121,21 @@ export function EntityTableHeader() {
const nextWidth = Math.round( const nextWidth = Math.round(
Math.max( Math.max(
columnsByKey[resizedFieldKey].size + tableColumnsByKey[resizedFieldKey].size +
snapshot.getLoadable(resizeFieldOffsetState).valueOrThrow(), snapshot.getLoadable(resizeFieldOffsetState).valueOrThrow(),
COLUMN_MIN_WIDTH, COLUMN_MIN_WIDTH,
), ),
); );
if (nextWidth !== columnsByKey[resizedFieldKey].size) { if (nextWidth !== tableColumnsByKey[resizedFieldKey].size) {
const nextColumns = columns.map((column) => const nextColumns = tableColumns.map((column) =>
column.key === resizedFieldKey column.key === resizedFieldKey
? { ...column, size: nextWidth } ? { ...column, size: nextWidth }
: column, : column,
); );
setColumns(nextColumns); setTableColumns(nextColumns);
setIsSortAndFilterBarOpen(true); setSortAndFilterBar(true);
} }
set(resizeFieldOffsetState, 0); set(resizeFieldOffsetState, 0);
@ -142,10 +144,10 @@ export function EntityTableHeader() {
}, },
[ [
resizedFieldKey, resizedFieldKey,
columnsByKey, tableColumnsByKey,
columns, tableColumns,
setColumns, setTableColumns,
setIsSortAndFilterBarOpen, setSortAndFilterBar,
], ],
); );
@ -173,13 +175,13 @@ export function EntityTableHeader() {
<SelectAllCheckbox /> <SelectAllCheckbox />
</th> </th>
{visibleColumns.map((column) => ( {visibleTableColumns.map((column) => (
<StyledColumnHeaderCell <StyledColumnHeaderCell
key={column.key} key={column.key}
isResizing={resizedFieldKey === column.key} isResizing={resizedFieldKey === column.key}
columnWidth={Math.max( columnWidth={Math.max(
columnsByKey[column.key].size + tableColumnsByKey[column.key].size +
(resizedFieldKey === column.key ? offset : 0), (resizedFieldKey === column.key ? resizeFieldOffset : 0),
COLUMN_MIN_WIDTH, COLUMN_MIN_WIDTH,
)} )}
> >
@ -194,7 +196,7 @@ export function EntityTableHeader() {
</StyledColumnHeaderCell> </StyledColumnHeaderCell>
))} ))}
<th> <th>
{hiddenColumns.length > 0 && ( {hiddenTableColumns.length > 0 && (
<StyledAddIconButtonWrapper> <StyledAddIconButtonWrapper>
<IconButton <IconButton
size="medium" size="medium"

View File

@ -24,7 +24,7 @@ export const EntityTableRow = forwardRef<
HTMLTableRowElement, HTMLTableRowElement,
EntityTableRowProps EntityTableRowProps
>(function EntityTableRow({ rowId }, ref) { >(function EntityTableRow({ rowId }, ref) {
const columns = useRecoilScopedValue( const visibleTableColumns = useRecoilScopedValue(
visibleTableColumnsScopedSelector, visibleTableColumnsScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -40,7 +40,7 @@ export const EntityTableRow = forwardRef<
<td> <td>
<CheckboxCell /> <CheckboxCell />
</td> </td>
{columns.map((column, columnIndex) => { {visibleTableColumns.map((column, columnIndex) => {
return ( return (
<ColumnContext.Provider value={column} key={column.key}> <ColumnContext.Provider value={column} key={column.key}>
<EntityTableCell cellIndex={columnIndex} /> <EntityTableCell cellIndex={columnIndex} />

View File

@ -19,7 +19,7 @@ export const useTableColumns = () => {
tableColumnsByKeyScopedSelector, tableColumnsByKeyScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const [, setIsSortAndFilterBarOpen] = useRecoilScopedState( const [, setSortAndFilterBar] = useRecoilScopedState(
sortAndFilterBarScopedState, sortAndFilterBarScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -37,14 +37,9 @@ export const useTableColumns = () => {
); );
setTableColumns(nextColumns); setTableColumns(nextColumns);
setIsSortAndFilterBarOpen(true); setSortAndFilterBar(true);
}, },
[ [tableColumnsByKey, tableColumns, setTableColumns, setSortAndFilterBar],
setIsSortAndFilterBarOpen,
setTableColumns,
tableColumns,
tableColumnsByKey,
],
); );
return { handleColumnVisibilityChange }; return { handleColumnVisibilityChange };

View File

@ -71,18 +71,18 @@ export function TableOptionsDropdownContent({
const viewEditInputRef = useRef<HTMLInputElement>(null); const viewEditInputRef = useRef<HTMLInputElement>(null);
const [viewEditMode, setViewEditMode] = useRecoilState( const [tableViewEditMode, setTableViewEditMode] = useRecoilState(
tableViewEditModeState, tableViewEditModeState,
); );
const visibleColumns = useRecoilScopedValue( const visibleTableColumns = useRecoilScopedValue(
visibleTableColumnsScopedSelector, visibleTableColumnsScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const hiddenColumns = useRecoilScopedValue( const hiddenTableColumns = useRecoilScopedValue(
hiddenTableColumnsScopedSelector, hiddenTableColumnsScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const viewsById = useRecoilScopedValue( const tableViewsById = useRecoilScopedValue(
tableViewsByIdState, tableViewsByIdState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -92,7 +92,7 @@ export function TableOptionsDropdownContent({
const renderFieldActions = useCallback( const renderFieldActions = useCallback(
(column: ColumnDefinition<ViewFieldMetadata>) => (column: ColumnDefinition<ViewFieldMetadata>) =>
// Do not allow hiding last visible column // Do not allow hiding last visible column
!column.isVisible || visibleColumns.length > 1 !column.isVisible || visibleTableColumns.length > 1
? [ ? [
<IconButton <IconButton
key={`action-${column.key}`} key={`action-${column.key}`}
@ -107,16 +107,20 @@ export function TableOptionsDropdownContent({
/>, />,
] ]
: undefined, : undefined,
[handleColumnVisibilityChange, theme.icon.size.sm, visibleColumns.length], [
handleColumnVisibilityChange,
theme.icon.size.sm,
visibleTableColumns.length,
],
); );
const resetViewEditMode = useCallback(() => { const resetViewEditMode = useCallback(() => {
setViewEditMode({ mode: undefined, viewId: undefined }); setTableViewEditMode({ mode: undefined, viewId: undefined });
if (viewEditInputRef.current) { if (viewEditInputRef.current) {
viewEditInputRef.current.value = ''; viewEditInputRef.current.value = '';
} }
}, [setViewEditMode]); }, [setTableViewEditMode]);
const handleViewNameSubmit = useRecoilCallback( const handleViewNameSubmit = useRecoilCallback(
({ set, snapshot }) => ({ set, snapshot }) =>
@ -125,13 +129,13 @@ export function TableOptionsDropdownContent({
const name = viewEditInputRef.current?.value; const name = viewEditInputRef.current?.value;
if (!viewEditMode.mode || !name) { if (!tableViewEditMode.mode || !name) {
return resetViewEditMode(); return resetViewEditMode();
} }
const views = await snapshot.getPromise(tableViewsState(tableScopeId)); const views = await snapshot.getPromise(tableViewsState(tableScopeId));
if (viewEditMode.mode === 'create') { if (tableViewEditMode.mode === 'create') {
const viewToCreate = { id: v4(), name }; const viewToCreate = { id: v4(), name };
const nextViews = [...views, viewToCreate]; const nextViews = [...views, viewToCreate];
@ -156,9 +160,9 @@ export function TableOptionsDropdownContent({
set(currentTableViewIdState(tableScopeId), viewToCreate.id); set(currentTableViewIdState(tableScopeId), viewToCreate.id);
} }
if (viewEditMode.mode === 'edit') { if (tableViewEditMode.mode === 'edit') {
const nextViews = views.map((view) => const nextViews = views.map((view) =>
view.id === viewEditMode.viewId ? { ...view, name } : view, view.id === tableViewEditMode.viewId ? { ...view, name } : view,
); );
set(tableViewsState(tableScopeId), nextViews); set(tableViewsState(tableScopeId), nextViews);
@ -171,8 +175,8 @@ export function TableOptionsDropdownContent({
onViewsChange, onViewsChange,
resetViewEditMode, resetViewEditMode,
tableScopeId, tableScopeId,
viewEditMode.mode, tableViewEditMode.mode,
viewEditMode.viewId, tableViewEditMode.viewId,
], ],
); );
@ -210,16 +214,16 @@ export function TableOptionsDropdownContent({
<StyledDropdownMenu> <StyledDropdownMenu>
{!selectedOption && ( {!selectedOption && (
<> <>
{!!viewEditMode.mode ? ( {!!tableViewEditMode.mode ? (
<DropdownMenuInput <DropdownMenuInput
ref={viewEditInputRef} ref={viewEditInputRef}
autoFocus autoFocus
placeholder={ placeholder={
viewEditMode.mode === 'create' ? 'New view' : 'View name' tableViewEditMode.mode === 'create' ? 'New view' : 'View name'
} }
defaultValue={ defaultValue={
viewEditMode.viewId tableViewEditMode.viewId
? viewsById[viewEditMode.viewId]?.name ? tableViewsById[tableViewEditMode.viewId]?.name
: undefined : undefined
} }
/> />
@ -255,15 +259,15 @@ export function TableOptionsDropdownContent({
<TableOptionsDropdownSection <TableOptionsDropdownSection
renderActions={renderFieldActions} renderActions={renderFieldActions}
title="Visible" title="Visible"
columns={visibleColumns} columns={visibleTableColumns}
/> />
{hiddenColumns.length > 0 && ( {hiddenTableColumns.length > 0 && (
<> <>
<StyledDropdownMenuSeparator /> <StyledDropdownMenuSeparator />
<TableOptionsDropdownSection <TableOptionsDropdownSection
renderActions={renderFieldActions} renderActions={renderFieldActions}
title="Hidden" title="Hidden"
columns={hiddenColumns} columns={hiddenTableColumns}
/> />
</> </>
)} )}

View File

@ -51,40 +51,39 @@ export const TableUpdateViewButtonGroup = ({
const tableScopeId = useContextScopeId(TableRecoilScopeContext); const tableScopeId = useContextScopeId(TableRecoilScopeContext);
const currentViewId = useRecoilScopedValue( const currentTableViewId = useRecoilScopedValue(
currentTableViewIdState, currentTableViewIdState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const currentColumns = useRecoilScopedValue( const tableColumns = useRecoilScopedValue(
tableColumnsScopedState, tableColumnsScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const setSavedColumns = useSetRecoilState( const setSavedColumns = useSetRecoilState(
savedTableColumnsScopedState(currentViewId), savedTableColumnsScopedState(currentTableViewId),
); );
const canPersistColumns = useRecoilValue( const canPersistColumns = useRecoilValue(
canPersistTableColumnsScopedSelector([tableScopeId, currentViewId]), canPersistTableColumnsScopedSelector([tableScopeId, currentTableViewId]),
); );
const selectedFilters = useRecoilScopedValue( const filters = useRecoilScopedValue(
filtersScopedState, filtersScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const setSavedFilters = useSetRecoilState( const setSavedFilters = useSetRecoilState(
savedFiltersScopedState(currentViewId), savedFiltersScopedState(currentTableViewId),
); );
const canPersistFilters = useRecoilValue( const canPersistFilters = useRecoilValue(
canPersistFiltersScopedSelector([tableScopeId, currentViewId]), canPersistFiltersScopedSelector([tableScopeId, currentTableViewId]),
); );
const selectedSorts = useRecoilScopedValue( const sorts = useRecoilScopedValue(sortsScopedState, TableRecoilScopeContext);
sortsScopedState, const setSavedSorts = useSetRecoilState(
TableRecoilScopeContext, savedSortsScopedState(currentTableViewId),
); );
const setSavedSorts = useSetRecoilState(savedSortsScopedState(currentViewId));
const canPersistSorts = useRecoilValue( const canPersistSorts = useRecoilValue(
canPersistSortsScopedSelector([tableScopeId, currentViewId]), canPersistSortsScopedSelector([tableScopeId, currentTableViewId]),
); );
const setViewEditMode = useSetRecoilState(tableViewEditModeState); const setViewEditMode = useSetRecoilState(tableViewEditModeState);
@ -108,22 +107,22 @@ export const TableUpdateViewButtonGroup = ({
}, []); }, []);
const handleViewSubmit = useCallback(async () => { const handleViewSubmit = useCallback(async () => {
if (canPersistColumns) setSavedColumns(currentColumns); if (canPersistColumns) setSavedColumns(tableColumns);
if (canPersistFilters) setSavedFilters(selectedFilters); if (canPersistFilters) setSavedFilters(filters);
if (canPersistSorts) setSavedSorts(selectedSorts); if (canPersistSorts) setSavedSorts(sorts);
await Promise.resolve(onViewSubmit?.()); await Promise.resolve(onViewSubmit?.());
}, [ }, [
canPersistColumns, canPersistColumns,
canPersistFilters, canPersistFilters,
canPersistSorts, canPersistSorts,
currentColumns, filters,
onViewSubmit, onViewSubmit,
selectedFilters,
selectedSorts,
setSavedColumns, setSavedColumns,
setSavedFilters, setSavedFilters,
setSavedSorts, setSavedSorts,
sorts,
tableColumns,
]); ]);
useScopedHotkeys( useScopedHotkeys(
@ -139,7 +138,7 @@ export const TableUpdateViewButtonGroup = ({
<Button <Button
title="Update view" title="Update view"
disabled={ disabled={
!currentViewId || !currentTableViewId ||
(!canPersistColumns && !canPersistFilters && !canPersistSorts) (!canPersistColumns && !canPersistFilters && !canPersistSorts)
} }
onClick={handleViewSubmit} onClick={handleViewSubmit}

View File

@ -92,15 +92,15 @@ export const TableViewsDropdownButton = ({
key: 'options', key: 'options',
}); });
const [, setCurrentViewId] = useRecoilScopedState( const [, setCurrentTableViewId] = useRecoilScopedState(
currentTableViewIdState, currentTableViewIdState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const currentView = useRecoilScopedValue( const currentTableView = useRecoilScopedValue(
currentTableViewState, currentTableViewState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const [views, setViews] = useRecoilScopedState( const [tableViews, setTableViews] = useRecoilScopedState(
tableViewsState, tableViewsState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -153,15 +153,21 @@ export const TableViewsDropdownButton = ({
async (event: MouseEvent<HTMLButtonElement>, viewId: string) => { async (event: MouseEvent<HTMLButtonElement>, viewId: string) => {
event.stopPropagation(); event.stopPropagation();
if (currentView?.id === viewId) setCurrentViewId(undefined); if (currentTableView?.id === viewId) setCurrentTableViewId(undefined);
const nextViews = views.filter((view) => view.id !== viewId); const nextViews = tableViews.filter((view) => view.id !== viewId);
setViews(nextViews); setTableViews(nextViews);
await Promise.resolve(onViewsChange?.(nextViews)); await Promise.resolve(onViewsChange?.(nextViews));
setIsUnfolded(false); setIsUnfolded(false);
}, },
[currentView?.id, onViewsChange, setCurrentViewId, setViews, views], [
currentTableView?.id,
onViewsChange,
setCurrentTableViewId,
setTableViews,
tableViews,
],
); );
useEffect(() => { useEffect(() => {
@ -181,10 +187,10 @@ export const TableViewsDropdownButton = ({
<> <>
<StyledViewIcon size={theme.icon.size.md} /> <StyledViewIcon size={theme.icon.size.md} />
<StyledViewName> <StyledViewName>
{currentView?.name || defaultViewName}{' '} {currentTableView?.name || defaultViewName}{' '}
</StyledViewName> </StyledViewName>
<StyledDropdownLabelAdornments> <StyledDropdownLabelAdornments>
· {views.length} <IconChevronDown size={theme.icon.size.sm} /> · {tableViews.length} <IconChevronDown size={theme.icon.size.sm} />
</StyledDropdownLabelAdornments> </StyledDropdownLabelAdornments>
</> </>
} }
@ -195,7 +201,7 @@ export const TableViewsDropdownButton = ({
HotkeyScope={HotkeyScope} HotkeyScope={HotkeyScope}
> >
<StyledDropdownMenuItemsContainer> <StyledDropdownMenuItemsContainer>
{views.map((view) => ( {tableViews.map((view) => (
<DropdownMenuItem <DropdownMenuItem
key={view.id} key={view.id}
actions={[ actions={[
@ -204,7 +210,7 @@ export const TableViewsDropdownButton = ({
onClick={(event) => handleEditViewButtonClick(event, view.id)} onClick={(event) => handleEditViewButtonClick(event, view.id)}
icon={<IconPencil size={theme.icon.size.sm} />} icon={<IconPencil size={theme.icon.size.sm} />}
/>, />,
views.length > 1 ? ( tableViews.length > 1 ? (
<IconButton <IconButton
key="delete" key="delete"
onClick={(event) => onClick={(event) =>

View File

@ -3,12 +3,12 @@ import { useRecoilCallback, useRecoilState } from 'recoil';
import { isDragSelectionStartEnabledState } from '../states/internal/isDragSelectionStartEnabledState'; import { isDragSelectionStartEnabledState } from '../states/internal/isDragSelectionStartEnabledState';
export function useDragSelect() { export function useDragSelect() {
const [, setIsDragSelectionStartEnabledInternal] = useRecoilState( const [, setIsDragSelectionStartEnabled] = useRecoilState(
isDragSelectionStartEnabledState, isDragSelectionStartEnabledState,
); );
function setDragSelectionStartEnabled(isEnabled: boolean) { function setDragSelectionStartEnabled(isEnabled: boolean) {
setIsDragSelectionStartEnabledInternal(isEnabled); setIsDragSelectionStartEnabled(isEnabled);
} }
const isDragSelectionStartEnabled = useRecoilCallback( const isDragSelectionStartEnabled = useRecoilCallback(

View File

@ -23,14 +23,14 @@ export function UserPicker({
onCancel, onCancel,
width, width,
}: UserPickerProps) { }: UserPickerProps) {
const [searchFilter] = useRecoilScopedState( const [relationPickerSearchFilter] = useRecoilScopedState(
relationPickerSearchFilterScopedState, relationPickerSearchFilterScopedState,
); );
const users = useFilteredSearchEntityQuery({ const users = useFilteredSearchEntityQuery({
queryHook: useSearchUserQuery, queryHook: useSearchUserQuery,
selectedIds: userId ? [userId] : [], selectedIds: userId ? [userId] : [],
searchFilter: searchFilter, searchFilter: relationPickerSearchFilter,
mappingFunction: (user) => ({ mappingFunction: (user) => ({
entityType: Entity.User, entityType: Entity.User,
id: user.id, id: user.id,

View File

@ -27,22 +27,19 @@ export const useTableViews = <Entity, SortField>({
objectId: 'company' | 'person'; objectId: 'company' | 'person';
columnDefinitions: ColumnDefinition<ViewFieldMetadata>[]; columnDefinitions: ColumnDefinition<ViewFieldMetadata>[];
}) => { }) => {
const currentViewId = useRecoilScopedValue( const currentTableViewId = useRecoilScopedValue(
currentTableViewIdState, currentTableViewIdState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const currentColumns = useRecoilScopedValue( const tableColumns = useRecoilScopedValue(
tableColumnsScopedState, tableColumnsScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const selectedFilters = useRecoilScopedValue( const filters = useRecoilScopedValue(
filtersScopedState, filtersScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const selectedSorts = useRecoilScopedValue( const sorts = useRecoilScopedValue(sortsScopedState, TableRecoilScopeContext);
sortsScopedState,
TableRecoilScopeContext,
);
const { createViewFields, persistColumns } = useTableViewFields({ const { createViewFields, persistColumns } = useTableViewFields({
objectId, objectId,
@ -50,28 +47,28 @@ export const useTableViews = <Entity, SortField>({
}); });
const { createViewFilters, persistFilters } = useViewFilters({ const { createViewFilters, persistFilters } = useViewFilters({
availableFilters, availableFilters,
currentViewId, currentViewId: currentTableViewId,
scopeContext: TableRecoilScopeContext, scopeContext: TableRecoilScopeContext,
}); });
const { createViewSorts, persistSorts } = useViewSorts({ const { createViewSorts, persistSorts } = useViewSorts({
availableSorts, availableSorts,
currentViewId, currentViewId: currentTableViewId,
scopeContext: TableRecoilScopeContext, scopeContext: TableRecoilScopeContext,
}); });
const handleViewCreate = useCallback( const handleViewCreate = useCallback(
async (viewId: string) => { async (viewId: string) => {
await createViewFields(currentColumns, viewId); await createViewFields(tableColumns, viewId);
await createViewFilters(selectedFilters, viewId); await createViewFilters(filters, viewId);
await createViewSorts(selectedSorts, viewId); await createViewSorts(sorts, viewId);
}, },
[ [
createViewFields, createViewFields,
createViewFilters, createViewFilters,
createViewSorts, createViewSorts,
currentColumns, filters,
selectedFilters, sorts,
selectedSorts, tableColumns,
], ],
); );

View File

@ -25,15 +25,15 @@ export const useViews = ({
objectId: 'company' | 'person'; objectId: 'company' | 'person';
onViewCreate: (viewId: string) => Promise<void>; onViewCreate: (viewId: string) => Promise<void>;
}) => { }) => {
const [currentViewId, setCurrentViewId] = useRecoilScopedState( const [currentTableViewId, setCurrentTableViewId] = useRecoilScopedState(
currentTableViewIdState, currentTableViewIdState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const [views, setViews] = useRecoilScopedState( const [tableViews, setTableViews] = useRecoilScopedState(
tableViewsState, tableViewsState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const viewsById = useRecoilScopedValue( const tableViewsById = useRecoilScopedValue(
tableViewsByIdState, tableViewsByIdState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -88,16 +88,17 @@ export const useViews = ({
name: view.name, name: view.name,
})); }));
if (!isDeeplyEqual(views, nextViews)) setViews(nextViews); if (!isDeeplyEqual(tableViews, nextViews)) setTableViews(nextViews);
if (nextViews.length && !currentViewId) setCurrentViewId(nextViews[0].id); if (nextViews.length && !currentTableViewId)
setCurrentTableViewId(nextViews[0].id);
}, },
}); });
const handleViewsChange = useCallback( const handleViewsChange = useCallback(
async (nextViews: TableView[]) => { async (nextViews: TableView[]) => {
const viewToCreate = nextViews.find( const viewToCreate = nextViews.find(
(nextView) => !viewsById[nextView.id], (nextView) => !tableViewsById[nextView.id],
); );
if (viewToCreate) { if (viewToCreate) {
await createView(viewToCreate); await createView(viewToCreate);
@ -106,8 +107,8 @@ export const useViews = ({
const viewToUpdate = nextViews.find( const viewToUpdate = nextViews.find(
(nextView) => (nextView) =>
viewsById[nextView.id] && tableViewsById[nextView.id] &&
viewsById[nextView.id].name !== nextView.name, tableViewsById[nextView.id].name !== nextView.name,
); );
if (viewToUpdate) { if (viewToUpdate) {
await updateView(viewToUpdate); await updateView(viewToUpdate);
@ -115,14 +116,14 @@ export const useViews = ({
} }
const nextViewIds = nextViews.map((nextView) => nextView.id); const nextViewIds = nextViews.map((nextView) => nextView.id);
const viewIdToDelete = Object.keys(viewsById).find( const viewIdToDelete = Object.keys(tableViewsById).find(
(previousViewId) => !nextViewIds.includes(previousViewId), (previousViewId) => !nextViewIds.includes(previousViewId),
); );
if (viewIdToDelete) await deleteView(viewIdToDelete); if (viewIdToDelete) await deleteView(viewIdToDelete);
return refetch(); return refetch();
}, },
[createView, deleteView, refetch, updateView, viewsById], [createView, deleteView, refetch, tableViewsById, updateView],
); );
return { handleViewsChange }; return { handleViewsChange };

View File

@ -2,11 +2,13 @@
const noHardcodedColors = require('./rules/no-hardcoded-colors'); const noHardcodedColors = require('./rules/no-hardcoded-colors');
const cssAlphabetically = require('./rules/sort-css-properties-alphabetically'); const cssAlphabetically = require('./rules/sort-css-properties-alphabetically');
const styledComponentsPrefixedWithStyled = require('./rules/styled-components-prefixed-with-styled'); const styledComponentsPrefixedWithStyled = require('./rules/styled-components-prefixed-with-styled');
const matchingStateVariable = require('./rules/matching-state-variable');
module.exports = { module.exports = {
rules: { rules: {
'no-hardcoded-colors': noHardcodedColors, 'no-hardcoded-colors': noHardcodedColors,
'sort-css-properties-alphabetically': cssAlphabetically, 'sort-css-properties-alphabetically': cssAlphabetically,
'styled-components-prefixed-with-styled': styledComponentsPrefixedWithStyled, 'styled-components-prefixed-with-styled': styledComponentsPrefixedWithStyled,
'matching-state-variable': matchingStateVariable
}, },
}; };

View File

@ -0,0 +1,92 @@
"use strict";
module.exports = {
meta: {
type: "problem",
docs: {
description:
"Ensure recoil value and setter are named after their atom name",
category: "Possible Errors",
recommended: true,
},
fixable: "code",
schema: [],
},
create: function (context) {
return {
VariableDeclarator(node) {
if (
node?.init?.callee?.name &&
typeof node.init.callee.name === "string" &&
node.init.callee.name.startsWith("useRecoil")
) {
const stateNameBase = node.init.arguments?.[0].name;
if (!stateNameBase) {
return;
}
let expectedVariableNameBase = stateNameBase.replace(
/(State|FamilyState|Selector|ScopedState|ScopedFamilyState|ScopedSelector)$/,
""
);
if (node.id.type === "Identifier") {
const actualVariableName = node.id.name;
if (actualVariableName !== expectedVariableNameBase) {
context.report({
node,
message: `Invalid usage of ${node.init.callee.name}: the value should be named '${expectedVariableNameBase}' but found '${actualVariableName}'.`,
fix(fixer) {
return fixer.replaceText(node.id, expectedVariableNameBase);
},
});
}
return;
}
if (node.id.type === "ArrayPattern") {
const actualVariableName = node.id.elements?.[0]?.name;
if (
actualVariableName &&
actualVariableName !== expectedVariableNameBase
) {
context.report({
node,
message: `Invalid usage of ${node.init.callee.name}: the value should be named '${expectedVariableNameBase}' but found '${actualVariableName}'.`,
fix(fixer) {
return fixer.replaceText(
node.id.elements[0],
expectedVariableNameBase
);
},
});
return;
}
if (node.id.elements?.[1]?.name) {
const actualSetterName = node.id.elements[1].name;
const expectedSetterName = `set${expectedVariableNameBase
.charAt(0)
.toUpperCase()}${expectedVariableNameBase.slice(1)}`;
if (actualSetterName !== expectedSetterName) {
context.report({
node,
message: `Invalid usage of ${node.init.callee.name}: Expected setter '${expectedSetterName}' but found '${actualSetterName}'.`,
fix(fixer) {
return fixer.replaceText(
node.id.elements[1],
expectedSetterName
);
},
});
}
}
}
}
},
};
},
};