mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-18 17:12:53 +03:00
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:
parent
d142376ef9
commit
afaa962758
@ -19,6 +19,9 @@ import { AppInternalHooks } from '~/sync-hooks/AppInternalHooks';
|
|||||||
|
|
||||||
import { SignInUp } from './pages/auth/SignInUp';
|
import { SignInUp } from './pages/auth/SignInUp';
|
||||||
|
|
||||||
|
// TEMP FEATURE FLAG FOR VIEW FIELDS
|
||||||
|
export const ACTIVATE_VIEW_FIELDS = false;
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
import { IconBuildingSkyscraper } from '@tabler/icons-react';
|
||||||
|
|
||||||
|
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
|
||||||
|
import {
|
||||||
|
ViewFieldChipMetadata,
|
||||||
|
ViewFieldDefinition,
|
||||||
|
} from '@/ui/table/types/ViewField';
|
||||||
|
|
||||||
|
export const companyViewFields: ViewFieldDefinition<unknown>[] = [
|
||||||
|
{
|
||||||
|
columnLabel: 'Name',
|
||||||
|
columnIcon: <IconBuildingSkyscraper size={16} />,
|
||||||
|
columnSize: 150,
|
||||||
|
type: 'chip',
|
||||||
|
columnOrder: 1,
|
||||||
|
metadata: {
|
||||||
|
urlFieldName: 'domainName',
|
||||||
|
contentFieldName: 'name',
|
||||||
|
relationType: Entity.Company,
|
||||||
|
},
|
||||||
|
} as ViewFieldDefinition<ViewFieldChipMetadata>,
|
||||||
|
];
|
@ -0,0 +1,54 @@
|
|||||||
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import { companyViewFields } from '@/companies/constants/companyFieldMetadataArray';
|
||||||
|
import { CompaniesSelectedSortType, defaultOrderBy } from '@/companies/queries';
|
||||||
|
import { GenericEntityTableData } from '@/people/components/GenericEntityTableData';
|
||||||
|
import { reduceSortsToOrderBy } from '@/ui/filter-n-sort/helpers';
|
||||||
|
import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState';
|
||||||
|
import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIntoWhereClause';
|
||||||
|
import { IconList } from '@/ui/icon';
|
||||||
|
import { useRecoilScopedValue } from '@/ui/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
|
import { EntityTable } from '@/ui/table/components/EntityTableV2';
|
||||||
|
import { TableContext } from '@/ui/table/states/TableContext';
|
||||||
|
import {
|
||||||
|
CompanyOrderByWithRelationInput,
|
||||||
|
useGetCompaniesQuery,
|
||||||
|
useUpdateOneCompanyMutation,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
import { companiesFilters } from '~/pages/companies/companies-filters';
|
||||||
|
import { availableSorts } from '~/pages/companies/companies-sorts';
|
||||||
|
|
||||||
|
export function CompanyTable() {
|
||||||
|
const [orderBy, setOrderBy] =
|
||||||
|
useState<CompanyOrderByWithRelationInput[]>(defaultOrderBy);
|
||||||
|
|
||||||
|
const updateSorts = useCallback((sorts: Array<CompaniesSelectedSortType>) => {
|
||||||
|
setOrderBy(sorts.length ? reduceSortsToOrderBy(sorts) : defaultOrderBy);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const filters = useRecoilScopedValue(filtersScopedState, TableContext);
|
||||||
|
|
||||||
|
const whereFilters = useMemo(() => {
|
||||||
|
return { AND: filters.map(turnFilterIntoWhereClause) };
|
||||||
|
}, [filters]) as any;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<GenericEntityTableData
|
||||||
|
getRequestResultKey="companies"
|
||||||
|
useGetRequest={useGetCompaniesQuery}
|
||||||
|
orderBy={orderBy}
|
||||||
|
whereFilters={whereFilters}
|
||||||
|
viewFields={companyViewFields}
|
||||||
|
filterDefinitionArray={companiesFilters}
|
||||||
|
/>
|
||||||
|
<EntityTable
|
||||||
|
viewName="All Companies"
|
||||||
|
viewIcon={<IconList size={16} />}
|
||||||
|
availableSorts={availableSorts}
|
||||||
|
onSortsUpdate={updateSorts}
|
||||||
|
useUpdateEntityMutation={useUpdateOneCompanyMutation}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { EntityFieldMetadata } from '@/ui/table/types/EntityFieldMetadata';
|
import { FilterDefinition } from '@/ui/filter-n-sort/types/FilterDefinition';
|
||||||
|
import { ViewFieldDefinition } from '@/ui/table/types/ViewField';
|
||||||
|
|
||||||
import { useSetEntityTableData } from '../hooks/useSetEntityTableData';
|
import { useSetEntityTableData } from '../hooks/useSetEntityTableData';
|
||||||
import { defaultOrderBy } from '../queries';
|
import { defaultOrderBy } from '../queries';
|
||||||
@ -8,13 +9,15 @@ export function GenericEntityTableData({
|
|||||||
getRequestResultKey,
|
getRequestResultKey,
|
||||||
orderBy = defaultOrderBy,
|
orderBy = defaultOrderBy,
|
||||||
whereFilters,
|
whereFilters,
|
||||||
fieldMetadataArray,
|
viewFields,
|
||||||
|
filterDefinitionArray,
|
||||||
}: {
|
}: {
|
||||||
useGetRequest: any;
|
useGetRequest: any;
|
||||||
getRequestResultKey: string;
|
getRequestResultKey: string;
|
||||||
orderBy?: any;
|
orderBy?: any;
|
||||||
whereFilters?: any;
|
whereFilters?: any;
|
||||||
fieldMetadataArray: EntityFieldMetadata[];
|
viewFields: ViewFieldDefinition<unknown>[];
|
||||||
|
filterDefinitionArray: FilterDefinition[];
|
||||||
}) {
|
}) {
|
||||||
const setEntityTableData = useSetEntityTableData();
|
const setEntityTableData = useSetEntityTableData();
|
||||||
|
|
||||||
@ -23,7 +26,7 @@ export function GenericEntityTableData({
|
|||||||
onCompleted: (data: any) => {
|
onCompleted: (data: any) => {
|
||||||
const entities = data[getRequestResultKey] ?? [];
|
const entities = data[getRequestResultKey] ?? [];
|
||||||
|
|
||||||
setEntityTableData(entities, fieldMetadataArray);
|
setEntityTableData(entities, viewFields, filterDefinitionArray);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5,29 +5,48 @@ import {
|
|||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
|
|
||||||
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
|
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
|
||||||
import { EntityFieldMetadata } from '@/ui/table/types/EntityFieldMetadata';
|
import {
|
||||||
|
ViewFieldDefinition,
|
||||||
|
ViewFieldRelationMetadata,
|
||||||
|
ViewFieldTextMetadata,
|
||||||
|
} from '@/ui/table/types/ViewField';
|
||||||
|
|
||||||
export const peopleFieldMetadataArray: EntityFieldMetadata[] = [
|
export const peopleViewFields: ViewFieldDefinition<unknown>[] = [
|
||||||
{
|
{
|
||||||
fieldName: 'city',
|
id: 'city',
|
||||||
label: 'City',
|
columnLabel: 'City',
|
||||||
icon: <IconMap size={16} />,
|
columnIcon: <IconMap size={16} />,
|
||||||
columnSize: 150,
|
columnSize: 150,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
columnOrder: 1,
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'city',
|
||||||
|
placeHolder: 'City',
|
||||||
|
},
|
||||||
|
} as ViewFieldDefinition<ViewFieldTextMetadata>,
|
||||||
{
|
{
|
||||||
fieldName: 'jobTitle',
|
id: 'jobTitle',
|
||||||
label: 'Job title',
|
columnLabel: 'Job title',
|
||||||
icon: <IconBriefcase size={16} />,
|
columnIcon: <IconBriefcase size={16} />,
|
||||||
columnSize: 150,
|
columnSize: 150,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
columnOrder: 2,
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'jobTitle',
|
||||||
|
placeHolder: 'Job title',
|
||||||
|
},
|
||||||
|
} as ViewFieldDefinition<ViewFieldTextMetadata>,
|
||||||
{
|
{
|
||||||
fieldName: 'company',
|
id: 'company',
|
||||||
label: 'Company',
|
columnLabel: 'Company',
|
||||||
icon: <IconBuildingSkyscraper size={16} />,
|
columnIcon: <IconBuildingSkyscraper size={16} />,
|
||||||
columnSize: 150,
|
columnSize: 150,
|
||||||
type: 'relation',
|
type: 'relation',
|
||||||
relationType: Entity.Company,
|
relationType: Entity.Company,
|
||||||
},
|
columnOrder: 3,
|
||||||
|
metadata: {
|
||||||
|
fieldName: 'company',
|
||||||
|
relationType: Entity.Company,
|
||||||
|
},
|
||||||
|
} as ViewFieldDefinition<ViewFieldRelationMetadata>,
|
||||||
];
|
];
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
import { FilterDefinition } from '@/ui/filter-n-sort/types/FilterDefinition';
|
import { FilterDefinition } from '@/ui/filter-n-sort/types/FilterDefinition';
|
||||||
import { entityFieldMetadataArrayState } from '@/ui/table/states/entityFieldMetadataArrayState';
|
|
||||||
import { tableEntitiesFamilyState } from '@/ui/table/states/tableEntitiesFamilyState';
|
import { tableEntitiesFamilyState } from '@/ui/table/states/tableEntitiesFamilyState';
|
||||||
import { EntityFieldMetadata } from '@/ui/table/types/EntityFieldMetadata';
|
import { viewFieldsState } from '@/ui/table/states/viewFieldsState';
|
||||||
|
import { ViewFieldDefinition } from '@/ui/table/types/ViewField';
|
||||||
|
|
||||||
import { availableFiltersScopedState } from '../../ui/filter-n-sort/states/availableFiltersScopedState';
|
import { availableFiltersScopedState } from '../../ui/filter-n-sort/states/availableFiltersScopedState';
|
||||||
import { useContextScopeId } from '../../ui/recoil-scope/hooks/useContextScopeId';
|
import { useContextScopeId } from '../../ui/recoil-scope/hooks/useContextScopeId';
|
||||||
@ -22,7 +22,8 @@ export function useSetEntityTableData() {
|
|||||||
({ set, snapshot }) =>
|
({ set, snapshot }) =>
|
||||||
<T extends { id: string }>(
|
<T extends { id: string }>(
|
||||||
newEntityArray: T[],
|
newEntityArray: T[],
|
||||||
entityFieldMetadataArray: EntityFieldMetadata[],
|
viewFields: ViewFieldDefinition<unknown>[],
|
||||||
|
filters: FilterDefinition[],
|
||||||
) => {
|
) => {
|
||||||
for (const entity of newEntityArray) {
|
for (const entity of newEntityArray) {
|
||||||
const currentEntity = snapshot
|
const currentEntity = snapshot
|
||||||
@ -47,23 +48,13 @@ export function useSetEntityTableData() {
|
|||||||
resetTableRowSelection();
|
resetTableRowSelection();
|
||||||
|
|
||||||
set(entityTableDimensionsState, {
|
set(entityTableDimensionsState, {
|
||||||
numberOfColumns: entityFieldMetadataArray.length,
|
numberOfColumns: viewFields.length,
|
||||||
numberOfRows: entityIds.length,
|
numberOfRows: entityIds.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
const filters = entityFieldMetadataArray.map(
|
|
||||||
(fieldMetadata) =>
|
|
||||||
({
|
|
||||||
field: fieldMetadata.fieldName,
|
|
||||||
icon: fieldMetadata.filterIcon,
|
|
||||||
label: fieldMetadata.label,
|
|
||||||
type: fieldMetadata.type,
|
|
||||||
} as FilterDefinition),
|
|
||||||
);
|
|
||||||
|
|
||||||
set(availableFiltersScopedState(tableContextScopeId), filters);
|
set(availableFiltersScopedState(tableContextScopeId), filters);
|
||||||
|
|
||||||
set(entityFieldMetadataArrayState, entityFieldMetadataArray);
|
set(viewFieldsState, viewFields);
|
||||||
|
|
||||||
set(isFetchingEntityTableDataState, false);
|
set(isFetchingEntityTableDataState, false);
|
||||||
},
|
},
|
||||||
|
@ -2,34 +2,38 @@ import { useContext } from 'react';
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { EntityForSelect } from '@/ui/relation-picker/types/EntityForSelect';
|
import { EntityForSelect } from '@/ui/relation-picker/types/EntityForSelect';
|
||||||
import { entityFieldMetadataArrayState } from '@/ui/table/states/entityFieldMetadataArrayState';
|
|
||||||
import { EntityUpdateMutationHookContext } from '@/ui/table/states/EntityUpdateMutationHookContext';
|
import { EntityUpdateMutationHookContext } from '@/ui/table/states/EntityUpdateMutationHookContext';
|
||||||
|
import { viewFieldsState } from '@/ui/table/states/viewFieldsState';
|
||||||
|
import { isViewFieldChip } from '@/ui/table/types/guards/isViewFieldChip';
|
||||||
|
import { isViewFieldRelation } from '@/ui/table/types/guards/isViewFieldRelation';
|
||||||
|
import { isViewFieldText } from '@/ui/table/types/guards/isViewFieldText';
|
||||||
|
|
||||||
export function useUpdateEntityField() {
|
export function useUpdateEntityField() {
|
||||||
const useUpdateEntityMutation = useContext(EntityUpdateMutationHookContext);
|
const useUpdateEntityMutation = useContext(EntityUpdateMutationHookContext);
|
||||||
|
|
||||||
const [updateEntity] = useUpdateEntityMutation();
|
const [updateEntity] = useUpdateEntityMutation();
|
||||||
|
|
||||||
const entityFieldMetadataArray = useRecoilValue(
|
const viewFields = useRecoilValue(viewFieldsState);
|
||||||
entityFieldMetadataArrayState,
|
|
||||||
);
|
|
||||||
|
|
||||||
return function updatePeopleField(
|
return function updatePeopleField(
|
||||||
currentEntityId: string,
|
currentEntityId: string,
|
||||||
fieldName: string,
|
viewFieldId: string,
|
||||||
newFieldValue: unknown,
|
newFieldValue: unknown,
|
||||||
) {
|
) {
|
||||||
const fieldMetadata = entityFieldMetadataArray.find(
|
const viewField = viewFields.find(
|
||||||
(metadata) => metadata.fieldName === fieldName,
|
(metadata) => metadata.id === viewFieldId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!fieldMetadata) {
|
if (!viewField) {
|
||||||
throw new Error(`Field metadata not found for field ${fieldName}`);
|
throw new Error(`View field not found for id ${viewFieldId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldMetadata.type === 'relation') {
|
// TODO: improve type narrowing here with validation maybe ? Also validate the newFieldValue with linked type guards
|
||||||
|
if (isViewFieldRelation(viewField)) {
|
||||||
const newSelectedEntity = newFieldValue as EntityForSelect | null;
|
const newSelectedEntity = newFieldValue as EntityForSelect | null;
|
||||||
|
|
||||||
|
const fieldName = viewField.metadata.fieldName;
|
||||||
|
|
||||||
if (!newSelectedEntity) {
|
if (!newSelectedEntity) {
|
||||||
updateEntity({
|
updateEntity({
|
||||||
variables: {
|
variables: {
|
||||||
@ -53,11 +57,22 @@ export function useUpdateEntityField() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else if (isViewFieldChip(viewField)) {
|
||||||
|
const newContent = newFieldValue as string;
|
||||||
|
|
||||||
updateEntity({
|
updateEntity({
|
||||||
variables: {
|
variables: {
|
||||||
where: { id: currentEntityId },
|
where: { id: currentEntityId },
|
||||||
data: { [fieldName]: newFieldValue },
|
data: { [viewField.metadata.contentFieldName]: newContent },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (isViewFieldText(viewField)) {
|
||||||
|
const newContent = newFieldValue as string;
|
||||||
|
|
||||||
|
updateEntity({
|
||||||
|
variables: {
|
||||||
|
where: { id: currentEntityId },
|
||||||
|
data: { [viewField.metadata.fieldName]: newContent },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { useCallback, useMemo, useState } from 'react';
|
|||||||
|
|
||||||
import { defaultOrderBy } from '@/companies/queries';
|
import { defaultOrderBy } from '@/companies/queries';
|
||||||
import { GenericEntityTableData } from '@/people/components/GenericEntityTableData';
|
import { GenericEntityTableData } from '@/people/components/GenericEntityTableData';
|
||||||
import { peopleFieldMetadataArray } from '@/people/constants/peopleFieldMetadataArray';
|
import { peopleViewFields } from '@/people/constants/peopleFieldMetadataArray';
|
||||||
import { PeopleSelectedSortType } from '@/people/queries';
|
import { PeopleSelectedSortType } from '@/people/queries';
|
||||||
import { reduceSortsToOrderBy } from '@/ui/filter-n-sort/helpers';
|
import { reduceSortsToOrderBy } from '@/ui/filter-n-sort/helpers';
|
||||||
import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState';
|
import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState';
|
||||||
@ -16,6 +16,7 @@ import {
|
|||||||
useGetPeopleQuery,
|
useGetPeopleQuery,
|
||||||
useUpdateOnePersonMutation,
|
useUpdateOnePersonMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
|
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() {
|
||||||
@ -39,7 +40,8 @@ export function PeopleTable() {
|
|||||||
useGetRequest={useGetPeopleQuery}
|
useGetRequest={useGetPeopleQuery}
|
||||||
orderBy={orderBy}
|
orderBy={orderBy}
|
||||||
whereFilters={whereFilters}
|
whereFilters={whereFilters}
|
||||||
fieldMetadataArray={peopleFieldMetadataArray}
|
viewFields={peopleViewFields}
|
||||||
|
filterDefinitionArray={peopleFilters}
|
||||||
/>
|
/>
|
||||||
<EntityTable
|
<EntityTable
|
||||||
viewName="All People"
|
viewName="All People"
|
||||||
|
@ -7,7 +7,7 @@ import { RecoilScope } from '../../recoil-scope/components/RecoilScope';
|
|||||||
import { useCurrentRowSelected } from '../hooks/useCurrentRowSelected';
|
import { useCurrentRowSelected } from '../hooks/useCurrentRowSelected';
|
||||||
import { ColumnIndexContext } from '../states/ColumnIndexContext';
|
import { ColumnIndexContext } from '../states/ColumnIndexContext';
|
||||||
import { contextMenuPositionState } from '../states/contextMenuPositionState';
|
import { contextMenuPositionState } from '../states/contextMenuPositionState';
|
||||||
import { EntityFieldMetadataContext } from '../states/EntityFieldMetadataContext';
|
import { ViewFieldContext } from '../states/ViewFieldContext';
|
||||||
|
|
||||||
export function EntityTableCell({ cellIndex }: { cellIndex: number }) {
|
export function EntityTableCell({ cellIndex }: { cellIndex: number }) {
|
||||||
const setContextMenuPosition = useSetRecoilState(contextMenuPositionState);
|
const setContextMenuPosition = useSetRecoilState(contextMenuPositionState);
|
||||||
@ -25,7 +25,7 @@ export function EntityTableCell({ cellIndex }: { cellIndex: number }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const entityFieldMetadata = useContext(EntityFieldMetadataContext);
|
const entityFieldMetadata = useContext(ViewFieldContext);
|
||||||
|
|
||||||
if (!entityFieldMetadata) {
|
if (!entityFieldMetadata) {
|
||||||
return null;
|
return null;
|
||||||
@ -42,7 +42,7 @@ export function EntityTableCell({ cellIndex }: { cellIndex: number }) {
|
|||||||
maxWidth: entityFieldMetadata.columnSize,
|
maxWidth: entityFieldMetadata.columnSize,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<GenericEditableCell entityFieldMetadata={entityFieldMetadata} />
|
<GenericEditableCell fieldDefinition={entityFieldMetadata} />
|
||||||
</td>
|
</td>
|
||||||
</ColumnIndexContext.Provider>
|
</ColumnIndexContext.Provider>
|
||||||
</RecoilScope>
|
</RecoilScope>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { entityFieldMetadataArrayState } from '../states/entityFieldMetadataArrayState';
|
import { viewFieldsState } from '../states/viewFieldsState';
|
||||||
|
|
||||||
import { ColumnHead } from './ColumnHead';
|
import { ColumnHead } from './ColumnHead';
|
||||||
import { SelectAllCheckbox } from './SelectAllCheckbox';
|
import { SelectAllCheckbox } from './SelectAllCheckbox';
|
||||||
|
|
||||||
export function EntityTableHeader() {
|
export function EntityTableHeader() {
|
||||||
const fieldMetadataArray = useRecoilValue(entityFieldMetadataArrayState);
|
const viewFields = useRecoilValue(viewFieldsState);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<thead>
|
<thead>
|
||||||
@ -20,18 +20,18 @@ export function EntityTableHeader() {
|
|||||||
>
|
>
|
||||||
<SelectAllCheckbox />
|
<SelectAllCheckbox />
|
||||||
</th>
|
</th>
|
||||||
{fieldMetadataArray.map((fieldMetadata) => (
|
{viewFields.map((viewField) => (
|
||||||
<th
|
<th
|
||||||
key={fieldMetadata.fieldName.toString()}
|
key={viewField.columnOrder.toString()}
|
||||||
style={{
|
style={{
|
||||||
width: fieldMetadata.columnSize,
|
width: viewField.columnSize,
|
||||||
minWidth: fieldMetadata.columnSize,
|
minWidth: viewField.columnSize,
|
||||||
maxWidth: fieldMetadata.columnSize,
|
maxWidth: viewField.columnSize,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ColumnHead
|
<ColumnHead
|
||||||
viewName={fieldMetadata.label}
|
viewName={viewField.columnLabel}
|
||||||
viewIcon={fieldMetadata.icon}
|
viewIcon={viewField.columnIcon}
|
||||||
/>
|
/>
|
||||||
</th>
|
</th>
|
||||||
))}
|
))}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { entityFieldMetadataArrayState } from '../states/entityFieldMetadataArrayState';
|
import { ViewFieldContext } from '../states/ViewFieldContext';
|
||||||
import { EntityFieldMetadataContext } from '../states/EntityFieldMetadataContext';
|
import { viewFieldsState } from '../states/viewFieldsState';
|
||||||
|
|
||||||
import { CheckboxCell } from './CheckboxCell';
|
import { CheckboxCell } from './CheckboxCell';
|
||||||
import { EntityTableCell } from './EntityTableCellV2';
|
import { EntityTableCell } from './EntityTableCellV2';
|
||||||
@ -13,9 +13,7 @@ const StyledRow = styled.tr<{ selected: boolean }>`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export function EntityTableRow({ rowId }: { rowId: string }) {
|
export function EntityTableRow({ rowId }: { rowId: string }) {
|
||||||
const entityFieldMetadataArray = useRecoilValue(
|
const entityFieldMetadataArray = useRecoilValue(viewFieldsState);
|
||||||
entityFieldMetadataArrayState,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledRow data-testid={`row-id-${rowId}`} selected={false}>
|
<StyledRow data-testid={`row-id-${rowId}`} selected={false}>
|
||||||
@ -24,12 +22,12 @@ export function EntityTableRow({ rowId }: { rowId: string }) {
|
|||||||
</td>
|
</td>
|
||||||
{entityFieldMetadataArray.map((entityFieldMetadata, columnIndex) => {
|
{entityFieldMetadataArray.map((entityFieldMetadata, columnIndex) => {
|
||||||
return (
|
return (
|
||||||
<EntityFieldMetadataContext.Provider
|
<ViewFieldContext.Provider
|
||||||
value={entityFieldMetadata}
|
value={entityFieldMetadata}
|
||||||
key={entityFieldMetadata.fieldName}
|
key={entityFieldMetadata.columnOrder}
|
||||||
>
|
>
|
||||||
<EntityTableCell cellIndex={columnIndex} />
|
<EntityTableCell cellIndex={columnIndex} />
|
||||||
</EntityFieldMetadataContext.Provider>
|
</ViewFieldContext.Provider>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<td></td>
|
<td></td>
|
||||||
|
@ -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 { GenericEditableRelationCell } from './GenericEditableRelationCell';
|
||||||
import { GenericEditableTextCell } from './GenericEditableTextCell';
|
import { GenericEditableTextCell } from './GenericEditableTextCell';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
entityFieldMetadata: EntityFieldMetadata;
|
fieldDefinition: ViewFieldDefinition<unknown>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GenericEditableCell({ entityFieldMetadata }: OwnProps) {
|
export function GenericEditableCell({ fieldDefinition }: OwnProps) {
|
||||||
switch (entityFieldMetadata.type) {
|
if (isViewFieldText(fieldDefinition)) {
|
||||||
case 'text':
|
return (
|
||||||
return (
|
<GenericEditableTextCell
|
||||||
<GenericEditableTextCell
|
viewField={fieldDefinition}
|
||||||
fieldName={entityFieldMetadata.fieldName}
|
editModeHorizontalAlign="left"
|
||||||
placeholder={entityFieldMetadata.label}
|
/>
|
||||||
editModeHorizontalAlign="left"
|
);
|
||||||
/>
|
} else if (isViewFieldRelation(fieldDefinition)) {
|
||||||
);
|
return <GenericEditableRelationCell fieldDefinition={fieldDefinition} />;
|
||||||
case 'relation': {
|
} else if (isViewFieldChip(fieldDefinition)) {
|
||||||
return (
|
return (
|
||||||
<GenericEditableRelationCell fieldMetadata={entityFieldMetadata} />
|
<GenericEditableChipCell
|
||||||
);
|
viewField={fieldDefinition}
|
||||||
}
|
editModeHorizontalAlign="left"
|
||||||
default:
|
/>
|
||||||
console.warn(
|
);
|
||||||
`Unknown field type: ${entityFieldMetadata.type} in GenericEditableCell`,
|
} else {
|
||||||
);
|
console.warn(
|
||||||
return <></>;
|
`Unknown field type: ${fieldDefinition.type} in GenericEditableCell`,
|
||||||
|
);
|
||||||
|
return <></>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
@ -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 <> </>;
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,21 @@
|
|||||||
import { RelationPickerHotkeyScope } from '@/ui/relation-picker/types/RelationPickerHotkeyScope';
|
import { RelationPickerHotkeyScope } from '@/ui/relation-picker/types/RelationPickerHotkeyScope';
|
||||||
import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
|
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 { GenericEditableRelationCellDisplayMode } from './GenericEditableRelationCellDisplayMode';
|
||||||
import { GenericEditableRelationCellEditMode } from './GenericEditableRelationCellEditMode';
|
import { GenericEditableRelationCellEditMode } from './GenericEditableRelationCellEditMode';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
fieldMetadata: EntityFieldMetadata;
|
fieldDefinition: ViewFieldDefinition<ViewFieldRelationMetadata>;
|
||||||
editModeHorizontalAlign?: 'left' | 'right';
|
editModeHorizontalAlign?: 'left' | 'right';
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GenericEditableRelationCell({
|
export function GenericEditableRelationCell({
|
||||||
fieldMetadata,
|
fieldDefinition,
|
||||||
editModeHorizontalAlign,
|
editModeHorizontalAlign,
|
||||||
placeholder,
|
placeholder,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
@ -21,11 +24,13 @@ export function GenericEditableRelationCell({
|
|||||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||||
editHotkeyScope={{ scope: RelationPickerHotkeyScope.RelationPicker }}
|
editHotkeyScope={{ scope: RelationPickerHotkeyScope.RelationPicker }}
|
||||||
editModeContent={
|
editModeContent={
|
||||||
<GenericEditableRelationCellEditMode fieldMetadata={fieldMetadata} />
|
<GenericEditableRelationCellEditMode
|
||||||
|
viewFieldDefinition={fieldDefinition}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
nonEditModeContent={
|
nonEditModeContent={
|
||||||
<GenericEditableRelationCellDisplayMode
|
<GenericEditableRelationCellDisplayMode
|
||||||
fieldMetadata={fieldMetadata}
|
fieldDefinition={fieldDefinition}
|
||||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
/>
|
/>
|
||||||
|
@ -4,28 +4,31 @@ import { CompanyChip } from '@/companies/components/CompanyChip';
|
|||||||
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
|
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
|
||||||
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
|
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
|
||||||
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
|
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';
|
import { getLogoUrlFromDomainName } from '~/utils';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
fieldMetadata: EntityFieldMetadata;
|
fieldDefinition: ViewFieldDefinition<ViewFieldRelationMetadata>;
|
||||||
editModeHorizontalAlign?: 'left' | 'right';
|
editModeHorizontalAlign?: 'left' | 'right';
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GenericEditableRelationCellDisplayMode({
|
export function GenericEditableRelationCellDisplayMode({
|
||||||
fieldMetadata,
|
fieldDefinition,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const currentRowEntityId = useCurrentRowEntityId();
|
const currentRowEntityId = useCurrentRowEntityId();
|
||||||
|
|
||||||
const fieldValue = useRecoilValue<any | null>(
|
const fieldValue = useRecoilValue<any | null>(
|
||||||
tableEntityFieldFamilySelector({
|
tableEntityFieldFamilySelector({
|
||||||
entityId: currentRowEntityId ?? '',
|
entityId: currentRowEntityId ?? '',
|
||||||
fieldName: fieldMetadata.fieldName,
|
fieldName: fieldDefinition.metadata.fieldName,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
switch (fieldMetadata.relationType) {
|
switch (fieldDefinition.metadata.relationType) {
|
||||||
case Entity.Company: {
|
case Entity.Company: {
|
||||||
return (
|
return (
|
||||||
<CompanyChip
|
<CompanyChip
|
||||||
@ -37,7 +40,7 @@ export function GenericEditableRelationCellDisplayMode({
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
console.warn(
|
console.warn(
|
||||||
`Unknown relation type: "${fieldMetadata.relationType}" in GenericEditableRelationCellEditMode`,
|
`Unknown relation type: "${fieldDefinition.metadata.relationType}" in GenericEditableRelationCellEditMode`,
|
||||||
);
|
);
|
||||||
return <> </>;
|
return <> </>;
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,17 @@ import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
|
|||||||
import { useEditableCell } from '@/ui/table/editable-cell/hooks/useEditableCell';
|
import { useEditableCell } from '@/ui/table/editable-cell/hooks/useEditableCell';
|
||||||
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
|
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
|
||||||
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
|
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
|
||||||
import { EntityFieldMetadata } from '@/ui/table/types/EntityFieldMetadata';
|
import {
|
||||||
|
ViewFieldDefinition,
|
||||||
|
ViewFieldRelationMetadata,
|
||||||
|
} from '@/ui/table/types/ViewField';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
fieldMetadata: EntityFieldMetadata;
|
viewFieldDefinition: ViewFieldDefinition<ViewFieldRelationMetadata>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GenericEditableRelationCellEditMode({
|
export function GenericEditableRelationCellEditMode({
|
||||||
fieldMetadata,
|
viewFieldDefinition,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const currentRowEntityId = useCurrentRowEntityId();
|
const currentRowEntityId = useCurrentRowEntityId();
|
||||||
|
|
||||||
@ -23,7 +26,7 @@ export function GenericEditableRelationCellEditMode({
|
|||||||
const [fieldValueEntity] = useRecoilState<any | null>(
|
const [fieldValueEntity] = useRecoilState<any | null>(
|
||||||
tableEntityFieldFamilySelector({
|
tableEntityFieldFamilySelector({
|
||||||
entityId: currentRowEntityId ?? '',
|
entityId: currentRowEntityId ?? '',
|
||||||
fieldName: fieldMetadata.fieldName,
|
fieldName: viewFieldDefinition.metadata.fieldName,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -37,7 +40,7 @@ export function GenericEditableRelationCellEditMode({
|
|||||||
) {
|
) {
|
||||||
updateEntityField(
|
updateEntityField(
|
||||||
currentRowEntityId,
|
currentRowEntityId,
|
||||||
fieldMetadata.fieldName,
|
viewFieldDefinition.id,
|
||||||
newFieldEntity,
|
newFieldEntity,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -49,7 +52,7 @@ export function GenericEditableRelationCellEditMode({
|
|||||||
closeEditableCell();
|
closeEditableCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (fieldMetadata.relationType) {
|
switch (viewFieldDefinition.metadata.relationType) {
|
||||||
case Entity.Company: {
|
case Entity.Company: {
|
||||||
return (
|
return (
|
||||||
<CompanyPickerCell
|
<CompanyPickerCell
|
||||||
@ -61,7 +64,7 @@ export function GenericEditableRelationCellEditMode({
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
console.warn(
|
console.warn(
|
||||||
`Unknown relation type: "${fieldMetadata.relationType}" in GenericEditableRelationCellEditMode`,
|
`Unknown relation type: "${viewFieldDefinition.metadata.relationType}" in GenericEditableRelationCellEditMode`,
|
||||||
);
|
);
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,18 @@ import { EditableCell } from '@/ui/table/editable-cell/components/EditableCell';
|
|||||||
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
|
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
|
||||||
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
|
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
|
||||||
|
|
||||||
|
import { ViewFieldDefinition, ViewFieldTextMetadata } from '../types/ViewField';
|
||||||
|
|
||||||
import { GenericEditableTextCellEditMode } from './GenericEditableTextCellEditMode';
|
import { GenericEditableTextCellEditMode } from './GenericEditableTextCellEditMode';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
fieldName: string;
|
viewField: ViewFieldDefinition<ViewFieldTextMetadata>;
|
||||||
editModeHorizontalAlign?: 'left' | 'right';
|
editModeHorizontalAlign?: 'left' | 'right';
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GenericEditableTextCell({
|
export function GenericEditableTextCell({
|
||||||
fieldName,
|
viewField,
|
||||||
editModeHorizontalAlign,
|
editModeHorizontalAlign,
|
||||||
placeholder,
|
placeholder,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
@ -23,7 +25,7 @@ export function GenericEditableTextCell({
|
|||||||
const fieldValue = useRecoilValue<string>(
|
const fieldValue = useRecoilValue<string>(
|
||||||
tableEntityFieldFamilySelector({
|
tableEntityFieldFamilySelector({
|
||||||
entityId: currentRowEntityId ?? '',
|
entityId: currentRowEntityId ?? '',
|
||||||
fieldName,
|
fieldName: viewField.metadata.fieldName,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -32,7 +34,8 @@ export function GenericEditableTextCell({
|
|||||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||||
editModeContent={
|
editModeContent={
|
||||||
<GenericEditableTextCellEditMode
|
<GenericEditableTextCellEditMode
|
||||||
fieldName={fieldName}
|
fieldName={viewField.metadata.fieldName}
|
||||||
|
viewFieldId={viewField.id}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,18 @@ import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFie
|
|||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
fieldName: string;
|
fieldName: string;
|
||||||
|
viewFieldId: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GenericEditableTextCellEditMode({
|
export function GenericEditableTextCellEditMode({
|
||||||
fieldName,
|
fieldName,
|
||||||
|
viewFieldId,
|
||||||
placeholder,
|
placeholder,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const currentRowEntityId = useCurrentRowEntityId();
|
const currentRowEntityId = useCurrentRowEntityId();
|
||||||
|
|
||||||
|
// TODO: we could use a hook that would return the field value with the right type
|
||||||
const [fieldValue, setFieldValue] = useRecoilState<string>(
|
const [fieldValue, setFieldValue] = useRecoilState<string>(
|
||||||
tableEntityFieldFamilySelector({
|
tableEntityFieldFamilySelector({
|
||||||
entityId: currentRowEntityId ?? '',
|
entityId: currentRowEntityId ?? '',
|
||||||
@ -31,7 +34,7 @@ export function GenericEditableTextCellEditMode({
|
|||||||
setFieldValue(newText);
|
setFieldValue(newText);
|
||||||
|
|
||||||
if (currentRowEntityId && updateField) {
|
if (currentRowEntityId && updateField) {
|
||||||
updateField(currentRowEntityId, fieldName, newText);
|
updateField(currentRowEntityId, viewFieldId, newText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
import { createContext } from 'react';
|
|
||||||
|
|
||||||
import { EntityFieldMetadata } from '../types/EntityFieldMetadata';
|
|
||||||
|
|
||||||
export const EntityFieldMetadataContext =
|
|
||||||
createContext<EntityFieldMetadata | null>(null);
|
|
6
front/src/modules/ui/table/states/ViewFieldContext.ts
Normal file
6
front/src/modules/ui/table/states/ViewFieldContext.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
import { ViewFieldDefinition } from '../types/ViewField';
|
||||||
|
|
||||||
|
export const ViewFieldContext =
|
||||||
|
createContext<ViewFieldDefinition<unknown> | null>(null);
|
@ -1,8 +0,0 @@
|
|||||||
import { atom } from 'recoil';
|
|
||||||
|
|
||||||
import { EntityFieldMetadata } from '../types/EntityFieldMetadata';
|
|
||||||
|
|
||||||
export const entityFieldMetadataArrayState = atom<EntityFieldMetadata[]>({
|
|
||||||
key: 'entityFieldMetadataArrayState',
|
|
||||||
default: [],
|
|
||||||
});
|
|
8
front/src/modules/ui/table/states/viewFieldsState.ts
Normal file
8
front/src/modules/ui/table/states/viewFieldsState.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { atom } from 'recoil';
|
||||||
|
|
||||||
|
import { ViewFieldDefinition } from '../types/ViewField';
|
||||||
|
|
||||||
|
export const viewFieldsState = atom<ViewFieldDefinition<unknown>[]>({
|
||||||
|
key: 'viewFieldsState',
|
||||||
|
default: [],
|
||||||
|
});
|
@ -1,13 +0,0 @@
|
|||||||
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
|
|
||||||
|
|
||||||
export type EntityFieldType = 'text' | 'relation';
|
|
||||||
|
|
||||||
export type EntityFieldMetadata = {
|
|
||||||
fieldName: string;
|
|
||||||
label: string;
|
|
||||||
type: EntityFieldType;
|
|
||||||
icon: JSX.Element;
|
|
||||||
columnSize: number;
|
|
||||||
filterIcon?: JSX.Element;
|
|
||||||
relationType?: Entity; // TODO: condition this type with type === "relation"
|
|
||||||
};
|
|
36
front/src/modules/ui/table/types/ViewField.ts
Normal file
36
front/src/modules/ui/table/types/ViewField.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { Entity } from '@/ui/relation-picker/types/EntityTypeForSelect';
|
||||||
|
|
||||||
|
export type ViewFieldType = 'text' | 'relation' | 'chip';
|
||||||
|
|
||||||
|
export type ViewFieldTextMetadata = {
|
||||||
|
placeHolder: string;
|
||||||
|
fieldName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ViewFieldRelationMetadata = {
|
||||||
|
relationType: Entity;
|
||||||
|
fieldName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ViewFieldChipMetadata = {
|
||||||
|
relationType: Entity;
|
||||||
|
contentFieldName: string;
|
||||||
|
urlFieldName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ViewFieldDefinition<
|
||||||
|
T extends
|
||||||
|
| ViewFieldTextMetadata
|
||||||
|
| ViewFieldRelationMetadata
|
||||||
|
| ViewFieldChipMetadata
|
||||||
|
| unknown,
|
||||||
|
> = {
|
||||||
|
id: string;
|
||||||
|
columnLabel: string;
|
||||||
|
columnSize: number;
|
||||||
|
columnOrder: number;
|
||||||
|
columnIcon?: JSX.Element;
|
||||||
|
filterIcon?: JSX.Element;
|
||||||
|
type: ViewFieldType;
|
||||||
|
metadata: T;
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
import { ViewFieldChipMetadata, ViewFieldDefinition } from '../ViewField';
|
||||||
|
|
||||||
|
export function isViewFieldChip(
|
||||||
|
field: ViewFieldDefinition<unknown>,
|
||||||
|
): field is ViewFieldDefinition<ViewFieldChipMetadata> {
|
||||||
|
return field.type === 'chip';
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
import { ViewFieldDefinition, ViewFieldRelationMetadata } from '../ViewField';
|
||||||
|
|
||||||
|
export function isViewFieldRelation(
|
||||||
|
field: ViewFieldDefinition<unknown>,
|
||||||
|
): field is ViewFieldDefinition<ViewFieldRelationMetadata> {
|
||||||
|
return field.type === 'relation';
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
import { ViewFieldDefinition, ViewFieldTextMetadata } from '../ViewField';
|
||||||
|
|
||||||
|
export function isViewFieldText(
|
||||||
|
field: ViewFieldDefinition<unknown>,
|
||||||
|
): field is ViewFieldDefinition<ViewFieldTextMetadata> {
|
||||||
|
return field.type === 'text';
|
||||||
|
}
|
@ -4,6 +4,7 @@ import styled from '@emotion/styled';
|
|||||||
|
|
||||||
import { GET_COMPANIES } from '@/companies/queries';
|
import { GET_COMPANIES } from '@/companies/queries';
|
||||||
import { CompanyTable } from '@/companies/table/components/CompanyTable';
|
import { CompanyTable } from '@/companies/table/components/CompanyTable';
|
||||||
|
import { CompanyTable as CompanyTableV2 } from '@/companies/table/components/CompanyTableV2';
|
||||||
import { TableActionBarButtonCreateActivityCompany } from '@/companies/table/components/TableActionBarButtonCreateActivityCompany';
|
import { TableActionBarButtonCreateActivityCompany } from '@/companies/table/components/TableActionBarButtonCreateActivityCompany';
|
||||||
import { TableActionBarButtonDeleteCompanies } from '@/companies/table/components/TableActionBarButtonDeleteCompanies';
|
import { TableActionBarButtonDeleteCompanies } from '@/companies/table/components/TableActionBarButtonDeleteCompanies';
|
||||||
import { IconBuildingSkyscraper } from '@/ui/icon';
|
import { IconBuildingSkyscraper } from '@/ui/icon';
|
||||||
@ -11,6 +12,7 @@ import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer'
|
|||||||
import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
|
import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
|
||||||
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
|
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
|
||||||
import { TableContext } from '@/ui/table/states/TableContext';
|
import { TableContext } from '@/ui/table/states/TableContext';
|
||||||
|
import { ACTIVATE_VIEW_FIELDS } from '~/App';
|
||||||
import { useInsertOneCompanyMutation } from '~/generated/graphql';
|
import { useInsertOneCompanyMutation } from '~/generated/graphql';
|
||||||
|
|
||||||
import { SEARCH_COMPANY_QUERY } from '../../modules/search/queries/search';
|
import { SEARCH_COMPANY_QUERY } from '../../modules/search/queries/search';
|
||||||
@ -41,6 +43,10 @@ export function Companies() {
|
|||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const CompanyTableComponent = ACTIVATE_VIEW_FIELDS
|
||||||
|
? CompanyTableV2
|
||||||
|
: CompanyTable;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WithTopBarContainer
|
<WithTopBarContainer
|
||||||
@ -50,7 +56,7 @@ export function Companies() {
|
|||||||
>
|
>
|
||||||
<RecoilScope SpecificContext={TableContext}>
|
<RecoilScope SpecificContext={TableContext}>
|
||||||
<StyledTableContainer>
|
<StyledTableContainer>
|
||||||
<CompanyTable />
|
<CompanyTableComponent />
|
||||||
</StyledTableContainer>
|
</StyledTableContainer>
|
||||||
<EntityTableActionBar>
|
<EntityTableActionBar>
|
||||||
<TableActionBarButtonCreateActivityCompany />
|
<TableActionBarButtonCreateActivityCompany />
|
||||||
|
@ -4,6 +4,7 @@ import styled from '@emotion/styled';
|
|||||||
|
|
||||||
import { GET_PEOPLE } from '@/people/queries';
|
import { GET_PEOPLE } from '@/people/queries';
|
||||||
import { PeopleTable } from '@/people/table/components/PeopleTable';
|
import { PeopleTable } from '@/people/table/components/PeopleTable';
|
||||||
|
import { PeopleTable as PeopleTableV2 } from '@/people/table/components/PeopleTableV2';
|
||||||
import { TableActionBarButtonCreateActivityPeople } from '@/people/table/components/TableActionBarButtonCreateActivityPeople';
|
import { TableActionBarButtonCreateActivityPeople } from '@/people/table/components/TableActionBarButtonCreateActivityPeople';
|
||||||
import { TableActionBarButtonDeletePeople } from '@/people/table/components/TableActionBarButtonDeletePeople';
|
import { TableActionBarButtonDeletePeople } from '@/people/table/components/TableActionBarButtonDeletePeople';
|
||||||
import { IconUser } from '@/ui/icon';
|
import { IconUser } from '@/ui/icon';
|
||||||
@ -11,6 +12,7 @@ import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer'
|
|||||||
import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
|
import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
|
||||||
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
|
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
|
||||||
import { TableContext } from '@/ui/table/states/TableContext';
|
import { TableContext } from '@/ui/table/states/TableContext';
|
||||||
|
import { ACTIVATE_VIEW_FIELDS } from '~/App';
|
||||||
import { useInsertOnePersonMutation } from '~/generated/graphql';
|
import { useInsertOnePersonMutation } from '~/generated/graphql';
|
||||||
|
|
||||||
const StyledTableContainer = styled.div`
|
const StyledTableContainer = styled.div`
|
||||||
@ -35,6 +37,10 @@ export function People() {
|
|||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const PeopleTableComponent = ACTIVATE_VIEW_FIELDS
|
||||||
|
? PeopleTableV2
|
||||||
|
: PeopleTable;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RecoilScope SpecificContext={TableContext}>
|
<RecoilScope SpecificContext={TableContext}>
|
||||||
<WithTopBarContainer
|
<WithTopBarContainer
|
||||||
@ -43,7 +49,7 @@ export function People() {
|
|||||||
onAddButtonClick={handleAddButtonClick}
|
onAddButtonClick={handleAddButtonClick}
|
||||||
>
|
>
|
||||||
<StyledTableContainer>
|
<StyledTableContainer>
|
||||||
<PeopleTable />
|
<PeopleTableComponent />
|
||||||
</StyledTableContainer>
|
</StyledTableContainer>
|
||||||
<EntityTableActionBar>
|
<EntityTableActionBar>
|
||||||
<TableActionBarButtonCreateActivityPeople />
|
<TableActionBarButtonCreateActivityPeople />
|
||||||
|
Loading…
Reference in New Issue
Block a user