Feat/generic editable cell chip (#982)

* Added generic relation cell

* Deactivated debug

* Added default warning

* Put back display component

* Removed unused types

* wip

* Renamed to view field

* Use new view field structure to have chip working

* Finished

* Added a temp feature flag
This commit is contained in:
Lucas Bordeau
2023-07-28 20:41:06 +02:00
committed by GitHub
parent d142376ef9
commit afaa962758
30 changed files with 414 additions and 141 deletions

View File

@ -7,7 +7,7 @@ import { RecoilScope } from '../../recoil-scope/components/RecoilScope';
import { useCurrentRowSelected } from '../hooks/useCurrentRowSelected';
import { ColumnIndexContext } from '../states/ColumnIndexContext';
import { contextMenuPositionState } from '../states/contextMenuPositionState';
import { EntityFieldMetadataContext } from '../states/EntityFieldMetadataContext';
import { ViewFieldContext } from '../states/ViewFieldContext';
export function EntityTableCell({ cellIndex }: { cellIndex: number }) {
const setContextMenuPosition = useSetRecoilState(contextMenuPositionState);
@ -25,7 +25,7 @@ export function EntityTableCell({ cellIndex }: { cellIndex: number }) {
});
}
const entityFieldMetadata = useContext(EntityFieldMetadataContext);
const entityFieldMetadata = useContext(ViewFieldContext);
if (!entityFieldMetadata) {
return null;
@ -42,7 +42,7 @@ export function EntityTableCell({ cellIndex }: { cellIndex: number }) {
maxWidth: entityFieldMetadata.columnSize,
}}
>
<GenericEditableCell entityFieldMetadata={entityFieldMetadata} />
<GenericEditableCell fieldDefinition={entityFieldMetadata} />
</td>
</ColumnIndexContext.Provider>
</RecoilScope>

View File

@ -1,12 +1,12 @@
import { useRecoilValue } from 'recoil';
import { entityFieldMetadataArrayState } from '../states/entityFieldMetadataArrayState';
import { viewFieldsState } from '../states/viewFieldsState';
import { ColumnHead } from './ColumnHead';
import { SelectAllCheckbox } from './SelectAllCheckbox';
export function EntityTableHeader() {
const fieldMetadataArray = useRecoilValue(entityFieldMetadataArrayState);
const viewFields = useRecoilValue(viewFieldsState);
return (
<thead>
@ -20,18 +20,18 @@ export function EntityTableHeader() {
>
<SelectAllCheckbox />
</th>
{fieldMetadataArray.map((fieldMetadata) => (
{viewFields.map((viewField) => (
<th
key={fieldMetadata.fieldName.toString()}
key={viewField.columnOrder.toString()}
style={{
width: fieldMetadata.columnSize,
minWidth: fieldMetadata.columnSize,
maxWidth: fieldMetadata.columnSize,
width: viewField.columnSize,
minWidth: viewField.columnSize,
maxWidth: viewField.columnSize,
}}
>
<ColumnHead
viewName={fieldMetadata.label}
viewIcon={fieldMetadata.icon}
viewName={viewField.columnLabel}
viewIcon={viewField.columnIcon}
/>
</th>
))}

View File

@ -1,8 +1,8 @@
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { entityFieldMetadataArrayState } from '../states/entityFieldMetadataArrayState';
import { EntityFieldMetadataContext } from '../states/EntityFieldMetadataContext';
import { ViewFieldContext } from '../states/ViewFieldContext';
import { viewFieldsState } from '../states/viewFieldsState';
import { CheckboxCell } from './CheckboxCell';
import { EntityTableCell } from './EntityTableCellV2';
@ -13,9 +13,7 @@ const StyledRow = styled.tr<{ selected: boolean }>`
`;
export function EntityTableRow({ rowId }: { rowId: string }) {
const entityFieldMetadataArray = useRecoilValue(
entityFieldMetadataArrayState,
);
const entityFieldMetadataArray = useRecoilValue(viewFieldsState);
return (
<StyledRow data-testid={`row-id-${rowId}`} selected={false}>
@ -24,12 +22,12 @@ export function EntityTableRow({ rowId }: { rowId: string }) {
</td>
{entityFieldMetadataArray.map((entityFieldMetadata, columnIndex) => {
return (
<EntityFieldMetadataContext.Provider
<ViewFieldContext.Provider
value={entityFieldMetadata}
key={entityFieldMetadata.fieldName}
key={entityFieldMetadata.columnOrder}
>
<EntityTableCell cellIndex={columnIndex} />
</EntityFieldMetadataContext.Provider>
</ViewFieldContext.Provider>
);
})}
<td></td>

View File

@ -1,31 +1,38 @@
import { EntityFieldMetadata } from '@/ui/table/types/EntityFieldMetadata';
import { ViewFieldDefinition } from '@/ui/table/types/ViewField';
import { isViewFieldChip } from '../types/guards/isViewFieldChip';
import { isViewFieldRelation } from '../types/guards/isViewFieldRelation';
import { isViewFieldText } from '../types/guards/isViewFieldText';
import { GenericEditableChipCell } from './GenericEditableChipCell';
import { GenericEditableRelationCell } from './GenericEditableRelationCell';
import { GenericEditableTextCell } from './GenericEditableTextCell';
type OwnProps = {
entityFieldMetadata: EntityFieldMetadata;
fieldDefinition: ViewFieldDefinition<unknown>;
};
export function GenericEditableCell({ entityFieldMetadata }: OwnProps) {
switch (entityFieldMetadata.type) {
case 'text':
return (
<GenericEditableTextCell
fieldName={entityFieldMetadata.fieldName}
placeholder={entityFieldMetadata.label}
editModeHorizontalAlign="left"
/>
);
case 'relation': {
return (
<GenericEditableRelationCell fieldMetadata={entityFieldMetadata} />
);
}
default:
console.warn(
`Unknown field type: ${entityFieldMetadata.type} in GenericEditableCell`,
);
return <></>;
export function GenericEditableCell({ fieldDefinition }: OwnProps) {
if (isViewFieldText(fieldDefinition)) {
return (
<GenericEditableTextCell
viewField={fieldDefinition}
editModeHorizontalAlign="left"
/>
);
} else if (isViewFieldRelation(fieldDefinition)) {
return <GenericEditableRelationCell fieldDefinition={fieldDefinition} />;
} else if (isViewFieldChip(fieldDefinition)) {
return (
<GenericEditableChipCell
viewField={fieldDefinition}
editModeHorizontalAlign="left"
/>
);
} else {
console.warn(
`Unknown field type: ${fieldDefinition.type} in GenericEditableCell`,
);
return <></>;
}
}

View File

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

View File

@ -0,0 +1,52 @@
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,18 +1,21 @@
import { RelationPickerHotkeyScope } from '@/ui/relation-picker/types/RelationPickerHotkeyScope';
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
import { EntityFieldMetadata } from '@/ui/table/types/EntityFieldMetadata';
import {
ViewFieldDefinition,
ViewFieldRelationMetadata,
} from '@/ui/table/types/ViewField';
import { GenericEditableRelationCellDisplayMode } from './GenericEditableRelationCellDisplayMode';
import { GenericEditableRelationCellEditMode } from './GenericEditableRelationCellEditMode';
type OwnProps = {
fieldMetadata: EntityFieldMetadata;
fieldDefinition: ViewFieldDefinition<ViewFieldRelationMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
placeholder?: string;
};
export function GenericEditableRelationCell({
fieldMetadata,
fieldDefinition,
editModeHorizontalAlign,
placeholder,
}: OwnProps) {
@ -21,11 +24,13 @@ export function GenericEditableRelationCell({
editModeHorizontalAlign={editModeHorizontalAlign}
editHotkeyScope={{ scope: RelationPickerHotkeyScope.RelationPicker }}
editModeContent={
<GenericEditableRelationCellEditMode fieldMetadata={fieldMetadata} />
<GenericEditableRelationCellEditMode
viewFieldDefinition={fieldDefinition}
/>
}
nonEditModeContent={
<GenericEditableRelationCellDisplayMode
fieldMetadata={fieldMetadata}
fieldDefinition={fieldDefinition}
editModeHorizontalAlign={editModeHorizontalAlign}
placeholder={placeholder}
/>

View File

@ -4,28 +4,31 @@ 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 { EntityFieldMetadata } from '@/ui/table/types/EntityFieldMetadata';
import {
ViewFieldDefinition,
ViewFieldRelationMetadata,
} from '@/ui/table/types/ViewField';
import { getLogoUrlFromDomainName } from '~/utils';
type OwnProps = {
fieldMetadata: EntityFieldMetadata;
fieldDefinition: ViewFieldDefinition<ViewFieldRelationMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
placeholder?: string;
};
export function GenericEditableRelationCellDisplayMode({
fieldMetadata,
fieldDefinition,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
const fieldValue = useRecoilValue<any | null>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: fieldMetadata.fieldName,
fieldName: fieldDefinition.metadata.fieldName,
}),
);
switch (fieldMetadata.relationType) {
switch (fieldDefinition.metadata.relationType) {
case Entity.Company: {
return (
<CompanyChip
@ -37,7 +40,7 @@ export function GenericEditableRelationCellDisplayMode({
}
default:
console.warn(
`Unknown relation type: "${fieldMetadata.relationType}" in GenericEditableRelationCellEditMode`,
`Unknown relation type: "${fieldDefinition.metadata.relationType}" in GenericEditableRelationCellEditMode`,
);
return <> </>;
}

View File

@ -7,14 +7,17 @@ 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 { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { EntityFieldMetadata } from '@/ui/table/types/EntityFieldMetadata';
import {
ViewFieldDefinition,
ViewFieldRelationMetadata,
} from '@/ui/table/types/ViewField';
type OwnProps = {
fieldMetadata: EntityFieldMetadata;
viewFieldDefinition: ViewFieldDefinition<ViewFieldRelationMetadata>;
};
export function GenericEditableRelationCellEditMode({
fieldMetadata,
viewFieldDefinition,
}: OwnProps) {
const currentRowEntityId = useCurrentRowEntityId();
@ -23,7 +26,7 @@ export function GenericEditableRelationCellEditMode({
const [fieldValueEntity] = useRecoilState<any | null>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName: fieldMetadata.fieldName,
fieldName: viewFieldDefinition.metadata.fieldName,
}),
);
@ -37,7 +40,7 @@ export function GenericEditableRelationCellEditMode({
) {
updateEntityField(
currentRowEntityId,
fieldMetadata.fieldName,
viewFieldDefinition.id,
newFieldEntity,
);
}
@ -49,7 +52,7 @@ export function GenericEditableRelationCellEditMode({
closeEditableCell();
}
switch (fieldMetadata.relationType) {
switch (viewFieldDefinition.metadata.relationType) {
case Entity.Company: {
return (
<CompanyPickerCell
@ -61,7 +64,7 @@ export function GenericEditableRelationCellEditMode({
}
default:
console.warn(
`Unknown relation type: "${fieldMetadata.relationType}" in GenericEditableRelationCellEditMode`,
`Unknown relation type: "${viewFieldDefinition.metadata.relationType}" in GenericEditableRelationCellEditMode`,
);
return <></>;
}

View File

@ -5,16 +5,18 @@ 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 = {
fieldName: string;
viewField: ViewFieldDefinition<ViewFieldTextMetadata>;
editModeHorizontalAlign?: 'left' | 'right';
placeholder?: string;
};
export function GenericEditableTextCell({
fieldName,
viewField,
editModeHorizontalAlign,
placeholder,
}: OwnProps) {
@ -23,7 +25,7 @@ export function GenericEditableTextCell({
const fieldValue = useRecoilValue<string>(
tableEntityFieldFamilySelector({
entityId: currentRowEntityId ?? '',
fieldName,
fieldName: viewField.metadata.fieldName,
}),
);
@ -32,7 +34,8 @@ export function GenericEditableTextCell({
editModeHorizontalAlign={editModeHorizontalAlign}
editModeContent={
<GenericEditableTextCellEditMode
fieldName={fieldName}
fieldName={viewField.metadata.fieldName}
viewFieldId={viewField.id}
placeholder={placeholder}
/>
}

View File

@ -7,15 +7,18 @@ import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFie
type OwnProps = {
fieldName: string;
viewFieldId: string;
placeholder?: string;
};
export function GenericEditableTextCellEditMode({
fieldName,
viewFieldId,
placeholder,
}: 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 ?? '',
@ -31,7 +34,7 @@ export function GenericEditableTextCellEditMode({
setFieldValue(newText);
if (currentRowEntityId && updateField) {
updateField(currentRowEntityId, fieldName, newText);
updateField(currentRowEntityId, viewFieldId, newText);
}
}