Clean and re-organize post table refactoring (#1000)

* Clean and re-organize post table refactoring

* Fix tests
This commit is contained in:
Charles Bochet
2023-07-30 18:26:32 -07:00
committed by GitHub
parent 86a2d67efd
commit ade5e52e55
336 changed files with 638 additions and 2757 deletions

View File

@ -2,7 +2,7 @@ import { useCallback } from 'react';
import styled from '@emotion/styled';
import { useSetRecoilState } from 'recoil';
import { Checkbox } from '@/ui/input/components/Checkbox';
import { Checkbox } from '@/ui/input/checkbox/components/Checkbox';
import { useCurrentRowSelected } from '../hooks/useCurrentRowSelected';
import { contextMenuPositionState } from '../states/contextMenuPositionState';

View File

@ -1,13 +1,12 @@
import * as React from 'react';
import styled from '@emotion/styled';
import { TableColumn } from '@/people/table/components/peopleColumns';
import { SelectedSortType, SortType } from '@/ui/filter-n-sort/types/interface';
import { useListenClickOutside } from '@/ui/hooks/useListenClickOutside';
import { useListenClickOutside } from '@/ui/utilities/click-outside/hooks/useListenClickOutside';
import { useIsPageLoading } from '../../hooks/useIsPageLoading';
import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus';
import { useMapKeyboardToSoftFocus } from '../hooks/useMapKeyboardToSoftFocus';
import { EntityUpdateMutationHookContext } from '../states/EntityUpdateMutationHookContext';
import { TableHeader } from '../table-header/components/TableHeader';
import { EntityTableBody } from './EntityTableBody';
@ -85,20 +84,20 @@ const StyledTableWrapper = styled.div`
`;
type OwnProps<SortField> = {
columns: Array<TableColumn>;
viewName: string;
viewIcon?: React.ReactNode;
availableSorts?: Array<SortType<SortField>>;
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
onRowSelectionChange?: (rowSelection: string[]) => void;
useUpdateEntityMutation: any;
};
export function EntityTable<SortField>({
columns,
viewName,
viewIcon,
availableSorts,
onSortsUpdate,
useUpdateEntityMutation,
}: OwnProps<SortField>) {
const tableBodyRef = React.useRef<HTMLDivElement>(null);
@ -113,28 +112,24 @@ export function EntityTable<SortField>({
},
});
const isPageLoading = useIsPageLoading();
if (isPageLoading) {
return null;
}
return (
<StyledTableWithHeader>
<StyledTableContainer ref={tableBodyRef}>
<TableHeader
viewName={viewName}
viewIcon={viewIcon}
availableSorts={availableSorts}
onSortsUpdate={onSortsUpdate}
/>
<StyledTableWrapper>
<StyledTable>
<EntityTableHeader columns={columns} />
<EntityTableBody columns={columns} />
</StyledTable>
</StyledTableWrapper>
</StyledTableContainer>
</StyledTableWithHeader>
<EntityUpdateMutationHookContext.Provider value={useUpdateEntityMutation}>
<StyledTableWithHeader>
<StyledTableContainer ref={tableBodyRef}>
<TableHeader
viewName={viewName}
viewIcon={viewIcon}
availableSorts={availableSorts}
onSortsUpdate={onSortsUpdate}
/>
<StyledTableWrapper>
<StyledTable>
<EntityTableHeader />
<EntityTableBody />
</StyledTable>
</StyledTableWrapper>
</StyledTableContainer>
</StyledTableWithHeader>
</EntityUpdateMutationHookContext.Provider>
);
}

View File

@ -1,6 +1,5 @@
import { useRecoilValue } from 'recoil';
import { TableColumn } from '@/people/table/components/peopleColumns';
import { isNavbarSwitchingSizeState } from '@/ui/layout/states/isNavbarSwitchingSizeState';
import { isFetchingEntityTableDataState } from '../states/isFetchingEntityTableDataState';
@ -10,7 +9,7 @@ import { tableRowIdsState } from '../states/tableRowIdsState';
import { EntityTableRow } from './EntityTableRow';
export function EntityTableBody({ columns }: { columns: Array<TableColumn> }) {
export function EntityTableBody() {
const rowIds = useRecoilValue(tableRowIdsState);
const isNavbarSwitchingSize = useRecoilValue(isNavbarSwitchingSizeState);
@ -28,7 +27,7 @@ export function EntityTableBody({ columns }: { columns: Array<TableColumn> }) {
{rowIds.map((rowId, index) => (
<RowIdContext.Provider value={rowId} key={rowId}>
<RowIndexContext.Provider value={index}>
<EntityTableRow columns={columns} rowId={rowId} />
<EntityTableRow rowId={rowId} />
</RowIndexContext.Provider>
</RowIdContext.Provider>
))}

View File

@ -1,36 +0,0 @@
import { useRecoilValue } from 'recoil';
import { isNavbarSwitchingSizeState } from '@/ui/layout/states/isNavbarSwitchingSizeState';
import { isFetchingEntityTableDataState } from '../states/isFetchingEntityTableDataState';
import { RowIdContext } from '../states/RowIdContext';
import { RowIndexContext } from '../states/RowIndexContext';
import { tableRowIdsState } from '../states/tableRowIdsState';
import { EntityTableRow } from './EntityTableRowV2';
export function EntityTableBody() {
const rowIds = useRecoilValue(tableRowIdsState);
const isNavbarSwitchingSize = useRecoilValue(isNavbarSwitchingSizeState);
const isFetchingEntityTableData = useRecoilValue(
isFetchingEntityTableDataState,
);
if (isFetchingEntityTableData || isNavbarSwitchingSize) {
return null;
}
return (
<tbody>
{rowIds.map((rowId, index) => (
<RowIdContext.Provider value={rowId} key={rowId}>
<RowIndexContext.Provider value={index}>
<EntityTableRow rowId={rowId} />
</RowIndexContext.Provider>
</RowIdContext.Provider>
))}
</tbody>
);
}

View File

@ -1,19 +1,15 @@
import { useContext } from 'react';
import { useSetRecoilState } from 'recoil';
import { RecoilScope } from '../../recoil-scope/components/RecoilScope';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { GenericEditableCell } from '../editable-cell/components/GenericEditableCell';
import { useCurrentRowSelected } from '../hooks/useCurrentRowSelected';
import { ColumnIndexContext } from '../states/ColumnIndexContext';
import { contextMenuPositionState } from '../states/contextMenuPositionState';
import { ViewFieldContext } from '../states/ViewFieldContext';
export function EntityTableCell({
cellIndex,
children,
size,
}: {
size: number;
cellIndex: number;
children: React.ReactNode;
}) {
export function EntityTableCell({ cellIndex }: { cellIndex: number }) {
const setContextMenuPosition = useSetRecoilState(contextMenuPositionState);
const { setCurrentRowSelected } = useCurrentRowSelected();
@ -29,18 +25,24 @@ export function EntityTableCell({
});
}
const viewField = useContext(ViewFieldContext);
if (!viewField) {
return null;
}
return (
<RecoilScope>
<ColumnIndexContext.Provider value={cellIndex}>
<td
onContextMenu={(event) => handleContextMenu(event)}
style={{
width: size,
minWidth: size,
maxWidth: size,
width: viewField.columnSize,
minWidth: viewField.columnSize,
maxWidth: viewField.columnSize,
}}
>
{children}
<GenericEditableCell viewField={viewField} />
</td>
</ColumnIndexContext.Provider>
</RecoilScope>

View File

@ -1,50 +0,0 @@
import { useContext } from 'react';
import { useSetRecoilState } from 'recoil';
import { GenericEditableCell } from '@/ui/table/components/GenericEditableCell';
import { RecoilScope } from '../../recoil-scope/components/RecoilScope';
import { useCurrentRowSelected } from '../hooks/useCurrentRowSelected';
import { ColumnIndexContext } from '../states/ColumnIndexContext';
import { contextMenuPositionState } from '../states/contextMenuPositionState';
import { ViewFieldContext } from '../states/ViewFieldContext';
export function EntityTableCell({ cellIndex }: { cellIndex: number }) {
const setContextMenuPosition = useSetRecoilState(contextMenuPositionState);
const { setCurrentRowSelected } = useCurrentRowSelected();
function handleContextMenu(event: React.MouseEvent) {
event.preventDefault();
setCurrentRowSelected(true);
setContextMenuPosition({
x: event.clientX,
y: event.clientY,
});
}
const viewField = useContext(ViewFieldContext);
if (!viewField) {
return null;
}
return (
<RecoilScope>
<ColumnIndexContext.Provider value={cellIndex}>
<td
onContextMenu={(event) => handleContextMenu(event)}
style={{
width: viewField.columnSize,
minWidth: viewField.columnSize,
maxWidth: viewField.columnSize,
}}
>
<GenericEditableCell viewField={viewField} />
</td>
</ColumnIndexContext.Provider>
</RecoilScope>
);
}

View File

@ -1,13 +1,13 @@
import { TableColumn } from '@/people/table/components/peopleColumns';
import { useRecoilValue } from 'recoil';
import { viewFieldsFamilyState } from '../states/viewFieldsState';
import { ColumnHead } from './ColumnHead';
import { SelectAllCheckbox } from './SelectAllCheckbox';
export function EntityTableHeader({
columns,
}: {
columns: Array<TableColumn>;
}) {
export function EntityTableHeader() {
const viewFields = useRecoilValue(viewFieldsFamilyState);
return (
<thead>
<tr>
@ -20,16 +20,19 @@ export function EntityTableHeader({
>
<SelectAllCheckbox />
</th>
{columns.map((column) => (
{viewFields.map((viewField) => (
<th
key={column.id.toString()}
key={viewField.columnOrder.toString()}
style={{
width: column.size,
minWidth: column.size,
maxWidth: column.size,
width: viewField.columnSize,
minWidth: viewField.columnSize,
maxWidth: viewField.columnSize,
}}
>
<ColumnHead viewName={column.title} viewIcon={column.icon} />
<ColumnHead
viewName={viewField.columnLabel}
viewIcon={viewField.columnIcon}
/>
</th>
))}
<th></th>

View File

@ -1,42 +0,0 @@
import { useRecoilValue } from 'recoil';
import { viewFieldsFamilyState } from '../states/viewFieldsState';
import { ColumnHead } from './ColumnHead';
import { SelectAllCheckbox } from './SelectAllCheckbox';
export function EntityTableHeader() {
const viewFields = useRecoilValue(viewFieldsFamilyState);
return (
<thead>
<tr>
<th
style={{
width: 30,
minWidth: 30,
maxWidth: 30,
}}
>
<SelectAllCheckbox />
</th>
{viewFields.map((viewField) => (
<th
key={viewField.columnOrder.toString()}
style={{
width: viewField.columnSize,
minWidth: viewField.columnSize,
maxWidth: viewField.columnSize,
}}
>
<ColumnHead
viewName={viewField.columnLabel}
viewIcon={viewField.columnIcon}
/>
</th>
))}
<th></th>
</tr>
</thead>
);
}

View File

@ -1,6 +1,8 @@
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { TableColumn } from '@/people/table/components/peopleColumns';
import { ViewFieldContext } from '../states/ViewFieldContext';
import { viewFieldsFamilyState } from '../states/viewFieldsState';
import { CheckboxCell } from './CheckboxCell';
import { EntityTableCell } from './EntityTableCell';
@ -10,27 +12,22 @@ const StyledRow = styled.tr<{ selected: boolean }>`
props.selected ? props.theme.background.secondary : 'none'};
`;
export function EntityTableRow({
columns,
rowId,
}: {
columns: TableColumn[];
rowId: string;
}) {
export function EntityTableRow({ rowId }: { rowId: string }) {
const viewFields = useRecoilValue(viewFieldsFamilyState);
return (
<StyledRow data-testid={`row-id-${rowId}`} selected={false}>
<td>
<CheckboxCell />
</td>
{columns.map((column, columnIndex) => {
{viewFields.map((viewField, columnIndex) => {
return (
<EntityTableCell
key={column.id}
size={column.size}
cellIndex={columnIndex}
<ViewFieldContext.Provider
value={viewField}
key={viewField.columnOrder}
>
{column.cellComponent}
</EntityTableCell>
<EntityTableCell cellIndex={columnIndex} />
</ViewFieldContext.Provider>
);
})}
<td></td>

View File

@ -1,36 +0,0 @@
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { ViewFieldContext } from '../states/ViewFieldContext';
import { viewFieldsFamilyState } from '../states/viewFieldsState';
import { CheckboxCell } from './CheckboxCell';
import { EntityTableCell } from './EntityTableCellV2';
const StyledRow = styled.tr<{ selected: boolean }>`
background: ${(props) =>
props.selected ? props.theme.background.secondary : 'none'};
`;
export function EntityTableRow({ rowId }: { rowId: string }) {
const viewFields = useRecoilValue(viewFieldsFamilyState);
return (
<StyledRow data-testid={`row-id-${rowId}`} selected={false}>
<td>
<CheckboxCell />
</td>
{viewFields.map((viewField, columnIndex) => {
return (
<ViewFieldContext.Provider
value={viewField}
key={viewField.columnOrder}
>
<EntityTableCell cellIndex={columnIndex} />
</ViewFieldContext.Provider>
);
})}
<td></td>
</StyledRow>
);
}

View File

@ -1,135 +0,0 @@
import * as React from 'react';
import styled from '@emotion/styled';
import { SelectedSortType, SortType } from '@/ui/filter-n-sort/types/interface';
import { useListenClickOutside } from '@/ui/hooks/useListenClickOutside';
import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus';
import { useMapKeyboardToSoftFocus } from '../hooks/useMapKeyboardToSoftFocus';
import { EntityUpdateMutationHookContext } from '../states/EntityUpdateMutationHookContext';
import { TableHeader } from '../table-header/components/TableHeader';
import { EntityTableBody } from './EntityTableBodyV2';
import { EntityTableHeader } from './EntityTableHeaderV2';
const StyledTable = styled.table`
border-collapse: collapse;
border-radius: ${({ theme }) => theme.border.radius.sm};
border-spacing: 0;
margin-left: ${({ theme }) => theme.table.horizontalCellMargin};
margin-right: ${({ theme }) => theme.table.horizontalCellMargin};
table-layout: fixed;
width: calc(100% - ${({ theme }) => theme.table.horizontalCellMargin} * 2);
th {
border: 1px solid ${({ theme }) => theme.border.color.light};
border-collapse: collapse;
color: ${({ theme }) => theme.font.color.tertiary};
padding: 0;
text-align: left;
:last-child {
border-right-color: transparent;
}
:first-of-type {
border-left-color: transparent;
border-right-color: transparent;
}
:last-of-type {
min-width: 0;
width: 100%;
}
}
td {
border: 1px solid ${({ theme }) => theme.border.color.light};
border-collapse: collapse;
color: ${({ theme }) => theme.font.color.primary};
padding: 0;
text-align: left;
:last-child {
border-right-color: transparent;
}
:first-of-type {
border-left-color: transparent;
border-right-color: transparent;
}
:last-of-type {
min-width: 0;
width: 100%;
}
}
`;
const StyledTableWithHeader = styled.div`
display: flex;
flex: 1;
flex-direction: column;
width: 100%;
`;
const StyledTableContainer = styled.div`
display: flex;
flex-direction: column;
height: 100%;
overflow: auto;
`;
const StyledTableWrapper = styled.div`
flex: 1;
overflow: auto;
`;
type OwnProps<SortField> = {
viewName: string;
viewIcon?: React.ReactNode;
availableSorts?: Array<SortType<SortField>>;
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
onRowSelectionChange?: (rowSelection: string[]) => void;
useUpdateEntityMutation: any;
};
export function EntityTable<SortField>({
viewName,
viewIcon,
availableSorts,
onSortsUpdate,
useUpdateEntityMutation,
}: OwnProps<SortField>) {
const tableBodyRef = React.useRef<HTMLDivElement>(null);
useMapKeyboardToSoftFocus();
const leaveTableFocus = useLeaveTableFocus();
useListenClickOutside({
refs: [tableBodyRef],
callback: () => {
leaveTableFocus();
},
});
return (
<EntityUpdateMutationHookContext.Provider value={useUpdateEntityMutation}>
<StyledTableWithHeader>
<StyledTableContainer ref={tableBodyRef}>
<TableHeader
viewName={viewName}
viewIcon={viewIcon}
availableSorts={availableSorts}
onSortsUpdate={onSortsUpdate}
/>
<StyledTableWrapper>
<StyledTable>
<EntityTableHeader />
<EntityTableBody />
</StyledTable>
</StyledTableWrapper>
</StyledTableContainer>
</StyledTableWithHeader>
</EntityUpdateMutationHookContext.Provider>
);
}

View File

@ -1,55 +0,0 @@
import {
ViewFieldDefinition,
ViewFieldMetadata,
} from '@/ui/table/types/ViewField';
import { isViewFieldChip } from '../types/guards/isViewFieldChip';
import { isViewFieldDate } from '../types/guards/isViewFieldDate';
import { isViewFieldDoubleText } from '../types/guards/isViewFieldDoubleText';
import { isViewFieldDoubleTextChip } from '../types/guards/isViewFieldDoubleTextChip';
import { isViewFieldNumber } from '../types/guards/isViewFieldNumber';
import { isViewFieldPhone } from '../types/guards/isViewFieldPhone';
import { isViewFieldRelation } from '../types/guards/isViewFieldRelation';
import { isViewFieldText } from '../types/guards/isViewFieldText';
import { isViewFieldURL } from '../types/guards/isViewFieldURL';
import { GenericEditableChipCell } from './GenericEditableChipCell';
import { GenericEditableDateCell } from './GenericEditableDateCell';
import { GenericEditableDoubleTextCell } from './GenericEditableDoubleTextCell';
import { GenericEditableDoubleTextChipCell } from './GenericEditableDoubleTextChipCell';
import { GenericEditableNumberCell } from './GenericEditableNumberCell';
import { GenericEditablePhoneCell } from './GenericEditablePhoneCell';
import { GenericEditableRelationCell } from './GenericEditableRelationCell';
import { GenericEditableTextCell } from './GenericEditableTextCell';
import { GenericEditableURLCell } from './GenericEditableURLCell';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldMetadata>;
};
export function GenericEditableCell({ viewField: fieldDefinition }: OwnProps) {
if (isViewFieldText(fieldDefinition)) {
return <GenericEditableTextCell viewField={fieldDefinition} />;
} else if (isViewFieldRelation(fieldDefinition)) {
return <GenericEditableRelationCell fieldDefinition={fieldDefinition} />;
} else if (isViewFieldDoubleTextChip(fieldDefinition)) {
return <GenericEditableDoubleTextChipCell viewField={fieldDefinition} />;
} else if (isViewFieldDoubleText(fieldDefinition)) {
return <GenericEditableDoubleTextCell viewField={fieldDefinition} />;
} else if (isViewFieldPhone(fieldDefinition)) {
return <GenericEditablePhoneCell viewField={fieldDefinition} />;
} else if (isViewFieldURL(fieldDefinition)) {
return <GenericEditableURLCell viewField={fieldDefinition} />;
} else if (isViewFieldDate(fieldDefinition)) {
return <GenericEditableDateCell viewField={fieldDefinition} />;
} else if (isViewFieldNumber(fieldDefinition)) {
return <GenericEditableNumberCell viewField={fieldDefinition} />;
} else if (isViewFieldChip(fieldDefinition)) {
return <GenericEditableChipCell viewField={fieldDefinition} />;
} else {
console.warn(
`Unknown field metadata type: ${fieldDefinition.metadata.type} in GenericEditableCell`,
);
return <></>;
}
}

View File

@ -1,29 +0,0 @@
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import { ViewFieldChipMetadata, ViewFieldDefinition } from '../types/ViewField';
import { GenericEditableChipCellDisplayMode } from './GenericEditableChipCellDisplayMode';
import { GenericEditableChipCellEditMode } from './GenericEditableChipCellEditMode';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldChipMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
placeholder?: string;
};
export function GenericEditableChipCell({
viewField,
editModeHorizontalAlign,
}: OwnProps) {
return (
<EditableCell
editModeHorizontalAlign={editModeHorizontalAlign}
editModeContent={
<GenericEditableChipCellEditMode viewField={viewField} />
}
nonEditModeContent={
<GenericEditableChipCellDisplayMode fieldDefinition={viewField} />
}
></EditableCell>
);
}

View File

@ -1,52 +0,0 @@
import { useRecoilValue } from 'recoil';
import { CompanyChip } from '@/companies/components/CompanyChip';
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldChipMetadata,
ViewFieldDefinition,
} from '@/ui/table/types/ViewField';
import { getLogoUrlFromDomainName } from '~/utils';
type OwnProps = {
fieldDefinition: ViewFieldDefinition<ViewFieldChipMetadata>;
};
export function GenericEditableChipCellDisplayMode({
fieldDefinition,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const content = useRecoilValue<any | null>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: fieldDefinition.metadata.contentFieldName,
}),
);
const chipUrl = useRecoilValue<any | null>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: fieldDefinition.metadata.urlFieldName,
}),
);
switch (fieldDefinition.metadata.relationType) {
case Entity.Company: {
return (
<CompanyChip
id={currentRowEntityId ?? ''}
name={content ?? ''}
pictureUrl={getLogoUrlFromDomainName(chipUrl)}
/>
);
}
default:
console.warn(
`Unknown relation type: "${fieldDefinition.metadata.relationType}" in GenericEditableChipCellEditMode`,
);
return <> </>;
}
}

View File

@ -1,45 +0,0 @@
import { useRecoilState } from 'recoil';
import { InplaceInputTextCellEditMode } from '@/ui/inplace-input/components/InplaceInputTextCellEditMode';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { ViewFieldChipMetadata, ViewFieldDefinition } from '../types/ViewField';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldChipMetadata>;
};
export function GenericEditableChipCellEditMode({ viewField }: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
// TODO: we could use a hook that would return the field value with the right type
const [fieldValue, setFieldValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.contentFieldName,
}),
);
const updateField = useUpdateEntityField();
function handleSubmit(newText: string) {
if (newText === fieldValue) return;
setFieldValue(newText);
if (currentRowEntityId && updateField) {
updateField(currentRowEntityId, viewField, newText);
}
}
return (
<InplaceInputTextCellEditMode
placeholder={viewField.metadata.placeHolder ?? ''}
autoFocus
value={fieldValue ?? ''}
onSubmit={handleSubmit}
/>
);
}

View File

@ -1,39 +0,0 @@
import { useRecoilValue } from 'recoil';
import { InplaceInputDateDisplayMode } from '@/ui/display/component/InplaceInputDateDisplayMode';
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { ViewFieldDateMetadata, ViewFieldDefinition } from '../types/ViewField';
import { GenericEditableDateCellEditMode } from './GenericEditableDateCellEditMode';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldDateMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
};
export function GenericEditableDateCell({
viewField,
editModeHorizontalAlign,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const fieldValue = useRecoilValue<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
return (
<EditableCell
editModeHorizontalAlign={editModeHorizontalAlign}
editModeContent={
<GenericEditableDateCellEditMode viewField={viewField} />
}
nonEditModeContent={<InplaceInputDateDisplayMode value={fieldValue} />}
></EditableCell>
);
}

View File

@ -1,50 +0,0 @@
import { DateTime } from 'luxon';
import { useRecoilState } from 'recoil';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { EditableCellDateEditMode } from '../editable-cell/types/EditableCellDateEditMode';
import { ViewFieldDateMetadata, ViewFieldDefinition } from '../types/ViewField';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldDateMetadata>;
};
export function GenericEditableDateCellEditMode({ viewField }: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
// TODO: we could use a hook that would return the field value with the right type
const [fieldValue, setFieldValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
const updateField = useUpdateEntityField();
function handleSubmit(newDate: Date) {
const fieldValueDate = fieldValue
? DateTime.fromISO(fieldValue).toJSDate()
: null;
const newDateISO = DateTime.fromJSDate(newDate).toISO();
if (newDate === fieldValueDate || !newDateISO) return;
setFieldValue(newDateISO);
if (currentRowEntityId && updateField && newDateISO) {
updateField(currentRowEntityId, viewField, newDateISO);
}
}
return (
<EditableCellDateEditMode
value={DateTime.fromISO(fieldValue).toJSDate()}
onSubmit={handleSubmit}
/>
);
}

View File

@ -1,48 +0,0 @@
import { useRecoilValue } from 'recoil';
import { InplaceInputTextDisplayMode } from '@/ui/display/component/InplaceInputTextDisplayMode';
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldDefinition,
ViewFieldDoubleTextMetadata,
} from '../types/ViewField';
import { GenericEditableDoubleTextCellEditMode } from './GenericEditableDoubleTextCellEditMode';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldDoubleTextMetadata>;
};
export function GenericEditableDoubleTextCell({ viewField }: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const firstValue = useRecoilValue<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.firstValueFieldName,
}),
);
const secondValue = useRecoilValue<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.secondValueFieldName,
}),
);
const displayName = `${firstValue ?? ''} ${secondValue ?? ''}`;
return (
<EditableCell
editModeContent={
<GenericEditableDoubleTextCellEditMode viewField={viewField} />
}
nonEditModeContent={
<InplaceInputTextDisplayMode>{displayName}</InplaceInputTextDisplayMode>
}
></EditableCell>
);
}

View File

@ -1,60 +0,0 @@
import { useRecoilState } from 'recoil';
import { InplaceInputDoubleTextCellEditMode } from '@/ui/inplace-input/components/InplaceInputDoubleTextCellEditMode';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldDefinition,
ViewFieldDoubleTextMetadata,
} from '../types/ViewField';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldDoubleTextMetadata>;
};
export function GenericEditableDoubleTextCellEditMode({ viewField }: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
// TODO: we could use a hook that would return the field value with the right type
const [firstValue, setFirstValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.firstValueFieldName,
}),
);
const [secondValue, setSecondValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.firstValueFieldName,
}),
);
const updateField = useUpdateEntityField();
function handleSubmit(newFirstValue: string, newSecondValue: string) {
if (newFirstValue === firstValue && newSecondValue === secondValue) return;
setFirstValue(newFirstValue);
setSecondValue(newSecondValue);
if (currentRowEntityId && updateField) {
updateField(currentRowEntityId, viewField, {
firstValue: newFirstValue,
secondValue: newSecondValue,
});
}
}
return (
<InplaceInputDoubleTextCellEditMode
firstValuePlaceholder={viewField.metadata.firstValuePlaceholder}
secondValuePlaceholder={viewField.metadata.secondValuePlaceholder}
firstValue={firstValue ?? ''}
secondValue={secondValue ?? ''}
onSubmit={handleSubmit}
/>
);
}

View File

@ -1,28 +0,0 @@
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import { TableHotkeyScope } from '../types/TableHotkeyScope';
import {
ViewFieldDefinition,
ViewFieldDoubleTextChipMetadata,
} from '../types/ViewField';
import { GenericEditableDoubleTextChipCellDisplayMode } from './GenericEditableDoubleTextChipCellDisplayMode';
import { GenericEditableDoubleTextChipCellEditMode } from './GenericEditableDoubleTextChipCellEditMode';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldDoubleTextChipMetadata>;
};
export function GenericEditableDoubleTextChipCell({ viewField }: OwnProps) {
return (
<EditableCell
editHotkeyScope={{ scope: TableHotkeyScope.CellDoubleTextInput }}
editModeContent={
<GenericEditableDoubleTextChipCellEditMode viewField={viewField} />
}
nonEditModeContent={
<GenericEditableDoubleTextChipCellDisplayMode viewField={viewField} />
}
></EditableCell>
);
}

View File

@ -1,64 +0,0 @@
import { useRecoilState } from 'recoil';
import { CompanyChip } from '@/companies/components/CompanyChip';
import { PersonChip } from '@/people/components/PersonChip';
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldDefinition,
ViewFieldDoubleTextChipMetadata,
} from '@/ui/table/types/ViewField';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldDoubleTextChipMetadata>;
};
export function GenericEditableDoubleTextChipCellDisplayMode({
viewField,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const [firstValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.firstValueFieldName,
}),
);
const [secondValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.secondValueFieldName,
}),
);
const [avatarUrlValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.avatarUrlFieldName,
}),
);
const displayName = `${firstValue} ${secondValue}`;
switch (viewField.metadata.entityType) {
case Entity.Company: {
return <CompanyChip id={currentRowEntityId ?? ''} name={displayName} />;
}
case Entity.Person: {
return (
<PersonChip
id={currentRowEntityId ?? ''}
name={displayName}
pictureUrl={avatarUrlValue}
/>
);
}
default:
console.warn(
`Unknown relation type: "${viewField.metadata.entityType}" in GenericEditableDoubleTextChipCellDisplayMode`,
);
return <> </>;
}
}

View File

@ -1,72 +0,0 @@
import { useRecoilState } from 'recoil';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { EditableCellDoubleTextEditMode } from '../editable-cell/types/EditableCellDoubleTextEditMode';
import {
ViewFieldDefinition,
ViewFieldDoubleTextChipMetadata,
} from '../types/ViewField';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldDoubleTextChipMetadata>;
};
export function GenericEditableDoubleTextChipCellEditMode({
viewField,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
// TODO: we could use a hook that would return the field value with the right type
const [firstValue, setFirstValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.firstValueFieldName,
}),
);
const [secondValue, setSecondValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.secondValueFieldName,
}),
);
const updateField = useUpdateEntityField();
function handleSubmit(newFirstValue: string, newSecondValue: string) {
const firstValueChanged = newFirstValue !== firstValue;
const secondValueChanged = newSecondValue !== secondValue;
if (firstValueChanged) {
setFirstValue(newFirstValue);
}
if (secondValueChanged) {
setSecondValue(newSecondValue);
}
if (
currentRowEntityId &&
updateField &&
(firstValueChanged || secondValueChanged)
) {
updateField(currentRowEntityId, viewField, {
firstValue: firstValueChanged ? newFirstValue : firstValue,
secondValue: secondValueChanged ? newSecondValue : secondValue,
});
}
}
return (
<EditableCellDoubleTextEditMode
firstValuePlaceholder={viewField.metadata.firstValuePlaceholder}
secondValuePlaceholder={viewField.metadata.secondValuePlaceholder}
firstValue={firstValue ?? ''}
secondValue={secondValue ?? ''}
onSubmit={handleSubmit}
/>
);
}

View File

@ -1,41 +0,0 @@
import { useRecoilValue } from 'recoil';
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldDefinition,
ViewFieldNumberMetadata,
} from '../types/ViewField';
import { GenericEditableNumberCellEditMode } from './GenericEditableNumberCellEditMode';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldNumberMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
};
export function GenericEditableNumberCell({
viewField,
editModeHorizontalAlign,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const fieldValue = useRecoilValue<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
return (
<EditableCell
editModeHorizontalAlign={editModeHorizontalAlign}
editModeContent={
<GenericEditableNumberCellEditMode viewField={viewField} />
}
nonEditModeContent={<>{fieldValue}</>}
></EditableCell>
);
}

View File

@ -1,66 +0,0 @@
import { useRecoilState } from 'recoil';
import { InplaceInputTextCellEditMode } from '@/ui/inplace-input/components/InplaceInputTextCellEditMode';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldDefinition,
ViewFieldNumberMetadata,
} from '../types/ViewField';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldNumberMetadata>;
};
export function GenericEditableNumberCellEditMode({ viewField }: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
// TODO: we could use a hook that would return the field value with the right type
const [fieldValue, setFieldValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
const updateField = useUpdateEntityField();
function handleSubmit(newText: string) {
if (newText === fieldValue) return;
try {
const numberValue = parseInt(newText);
if (isNaN(numberValue)) {
throw new Error('Not a number');
}
// TODO: find a way to store this better in DB
if (numberValue > 2000000000) {
throw new Error('Number too big');
}
console.log({ numberValue });
setFieldValue(numberValue.toString());
if (currentRowEntityId && updateField) {
updateField(currentRowEntityId, viewField, numberValue);
}
} catch (error) {
console.warn(
`In GenericEditableNumberCellEditMode, Invalid number: ${newText}, ${error}`,
);
}
}
return (
<InplaceInputTextCellEditMode
autoFocus
value={fieldValue ?? ''}
onSubmit={handleSubmit}
/>
);
}

View File

@ -1,42 +0,0 @@
import { useRecoilValue } from 'recoil';
import { InplaceInputPhoneDisplayMode } from '@/ui/display/component/InplaceInputPhoneDisplayMode';
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldDefinition,
ViewFieldPhoneMetadata,
} from '../types/ViewField';
import { GenericEditablePhoneCellEditMode } from './GenericEditablePhoneCellEditMode';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldPhoneMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
};
export function GenericEditablePhoneCell({
viewField,
editModeHorizontalAlign,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const fieldValue = useRecoilValue<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
return (
<EditableCell
editModeHorizontalAlign={editModeHorizontalAlign}
editModeContent={
<GenericEditablePhoneCellEditMode viewField={viewField} />
}
nonEditModeContent={<InplaceInputPhoneDisplayMode value={fieldValue} />}
></EditableCell>
);
}

View File

@ -1,48 +0,0 @@
import { useRecoilState } from 'recoil';
import { InplaceInputTextCellEditMode } from '@/ui/inplace-input/components/InplaceInputTextCellEditMode';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldDefinition,
ViewFieldPhoneMetadata,
} from '../types/ViewField';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldPhoneMetadata>;
};
export function GenericEditablePhoneCellEditMode({ viewField }: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
// TODO: we could use a hook that would return the field value with the right type
const [fieldValue, setFieldValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
const updateField = useUpdateEntityField();
function handleSubmit(newText: string) {
if (newText === fieldValue) return;
setFieldValue(newText);
if (currentRowEntityId && updateField) {
updateField(currentRowEntityId, viewField, newText);
}
}
return (
<InplaceInputTextCellEditMode
placeholder={viewField.metadata.placeHolder ?? ''}
autoFocus
value={fieldValue ?? ''}
onSubmit={handleSubmit}
/>
);
}

View File

@ -1,38 +0,0 @@
import { RelationPickerHotkeyScope } from '@/ui/relation-picker/types/RelationPickerHotkeyScope';
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import {
ViewFieldDefinition,
ViewFieldRelationMetadata,
} from '@/ui/table/types/ViewField';
import { GenericEditableRelationCellDisplayMode } from './GenericEditableRelationCellDisplayMode';
import { GenericEditableRelationCellEditMode } from './GenericEditableRelationCellEditMode';
type OwnProps = {
fieldDefinition: ViewFieldDefinition<ViewFieldRelationMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
placeholder?: string;
};
export function GenericEditableRelationCell({
fieldDefinition,
editModeHorizontalAlign,
placeholder,
}: OwnProps) {
return (
<EditableCell
editModeHorizontalAlign={editModeHorizontalAlign}
editHotkeyScope={{ scope: RelationPickerHotkeyScope.RelationPicker }}
editModeContent={
<GenericEditableRelationCellEditMode viewField={fieldDefinition} />
}
nonEditModeContent={
<GenericEditableRelationCellDisplayMode
fieldDefinition={fieldDefinition}
editModeHorizontalAlign={editModeHorizontalAlign}
placeholder={placeholder}
/>
}
></EditableCell>
);
}

View File

@ -1,58 +0,0 @@
import { useRecoilValue } from 'recoil';
import { CompanyChip } from '@/companies/components/CompanyChip';
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldDefinition,
ViewFieldRelationMetadata,
} from '@/ui/table/types/ViewField';
import { UserChip } from '@/users/components/UserChip';
import { getLogoUrlFromDomainName } from '~/utils';
type OwnProps = {
fieldDefinition: ViewFieldDefinition<ViewFieldRelationMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
placeholder?: string;
};
export function GenericEditableRelationCellDisplayMode({
fieldDefinition,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
// TODO: type value with generic getter
const fieldValue = useRecoilValue<any | null>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: fieldDefinition.metadata.fieldName,
}),
);
switch (fieldDefinition.metadata.relationType) {
case Entity.Company: {
return (
<CompanyChip
id={fieldValue?.id ?? ''}
name={fieldValue?.name ?? ''}
pictureUrl={getLogoUrlFromDomainName(fieldValue?.domainName)}
/>
);
}
case Entity.User: {
return (
<UserChip
id={fieldValue?.id ?? ''}
name={fieldValue?.displayName ?? ''}
pictureUrl={fieldValue?.avatarUrl ?? ''}
/>
);
}
default:
console.warn(
`Unknown relation type: "${fieldDefinition.metadata.relationType}" in GenericEditableRelationCellEditMode`,
);
return <> </>;
}
}

View File

@ -1,75 +0,0 @@
import { useRecoilState } from 'recoil';
import { CompanyPickerCell } from '@/companies/components/CompanyPickerCell';
import { EntityForSelect } from '@/ui/relation-picker/types/EntityForSelect';
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
import { useEditableCell } from '@/ui/table/editable-cell/hooks/useEditableCell';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import {
ViewFieldDefinition,
ViewFieldRelationMetadata,
} from '@/ui/table/types/ViewField';
import { UserPicker } from '@/users/components/UserPicker';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldRelationMetadata>;
};
export function GenericEditableRelationCellEditMode({ viewField }: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const { closeEditableCell } = useEditableCell();
const [fieldValueEntity] = useRecoilState<any | null>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
const updateEntityField = useUpdateEntityField();
function handleEntitySubmit(newFieldEntity: EntityForSelect | null) {
if (
newFieldEntity?.id !== fieldValueEntity?.id &&
currentRowEntityId &&
updateEntityField
) {
updateEntityField(currentRowEntityId, viewField, newFieldEntity);
}
closeEditableCell();
}
function handleCancel() {
closeEditableCell();
}
switch (viewField.metadata.relationType) {
case Entity.Company: {
return (
<CompanyPickerCell
companyId={fieldValueEntity?.id ?? null}
onSubmit={handleEntitySubmit}
onCancel={handleCancel}
/>
);
}
case Entity.User: {
return (
<UserPicker
userId={fieldValueEntity?.id ?? null}
onSubmit={handleEntitySubmit}
onCancel={handleCancel}
/>
);
}
default:
console.warn(
`Unknown relation type: "${viewField.metadata.relationType}" in GenericEditableRelationCellEditMode`,
);
return <></>;
}
}

View File

@ -1,41 +0,0 @@
import { useRecoilValue } from 'recoil';
import { InplaceInputTextDisplayMode } from '@/ui/display/component/InplaceInputTextDisplayMode';
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { ViewFieldDefinition, ViewFieldTextMetadata } from '../types/ViewField';
import { GenericEditableTextCellEditMode } from './GenericEditableTextCellEditMode';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldTextMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
};
export function GenericEditableTextCell({
viewField,
editModeHorizontalAlign,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const fieldValue = useRecoilValue<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
return (
<EditableCell
editModeHorizontalAlign={editModeHorizontalAlign}
editModeContent={
<GenericEditableTextCellEditMode viewField={viewField} />
}
nonEditModeContent={
<InplaceInputTextDisplayMode>{fieldValue}</InplaceInputTextDisplayMode>
}
></EditableCell>
);
}

View File

@ -1,45 +0,0 @@
import { useRecoilState } from 'recoil';
import { InplaceInputTextCellEditMode } from '@/ui/inplace-input/components/InplaceInputTextCellEditMode';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { ViewFieldDefinition, ViewFieldTextMetadata } from '../types/ViewField';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldTextMetadata>;
};
export function GenericEditableTextCellEditMode({ viewField }: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
// TODO: we could use a hook that would return the field value with the right type
const [fieldValue, setFieldValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
const updateField = useUpdateEntityField();
function handleSubmit(newText: string) {
if (newText === fieldValue) return;
setFieldValue(newText);
if (currentRowEntityId && updateField) {
updateField(currentRowEntityId, viewField, newText);
}
}
return (
<InplaceInputTextCellEditMode
placeholder={viewField.metadata.placeHolder ?? ''}
autoFocus
value={fieldValue ?? ''}
onSubmit={handleSubmit}
/>
);
}

View File

@ -1,37 +0,0 @@
import { useRecoilValue } from 'recoil';
import { InplaceInputURLDisplayMode } from '@/ui/display/component/InplaceInputURLDisplayMode';
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { ViewFieldDefinition, ViewFieldURLMetadata } from '../types/ViewField';
import { GenericEditableURLCellEditMode } from './GenericEditableURLCellEditMode';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldURLMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
};
export function GenericEditableURLCell({
viewField,
editModeHorizontalAlign,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const fieldValue = useRecoilValue<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
return (
<EditableCell
editModeHorizontalAlign={editModeHorizontalAlign}
editModeContent={<GenericEditableURLCellEditMode viewField={viewField} />}
nonEditModeContent={<InplaceInputURLDisplayMode value={fieldValue} />}
></EditableCell>
);
}

View File

@ -1,45 +0,0 @@
import { useRecoilState } from 'recoil';
import { InplaceInputTextCellEditMode } from '@/ui/inplace-input/components/InplaceInputTextCellEditMode';
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { ViewFieldDefinition, ViewFieldURLMetadata } from '../types/ViewField';
type OwnProps = {
viewField: ViewFieldDefinition<ViewFieldURLMetadata>;
};
export function GenericEditableURLCellEditMode({ viewField }: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
// TODO: we could use a hook that would return the field value with the right type
const [fieldValue, setFieldValue] = useRecoilState<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: viewField.metadata.fieldName,
}),
);
const updateField = useUpdateEntityField();
function handleSubmit(newText: string) {
if (newText === fieldValue) return;
setFieldValue(newText);
if (currentRowEntityId && updateField) {
updateField(currentRowEntityId, viewField, newText);
}
}
return (
<InplaceInputTextCellEditMode
placeholder={viewField.metadata.placeHolder ?? ''}
autoFocus
value={fieldValue ?? ''}
onSubmit={handleSubmit}
/>
);
}

View File

@ -1,6 +1,6 @@
import styled from '@emotion/styled';
import { Checkbox } from '@/ui/input/components/Checkbox';
import { Checkbox } from '@/ui/input/checkbox/components/Checkbox';
import { useSelectAllRows } from '../hooks/useSelectAllRows';