Remove unused components (#1180)

* Remove unused components

* Fix company not being created issue

* Fix company not being created issue

* Fix company not being created issue

* Optimize rendering

* Optimize rendering
This commit is contained in:
Charles Bochet
2023-08-13 01:29:18 +02:00
committed by GitHub
parent 35ea6b5a2f
commit 09ab1300a3
34 changed files with 184 additions and 806 deletions

View File

@ -1,43 +1,38 @@
import { gql } from '@apollo/client';
export const COMPANY_FIELDS_FRAGMENT = gql`
fragment CompanyFieldsFragment on Company {
accountOwner {
id
email
displayName
avatarUrl
}
address
createdAt
domainName
employees
linkedinUrl
id
name
}
`;
export const UPDATE_ONE_COMPANY = gql`
mutation UpdateOneCompany(
$where: CompanyWhereUniqueInput!
$data: CompanyUpdateInput!
) {
updateOneCompany(data: $data, where: $where) {
accountOwner {
id
email
displayName
firstName
lastName
}
address
createdAt
domainName
employees
linkedinUrl
id
name
...CompanyFieldsFragment
}
}
`;
export const INSERT_COMPANY_FRAGMENT = gql`
fragment InsertCompanyFragment on Company {
domainName
address
id
name
createdAt
}
`;
export const INSERT_ONE_COMPANY = gql`
mutation InsertOneCompany($data: CompanyCreateInput!) {
createOneCompany(data: $data) {
...InsertCompanyFragment
...CompanyFieldsFragment
}
}
`;

View File

@ -8,12 +8,14 @@ import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIn
import { IconList } from '@/ui/icon';
import { EntityTable } from '@/ui/table/components/EntityTable';
import { GenericEntityTableData } from '@/ui/table/components/GenericEntityTableData';
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
import { TableContext } from '@/ui/table/states/TableContext';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useTableViewFields } from '@/views/hooks/useTableViewFields';
import { useViewSorts } from '@/views/hooks/useViewSorts';
import { currentViewIdState } from '@/views/states/currentViewIdState';
import {
UpdateOneCompanyMutationVariables,
useGetCompaniesQuery,
useUpdateOneCompanyMutation,
} from '~/generated/graphql';
@ -25,6 +27,8 @@ import { defaultOrderBy } from '../../queries';
export function CompanyTable() {
const currentViewId = useRecoilValue(currentViewIdState);
const orderBy = useRecoilScopedValue(sortsOrderByScopedState, TableContext);
const [updateEntityMutation] = useUpdateOneCompanyMutation();
const upsertEntityTableItem = useUpsertEntityTableItem();
const { handleColumnsChange } = useTableViewFields({
objectName: 'company',
@ -56,7 +60,21 @@ export function CompanyTable() {
availableSorts={availableSorts}
onColumnsChange={handleColumnsChange}
onSortsUpdate={currentViewId ? updateSorts : undefined}
useUpdateEntityMutation={useUpdateOneCompanyMutation}
updateEntityMutation={({
variables,
}: {
variables: UpdateOneCompanyMutationVariables;
}) =>
updateEntityMutation({
variables,
onCompleted: (data) => {
if (!data.updateOneCompany) {
return;
}
upsertEntityTableItem(data.updateOneCompany);
},
})
}
/>
</>
);

View File

@ -13,7 +13,7 @@ export function CompanyTableMockMode() {
viewName="All Companies"
viewIcon={<IconList size={16} />}
availableSorts={availableSorts}
useUpdateEntityMutation={useUpdateOneCompanyMutation}
updateEntityMutation={[useUpdateOneCompanyMutation()]}
/>
</>
);

View File

@ -8,12 +8,14 @@ import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIn
import { IconList } from '@/ui/icon';
import { EntityTable } from '@/ui/table/components/EntityTable';
import { GenericEntityTableData } from '@/ui/table/components/GenericEntityTableData';
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
import { TableContext } from '@/ui/table/states/TableContext';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useTableViewFields } from '@/views/hooks/useTableViewFields';
import { useViewSorts } from '@/views/hooks/useViewSorts';
import { currentViewIdState } from '@/views/states/currentViewIdState';
import {
UpdateOnePersonMutationVariables,
useGetPeopleQuery,
useUpdateOnePersonMutation,
} from '~/generated/graphql';
@ -25,6 +27,8 @@ import { defaultOrderBy } from '../../queries';
export function PeopleTable() {
const currentViewId = useRecoilValue(currentViewIdState);
const orderBy = useRecoilScopedValue(sortsOrderByScopedState, TableContext);
const [updateEntityMutation] = useUpdateOnePersonMutation();
const upsertEntityTableItem = useUpsertEntityTableItem();
const { handleColumnsChange } = useTableViewFields({
objectName: 'person',
@ -56,7 +60,21 @@ export function PeopleTable() {
availableSorts={availableSorts}
onColumnsChange={handleColumnsChange}
onSortsUpdate={currentViewId ? updateSorts : undefined}
useUpdateEntityMutation={useUpdateOnePersonMutation}
updateEntityMutation={({
variables,
}: {
variables: UpdateOnePersonMutationVariables;
}) =>
updateEntityMutation({
variables,
onCompleted: (data) => {
if (!data.updateOnePerson) {
return;
}
upsertEntityTableItem(data.updateOnePerson);
},
})
}
/>
</>
);

View File

@ -64,9 +64,7 @@ export const SEARCH_COMPANY_QUERY = gql`
take: $limit
orderBy: $orderBy
) {
id
name
domainName
...CompanyFieldsFragment
}
}
`;

View File

@ -1,24 +0,0 @@
import { ReactElement } from 'react';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { BoardCardFieldContext } from '../states/BoardCardFieldContext';
import { BoardCardEditableFieldInternal } from './BoardCardEditableFieldInternal';
type OwnProps = {
editModeContent: ReactElement;
nonEditModeContent: ReactElement;
editModeHorizontalAlign?: 'left' | 'right';
editModeVerticalPosition?: 'over' | 'below';
editHotkeyScope?: HotkeyScope;
};
export function BoardCardEditableField(props: OwnProps) {
return (
<RecoilScope SpecificContext={BoardCardFieldContext}>
<BoardCardEditableFieldInternal {...props} />
</RecoilScope>
);
}

View File

@ -1,39 +0,0 @@
import { useMemo, useState } from 'react';
import { DateInputDisplay } from '@/ui/input/date/components/DateInputDisplay';
import { debounce } from '~/utils/debounce';
import { BoardCardEditableField } from './BoardCardEditableField';
import { BoardCardEditableFieldDateEditMode } from './BoardCardEditableFieldDateEditMode';
type OwnProps = {
value: Date;
onChange: (newValue: Date) => void;
editModeHorizontalAlign?: 'left' | 'right';
};
export function BoardCardEditableFieldDate({
value,
onChange,
editModeHorizontalAlign,
}: OwnProps) {
const [internalValue, setInternalValue] = useState(value);
const debouncedOnChange = useMemo(() => {
return debounce(onChange, 200);
}, [onChange]);
return (
<BoardCardEditableField
editModeHorizontalAlign={editModeHorizontalAlign}
editModeContent={
<BoardCardEditableFieldDateEditMode
value={internalValue}
onChange={(date: Date) => {
setInternalValue(date);
debouncedOnChange(date);
}}
/>
}
nonEditModeContent={<DateInputDisplay value={value} />}
></BoardCardEditableField>
);
}

View File

@ -1,17 +0,0 @@
import { DateInputEdit } from '@/ui/input/date/components/DateInputEdit';
type OwnProps = {
value: Date;
onChange: (newValue: Date) => void;
};
export function BoardCardEditableFieldDateEditMode({
value,
onChange,
}: OwnProps) {
function handleDateChange(newDate: Date) {
onChange(newDate);
}
return <DateInputEdit value={value} onChange={handleDateChange} />;
}

View File

@ -1,32 +0,0 @@
import styled from '@emotion/styled';
export const BoardCardFieldDisplayModeOuterContainer = styled.div`
align-items: center;
display: flex;
height: 100%;
overflow: hidden;
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(1)};
width: 100%;
`;
export const BoardCardFieldDisplayModeInnerContainer = styled.div`
align-items: center;
display: flex;
height: 100%;
overflow: hidden;
width: 100%;
`;
export function BoardCardEditableFieldDisplayMode({
children,
}: React.PropsWithChildren<unknown>) {
return (
<BoardCardFieldDisplayModeOuterContainer>
<BoardCardFieldDisplayModeInnerContainer>
{children}
</BoardCardFieldDisplayModeInnerContainer>
</BoardCardFieldDisplayModeOuterContainer>
);
}

View File

@ -1,81 +0,0 @@
import { ReactElement, useRef } from 'react';
import styled from '@emotion/styled';
import { overlayBackground } from '@/ui/theme/constants/effects';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { BoardCardFieldHotkeyScope } from '../types/BoardCardFieldHotkeyScope';
export const BoardCardFieldEditModeContainer = styled.div<
Omit<OwnProps, 'onExit'>
>`
align-items: center;
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.sm};
display: flex;
left: ${(props) =>
props.editModeHorizontalAlign === 'right' ? 'auto' : '0'};
margin-left: -2px;
min-height: 100%;
min-width: calc(100% + 20px);
position: absolute;
right: ${(props) =>
props.editModeHorizontalAlign === 'right' ? '0' : 'auto'};
top: ${(props) => (props.editModeVerticalPosition === 'over' ? '0' : '100%')};
z-index: 1;
${overlayBackground}
`;
type OwnProps = {
children: ReactElement;
editModeHorizontalAlign?: 'left' | 'right';
editModeVerticalPosition?: 'over' | 'below';
onExit: () => void;
};
export function BoardCardEditableFieldEditMode({
editModeHorizontalAlign,
editModeVerticalPosition,
children,
onExit,
}: OwnProps) {
const wrapperRef = useRef(null);
useListenClickOutside({
refs: [wrapperRef],
callback: () => {
onExit();
},
});
useScopedHotkeys(
'enter',
() => {
onExit();
},
BoardCardFieldHotkeyScope.BoardCardFieldEditMode,
[onExit],
);
useScopedHotkeys(
'esc',
() => {
onExit();
},
BoardCardFieldHotkeyScope.BoardCardFieldEditMode,
[onExit],
);
return (
<BoardCardFieldEditModeContainer
data-testid="editable-cell-edit-mode-container"
ref={wrapperRef}
editModeHorizontalAlign={editModeHorizontalAlign}
editModeVerticalPosition={editModeVerticalPosition}
>
{children}
</BoardCardFieldEditModeContainer>
);
}

View File

@ -1,82 +0,0 @@
import { ReactElement } from 'react';
import styled from '@emotion/styled';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useBoardCardField } from '../hooks/useBoardCardField';
import { BoardCardFieldHotkeyScope } from '../types/BoardCardFieldHotkeyScope';
import { BoardCardEditableFieldDisplayMode } from './BoardCardEditableFieldDisplayMode';
import { BoardCardEditableFieldEditMode } from './BoardCardEditableFieldEditMode';
export const BoardCardFieldContainer = styled.div`
align-items: center;
box-sizing: border-box;
cursor: pointer;
display: flex;
height: 32px;
position: relative;
user-select: none;
width: 100%;
`;
type OwnProps = {
editModeContent: ReactElement;
nonEditModeContent: ReactElement;
editModeHorizontalAlign?: 'left' | 'right';
editModeVerticalPosition?: 'over' | 'below';
editHotkeyScope?: HotkeyScope;
};
export function BoardCardEditableFieldInternal({
editModeHorizontalAlign = 'left',
editModeVerticalPosition = 'over',
editModeContent,
nonEditModeContent,
editHotkeyScope,
}: OwnProps) {
const { openBoardCardField, isBoardCardFieldInEditMode } =
useBoardCardField();
const { closeBoardCardField } = useBoardCardField();
const {
goBackToPreviousHotkeyScope,
setHotkeyScopeAndMemorizePreviousScope,
} = usePreviousHotkeyScope();
function handleOnClick() {
if (!isBoardCardFieldInEditMode) {
openBoardCardField();
setHotkeyScopeAndMemorizePreviousScope(
editHotkeyScope?.scope ??
BoardCardFieldHotkeyScope.BoardCardFieldEditMode,
editHotkeyScope?.customScopes ?? {},
);
}
}
function handleEditModeExit() {
goBackToPreviousHotkeyScope();
closeBoardCardField();
}
return (
<BoardCardFieldContainer onClick={handleOnClick}>
{isBoardCardFieldInEditMode ? (
<BoardCardEditableFieldEditMode
editModeHorizontalAlign={editModeHorizontalAlign}
editModeVerticalPosition={editModeVerticalPosition}
onExit={handleEditModeExit}
>
{editModeContent}
</BoardCardEditableFieldEditMode>
) : (
<BoardCardEditableFieldDisplayMode>
{nonEditModeContent}
</BoardCardEditableFieldDisplayMode>
)}
</BoardCardFieldContainer>
);
}

View File

@ -1,46 +0,0 @@
import { ChangeEvent, useMemo, useState } from 'react';
import { TextInputDisplay } from '@/ui/input/text/components/TextInputDisplay';
import { StyledInput } from '@/ui/table/editable-cell/type/components/TextCellEdit';
import { debounce } from '~/utils/debounce';
import { BoardCardEditableField } from './BoardCardEditableField';
type OwnProps = {
placeholder?: string;
value: string;
onChange: (newValue: string) => void;
editModeHorizontalAlign?: 'left' | 'right';
};
export function BoardCardEditableFieldText({
value,
placeholder,
onChange,
editModeHorizontalAlign,
}: OwnProps) {
const [internalValue, setInternalValue] = useState(value);
const debouncedOnChange = useMemo(() => {
return debounce(onChange, 200);
}, [onChange]);
return (
<BoardCardEditableField
editModeHorizontalAlign={editModeHorizontalAlign}
editModeContent={
<StyledInput
placeholder={placeholder || ''}
autoFocus
value={internalValue}
autoComplete="off"
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setInternalValue(event.target.value);
debouncedOnChange(event.target.value);
}}
/>
}
nonEditModeContent={<TextInputDisplay>{value}</TextInputDisplay>}
></BoardCardEditableField>
);
}

View File

@ -1,26 +0,0 @@
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { BoardCardFieldContext } from '../states/BoardCardFieldContext';
import { isBoardCardFieldInEditModeScopedState } from '../states/isBoardCardFieldInEditModeScopedState';
export function useBoardCardField() {
const [isBoardCardFieldInEditMode, setIsBoardCardFieldInEditMode] =
useRecoilScopedState(
isBoardCardFieldInEditModeScopedState,
BoardCardFieldContext,
);
function openBoardCardField() {
setIsBoardCardFieldInEditMode(true);
}
function closeBoardCardField() {
setIsBoardCardFieldInEditMode(false);
}
return {
isBoardCardFieldInEditMode,
openBoardCardField,
closeBoardCardField,
};
}

View File

@ -1,3 +0,0 @@
import { createContext } from 'react';
export const BoardCardFieldContext = createContext<string | null>(null);

View File

@ -1,9 +0,0 @@
import { atomFamily } from 'recoil';
export const isBoardCardFieldInEditModeScopedState = atomFamily<
boolean,
string
>({
key: 'isBoardCardFieldInEditModeScopedState',
default: false,
});

View File

@ -1,3 +0,0 @@
export enum BoardCardFieldHotkeyScope {
BoardCardFieldEditMode = 'board-card-field-edit-mode',
}

View File

@ -1,53 +0,0 @@
// TODO: refactor this test with Recoil
describe('getOptimisticlyUpdatedBoard', () => {
it('should return a new board with the updated cell', () => {
// const initialColumn1: string[] = ['item-1', 'item-2', 'item-3'];
// const initialColumn2: string[] = ['item-4', 'item-5'];
// const finalColumn1: string[] = ['item-2', 'item-3'];
// const finalColumn2: string[] = ['item-4', 'item-1', 'item-5'];
// const dropResult = {
// source: {
// droppableId: 'column-1',
// index: 0,
// },
// destination: {
// droppableId: 'column-2',
// index: 1,
// },
// } as DropResult;
// const initialBoard = [
// {
// id: 'column-1',
// title: 'My Column',
// pipelineStageId: 'column-1',
// pipelineProgressIds: initialColumn1,
// },
// {
// id: 'column-2',
// title: 'My Column',
// pipelineStageId: 'column-2',
// pipelineProgressIds: initialColumn2,
// },
// ];
// const updatedBoard = u(
// initialBoard,
// dropResult,
// );
// const finalBoard = [
// {
// id: 'column-1',
// title: 'My Column',
// pipelineStageId: 'column-1',
// pipelineProgressIds: finalColumn1,
// },
// {
// id: 'column-2',
// title: 'My Column',
// pipelineStageId: 'column-2',
// pipelineProgressIds: finalColumn2,
// },
// ];
// expect(updatedBoard).toEqual(finalBoard);
// expect(updatedBoard).not.toBe(initialBoard);
});
});

View File

@ -1,64 +0,0 @@
import { useEffect, useState } from 'react';
import { EditableField } from '@/ui/editable-field/components/EditableField';
import { FieldContext } from '@/ui/editable-field/states/FieldContext';
import { IconMap } from '@/ui/icon';
import { TextInputEdit } from '@/ui/input/text/components/TextInputEdit';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { Company, useUpdateOneCompanyMutation } from '~/generated/graphql';
type OwnProps = {
company: Pick<Company, 'id' | 'address'>;
};
export function CompanyEditableFieldAddress({ company }: OwnProps) {
const [internalValue, setInternalValue] = useState(company.address);
const [updateCompany] = useUpdateOneCompanyMutation();
useEffect(() => {
setInternalValue(company.address);
}, [company.address]);
async function handleChange(newValue: string) {
setInternalValue(newValue);
}
async function handleSubmit() {
await updateCompany({
variables: {
where: {
id: company.id,
},
data: {
address: internalValue ?? '',
},
},
});
}
async function handleCancel() {
setInternalValue(company.address);
}
return (
<RecoilScope SpecificContext={FieldContext}>
<EditableField
onSubmit={handleSubmit}
onCancel={handleCancel}
iconLabel={<IconMap />}
editModeContent={
<TextInputEdit
placeholder={'Address'}
autoFocus
value={internalValue}
onChange={(newValue: string) => {
handleChange(newValue);
}}
/>
}
displayModeContent={internalValue !== '' ? internalValue : 'No address'}
/>
</RecoilScope>
);
}

View File

@ -1,58 +0,0 @@
import { ReactNode } from 'react';
import styled from '@emotion/styled';
const StyledPropertyBoxItem = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(1)};
`;
const StyledIconContainer = styled.div`
align-items: center;
display: flex;
svg {
align-items: center;
display: flex;
height: 16px;
justify-content: center;
width: 16px;
}
`;
const StyledValueContainer = styled.div`
align-content: flex-start;
align-items: center;
color: ${({ theme }) => theme.font.color.primary};
display: flex;
flex: 1 0 0;
flex-wrap: wrap;
`;
const StyledLabelAndIconContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.tertiary};
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
`;
export function PropertyBoxItem({
icon,
label,
value,
}: {
icon: ReactNode;
label?: string;
value: ReactNode;
}) {
return (
<StyledPropertyBoxItem>
<StyledLabelAndIconContainer>
<StyledIconContainer>{icon}</StyledIconContainer>
{label}
</StyledLabelAndIconContainer>
<StyledValueContainer>{value}</StyledValueContainer>
</StyledPropertyBoxItem>
);
}

View File

@ -1,64 +0,0 @@
import { useEffect, useState } from 'react';
import { EditableField } from '@/ui/editable-field/components/EditableField';
import { FieldContext } from '@/ui/editable-field/states/FieldContext';
import { TextInputEdit } from '@/ui/input/text/components/TextInputEdit';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { OverflowingTextWithTooltip } from '../../../tooltip/OverflowingTextWithTooltip';
type OwnProps = {
icon?: React.ReactNode;
placeholder?: string;
value: string | null | undefined;
onSubmit?: (newValue: string) => void;
};
export function TextEditableField({
icon,
placeholder,
value,
onSubmit,
}: OwnProps) {
const [internalValue, setInternalValue] = useState(value);
useEffect(() => {
setInternalValue(value);
}, [value]);
async function handleChange(newValue: string) {
setInternalValue(newValue);
}
async function handleSubmit() {
if (!internalValue) return;
onSubmit?.(internalValue);
}
async function handleCancel() {
setInternalValue(value);
}
return (
<RecoilScope SpecificContext={FieldContext}>
<EditableField
onSubmit={handleSubmit}
onCancel={handleCancel}
iconLabel={icon}
editModeContent={
<TextInputEdit
placeholder={placeholder ?? ''}
autoFocus
value={internalValue ?? ''}
onChange={(newValue: string) => {
handleChange(newValue);
}}
/>
}
displayModeContent={<OverflowingTextWithTooltip text={internalValue} />}
isDisplayModeContentEmpty={!(internalValue !== '')}
/>
</RecoilScope>
);
}

View File

@ -1,31 +0,0 @@
import type { Meta, StoryObj } from '@storybook/react';
import { IconUser } from '@tabler/icons-react';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { TextEditableField } from '../TextEditableField';
const meta: Meta<typeof TextEditableField> = {
title: 'UI/EditableField/TextEditableField',
component: TextEditableField,
decorators: [ComponentDecorator],
argTypes: {
icon: {
type: 'boolean',
mapping: {
true: <IconUser />,
false: undefined,
},
},
},
args: {
value: 'John Doe',
icon: true,
placeholder: 'Name',
},
};
export default meta;
type Story = StoryObj<typeof TextEditableField>;
export const Default: Story = {};

View File

@ -1,6 +1,5 @@
import { useRef } from 'react';
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import type {
ViewFieldDefinition,
@ -12,9 +11,9 @@ import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useLis
import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus';
import { useMapKeyboardToSoftFocus } from '../hooks/useMapKeyboardToSoftFocus';
import { useResetTableRowSelection } from '../hooks/useResetTableRowSelection';
import { useSetRowSelectedState } from '../hooks/useSetRowSelectedState';
import { EntityUpdateMutationHookContext } from '../states/EntityUpdateMutationHookContext';
import { tableRowIdsState } from '../states/tableRowIdsState';
import { EntityUpdateMutationContext } from '../states/EntityUpdateMutationHookContext';
import { TableHeader } from '../table-header/components/TableHeader';
import { EntityTableBody } from './EntityTableBody';
@ -97,7 +96,7 @@ type OwnProps<SortField> = {
onColumnsChange?: (columns: ViewFieldDefinition<ViewFieldMetadata>[]) => void;
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
onRowSelectionChange?: (rowSelection: string[]) => void;
useUpdateEntityMutation: any;
updateEntityMutation: any;
};
export function EntityTable<SortField>({
@ -106,18 +105,12 @@ export function EntityTable<SortField>({
availableSorts,
onColumnsChange,
onSortsUpdate,
useUpdateEntityMutation,
updateEntityMutation,
}: OwnProps<SortField>) {
const tableBodyRef = useRef<HTMLDivElement>(null);
const rowIds = useRecoilValue(tableRowIdsState);
const setRowSelectedState = useSetRowSelectedState();
function resetSelections() {
for (const rowId of rowIds) {
setRowSelectedState(rowId, false);
}
}
const resetTableRowSelection = useResetTableRowSelection();
useMapKeyboardToSoftFocus();
@ -131,7 +124,7 @@ export function EntityTable<SortField>({
});
return (
<EntityUpdateMutationHookContext.Provider value={useUpdateEntityMutation}>
<EntityUpdateMutationContext.Provider value={updateEntityMutation}>
<StyledTableWithHeader>
<StyledTableContainer ref={tableBodyRef}>
<TableHeader
@ -149,11 +142,11 @@ export function EntityTable<SortField>({
</StyledTableWrapper>
<DragSelect
dragSelectable={tableBodyRef}
onDragSelectionStart={resetSelections}
onDragSelectionStart={resetTableRowSelection}
onDragSelectionChange={setRowSelectedState}
/>
</StyledTableContainer>
</StyledTableWithHeader>
</EntityUpdateMutationHookContext.Provider>
</EntityUpdateMutationContext.Provider>
);
}

View File

@ -16,7 +16,6 @@ export function GenericEntityTableData({
filterDefinitionArray: FilterDefinition[];
}) {
const setEntityTableData = useSetEntityTableData();
useGetRequest({
variables: { orderBy, where: whereFilters },
onCompleted: (data: any) => {

View File

@ -1,19 +0,0 @@
import styled from '@emotion/styled';
export const HoverableMenuItem = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.primary};
border-radius: ${({ theme }) => theme.border.radius.sm};
box-sizing: border-box;
cursor: pointer;
display: flex;
height: 100%;
position: relative;
transition: background 0.1s ease;
user-select: none;
width: 100%;
&:hover {
background: ${({ theme }) => theme.background.transparent.light};
}
`;

View File

@ -1,23 +0,0 @@
import { useEffect } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { numberOfTableRowsState } from '../states/numberOfTableRowsState';
import { tableRowIdsState } from '../states/tableRowIdsState';
import { useResetTableRowSelection } from './useResetTableRowSelection';
export function useInitializeEntityTable() {
const resetTableRowSelection = useResetTableRowSelection();
const tableRowIds = useRecoilValue(tableRowIdsState);
useEffect(() => {
resetTableRowSelection();
}, [resetTableRowSelection]);
const setNumberOfTableRows = useSetRecoilState(numberOfTableRowsState);
useEffect(() => {
setNumberOfTableRows(tableRowIds?.length);
}, [tableRowIds, setNumberOfTableRows]);
}

View File

@ -1,22 +0,0 @@
import { useEffect } from 'react';
import { availableFiltersScopedState } from '@/ui/filter-n-sort/states/availableFiltersScopedState';
import { FilterDefinition } from '@/ui/filter-n-sort/types/FilterDefinition';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { TableContext } from '../states/TableContext';
export function useInitializeEntityTableFilters({
availableFilters,
}: {
availableFilters: FilterDefinition[];
}) {
const [, setAvailableFilters] = useRecoilScopedState(
availableFiltersScopedState,
TableContext,
);
useEffect(() => {
setAvailableFilters(availableFilters);
}, [setAvailableFilters, availableFilters]);
}

View File

@ -0,0 +1,19 @@
import { useRecoilCallback } from 'recoil';
import { tableRowIdsState } from '../states/tableRowIdsState';
export function useSetTableRowIds() {
return useRecoilCallback(
({ set, snapshot }) =>
(rowIds: string[]) => {
const currentRowIds = snapshot
.getLoadable(tableRowIdsState)
.valueOrThrow();
if (JSON.stringify(rowIds) !== JSON.stringify(currentRowIds)) {
set(tableRowIdsState, rowIds);
}
},
[],
);
}

View File

@ -17,7 +17,6 @@ import { isViewFieldText } from '@/ui/editable-field/types/guards/isViewFieldTex
import { isViewFieldTextValue } from '@/ui/editable-field/types/guards/isViewFieldTextValue';
import { isViewFieldURL } from '@/ui/editable-field/types/guards/isViewFieldURL';
import { isViewFieldURLValue } from '@/ui/editable-field/types/guards/isViewFieldURLValue';
import { EntityUpdateMutationHookContext } from '@/ui/table/states/EntityUpdateMutationHookContext';
import { isViewFieldChipValue } from '../../editable-field/types/guards/isViewFieldChipValue';
import {
@ -42,11 +41,10 @@ import {
ViewFieldURLMetadata,
ViewFieldURLValue,
} from '../../editable-field/types/ViewField';
import { EntityUpdateMutationContext } from '../states/EntityUpdateMutationHookContext';
export function useUpdateEntityField() {
const useUpdateEntityMutation = useContext(EntityUpdateMutationHookContext);
const [updateEntity] = useUpdateEntityMutation();
const updateEntity = useContext(EntityUpdateMutationContext);
return function updatePeopleField<
MetadataType extends ViewFieldMetadata,

View File

@ -0,0 +1,19 @@
import { useRecoilCallback } from 'recoil';
import { tableEntitiesFamilyState } from '@/ui/table/states/tableEntitiesFamilyState';
export function useUpsertEntityTableItem() {
return useRecoilCallback(
({ set, snapshot }) =>
<T extends { id: string }>(entity: T) => {
const currentEntity = snapshot
.getLoadable(tableEntitiesFamilyState(entity.id))
.valueOrThrow();
if (JSON.stringify(currentEntity) !== JSON.stringify(entity)) {
set(tableEntitiesFamilyState(entity.id), entity);
}
},
[],
);
}

View File

@ -0,0 +1,17 @@
import { useRecoilCallback } from 'recoil';
import { tableRowIdsState } from '../states/tableRowIdsState';
export function useUpsertTableRowId() {
return useRecoilCallback(
({ set, snapshot }) =>
(rowId: string) => {
const currentRowIds = snapshot
.getLoadable(tableRowIdsState)
.valueOrThrow();
set(tableRowIdsState, Array.from(new Set([...currentRowIds, rowId])));
},
[],
);
}

View File

@ -1,3 +1,3 @@
import { createContext } from 'react';
export const EntityUpdateMutationHookContext = createContext<any | null>(null);
export const EntityUpdateMutationContext = createContext<any | null>(null);