diff --git a/front/src/modules/companies/components/CompanyBoardCard.tsx b/front/src/modules/companies/components/CompanyBoardCard.tsx
index 95a0e911b..1e5f91f32 100644
--- a/front/src/modules/companies/components/CompanyBoardCard.tsx
+++ b/front/src/modules/companies/components/CompanyBoardCard.tsx
@@ -143,7 +143,7 @@ export const CompanyBoardCard = () => {
const showCompactView = isCompactViewEnabled && isCardInCompactView;
- const { pipelineProgress, company } = companyProgress ?? {};
+ const { opportunity, company } = companyProgress ?? {};
const visibleBoardCardFields = useRecoilScopedValue(
visibleBoardCardFieldsScopedSelector,
@@ -175,7 +175,7 @@ export const CompanyBoardCard = () => {
};
// boardCardId check can be moved to a wrapper to avoid unnecessary logic above
- if (!company || !pipelineProgress || !boardCardId) {
+ if (!company || !opportunity || !boardCardId) {
return null;
}
diff --git a/front/src/modules/companies/components/CompanyProgressPicker.tsx b/front/src/modules/companies/components/CompanyProgressPicker.tsx
index bf70bc294..e0d06e306 100644
--- a/front/src/modules/companies/components/CompanyProgressPicker.tsx
+++ b/front/src/modules/companies/components/CompanyProgressPicker.tsx
@@ -17,7 +17,7 @@ export type CompanyProgressPickerProps = {
companyId: string | null;
onSubmit: (
newCompanyId: EntityForSelect | null,
- newPipelineStageId: string | null,
+ newPipelineStepId: string | null,
) => void;
onCancel?: () => void;
};
@@ -39,40 +39,40 @@ export const CompanyProgressPicker = ({
const [isProgressSelectionUnfolded, setIsProgressSelectionUnfolded] =
useState(false);
- const [selectedPipelineStageId, setSelectedPipelineStageId] = useState<
+ const [selectedPipelineStepId, setSelectedPipelineStepId] = useState<
string | null
>(null);
const [currentPipeline] = useRecoilState(currentPipelineState);
- const currentPipelineStages = useMemo(
- () => currentPipeline?.pipelineStages ?? [],
+ const currentPipelineSteps = useMemo(
+ () => currentPipeline?.pipelineSteps ?? [],
[currentPipeline],
);
- const handlePipelineStageChange = (newPipelineStageId: string) => {
- setSelectedPipelineStageId(newPipelineStageId);
+ const handlePipelineStepChange = (newPipelineStepId: string) => {
+ setSelectedPipelineStepId(newPipelineStepId);
setIsProgressSelectionUnfolded(false);
};
const handleEntitySelected = async (
selectedCompany: EntityForSelect | null | undefined,
) => {
- onSubmit(selectedCompany ?? null, selectedPipelineStageId);
+ onSubmit(selectedCompany ?? null, selectedPipelineStepId);
};
useEffect(() => {
- if (currentPipelineStages?.[0]?.id) {
- setSelectedPipelineStageId(currentPipelineStages?.[0]?.id);
+ if (currentPipelineSteps?.[0]?.id) {
+ setSelectedPipelineStepId(currentPipelineSteps?.[0]?.id);
}
- }, [currentPipelineStages]);
+ }, [currentPipelineSteps]);
- const selectedPipelineStage = useMemo(
+ const selectedPipelineStep = useMemo(
() =>
- currentPipelineStages.find(
- (pipelineStage: any) => pipelineStage.id === selectedPipelineStageId,
+ currentPipelineSteps.find(
+ (pipelineStep: any) => pipelineStep.id === selectedPipelineStepId,
),
- [currentPipelineStages, selectedPipelineStageId],
+ [currentPipelineSteps, selectedPipelineStepId],
);
return (
@@ -82,14 +82,14 @@ export const CompanyProgressPicker = ({
>
{isProgressSelectionUnfolded ? (
- {currentPipelineStages.map((pipelineStage: any, index: number) => (
+ {currentPipelineSteps.map((pipelineStep: any, index: number) => (
@@ -100,7 +100,7 @@ export const CompanyProgressPicker = ({
EndIcon={IconChevronDown}
onClick={() => setIsProgressSelectionUnfolded(true)}
>
- {selectedPipelineStage?.name}
+ {selectedPipelineStep?.name}
{
const currentViewFields = useRecoilValue(currentViewFieldsState);
+ const { objectMetadataItem } = useObjectMetadataItem({
+ objectNamePlural: 'opportunities',
+ });
+
+ const { columnDefinitions, filterDefinitions, sortDefinitions } =
+ useComputeDefinitionsFromFieldMetadata(objectMetadataItem);
+
const [, setIsBoardLoaded] = useRecoilState(isBoardLoadedState);
const { BoardRecoilScopeContext } = useBoardContext();
@@ -50,10 +61,6 @@ export const HooksCompanyBoardEffect = () => {
BoardRecoilScopeContext,
);
- const [, setAvailableBoardCardFields] = useRecoilScopedState(
- availableBoardCardFieldsScopedState,
- BoardRecoilScopeContext,
- );
const updateCompanyBoardCardIds = useUpdateCompanyBoardCardIds();
const updateCompanyBoard = useUpdateCompanyBoard();
@@ -70,9 +77,9 @@ export const HooksCompanyBoardEffect = () => {
const whereFilters = useMemo(() => {
return {
- AND: [
+ and: [
{
- pipelineStageId: {
+ pipelineStepId: {
in: pipelineSteps.map((pipelineStep) => pipelineStep.id),
},
},
@@ -86,8 +93,10 @@ export const HooksCompanyBoardEffect = () => {
objectNamePlural: 'opportunities',
filter: whereFilters,
onCompleted: useCallback(
- (_data: PaginatedObjectTypeResults) => {
- const pipelineProgresses: Array = [];
+ (data: PaginatedObjectTypeResults) => {
+ const pipelineProgresses: Array = data.edges.map(
+ (edge) => edge.node,
+ );
updateCompanyBoardCardIds(pipelineProgresses);
@@ -112,15 +121,63 @@ export const HooksCompanyBoardEffect = () => {
});
useEffect(() => {
- setAvailableFilterDefinitions(opportunitiesBoardOptions.filterDefinitions);
- setAvailableSortDefinitions?.(opportunitiesBoardOptions.sortDefinitions);
- setAvailableFieldDefinitions?.([]);
+ if (!objectMetadataItem) {
+ return;
+ }
+ setAvailableFilterDefinitions?.(filterDefinitions);
+ setAvailableSortDefinitions?.(sortDefinitions);
+ setAvailableFieldDefinitions?.(columnDefinitions);
}, [
+ columnDefinitions,
+ filterDefinitions,
+ objectMetadataItem,
setAvailableFieldDefinitions,
setAvailableFilterDefinitions,
setAvailableSortDefinitions,
+ sortDefinitions,
]);
+ const setAvailableBoardCardFields = useRecoilCallback(
+ ({ snapshot, set }) =>
+ (availableBoardCardFields: any) => {
+ const availableBoardCardFieldsFromState = snapshot
+ .getLoadable(
+ availableBoardCardFieldsScopedState({
+ scopeId: 'company-board-view',
+ }),
+ )
+ .getValue();
+
+ if (
+ !isDeeplyEqual(
+ availableBoardCardFieldsFromState,
+ availableBoardCardFields,
+ )
+ ) {
+ set(
+ availableBoardCardFieldsScopedState({
+ scopeId: 'company-board-view',
+ }),
+ availableBoardCardFields,
+ );
+ }
+ },
+ [],
+ );
+
+ useRecoilScopedStateV2(
+ availableBoardCardFieldsScopedState,
+ 'company-board-view',
+ );
+
+ useEffect(() => {
+ const availableTableColumns = columnDefinitions.filter(
+ filterAvailableTableColumns,
+ );
+
+ setAvailableBoardCardFields(availableTableColumns);
+ }, [columnDefinitions, setAvailableBoardCardFields]);
+
useEffect(() => {
setViewObjectMetadataId?.('company');
setViewType?.(ViewType.Kanban);
@@ -137,21 +194,19 @@ export const HooksCompanyBoardEffect = () => {
if (!loading && opportunities && companies) {
setActionBarEntries();
setContextMenuEntries();
- setAvailableBoardCardFields([]);
+
updateCompanyBoard(pipelineSteps, opportunities, companies);
setEntityCountInCurrentView(companies.length);
}
}, [
+ companies,
loading,
- updateCompanyBoard,
+ opportunities,
+ pipelineSteps,
setActionBarEntries,
setContextMenuEntries,
- searchParams,
setEntityCountInCurrentView,
- setAvailableBoardCardFields,
- opportunities,
- companies,
- pipelineSteps,
+ updateCompanyBoard,
]);
useEffect(() => {
diff --git a/front/src/modules/companies/components/NewCompanyProgressButton.tsx b/front/src/modules/companies/components/NewCompanyProgressButton.tsx
index 2f3e386f1..2d69f0c2e 100644
--- a/front/src/modules/companies/components/NewCompanyProgressButton.tsx
+++ b/front/src/modules/companies/components/NewCompanyProgressButton.tsx
@@ -12,7 +12,7 @@ export const NewCompanyProgressButton = () => {
const [isCreatingCard, setIsCreatingCard] = useState(false);
const column = useContext(BoardColumnContext);
- const pipelineStageId = column?.columnDefinition.id || '';
+ const pipelineStepId = column?.columnDefinition.id || '';
const { enqueueSnackBar } = useSnackBar();
@@ -25,7 +25,7 @@ export const NewCompanyProgressButton = () => {
setIsCreatingCard(false);
goBackToPreviousHotkeyScope();
- if (!pipelineStageId) {
+ if (!pipelineStepId) {
enqueueSnackBar('Pipeline stage id is not defined', {
variant: 'error',
});
@@ -33,7 +33,7 @@ export const NewCompanyProgressButton = () => {
throw new Error('Pipeline stage id is not defined');
}
- //createCompanyProgress(company.id, pipelineStageId);
+ //createCompanyProgress(company.id, pipelineStepId);
};
const handleNewClick = useCallback(() => {
diff --git a/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts b/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts
index 332812581..97b50edd5 100644
--- a/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts
+++ b/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts
@@ -7,7 +7,7 @@ import { boardColumnsState } from '@/ui/layout/board/states/boardColumnsState';
export const useUpdateCompanyBoardCardIds = () =>
useRecoilCallback(
({ snapshot, set }) =>
- (pipelineProgresses: Opportunity[]) => {
+ (pipelineProgresses: Pick[]) => {
const boardColumns = snapshot
.getLoadable(boardColumnsState)
.valueOrThrow();
@@ -16,7 +16,7 @@ export const useUpdateCompanyBoardCardIds = () =>
const boardCardIds = pipelineProgresses
.filter(
(pipelineProgressToFilter) =>
- pipelineProgressToFilter.pipelineStageId === boardColumn.id,
+ pipelineProgressToFilter.pipelineStepId === boardColumn.id,
)
.map((pipelineProgress) => pipelineProgress.id);
diff --git a/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts b/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts
index 9e74ee755..7bb049049 100644
--- a/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts
+++ b/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts
@@ -20,7 +20,7 @@ export const useUpdateCompanyBoard = () =>
({ set, snapshot }) =>
(
pipelineSteps: PipelineStep[],
- pipelineProgresses: Opportunity[],
+ opportunities: Opportunity[],
companies: CompanyForBoard[],
) => {
const indexCompanyByIdReducer = (
@@ -37,27 +37,26 @@ export const useUpdateCompanyBoard = () =>
{} as { [key: string]: CompanyForBoard },
) ?? {};
- const indexPipelineProgressByIdReducer = (
+ const indexOpportunityByIdReducer = (
acc: CompanyProgressDict,
- pipelineProgress: Opportunity,
+ opportunity: Opportunity,
) => {
const company =
- pipelineProgress.companyId &&
- companiesDict[pipelineProgress.companyId];
+ opportunity.companyId && companiesDict[opportunity.companyId];
if (!company) return acc;
return {
...acc,
- [pipelineProgress.id]: {
- pipelineProgress,
+ [opportunity.id]: {
+ opportunity,
company,
},
};
};
- const companyBoardIndex = pipelineProgresses.reduce(
- indexPipelineProgressByIdReducer,
+ const companyBoardIndex = opportunities.reduce(
+ indexOpportunityByIdReducer,
{} as CompanyProgressDict,
);
@@ -68,7 +67,7 @@ export const useUpdateCompanyBoard = () =>
if (!isDeeplyEqual(currentCompanyProgress, companyProgress)) {
set(companyProgressesFamilyState(id), companyProgress);
- set(entityFieldsFamilyState(id), companyProgress.pipelineProgress);
+ set(entityFieldsFamilyState(id), companyProgress.opportunity);
}
}
@@ -81,29 +80,29 @@ export const useUpdateCompanyBoard = () =>
.valueOrThrow();
if (!isDeeplyEqual(pipelineSteps, currentPipelineSteps)) {
- set(currentPipelineStepsState, currentPipelineSteps);
+ set(currentPipelineStepsState, pipelineSteps);
}
- const orderedPipelineStages = [...pipelineSteps].sort((a, b) => {
+ const orderedPipelineSteps = [...pipelineSteps].sort((a, b) => {
if (!a.position || !b.position) return 0;
return a.position - b.position;
});
const newBoardColumns: BoardColumnDefinition[] =
- orderedPipelineStages?.map((pipelineStage) => {
- if (!isThemeColor(pipelineStage.color)) {
+ orderedPipelineSteps?.map((pipelineStep) => {
+ if (!isThemeColor(pipelineStep.color)) {
logError(
- `Color ${pipelineStage.color} is not recognized in useUpdateCompanyBoard.`,
+ `Color ${pipelineStep.color} is not recognized in useUpdateCompanyBoard.`,
);
}
return {
- id: pipelineStage.id,
- title: pipelineStage.name,
- colorCode: isThemeColor(pipelineStage.color)
- ? pipelineStage.color
+ id: pipelineStep.id,
+ title: pipelineStep.name,
+ colorCode: isThemeColor(pipelineStep.color)
+ ? pipelineStep.color
: undefined,
- position: pipelineStage.position ?? 0,
+ position: pipelineStep.position ?? 0,
};
});
if (currentBoardColumns.length === 0) {
@@ -111,12 +110,12 @@ export const useUpdateCompanyBoard = () =>
set(savedBoardColumnsState, newBoardColumns);
}
for (const boardColumn of newBoardColumns) {
- const boardCardIds = pipelineProgresses
+ const boardCardIds = opportunities
.filter(
- (pipelineProgressToFilter) =>
- pipelineProgressToFilter.pipelineStageId === boardColumn.id,
+ (opportunityToFilter) =>
+ opportunityToFilter.pipelineStepId === boardColumn.id,
)
- .map((pipelineProgress) => pipelineProgress.id);
+ .map((opportunity) => opportunity.id);
const currentBoardCardIds = snapshot
.getLoadable(boardCardIdsByColumnIdFamilyState(boardColumn.id))
diff --git a/front/src/modules/companies/types/CompanyProgress.ts b/front/src/modules/companies/types/CompanyProgress.ts
index 6791fca10..ab797dca2 100644
--- a/front/src/modules/companies/types/CompanyProgress.ts
+++ b/front/src/modules/companies/types/CompanyProgress.ts
@@ -2,11 +2,10 @@ import { Company } from '@/companies/types/Company';
import { Opportunity } from '@/pipeline/types/Opportunity';
export type CompanyForBoard = Pick;
-export type PipelineProgressForBoard = Opportunity;
export type CompanyProgress = {
company: CompanyForBoard;
- pipelineProgress: PipelineProgressForBoard;
+ opportunity: Opportunity;
};
export type CompanyProgressDict = {
diff --git a/front/src/modules/object-metadata/hooks/useObjectMainIdentifier.ts b/front/src/modules/object-metadata/hooks/useObjectMainIdentifier.ts
index 1717361b4..dd4121f51 100644
--- a/front/src/modules/object-metadata/hooks/useObjectMainIdentifier.ts
+++ b/front/src/modules/object-metadata/hooks/useObjectMainIdentifier.ts
@@ -1,47 +1,34 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
-import { MainIdentifierMapper } from '@/ui/object/field/types/MainIdentifierMapper';
+import { AvatarType } from '@/users/components/Avatar';
import { Nullable } from '~/types/Nullable';
export const useObjectMainIdentifier = (
objectMetadataItem?: Nullable,
) => {
if (!objectMetadataItem) {
- return {
- mainIdentifierMapper: undefined,
- mainIdentifierFieldMetadataId: undefined,
- basePathToShowPage: undefined,
- };
+ return {};
}
- const mainIdentifierMapper: MainIdentifierMapper = (record: any) => {
- if (objectMetadataItem.nameSingular === 'company') {
- return {
- id: record.id,
- name: record.name,
- avatarUrl: record.avatarUrl,
- avatarType: 'squared',
- record: record,
- };
- }
-
- if (objectMetadataItem.nameSingular === 'workspaceMember') {
- return {
- id: record.id,
- name: record.name.firstName + ' ' + record.name.lastName,
- avatarUrl: record.avatarUrl,
- avatarType: 'rounded',
- record: record,
- };
- }
-
- return {
- id: record.id,
- name: record.name,
- avatarUrl: record.avatarUrl,
- avatarType: 'rounded',
- record: record,
- };
- };
+ const labelIdentifierFieldPaths = ['person', 'workspaceMember'].includes(
+ objectMetadataItem.nameSingular,
+ )
+ ? ['name.firstName', 'name.lastName']
+ : ['name'];
+ const imageIdentifierFormat: AvatarType = ['company'].includes(
+ objectMetadataItem.nameSingular,
+ )
+ ? 'squared'
+ : 'rounded';
+ const imageIdentifierUrlPrefix = ['company'].includes(
+ objectMetadataItem.nameSingular,
+ )
+ ? 'https://favicon.twenty.com/'
+ : '';
+ const imageIdentifierUrlField = ['company'].includes(
+ objectMetadataItem.nameSingular,
+ )
+ ? 'domainName'
+ : 'avatarUrl';
const mainIdentifierFieldMetadataId = objectMetadataItem.fields.find(
({ name }) => name === 'name',
@@ -50,7 +37,10 @@ export const useObjectMainIdentifier = (
const basePathToShowPage = `/object/${objectMetadataItem.nameSingular}/`;
return {
- mainIdentifierMapper,
+ labelIdentifierFieldPaths,
+ imageIdentifierUrlField,
+ imageIdentifierUrlPrefix,
+ imageIdentifierFormat,
mainIdentifierFieldMetadataId,
basePathToShowPage,
};
diff --git a/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts b/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts
index a7d18f2ae..d5ee3859b 100644
--- a/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts
+++ b/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts
@@ -1,8 +1,7 @@
import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelationType';
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
-import { MainIdentifierMapper } from '@/ui/object/field/types/MainIdentifierMapper';
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
-import { getLogoUrlFromDomainName } from '~/utils';
+import { AvatarType } from '@/users/components/Avatar';
import { FieldMetadataItem } from '../types/FieldMetadataItem';
@@ -18,34 +17,26 @@ export const formatFieldMetadataItemAsColumnDefinition = ({
const relationObjectMetadataItem =
field.toRelationMetadata?.fromObjectMetadata;
- const mainIdentifierMapper: MainIdentifierMapper = (record: any) => {
- if (relationObjectMetadataItem?.nameSingular === 'company') {
- return {
- id: record.id,
- name: record.name,
- avatarUrl: getLogoUrlFromDomainName(record.domainName),
- avatarType: 'squared',
- record: record,
- };
- }
- if (relationObjectMetadataItem?.nameSingular === 'workspaceMember') {
- return {
- id: record.id,
- name: record.name.firstName + ' ' + record.name.lastName,
- avatarUrl: record.avatarUrl,
- avatarType: 'rounded',
- record: record,
- };
- }
-
- return {
- id: record.id,
- name: record.name,
- avatarUrl: record.avatarUrl,
- avatarType: 'rounded',
- record: record,
- };
- };
+ const labelIdentifierFieldPaths = ['person', 'workspaceMember'].includes(
+ relationObjectMetadataItem?.nameSingular ?? '',
+ )
+ ? ['name.firstName', 'name.lastName']
+ : ['name'];
+ const imageIdentifierFormat: AvatarType = ['company'].includes(
+ relationObjectMetadataItem?.nameSingular ?? '',
+ )
+ ? 'squared'
+ : 'rounded';
+ const imageIdentifierUrlPrefix = ['company'].includes(
+ relationObjectMetadataItem?.nameSingular ?? '',
+ )
+ ? 'https://favicon.twenty.com/'
+ : '';
+ const imageIdentifierUrlField = ['company'].includes(
+ relationObjectMetadataItem?.nameSingular ?? '',
+ )
+ ? 'domainName'
+ : 'avatarUrl';
return {
position,
@@ -56,11 +47,15 @@ export const formatFieldMetadataItemAsColumnDefinition = ({
metadata: {
fieldName: field.name,
placeHolder: field.label,
- mainIdentifierMapper: mainIdentifierMapper,
+ labelIdentifierFieldPaths,
+ imageIdentifierUrlField,
+ imageIdentifierUrlPrefix,
+ imageIdentifierFormat,
relationType: parseFieldRelationType(field),
searchFields: ['name'],
- objectMetadataNamePlural: relationObjectMetadataItem?.namePlural,
- objectMetadataNameSingular: relationObjectMetadataItem?.nameSingular,
+ objectMetadataNamePlural: relationObjectMetadataItem?.namePlural ?? '',
+ objectMetadataNameSingular:
+ relationObjectMetadataItem?.nameSingular ?? '',
},
iconName: field.icon ?? 'Icon123',
isVisible: true,
diff --git a/front/src/modules/object-record/components/RecordTableEffect.tsx b/front/src/modules/object-record/components/RecordTableEffect.tsx
index ee5c768bb..da3f7db08 100644
--- a/front/src/modules/object-record/components/RecordTableEffect.tsx
+++ b/front/src/modules/object-record/components/RecordTableEffect.tsx
@@ -22,9 +22,12 @@ export const RecordTableEffect = () => {
});
const {
- mainIdentifierMapper,
basePathToShowPage,
mainIdentifierFieldMetadataId,
+ labelIdentifierFieldPaths,
+ imageIdentifierUrlField,
+ imageIdentifierUrlPrefix,
+ imageIdentifierFormat,
} = useObjectMainIdentifier(objectMetadataItem);
const { columnDefinitions, filterDefinitions, sortDefinitions } =
@@ -40,13 +43,12 @@ export const RecordTableEffect = () => {
} = useView();
useEffect(() => {
- if (
- mainIdentifierMapper &&
- basePathToShowPage &&
- mainIdentifierFieldMetadataId
- ) {
+ if (basePathToShowPage && mainIdentifierFieldMetadataId) {
setObjectMetadataConfig?.({
- mainIdentifierMapper,
+ labelIdentifierFieldPaths,
+ imageIdentifierUrlField,
+ imageIdentifierUrlPrefix,
+ imageIdentifierFormat,
basePathToShowPage,
mainIdentifierFieldMetadataId,
});
@@ -55,8 +57,11 @@ export const RecordTableEffect = () => {
basePathToShowPage,
objectMetadataItem,
mainIdentifierFieldMetadataId,
- mainIdentifierMapper,
setObjectMetadataConfig,
+ labelIdentifierFieldPaths,
+ imageIdentifierUrlField,
+ imageIdentifierUrlPrefix,
+ imageIdentifierFormat,
]);
useEffect(() => {
diff --git a/front/src/modules/object-record/hooks/useDeleteOneObjectRecord.ts b/front/src/modules/object-record/hooks/useDeleteOneObjectRecord.ts
index 907b58e2f..0b9287518 100644
--- a/front/src/modules/object-record/hooks/useDeleteOneObjectRecord.ts
+++ b/front/src/modules/object-record/hooks/useDeleteOneObjectRecord.ts
@@ -1,3 +1,4 @@
+import { useCallback } from 'react';
import { useMutation } from '@apollo/client';
import { getOperationName } from '@apollo/client/utilities';
@@ -20,20 +21,25 @@ export const useDeleteOneObjectRecord = ({
// TODO: type this with a minimal type at least with Record
const [mutate] = useMutation(deleteOneMutation);
- const deleteOneObject =
- objectNameSingular && foundObjectMetadataItem
- ? async (idToDelete: string) => {
- const deletedObject = await mutate({
- variables: {
- idToDelete,
- },
- refetchQueries: [getOperationName(findManyQuery) ?? ''],
- });
- return deletedObject.data[
- `create${capitalize(objectNameSingular)}`
- ] as T;
- }
- : undefined;
+ const deleteOneObject = useCallback(
+ async (idToDelete: string) => {
+ if (objectNameSingular && foundObjectMetadataItem) {
+ const deletedObject = await mutate({
+ variables: {
+ idToDelete,
+ },
+ refetchQueries: [getOperationName(findManyQuery) ?? ''],
+ });
+
+ return deletedObject.data[
+ `create${capitalize(objectNameSingular)}`
+ ] as T;
+ }
+
+ return null;
+ },
+ [foundObjectMetadataItem, mutate, objectNameSingular, findManyQuery],
+ );
return {
deleteOneObject,
diff --git a/front/src/modules/object-record/utils/filterAvailableTableColumns.ts b/front/src/modules/object-record/utils/filterAvailableTableColumns.ts
index a082bcb76..16ed62771 100644
--- a/front/src/modules/object-record/utils/filterAvailableTableColumns.ts
+++ b/front/src/modules/object-record/utils/filterAvailableTableColumns.ts
@@ -16,5 +16,12 @@ export const filterAvailableTableColumns = (
return false;
}
+ if (
+ isFieldRelation(columnDefinition) &&
+ columnDefinition.metadata?.fieldName === 'pipelineStep'
+ ) {
+ return false;
+ }
+
return true;
};
diff --git a/front/src/modules/pipeline/components/PipelineAddButton.tsx b/front/src/modules/pipeline/components/PipelineAddButton.tsx
index e0be2cee2..4334230b6 100644
--- a/front/src/modules/pipeline/components/PipelineAddButton.tsx
+++ b/front/src/modules/pipeline/components/PipelineAddButton.tsx
@@ -19,7 +19,7 @@ export const PipelineAddButton = () => {
const handleCompanySelected = (
selectedCompany: EntityForSelect | null,
- selectedPipelineStageId: string | null,
+ selectedPipelineStepId: string | null,
) => {
if (!selectedCompany?.id) {
enqueueSnackBar(
@@ -33,7 +33,7 @@ export const PipelineAddButton = () => {
return;
}
- if (!selectedPipelineStageId) {
+ if (!selectedPipelineStepId) {
enqueueSnackBar(
'There was a problem with the pipeline stage selection, please retry.',
{
@@ -45,7 +45,7 @@ export const PipelineAddButton = () => {
return;
}
closeDropdown();
- //createCompanyProgress(selectedCompany.id, selectedPipelineStageId);
+ //createCompanyProgress(selectedCompany.id, selectedPipelineStepId);
};
return (
diff --git a/front/src/modules/pipeline/hooks/usePipelineStages.ts b/front/src/modules/pipeline/hooks/usePipelineSteps.ts
similarity index 83%
rename from front/src/modules/pipeline/hooks/usePipelineStages.ts
rename to front/src/modules/pipeline/hooks/usePipelineSteps.ts
index 032ec555c..39f0e6468 100644
--- a/front/src/modules/pipeline/hooks/usePipelineStages.ts
+++ b/front/src/modules/pipeline/hooks/usePipelineSteps.ts
@@ -7,7 +7,7 @@ import { BoardColumnDefinition } from '@/ui/layout/board/types/BoardColumnDefini
import { currentPipelineState } from '../states/currentPipelineState';
-export const usePipelineStages = () => {
+export const usePipelineSteps = () => {
const currentPipeline = useRecoilValue(currentPipelineState);
const { createOneObject: createOnePipelineStep } =
@@ -20,7 +20,7 @@ export const usePipelineStages = () => {
objectNameSingular: 'pipelineStep',
});
- const handlePipelineStageAdd = async (boardColumn: BoardColumnDefinition) => {
+ const handlePipelineStepAdd = async (boardColumn: BoardColumnDefinition) => {
if (!currentPipeline?.id) return;
return createOnePipelineStep?.({
@@ -37,11 +37,11 @@ export const usePipelineStages = () => {
});
};
- const handlePipelineStageDelete = async (boardColumnId: string) => {
+ const handlePipelineStepDelete = async (boardColumnId: string) => {
if (!currentPipeline?.id) return;
return deleteOnePipelineStep?.(boardColumnId);
};
- return { handlePipelineStageAdd, handlePipelineStageDelete };
+ return { handlePipelineStepAdd, handlePipelineStepDelete };
};
diff --git a/front/src/modules/pipeline/types/Opportunity.ts b/front/src/modules/pipeline/types/Opportunity.ts
index fc841efab..3525841f8 100644
--- a/front/src/modules/pipeline/types/Opportunity.ts
+++ b/front/src/modules/pipeline/types/Opportunity.ts
@@ -2,6 +2,7 @@ import { Person } from '@/people/types/Person';
import { PipelineStep } from '@/pipeline/types/PipelineStep';
export type Opportunity = {
+ [key: string]: any;
id: string;
amount: {
amountMicros: number;
@@ -13,5 +14,4 @@ export type Opportunity = {
pipelineStep: PipelineStep;
pointOfContactId: string;
pointOfContact: Pick;
- [key: string]: any;
};
diff --git a/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx b/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx
index f91a08467..bd71de588 100644
--- a/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx
+++ b/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx
@@ -92,7 +92,10 @@ export const SettingsObjectFieldPreview = ({
const {
defaultValue: relationDefaultValue,
- recordMapper: mainIdentifierMapper,
+ labelIdentifierFieldPaths,
+ imageIdentifierUrlField,
+ imageIdentifierUrlPrefix,
+ imageIdentifierFormat,
} = useRelationFieldPreview({
relationObjectMetadataId,
skipDefaultValue:
@@ -104,6 +107,15 @@ export const SettingsObjectFieldPreview = ({
? relationDefaultValue
: dataTypes[fieldMetadata.type].defaultValue;
+ if (
+ !labelIdentifierFieldPaths ||
+ !imageIdentifierUrlField ||
+ !imageIdentifierUrlPrefix ||
+ !imageIdentifierFormat
+ ) {
+ return <>>;
+ }
+
return (
@@ -146,7 +158,13 @@ export const SettingsObjectFieldPreview = ({
iconName: 'FieldIcon',
fieldMetadataId: fieldMetadata.id || '',
label: fieldMetadata.label,
- metadata: { fieldName, mainIdentifierMapper },
+ metadata: {
+ fieldName,
+ labelIdentifierFieldPaths,
+ imageIdentifierUrlField,
+ imageIdentifierUrlPrefix,
+ imageIdentifierFormat,
+ },
},
hotkeyScope: 'field-preview',
}}
diff --git a/front/src/modules/settings/data-model/hooks/useRelationFieldPreview.ts b/front/src/modules/settings/data-model/hooks/useRelationFieldPreview.ts
index dfd78d429..f0300587d 100644
--- a/front/src/modules/settings/data-model/hooks/useRelationFieldPreview.ts
+++ b/front/src/modules/settings/data-model/hooks/useRelationFieldPreview.ts
@@ -1,7 +1,6 @@
import { useObjectMainIdentifier } from '@/object-metadata/hooks/useObjectMainIdentifier';
import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings';
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
-import { MainIdentifierMapper } from '@/ui/object/field/types/MainIdentifierMapper';
export const useRelationFieldPreview = ({
relationObjectMetadataId,
@@ -21,24 +20,18 @@ export const useRelationFieldPreview = ({
skip: skipDefaultValue || !relationObjectMetadataItem,
});
- const { mainIdentifierMapper } = useObjectMainIdentifier(
- relationObjectMetadataItem,
- );
-
- const recordMapper: MainIdentifierMapper | undefined =
- relationObjectMetadataItem && mainIdentifierMapper
- ? (record: { id: string }) => {
- const mappedRecord = mainIdentifierMapper(record);
-
- return {
- ...mappedRecord,
- name: mappedRecord.name || relationObjectMetadataItem.labelSingular,
- };
- }
- : undefined;
+ const {
+ labelIdentifierFieldPaths,
+ imageIdentifierUrlField,
+ imageIdentifierUrlPrefix,
+ imageIdentifierFormat,
+ } = useObjectMainIdentifier(relationObjectMetadataItem);
return {
defaultValue: relationObjects?.[0],
- recordMapper,
+ labelIdentifierFieldPaths,
+ imageIdentifierUrlField,
+ imageIdentifierUrlPrefix,
+ imageIdentifierFormat,
};
};
diff --git a/front/src/modules/ui/layout/board/components/BoardOptionsDropdownContent.tsx b/front/src/modules/ui/layout/board/components/BoardOptionsDropdownContent.tsx
index 1adb3af84..472862def 100644
--- a/front/src/modules/ui/layout/board/components/BoardOptionsDropdownContent.tsx
+++ b/front/src/modules/ui/layout/board/components/BoardOptionsDropdownContent.tsx
@@ -74,6 +74,7 @@ export const BoardOptionsDropdownContent = ({
hiddenBoardCardFieldsScopedSelector,
BoardRecoilScopeContext,
);
+
const hasHiddenFields = hiddenBoardCardFields.length > 0;
const visibleBoardCardFields = useRecoilScopedValue(
visibleBoardCardFieldsScopedSelector,
diff --git a/front/src/modules/ui/layout/board/components/EntityBoard.tsx b/front/src/modules/ui/layout/board/components/EntityBoard.tsx
index f786d5e86..2178fdc49 100644
--- a/front/src/modules/ui/layout/board/components/EntityBoard.tsx
+++ b/front/src/modules/ui/layout/board/components/EntityBoard.tsx
@@ -65,11 +65,11 @@ export const EntityBoard = ({
const { unselectAllActiveCards } = useCurrentCardSelected();
const updatePipelineProgressStageInDB = useCallback(
- async (pipelineProgressId: string, pipelineStageId: string) => {
+ async (pipelineProgressId: string, pipelineStepId: string) => {
await updateOneOpportunity?.({
idToUpdate: pipelineProgressId,
input: {
- pipelineStepId: pipelineStageId,
+ pipelineStepId: pipelineStepId,
},
});
@@ -80,7 +80,7 @@ export const EntityBoard = ({
__typename: 'PipelineProgress',
}),
fields: {
- pipelineStageId: () => pipelineStageId,
+ pipelineStepId: () => pipelineStepId,
},
});
},
diff --git a/front/src/modules/ui/layout/board/hooks/useBoardActionBarEntries.tsx b/front/src/modules/ui/layout/board/hooks/useBoardActionBarEntries.tsx
index f3e377aa4..13e0acc37 100644
--- a/front/src/modules/ui/layout/board/hooks/useBoardActionBarEntries.tsx
+++ b/front/src/modules/ui/layout/board/hooks/useBoardActionBarEntries.tsx
@@ -1,3 +1,4 @@
+import { useCallback } from 'react';
import { useSetRecoilState } from 'recoil';
import { IconTrash } from '@/ui/display/icon';
@@ -5,19 +6,22 @@ import { useDeleteSelectedBoardCards } from '@/ui/layout/board/hooks/useDeleteSe
import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState';
export const useBoardActionBarEntries = () => {
- const setActionBarEntries = useSetRecoilState(actionBarEntriesState);
+ const setActionBarEntriesRecoil = useSetRecoilState(actionBarEntriesState);
const deleteSelectedBoardCards = useDeleteSelectedBoardCards();
+ const setActionBarEntries = useCallback(() => {
+ setActionBarEntriesRecoil([
+ {
+ label: 'Delete',
+ Icon: IconTrash,
+ accent: 'danger',
+ onClick: deleteSelectedBoardCards,
+ },
+ ]);
+ }, [deleteSelectedBoardCards, setActionBarEntriesRecoil]);
+
return {
- setActionBarEntries: () =>
- setActionBarEntries([
- {
- label: 'Delete',
- Icon: IconTrash,
- accent: 'danger',
- onClick: deleteSelectedBoardCards,
- },
- ]),
+ setActionBarEntries,
};
};
diff --git a/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts b/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts
index 458a9967e..834d61d97 100644
--- a/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts
+++ b/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts
@@ -17,7 +17,7 @@ export const useBoardColumns = () => {
objectNameSingular: 'pipelineStep',
});
- const updatedPipelineStages = (stages: BoardColumnDefinition[]) => {
+ const updatedPipelineSteps = (stages: BoardColumnDefinition[]) => {
if (!stages.length) return;
return Promise.all(
@@ -33,7 +33,7 @@ export const useBoardColumns = () => {
};
const persistBoardColumns = async () => {
- await updatedPipelineStages(boardColumns);
+ await updatedPipelineSteps(boardColumns);
};
const handleMoveBoardColumn = (
diff --git a/front/src/modules/ui/layout/board/hooks/useBoardContextMenuEntries.tsx b/front/src/modules/ui/layout/board/hooks/useBoardContextMenuEntries.tsx
index d51437057..806a8939f 100644
--- a/front/src/modules/ui/layout/board/hooks/useBoardContextMenuEntries.tsx
+++ b/front/src/modules/ui/layout/board/hooks/useBoardContextMenuEntries.tsx
@@ -1,3 +1,4 @@
+import { useCallback } from 'react';
import { useSetRecoilState } from 'recoil';
import { IconTrash } from '@/ui/display/icon';
@@ -5,19 +6,24 @@ import { useDeleteSelectedBoardCards } from '@/ui/layout/board/hooks/useDeleteSe
import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState';
export const useBoardContextMenuEntries = () => {
- const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState);
+ const setContextMenuEntriesRecoil = useSetRecoilState(
+ contextMenuEntriesState,
+ );
const deleteSelectedBoardCards = useDeleteSelectedBoardCards();
+ const setContextMenuEntries = useCallback(() => {
+ setContextMenuEntriesRecoil([
+ {
+ label: 'Delete',
+ Icon: IconTrash,
+ accent: 'danger',
+ onClick: deleteSelectedBoardCards,
+ },
+ ]);
+ }, [deleteSelectedBoardCards, setContextMenuEntriesRecoil]);
+
return {
- setContextMenuEntries: () =>
- setContextMenuEntries([
- {
- label: 'Delete',
- Icon: IconTrash,
- accent: 'danger',
- onClick: () => deleteSelectedBoardCards(),
- },
- ]),
+ setContextMenuEntries,
};
};
diff --git a/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts b/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts
index a0db15049..ad31e1ff7 100644
--- a/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts
+++ b/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts
@@ -34,7 +34,7 @@ export const useDeleteSelectedBoardCards = () => {
apolloClient.cache.evict({ id: `Opportunity:${id}` });
});
},
- [apolloClient.cache, deleteOneOpportunity, removeCardIds],
+ [apolloClient.cache, removeCardIds, deleteOneOpportunity],
);
return deleteSelectedBoardCards;
diff --git a/front/src/modules/ui/layout/board/states/availableBoardCardFieldsScopedState.ts b/front/src/modules/ui/layout/board/states/availableBoardCardFieldsScopedState.ts
index 3202a6a36..86205c5ce 100644
--- a/front/src/modules/ui/layout/board/states/availableBoardCardFieldsScopedState.ts
+++ b/front/src/modules/ui/layout/board/states/availableBoardCardFieldsScopedState.ts
@@ -1,13 +1,11 @@
-import { atomFamily } from 'recoil';
-
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
+import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
import { BoardFieldDefinition } from '../types/BoardFieldDefinition';
-export const availableBoardCardFieldsScopedState = atomFamily<
- BoardFieldDefinition[],
- string
+export const availableBoardCardFieldsScopedState = createScopedState<
+ BoardFieldDefinition[]
>({
key: 'availableBoardCardFieldsScopedState',
- default: [],
+ defaultValue: [],
});
diff --git a/front/src/modules/ui/layout/board/states/selectors/boardColumnTotalsFamilySelector.ts b/front/src/modules/ui/layout/board/states/selectors/boardColumnTotalsFamilySelector.ts
index 5a70fef68..77aca5f72 100644
--- a/front/src/modules/ui/layout/board/states/selectors/boardColumnTotalsFamilySelector.ts
+++ b/front/src/modules/ui/layout/board/states/selectors/boardColumnTotalsFamilySelector.ts
@@ -9,20 +9,21 @@ import { boardCardIdsByColumnIdFamilyState } from '../boardCardIdsByColumnIdFami
export const boardColumnTotalsFamilySelector = selectorFamily({
key: 'boardColumnTotalsFamilySelector',
get:
- (pipelineStageId: string) =>
+ (pipelineStepId: string) =>
({ get }) => {
- const cardIds = get(boardCardIdsByColumnIdFamilyState(pipelineStageId));
+ const cardIds = get(boardCardIdsByColumnIdFamilyState(pipelineStepId));
- const pipelineProgresses = cardIds.map((pipelineProgressId: string) =>
- get(companyProgressesFamilyState(pipelineProgressId)),
+ const opportunities = cardIds.map((opportunityId: string) =>
+ get(companyProgressesFamilyState(opportunityId)),
);
- const pipelineStageTotal: number =
- pipelineProgresses?.reduce(
- (acc: number, curr: any) => acc + curr?.pipelineProgress.amount,
+ const pipelineStepTotal: number =
+ opportunities?.reduce(
+ (acc: number, curr: any) =>
+ acc + curr?.opportunity.amount.amountMicros / 1000000,
0,
) || 0;
- return pipelineStageTotal;
+ return pipelineStepTotal;
},
});
diff --git a/front/src/modules/ui/layout/board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts b/front/src/modules/ui/layout/board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts
index 29c56cc4c..3dae2d8e2 100644
--- a/front/src/modules/ui/layout/board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts
+++ b/front/src/modules/ui/layout/board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts
@@ -11,7 +11,7 @@ export const hiddenBoardCardFieldsScopedSelector = selectorFamily({
const fields = get(boardCardFieldsScopedState(scopeId));
const fieldKeys = fields.map(({ fieldMetadataId }) => fieldMetadataId);
const otherAvailableKeys = get(
- availableBoardCardFieldsScopedState(scopeId),
+ availableBoardCardFieldsScopedState({ scopeId }),
).filter(({ fieldMetadataId }) => !fieldKeys.includes(fieldMetadataId));
return [
diff --git a/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx b/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx
index 092fe0a2a..414f52e10 100644
--- a/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx
+++ b/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx
@@ -5,19 +5,20 @@ import { useRelationField } from '../../hooks/useRelationField';
export const RelationFieldDisplay = () => {
const { fieldValue, fieldDefinition } = useRelationField();
+ const { mapToObjectIdentifiers } = useRelationField();
+
if (!fieldValue || !fieldDefinition) {
return <>>;
}
- const mainIdentifierMapped =
- fieldDefinition.metadata.mainIdentifierMapper(fieldValue);
+ const objectIdentifiers = mapToObjectIdentifiers(fieldValue);
return (
);
};
diff --git a/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts b/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts
index a48f60a26..ea8b80ea5 100644
--- a/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts
+++ b/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts
@@ -30,11 +30,40 @@ export const useRelationField = () => {
const initialValue = fieldInitialValue?.isEmpty ? null : fieldValue;
+ const mapToObjectIdentifiers = (record: any) => {
+ let name = '';
+ for (const fieldPath of fieldDefinition.metadata
+ .labelIdentifierFieldPaths) {
+ const fieldPathParts = fieldPath.split('.');
+
+ if (fieldPathParts.length === 1) {
+ name += record[fieldPathParts[0]];
+ } else if (fieldPathParts.length === 2) {
+ name += record[fieldPathParts[0]][fieldPathParts[1]];
+ } else {
+ throw new Error(
+ `Invalid field path ${fieldPath}. Relation picker only supports field paths with 1 or 2 parts.`,
+ );
+ }
+ }
+
+ return {
+ id: record.id,
+ name: record[name],
+ avatarUrl:
+ fieldDefinition.metadata.imageIdentifierUrlPrefix +
+ record[fieldDefinition.metadata.imageIdentifierUrlField],
+ avatarType: fieldDefinition.metadata.imageIdentifierFormat,
+ record: record,
+ };
+ };
+
return {
fieldDefinition,
fieldValue,
initialValue,
initialSearchValue,
setFieldValue,
+ mapToObjectIdentifiers,
};
};
diff --git a/front/src/modules/ui/object/field/meta-types/input/components/internal/RelationPicker.tsx b/front/src/modules/ui/object/field/meta-types/input/components/internal/RelationPicker.tsx
index e093ed8c6..716731d1d 100644
--- a/front/src/modules/ui/object/field/meta-types/input/components/internal/RelationPicker.tsx
+++ b/front/src/modules/ui/object/field/meta-types/input/components/internal/RelationPicker.tsx
@@ -7,6 +7,7 @@ import { IconUserCircle } from '@/ui/display/icon';
import { SingleEntitySelect } from '@/ui/input/relation-picker/components/SingleEntitySelect';
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
+import { useRelationField } from '@/ui/object/field/meta-types/hooks/useRelationField';
import { FieldDefinition } from '@/ui/object/field/types/FieldDefinition';
import { FieldRelationMetadata } from '@/ui/object/field/types/FieldMetadata';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
@@ -41,6 +42,8 @@ export const RelationPicker = ({
const useFindManyQuery = (options: any) => useQuery(findManyQuery, options);
+ const { mapToObjectIdentifiers } = useRelationField();
+
const workspaceMembers = useFilteredSearchEntityQuery({
queryHook: useFindManyQuery,
filters: [
@@ -50,7 +53,7 @@ export const RelationPicker = ({
},
],
orderByField: 'createdAt',
- mappingFunction: fieldDefinition.metadata.mainIdentifierMapper,
+ mappingFunction: mapToObjectIdentifiers,
selectedIds: recordId ? [recordId] : [],
objectNamePlural: fieldDefinition.metadata.objectMetadataNamePlural,
});
diff --git a/front/src/modules/ui/object/field/types/FieldMetadata.ts b/front/src/modules/ui/object/field/types/FieldMetadata.ts
index 704849463..24559560c 100644
--- a/front/src/modules/ui/object/field/types/FieldMetadata.ts
+++ b/front/src/modules/ui/object/field/types/FieldMetadata.ts
@@ -1,5 +1,4 @@
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
-import { MainIdentifierMapper } from '@/ui/object/field/types/MainIdentifierMapper';
export type FieldUuidMetadata = {
fieldName: string;
@@ -65,7 +64,10 @@ export type FieldRelationMetadata = {
fieldName: string;
useEditButton?: boolean;
relationType?: FieldDefinitionRelationType;
- mainIdentifierMapper: MainIdentifierMapper;
+ labelIdentifierFieldPaths: string[];
+ imageIdentifierUrlField: string;
+ imageIdentifierUrlPrefix: string;
+ imageIdentifierFormat: 'squared' | 'rounded';
searchFields: string[];
objectMetadataNameSingular: string;
objectMetadataNamePlural: string;
diff --git a/front/src/modules/ui/object/field/types/MainIdentifierMapper.ts b/front/src/modules/ui/object/field/types/MainIdentifierMapper.ts
deleted file mode 100644
index 2b275de6b..000000000
--- a/front/src/modules/ui/object/field/types/MainIdentifierMapper.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { AvatarType } from '@/users/components/Avatar';
-
-export type MainIdentifierMapper = (record: any) => {
- id: string;
- name: string;
- avatarUrl?: string;
- avatarType: AvatarType;
- record: any;
-};
diff --git a/front/src/modules/ui/object/field/types/RelationFieldConfig.ts b/front/src/modules/ui/object/field/types/RelationFieldConfig.ts
deleted file mode 100644
index e2e32229c..000000000
--- a/front/src/modules/ui/object/field/types/RelationFieldConfig.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { MainIdentifierMapper } from '@/ui/object/field/types/MainIdentifierMapper';
-
-export type FieldDefinitionRelationType =
- | 'FROM_MANY_OBJECTS'
- | 'FROM_ONE_OBJECT'
- | 'TO_MANY_OBJECTS'
- | 'TO_ONE_OBJECT';
-
-export type RelationFieldConfig = {
- relationType?: FieldDefinitionRelationType;
- mainIdentifierMapper: MainIdentifierMapper;
- searchFields: string[];
- objectMetadataNameSingular: string;
-};
diff --git a/front/src/modules/ui/object/record-table/components/RecordTableCell.tsx b/front/src/modules/ui/object/record-table/components/RecordTableCell.tsx
index 375b1ca7f..1181f2870 100644
--- a/front/src/modules/ui/object/record-table/components/RecordTableCell.tsx
+++ b/front/src/modules/ui/object/record-table/components/RecordTableCell.tsx
@@ -63,7 +63,6 @@ export const RecordTableCell = ({ cellIndex }: { cellIndex: number }) => {
isMainIdentifier:
columnDefinition.fieldMetadataId ===
objectMetadataConfig?.mainIdentifierFieldMetadataId,
- mainIdentifierMapper: objectMetadataConfig?.mainIdentifierMapper,
}}
>
diff --git a/front/src/modules/ui/object/record-table/types/ObjectMetadataConfig.ts b/front/src/modules/ui/object/record-table/types/ObjectMetadataConfig.ts
index 41b7d5047..d12811ae7 100644
--- a/front/src/modules/ui/object/record-table/types/ObjectMetadataConfig.ts
+++ b/front/src/modules/ui/object/record-table/types/ObjectMetadataConfig.ts
@@ -2,10 +2,9 @@ import { AvatarType } from '@/users/components/Avatar';
export type ObjectMetadataConfig = {
mainIdentifierFieldMetadataId: string;
- mainIdentifierMapper: (record: any) => {
- name: string;
- avatarUrl?: string;
- avatarType: AvatarType;
- };
+ labelIdentifierFieldPaths: string[];
+ imageIdentifierUrlField: string;
+ imageIdentifierUrlPrefix: string;
+ imageIdentifierFormat: AvatarType;
basePathToShowPage: string;
};
diff --git a/front/src/pages/opportunities/Opportunities.tsx b/front/src/pages/opportunities/Opportunities.tsx
index 251f64efc..54e77c9c1 100644
--- a/front/src/pages/opportunities/Opportunities.tsx
+++ b/front/src/pages/opportunities/Opportunities.tsx
@@ -6,7 +6,7 @@ import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord';
import { PipelineAddButton } from '@/pipeline/components/PipelineAddButton';
-import { usePipelineStages } from '@/pipeline/hooks/usePipelineStages';
+import { usePipelineSteps } from '@/pipeline/hooks/usePipelineSteps';
import { PipelineStep } from '@/pipeline/types/PipelineStep';
import { IconTargetArrow } from '@/ui/display/icon';
import { BoardOptionsContext } from '@/ui/layout/board/contexts/BoardOptionsContext';
@@ -23,8 +23,8 @@ const StyledBoardContainer = styled.div`
`;
export const Opportunities = () => {
- const { handlePipelineStageAdd, handlePipelineStageDelete } =
- usePipelineStages();
+ const { handlePipelineStepAdd, handlePipelineStepDelete } =
+ usePipelineSteps();
const { updateOneObject: updateOnePipelineStep } =
useUpdateOneObjectRecord({
@@ -68,8 +68,8 @@ export const Opportunities = () => {
diff --git a/front/src/pages/opportunities/__stories__/Opportunities.stories.tsx b/front/src/pages/opportunities/__stories__/Opportunities.stories.tsx
index 3e078ac67..d4342ca54 100644
--- a/front/src/pages/opportunities/__stories__/Opportunities.stories.tsx
+++ b/front/src/pages/opportunities/__stories__/Opportunities.stories.tsx
@@ -43,17 +43,17 @@ export const AddCompanyFromHeader: Story = {
});
await step('Change pipeline stage', async () => {
- const pipelineStageDropdownHeader = await canvas.findByRole(
+ const pipelineStepDropdownHeader = await canvas.findByRole(
'listitem',
{ name: (_, element) => !!element?.textContent?.includes('New') },
{ timeout: 1000 },
);
- const pipelineStageDropdownUnfoldButton = within(
- pipelineStageDropdownHeader,
+ const pipelineStepDropdownUnfoldButton = within(
+ pipelineStepDropdownHeader,
).getByRole('button');
- await userEvent.click(pipelineStageDropdownUnfoldButton);
+ await userEvent.click(pipelineStepDropdownUnfoldButton);
const menuItem1 = await canvas.findByRole(
'listitem',