Display RecordBoardCards on new board (#3657)

* Before remove saveEditModeValue logic

* Fixes

* Fix tests

* Fix tests
This commit is contained in:
Charles Bochet 2024-01-27 15:55:45 +01:00 committed by GitHub
parent 9053769616
commit d6f117c688
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
64 changed files with 479 additions and 192 deletions

View File

@ -13,7 +13,7 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = (
) => {
const openCreateActivityDrawer = useOpenCreateActivityDrawer();
const { selectedRowIdsSelector } = useRecordTableStates(recordTableId);
const { getSelectedRowIdsSelector } = useRecordTableStates(recordTableId);
return useRecoilCallback(
({ snapshot }) =>
@ -24,7 +24,7 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = (
) => {
const selectedRowIds = getSnapshotValue(
snapshot,
selectedRowIdsSelector,
getSelectedRowIdsSelector(),
);
let activityTargetableEntityArray: ActivityTargetableObject[] =
@ -44,6 +44,6 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = (
targetableObjects: activityTargetableEntityArray,
});
},
[openCreateActivityDrawer, selectedRowIdsSelector],
[openCreateActivityDrawer, getSelectedRowIdsSelector],
);
};

View File

@ -1,12 +1,12 @@
import React from 'react';
import styled from '@emotion/styled';
import { useRecoilState } from 'recoil';
import { useSetRecoilState } from 'recoil';
import { ActivityEditor } from '@/activities/components/ActivityEditor';
import { Activity } from '@/activities/types/Activity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
const StyledContainer = styled.div`
box-sizing: border-box;
@ -29,9 +29,7 @@ export const RightDrawerActivity = ({
showComment = true,
autoFillTitle = false,
}: RightDrawerActivityProps) => {
const [, setEntityFields] = useRecoilState(
entityFieldsFamilyState(activityId),
);
const setEntityFields = useSetRecoilState(recordStoreFamilyState(activityId));
const { record: activity } = useFindOneRecord({
objectNameSingular: CoreObjectNameSingular.Activity,

View File

@ -5,7 +5,7 @@ import { RecoilRoot, useSetRecoilState } from 'recoil';
import { phoneFieldDefinition } from '@/object-record/field/__mocks__/fieldDefinitions';
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
import { useIsFieldEmpty } from '@/object-record/field/hooks/useIsFieldEmpty';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
const entityId = 'entityId';
@ -27,7 +27,7 @@ describe('useIsFieldEmpty', () => {
const { result } = renderHook(
() => {
const setFieldState = useSetRecoilState(
entityFieldsFamilyState(entityId),
recordStoreFamilyState(entityId),
);
return {
setFieldState,

View File

@ -15,10 +15,10 @@ import {
RecordUpdateHookParams,
} from '@/object-record/field/contexts/FieldContext';
import { usePersistField } from '@/object-record/field/hooks/usePersistField';
import { entityFieldsFamilySelector } from '@/object-record/field/states/selectors/entityFieldsFamilySelector';
import { FieldDefinition } from '@/object-record/field/types/FieldDefinition';
import { FieldMetadata } from '@/object-record/field/types/FieldMetadata';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
jest.mock('@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery', () => ({
useMapFieldMetadataToGraphQLQuery: () => () => '\n',
@ -113,7 +113,7 @@ describe('usePersistField', () => {
const { result } = renderHook(
() => {
const entityFields = useRecoilValue(
entityFieldsFamilySelector({ entityId, fieldName }),
recordStoreFamilySelector({ recordId: entityId, fieldName }),
);
return {
@ -137,7 +137,7 @@ describe('usePersistField', () => {
const { result } = renderHook(
() => {
const entityFields = useRecoilValue(
entityFieldsFamilySelector({ entityId, fieldName }),
recordStoreFamilySelector({ recordId: entityId, fieldName }),
);
return {

View File

@ -1,21 +1,22 @@
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { isFieldValueEmpty } from '@/object-record/field/utils/isFieldValueEmpty';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../contexts/FieldContext';
import { isEntityFieldEmptyFamilySelector } from '../states/selectors/isEntityFieldEmptyFamilySelector';
export const useIsFieldEmpty = () => {
const { entityId, fieldDefinition } = useContext(FieldContext);
const isFieldEmpty = useRecoilValue(
isEntityFieldEmptyFamilySelector({
fieldDefinition: {
type: fieldDefinition.type,
},
const fieldValue = useRecoilValue(
recordStoreFamilySelector({
fieldName: fieldDefinition.metadata.fieldName,
entityId,
recordId: entityId,
}),
);
return isFieldEmpty;
return isFieldValueEmpty({
fieldDefinition,
fieldValue,
});
};

View File

@ -5,9 +5,9 @@ import { isFieldFullName } from '@/object-record/field/types/guards/isFieldFullN
import { isFieldFullNameValue } from '@/object-record/field/types/guards/isFieldFullNameValue';
import { isFieldSelect } from '@/object-record/field/types/guards/isFieldSelect';
import { isFieldSelectValue } from '@/object-record/field/types/guards/isFieldSelectValue';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../contexts/FieldContext';
import { entityFieldsFamilySelector } from '../states/selectors/entityFieldsFamilySelector';
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
import { isFieldBooleanValue } from '../types/guards/isFieldBooleanValue';
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
@ -86,7 +86,7 @@ export const usePersistField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
set(
entityFieldsFamilySelector({ entityId, fieldName }),
recordStoreFamilySelector({ recordId: entityId, fieldName }),
valueToPersist,
);
@ -114,7 +114,7 @@ export const usePersistField = () => {
) {
const fieldName = fieldDefinition.metadata.fieldName;
set(
entityFieldsFamilySelector({ entityId, fieldName }),
recordStoreFamilySelector({ recordId: entityId, fieldName }),
valueToPersist,
);

View File

@ -1,8 +1,9 @@
import { useContext } from 'react';
import { useRecoilCallback } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../contexts/FieldContext';
import { entityFieldsFamilySelector } from '../states/selectors/entityFieldsFamilySelector';
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
export const useToggleEditOnlyInput = () => {
@ -22,11 +23,13 @@ export const useToggleEditOnlyInput = () => {
if (fieldIsBoolean) {
const fieldName = fieldDefinition.metadata.fieldName;
const oldValue = snapshot
.getLoadable(entityFieldsFamilySelector({ entityId, fieldName }))
.valueOrThrow();
.getLoadable(
recordStoreFamilySelector({ recordId: entityId, fieldName }),
)
.getValue();
const valueToPersist = !oldValue;
set(
entityFieldsFamilySelector({ entityId, fieldName }),
recordStoreFamilySelector({ recordId: entityId, fieldName }),
valueToPersist,
);

View File

@ -4,13 +4,13 @@ import { Meta, StoryObj } from '@storybook/react';
import { useSetRecoilState } from 'recoil';
import { ChipFieldDisplay } from '@/object-record/field/meta-types/display/components/ChipFieldDisplay';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { FieldContext } from '../../../../contexts/FieldContext';
const ChipFieldValueSetterEffect = () => {
const setEntityFields = useSetRecoilState(entityFieldsFamilyState('123'));
const setEntityFields = useSetRecoilState(recordStoreFamilyState('123'));
useEffect(() => {
setEntityFields({

View File

@ -1,8 +1,9 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../../contexts/FieldContext';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldBoolean } from '../../types/guards/isFieldBoolean';
@ -14,8 +15,8 @@ export const useBooleanField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<boolean>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -1,10 +1,10 @@
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { isFieldFullName } from '@/object-record/field/types/guards/isFieldFullName';
import { isFieldNumber } from '@/object-record/field/types/guards/isFieldNumber';
import { isFieldText } from '@/object-record/field/types/guards/isFieldText';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { FieldContext } from '../../contexts/FieldContext';
@ -18,7 +18,7 @@ export const useChipField = () => {
? fieldDefinition.metadata.objectMetadataNameSingular
: undefined;
const record = useRecoilValue(entityFieldsFamilyState(entityId));
const record = useRecoilValue(recordStoreFamilyState(entityId));
return {
objectNameSingular,

View File

@ -3,6 +3,7 @@ import { useRecoilState } from 'recoil';
import { CurrencyCode } from '@/object-record/field/types/CurrencyCode';
import { FieldInitialValue } from '@/object-record/field/types/FieldInitialValue';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { canBeCastAsIntegerOrNull } from '~/utils/cast-as-integer-or-null';
import {
convertCurrencyMicrosToCurrency,
@ -12,7 +13,6 @@ import {
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { usePersistField } from '../../hooks/usePersistField';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { FieldCurrencyValue } from '../../types/FieldMetadata';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldCurrency } from '../../types/guards/isFieldCurrency';
@ -50,8 +50,8 @@ export const useCurrencyField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<FieldCurrencyValue>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -1,8 +1,9 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../../contexts/FieldContext';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldDateTime } from '../../types/guards/isFieldDateTime';
@ -15,8 +16,8 @@ export const useDateTimeField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<string>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -1,9 +1,10 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldEmail } from '../../types/guards/isFieldEmail';
@ -15,8 +16,8 @@ export const useEmailField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<string>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -1,10 +1,11 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { usePersistField } from '../../hooks/usePersistField';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { FieldFullNameValue } from '../../types/FieldMetadata';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldFullName } from '../../types/guards/isFieldFullName';
@ -18,8 +19,8 @@ export const useFullNameField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<FieldFullNameValue>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -1,10 +1,11 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { usePersistField } from '../../hooks/usePersistField';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { FieldLinkValue } from '../../types/FieldMetadata';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldLink } from '../../types/guards/isFieldLink';
@ -18,8 +19,8 @@ export const useLinkField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<FieldLinkValue>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -1,6 +1,7 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import {
canBeCastAsIntegerOrNull,
castAsIntegerOrNull,
@ -9,7 +10,6 @@ import {
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { usePersistField } from '../../hooks/usePersistField';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldNumber } from '../../types/guards/isFieldNumber';
@ -21,8 +21,8 @@ export const useNumberField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<number | null>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -2,10 +2,11 @@ import { useContext } from 'react';
import { isPossiblePhoneNumber } from 'libphonenumber-js';
import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { usePersistField } from '../../hooks/usePersistField';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldPhone } from '../../types/guards/isFieldPhone';
@ -18,8 +19,8 @@ export const usePhoneField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<string>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -1,10 +1,10 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { FieldContext } from '../../contexts/FieldContext';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { FieldRatingValue } from '../../types/FieldMetadata';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldRating } from '../../types/guards/isFieldRating';
@ -17,8 +17,8 @@ export const useRatingField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<FieldRatingValue | null>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -2,10 +2,10 @@ import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { useGetButtonIcon } from '@/object-record/field/hooks/useGetButtonIcon';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldRelation } from '../../types/guards/isFieldRelation';
@ -18,7 +18,7 @@ export const useRelationField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<any | null>(
entityFieldsFamilySelector({ entityId, fieldName }),
recordStoreFamilySelector({ recordId: entityId, fieldName }),
);
const fieldInitialValue = useFieldInitialValue();

View File

@ -2,11 +2,11 @@ import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { usePersistField } from '@/object-record/field/hooks/usePersistField';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldMetadataType } from '~/generated/graphql';
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { FieldSelectValue } from '../../types/FieldMetadata';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldSelect } from '../../types/guards/isFieldSelect';
@ -20,8 +20,8 @@ export const useSelectField = () => {
const { fieldName } = fieldDefinition.metadata;
const [fieldValue, setFieldValue] = useRecoilState<FieldSelectValue>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -1,9 +1,10 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldText } from '../../types/guards/isFieldText';
import { isFieldTextValue } from '../../types/guards/isFieldTextValue';
@ -17,8 +18,8 @@ export const useTextField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<string>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -2,10 +2,10 @@ import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { isFieldUuid } from '@/object-record/field/types/guards/isFieldUuid';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldTextValue } from '../../types/guards/isFieldTextValue';
@ -17,8 +17,8 @@ export const useUuidField = () => {
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<string>(
entityFieldsFamilySelector({
entityId: entityId,
recordStoreFamilySelector({
recordId: entityId,
fieldName: fieldName,
}),
);

View File

@ -3,7 +3,7 @@ import { Meta, StoryObj } from '@storybook/react';
import { expect, fn, userEvent, within } from '@storybook/test';
import { useSetRecoilState } from 'recoil';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { FieldContextProvider } from '../../../__stories__/FieldContextProvider';
import {
@ -18,7 +18,7 @@ const BooleanFieldValueSetterEffect = ({
value: boolean;
entityId: string;
}) => {
const setField = useSetRecoilState(entityFieldsFamilyState(entityId));
const setField = useSetRecoilState(recordStoreFamilyState(entityId));
useEffect(() => {
setField({ id: entityId, Boolean: value });

View File

@ -1,8 +0,0 @@
import { atomFamily } from 'recoil';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
export const entityFieldsFamilyState = atomFamily<ObjectRecord | null, string>({
key: 'entityFieldsFamilyState',
default: null,
});

View File

@ -1,17 +0,0 @@
import { selectorFamily } from 'recoil';
import { entityFieldsFamilyState } from '../entityFieldsFamilyState';
export const entityFieldsFamilySelector = selectorFamily({
key: 'entityFieldsFamilySelector',
get:
<T>({ fieldName, entityId }: { fieldName: string; entityId: string }) =>
({ get }) =>
get(entityFieldsFamilyState(entityId))?.[fieldName] as T,
set:
<T>({ fieldName, entityId }: { fieldName: string; entityId: string }) =>
({ set }, newValue: T) =>
set(entityFieldsFamilyState(entityId), (prevState) =>
prevState ? { ...prevState, [fieldName]: newValue } : null,
),
});

View File

@ -1,7 +1,7 @@
import { selectorFamily } from 'recoil';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { isFieldValueEmpty } from '@/object-record/field/utils/isFieldValueEmpty';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { FieldDefinition } from '../../types/FieldDefinition';
import { FieldMetadata } from '../../types/FieldMetadata';
@ -18,7 +18,7 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
entityId: string;
}) => {
return ({ get }) => {
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
const fieldValue = get(recordStoreFamilyState(entityId))?.[fieldName];
return isFieldValueEmpty({
fieldDefinition,

View File

@ -5,9 +5,9 @@ import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil';
import { useOpenCreateActivityDrawerForSelectedRowIds } from '@/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords';
import { useExecuteQuickActionOnOneRecord } from '@/object-record/hooks/useExecuteQuickActionOnOneRecord';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import {
@ -38,9 +38,11 @@ export const useRecordTableContextMenuEntries = (
const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState);
const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState);
const { selectedRowIdsSelector } = useRecordTableStates(props?.recordTableId);
const { getSelectedRowIdsSelector } = useRecordTableStates(
props?.recordTableId,
);
const selectedRowIds = useRecoilValue(selectedRowIdsSelector);
const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector());
const { resetTableRowSelection } = useRecordTable({
recordTableId: props?.recordTableId,
@ -53,12 +55,15 @@ export const useRecordTableContextMenuEntries = (
const { createFavorite, favorites, deleteFavorite } = useFavorites();
const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => {
const selectedRowIds = getSnapshotValue(snapshot, selectedRowIdsSelector);
const selectedRowIds = getSnapshotValue(
snapshot,
getSelectedRowIdsSelector(),
);
const selectedRowId = selectedRowIds.length === 1 ? selectedRowIds[0] : '';
const selectedRecord = snapshot
.getLoadable(entityFieldsFamilyState(selectedRowId))
.getLoadable(recordStoreFamilyState(selectedRowId))
.getValue();
const foundFavorite = favorites?.find(
@ -89,13 +94,13 @@ export const useRecordTableContextMenuEntries = (
async () => {
const rowIdsToDelete = getSnapshotValue(
snapshot,
selectedRowIdsSelector,
getSelectedRowIdsSelector(),
);
resetTableRowSelection();
await deleteManyRecords(rowIdsToDelete);
},
[deleteManyRecords, resetTableRowSelection, selectedRowIdsSelector],
[deleteManyRecords, resetTableRowSelection, getSelectedRowIdsSelector],
);
const handleExecuteQuickActionOnClick = useRecoilCallback(
@ -103,7 +108,7 @@ export const useRecordTableContextMenuEntries = (
async () => {
const rowIdsToExecuteQuickActionOn = getSnapshotValue(
snapshot,
selectedRowIdsSelector,
getSelectedRowIdsSelector(),
);
resetTableRowSelection();
@ -116,7 +121,7 @@ export const useRecordTableContextMenuEntries = (
[
executeQuickActionOnOneRecord,
resetTableRowSelection,
selectedRowIdsSelector,
getSelectedRowIdsSelector,
],
);

View File

@ -1,6 +1,6 @@
import { useRecoilCallback } from 'recoil';
import { entityFieldsFamilySelector } from '@/object-record/field/states/selectors/entityFieldsFamilySelector';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
export const useUpsertRecordFieldFromState = () =>
@ -14,7 +14,7 @@ export const useUpsertRecordFieldFromState = () =>
fieldName: F extends string ? F : never;
}) =>
set(
entityFieldsFamilySelector({ entityId: record.id, fieldName }),
recordStoreFamilySelector({ recordId: record.id, fieldName }),
(previousField) =>
isDeeplyEqual(previousField, record[fieldName])
? previousField

View File

@ -1,6 +1,6 @@
import { useRecoilCallback } from 'recoil';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
// TODO: refactor with scoped state later
@ -8,7 +8,7 @@ export const useUpsertRecordFromState = () =>
useRecoilCallback(
({ set }) =>
<T extends { id: string }>(record: T) =>
set(entityFieldsFamilyState(record.id), (previousRecord) =>
set(recordStoreFamilyState(record.id), (previousRecord) =>
isDeeplyEqual(previousRecord, record) ? previousRecord : record,
),
[],

View File

@ -1,9 +1,9 @@
import { useRecoilCallback } from 'recoil';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { useRecordBoardDeprecatedScopedStates } from '@/object-record/record-board-deprecated/hooks/internal/useRecordBoardDeprecatedScopedStates';
import { recordBoardCardIdsByColumnIdFamilyState } from '@/object-record/record-board-deprecated/states/recordBoardCardIdsByColumnIdFamilyState';
import { BoardColumnDefinition } from '@/object-record/record-board-deprecated/types/BoardColumnDefinition';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { currentPipelineStepsState } from '@/pipeline/states/currentPipelineStepsState';
import { Opportunity } from '@/pipeline/types/Opportunity';
import { PipelineStep } from '@/pipeline/types/PipelineStep';
@ -72,7 +72,7 @@ export const useUpdateCompanyBoardColumnsInternal = () => {
if (!isDeeplyEqual(currentCompanyProgress, companyProgress)) {
set(companyProgressesFamilyState(id), companyProgress);
set(entityFieldsFamilyState(id), companyProgress.opportunity);
set(recordStoreFamilyState(id), companyProgress.opportunity);
}
}

View File

@ -1,16 +1,20 @@
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
import { isFirstRecordBoardColumnFamilyStateScopeMap } from '@/object-record/record-board/states/isFirstRecordBoardColumnFamilyStateScopeMap';
import { isLastRecordBoardColumnFamilyStateScopeMap } from '@/object-record/record-board/states/isLastRecordBoardColumnFamilyStateScopeMap';
import { isRecordBoardCardSelectedFamilyStateScopeMap } from '@/object-record/record-board/states/isRecordBoardCardSelectedFamilyStateScopeMap';
import { isRecordBoardCompactModeActiveStateScopeMap } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveStateScopeMap';
import { recordBoardColumnIdsStateScopeMap } from '@/object-record/record-board/states/recordBoardColumnIdsStateScopeMap';
import { recordBoardFieldDefinitionsStateScopeMap } from '@/object-record/record-board/states/recordBoardFieldDefinitionsStateScopeMap';
import { recordBoardFiltersStateScopeMap } from '@/object-record/record-board/states/recordBoardFiltersStateScopeMap';
import { recordBoardObjectMetadataSingularNameStateScopeMap } from '@/object-record/record-board/states/recordBoardObjectMetadataSingularNameStateScopeMap';
import { recordBoardObjectSingularNameStateScopeMap } from '@/object-record/record-board/states/recordBoardObjectSingularNameStateScopeMap';
import { recordBoardRecordIdsByColumnIdFamilyStateScopeMap } from '@/object-record/record-board/states/recordBoardRecordIdsByColumnIdFamilyStateScopeMap';
import { recordBoardSortsStateScopeMap } from '@/object-record/record-board/states/recordBoardSortsStateScopeMap';
import { recordBoardColumnsFamilySelectorScopeMap } from '@/object-record/record-board/states/selectors/recordBoardColumnsFamilySelectorScopeMap';
import { recordBoardVisibleFieldDefinitionsScopedSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsScopedSelector';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { getFamilyState } from '@/ui/utilities/recoil-scope/utils/getFamilyState';
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
import { getSelector } from '@/ui/utilities/recoil-scope/utils/getSelector';
import { getState } from '@/ui/utilities/recoil-scope/utils/getState';
export const useRecordBoardStates = (recordBoardId?: string) => {
@ -21,8 +25,8 @@ export const useRecordBoardStates = (recordBoardId?: string) => {
return {
scopeId,
getObjectMetadataSingularNameState: getState(
recordBoardObjectMetadataSingularNameStateScopeMap,
getObjectSingularNameState: getState(
recordBoardObjectSingularNameStateScopeMap,
scopeId,
),
getColumnIdsState: getState(recordBoardColumnIdsStateScopeMap, scopeId),
@ -45,10 +49,23 @@ export const useRecordBoardStates = (recordBoardId?: string) => {
recordBoardFieldDefinitionsStateScopeMap,
scopeId,
),
getVisibleFieldDefinitionsState: getSelector(
recordBoardVisibleFieldDefinitionsScopedSelector,
scopeId,
),
recordBoardRecordIdsByColumnIdFamilyState: getFamilyState(
recordBoardRecordIdsByColumnIdFamilyStateScopeMap,
scopeId,
),
isRecordBoardCardSelectedFamilyState: getFamilyState(
isRecordBoardCardSelectedFamilyStateScopeMap,
scopeId,
),
getIsCompactModeActiveState: getState(
isRecordBoardCompactModeActiveStateScopeMap,
scopeId,
),
};
};

View File

@ -5,17 +5,19 @@ import { useSetRecordBoardColumns } from '@/object-record/record-board/hooks/int
import { useSetRecordBoardRecordIds } from '@/object-record/record-board/hooks/internal/useSetRecordBoardRecordIds';
export const useRecordBoard = (recordBoardId?: string) => {
const { scopeId, getFieldDefinitionsState } =
const { scopeId, getFieldDefinitionsState, getObjectSingularNameState } =
useRecordBoardStates(recordBoardId);
const { setColumns } = useSetRecordBoardColumns(recordBoardId);
const { setRecordIds } = useSetRecordBoardRecordIds(recordBoardId);
const setFieldDefinitions = useSetRecoilState(getFieldDefinitionsState());
const setObjectSingularName = useSetRecoilState(getObjectSingularNameState());
return {
scopeId,
setColumns,
setRecordIds,
setFieldDefinitions,
setObjectSingularName,
};
};

View File

@ -0,0 +1,226 @@
import { ReactNode, useContext, useState } from 'react';
import styled from '@emotion/styled';
import { useRecoilState, useRecoilValue } from 'recoil';
import { RecordChip } from '@/object-record/components/RecordChip';
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell';
import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { IconEye } from '@/ui/display/icon/index';
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
import { Checkbox, CheckboxVariant } from '@/ui/input/components/Checkbox';
import { AnimatedEaseInOut } from '@/ui/utilities/animation/components/AnimatedEaseInOut';
const StyledBoardCard = styled.div<{ selected: boolean }>`
background-color: ${({ theme, selected }) =>
selected ? theme.accent.quaternary : theme.background.secondary};
border: 1px solid
${({ theme, selected }) =>
selected ? theme.accent.secondary : theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
box-shadow: ${({ theme }) => theme.boxShadow.light};
color: ${({ theme }) => theme.font.color.primary};
&:hover {
background-color: ${({ theme, selected }) =>
selected && theme.accent.tertiary};
border: 1px solid
${({ theme, selected }) =>
selected ? theme.accent.primary : theme.border.color.medium};
}
cursor: pointer;
.checkbox-container {
transition: all ease-in-out 160ms;
opacity: ${({ selected }) => (selected ? 1 : 0)};
}
&:hover .checkbox-container {
opacity: 1;
}
.compact-icon-container {
transition: all ease-in-out 160ms;
opacity: 0;
}
&:hover .compact-icon-container {
opacity: 1;
}
`;
const StyledBoardCardWrapper = styled.div`
padding-bottom: ${({ theme }) => theme.spacing(2)};
width: 100%;
`;
const StyledBoardCardHeader = styled.div<{
showCompactView: boolean;
}>`
align-items: center;
display: flex;
flex-direction: row;
font-weight: ${({ theme }) => theme.font.weight.medium};
height: 24px;
padding-bottom: ${({ theme, showCompactView }) =>
theme.spacing(showCompactView ? 0 : 1)};
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(2)};
padding-top: ${({ theme }) => theme.spacing(2)};
transition: padding ease-in-out 160ms;
img {
height: ${({ theme }) => theme.icon.size.md}px;
margin-right: ${({ theme }) => theme.spacing(2)};
object-fit: cover;
width: ${({ theme }) => theme.icon.size.md}px;
}
`;
const StyledBoardCardBody = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(0.5)};
padding-bottom: ${({ theme }) => theme.spacing(2)};
padding-left: ${({ theme }) => theme.spacing(2.5)};
padding-right: ${({ theme }) => theme.spacing(2)};
span {
align-items: center;
display: flex;
flex-direction: row;
svg {
color: ${({ theme }) => theme.font.color.tertiary};
margin-right: ${({ theme }) => theme.spacing(2)};
}
}
`;
const StyledCheckboxContainer = styled.div`
display: flex;
flex: 1;
justify-content: end;
`;
const StyledFieldContainer = styled.div`
display: flex;
flex-direction: row;
width: 100%;
`;
const StyledCompactIconContainer = styled.div`
align-items: center;
display: flex;
justify-content: center;
`;
export const RecordBoardCard = () => {
const { recordId } = useContext(RecordBoardCardContext);
const {
getObjectSingularNameState,
getIsCompactModeActiveState,
isRecordBoardCardSelectedFamilyState,
getVisibleFieldDefinitionsState,
} = useRecordBoardStates();
const isCompactModeActive = useRecoilValue(getIsCompactModeActiveState());
const objectNameSingular = useRecoilValue(getObjectSingularNameState());
const [isCardInCompactMode, setIsCardInCompactMode] =
useState(isCompactModeActive);
const [isCurrentCardSelected, setIsCurrentCardSelected] = useRecoilState(
isRecordBoardCardSelectedFamilyState(recordId),
);
const visibleBoardCardFieldDefinitions = useRecoilValue(
getVisibleFieldDefinitionsState(),
);
const record = useRecoilValue(recordStoreFamilyState(recordId));
const PreventSelectOnClickContainer = ({
children,
}: {
children: ReactNode;
}) => (
<StyledFieldContainer
onClick={(e) => {
e.stopPropagation();
}}
>
{children}
</StyledFieldContainer>
);
const onMouseLeaveBoard = () => {
if (isCompactModeActive) {
setIsCardInCompactMode(true);
}
};
if (!objectNameSingular || !record) {
return null;
}
return (
<StyledBoardCardWrapper>
<StyledBoardCard
selected={isCurrentCardSelected}
onMouseLeave={onMouseLeaveBoard}
onClick={() => setIsCurrentCardSelected(!isCurrentCardSelected)}
>
<StyledBoardCardHeader showCompactView={isCompactModeActive}>
<RecordChip objectNameSingular={objectNameSingular} record={record} />
{isCompactModeActive && (
<StyledCompactIconContainer className="compact-icon-container">
<LightIconButton
Icon={IconEye}
accent="tertiary"
onClick={(e) => {
e.stopPropagation();
setIsCardInCompactMode(false);
}}
/>
</StyledCompactIconContainer>
)}
<StyledCheckboxContainer className="checkbox-container">
<Checkbox
checked={isCurrentCardSelected}
onChange={() => setIsCurrentCardSelected(!isCurrentCardSelected)}
variant={CheckboxVariant.Secondary}
/>
</StyledCheckboxContainer>
</StyledBoardCardHeader>
<StyledBoardCardBody>
<AnimatedEaseInOut isOpen={!isCardInCompactMode} initial={false}>
{visibleBoardCardFieldDefinitions.map((fieldDefinition) => (
<PreventSelectOnClickContainer
key={fieldDefinition.fieldMetadataId}
>
<FieldContext.Provider
value={{
entityId: recordId,
maxWidth: 156,
recoilScopeId: recordId + fieldDefinition.fieldMetadataId,
isLabelIdentifier: false,
fieldDefinition: {
fieldMetadataId: fieldDefinition.fieldMetadataId,
label: fieldDefinition.label,
iconName: fieldDefinition.iconName,
type: fieldDefinition.type,
metadata: fieldDefinition.metadata,
},
hotkeyScope: InlineCellHotkeyScope.InlineCell,
}}
>
<RecordInlineCell />
</FieldContext.Provider>
</PreventSelectOnClickContainer>
))}
</AnimatedEaseInOut>
</StyledBoardCardBody>
</StyledBoardCard>
</StyledBoardCardWrapper>
);
};

View File

@ -0,0 +1,8 @@
import { createContext } from 'react';
type RecordBoardCardContextProps = {
recordId: string;
};
export const RecordBoardCardContext =
createContext<RecordBoardCardContextProps>({} as RecordBoardCardContextProps);

View File

@ -2,11 +2,12 @@ import styled from '@emotion/styled';
import { Droppable } from '@hello-pangea/dnd';
import { useRecoilValue } from 'recoil';
import { RecordBoardColumnContext } from '@/object-record/record-board/contexts/RecordBoardColumnContext';
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
import { RecordBoardCard } from '@/object-record/record-board/record-board-card/components/RecordBoardCard';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { RecordBoardColumnCardsContainer } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer';
import { RecordBoardColumnHeader } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeader';
import { BoardCardIdContext } from '@/object-record/record-board-deprecated/contexts/BoardCardIdContext';
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
const StyledColumn = styled.div<{ isFirstColumn: boolean }>`
background-color: ${({ theme }) => theme.background.primary};
@ -71,9 +72,12 @@ export const RecordBoardColumn = ({
droppableProvided={droppableProvided}
>
{recordIds.map((recordId) => (
<BoardCardIdContext.Provider value={recordId} key={recordId}>
<div>Card</div>
</BoardCardIdContext.Provider>
<RecordBoardCardContext.Provider
value={{ recordId }}
key={recordId}
>
<RecordBoardCard />
</RecordBoardCardContext.Provider>
))}
</RecordBoardColumnCardsContainer>
</StyledColumn>

View File

@ -2,7 +2,7 @@ import { useCallback, useContext, useRef } from 'react';
import styled from '@emotion/styled';
import { MenuItem } from 'tsup.ui.index';
import { RecordBoardColumnContext } from '@/object-record/record-board/contexts/RecordBoardColumnContext';
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';

View File

@ -1,8 +1,8 @@
import React, { useContext, useState } from 'react';
import styled from '@emotion/styled';
import { RecordBoardColumnContext } from '@/object-record/record-board/contexts/RecordBoardColumnContext';
import { RecordBoardColumnDropdownMenu } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnDropdownMenu';
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
import { BoardColumnHotkeyScope } from '@/object-record/record-board-deprecated/types/BoardColumnHotkeyScope';
import { IconDotsVertical } from '@/ui/display/icon';
import { Tag } from '@/ui/display/tag/components/Tag';

View File

@ -0,0 +1,7 @@
import { createFamilyStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createFamilyStateScopeMap';
export const isRecordBoardCardSelectedFamilyStateScopeMap =
createFamilyStateScopeMap<boolean, string>({
key: 'isRecordBoardCardSelectedFamilyStateScopeMap',
defaultValue: false,
});

View File

@ -0,0 +1,7 @@
import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap';
export const isRecordBoardCompactModeActiveStateScopeMap =
createStateScopeMap<boolean>({
key: 'isRecordBoardCompactModeActiveStateScopeMap',
defaultValue: false,
});

View File

@ -1,7 +0,0 @@
import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap';
export const recordBoardObjectMetadataSingularNameStateScopeMap =
createStateScopeMap<string | undefined>({
key: 'recordBoardObjectMetadataSingularNameStateScopeMap',
defaultValue: undefined,
});

View File

@ -0,0 +1,8 @@
import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap';
export const recordBoardObjectSingularNameStateScopeMap = createStateScopeMap<
string | undefined
>({
key: 'recordBoardObjectSingularNameStateScopeMap',
defaultValue: undefined,
});

View File

@ -0,0 +1,13 @@
import { recordBoardFieldDefinitionsStateScopeMap } from '@/object-record/record-board/states/recordBoardFieldDefinitionsStateScopeMap';
import { createSelectorScopeMap } from '@/ui/utilities/recoil-scope/utils/createSelectorScopeMap';
export const recordBoardVisibleFieldDefinitionsScopedSelector =
createSelectorScopeMap({
key: 'recordBoardVisibleFieldDefinitionsScopedSelector',
get:
({ scopeId }) =>
({ get }) =>
get(recordBoardFieldDefinitionsStateScopeMap({ scopeId }))
.filter((field) => field.isVisible)
.sort((a, b) => a.position - b.position),
});

View File

@ -28,7 +28,11 @@ export const RecordIndexBoardContainerEffect = ({
navigate(`/settings/objects/${objectMetadataItem.namePlural}`);
}, [navigate, objectMetadataItem.namePlural]);
const { setColumns } = useRecordBoard(recordBoardId);
const { setColumns, setObjectSingularName } = useRecordBoard(recordBoardId);
useEffect(() => {
setObjectSingularName(objectNameSingular);
}, [objectNameSingular, setObjectSingularName]);
useEffect(() => {
setColumns(

View File

@ -10,10 +10,10 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { FieldDisplay } from '@/object-record/field/components/FieldDisplay';
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
import { usePersistField } from '@/object-record/field/hooks/usePersistField';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { FieldRelationMetadata } from '@/object-record/field/types/FieldMetadata';
import { useFieldContext } from '@/object-record/hooks/useFieldContext';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { IconDotsVertical, IconUnlink } from '@/ui/display/icon';
import { CardContent } from '@/ui/layout/card/components/CardContent';
@ -100,7 +100,7 @@ export const RecordRelationFieldCardContent = ({
// TODO: temporary as ChipDisplay expect to find the entity in the entityFieldsFamilyState
const setRelationEntityFields = useSetRecoilState(
entityFieldsFamilyState(relationRecord.id),
recordStoreFamilyState(relationRecord.id),
);
useEffect(() => {

View File

@ -10,12 +10,12 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelationType';
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
import { usePersistField } from '@/object-record/field/hooks/usePersistField';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { entityFieldsFamilySelector } from '@/object-record/field/states/selectors/entityFieldsFamilySelector';
import { FieldRelationMetadata } from '@/object-record/field/types/FieldMetadata';
import { useModifyRecordFromCache } from '@/object-record/hooks/useModifyRecordFromCache';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { RecordRelationFieldCardContent } from '@/object-record/record-relation-card/components/RecordRelationFieldCardContent';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { SingleEntitySelectMenuItemsWithSearch } from '@/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch';
import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker';
import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope';
@ -91,7 +91,7 @@ export const RecordRelationFieldCardSection = () => {
relationType,
objectMetadataNameSingular,
} = fieldDefinition.metadata as FieldRelationMetadata;
const record = useRecoilValue(entityFieldsFamilyState(entityId));
const record = useRecoilValue(recordStoreFamilyState(entityId));
const {
labelIdentifierFieldMetadata: relationLabelIdentifierFieldMetadata,
@ -110,7 +110,7 @@ export const RecordRelationFieldCardSection = () => {
const fieldValue = useRecoilValue<
({ id: string } & Record<string, any>) | null
>(entityFieldsFamilySelector({ entityId, fieldName }));
>(recordStoreFamilySelector({ recordId: entityId, fieldName }));
const isToOneObject = relationType === 'TO_ONE_OBJECT';

View File

@ -10,13 +10,13 @@ import {
RecordUpdateHook,
RecordUpdateHookParams,
} from '@/object-record/field/contexts/FieldContext';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell';
import { PropertyBox } from '@/object-record/record-inline-cell/property-box/components/PropertyBox';
import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
import { RecordRelationFieldCardSection } from '@/object-record/record-relation-card/components/RecordRelationFieldCardSection';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { isFieldMetadataItemAvailable } from '@/object-record/utils/isFieldMetadataItemAvailable';
import { ShowPageContainer } from '@/ui/layout/page/ShowPageContainer';
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
@ -48,7 +48,7 @@ export const RecordShowContainer = ({
});
const setEntityFields = useSetRecoilState(
entityFieldsFamilyState(objectRecordId ?? ''),
recordStoreFamilyState(objectRecordId),
);
const { record, loading } = useFindOneRecord({

View File

@ -8,9 +8,9 @@ export const RecordTableActionBar = ({
}: {
recordTableId: string;
}) => {
const { selectedRowIdsSelector } = useRecordTableStates(recordTableId);
const { getSelectedRowIdsSelector } = useRecordTableStates(recordTableId);
const selectedRowIds = useRecoilValue(selectedRowIdsSelector);
const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector());
return <ActionBar selectedIds={selectedRowIds} />;
};

View File

@ -56,17 +56,16 @@ export const RecordTableHeader = ({
}: {
createRecord: () => void;
}) => {
const { hiddenTableColumnsSelector, visibleTableColumnsSelector } =
const { getHiddenTableColumnsSelector, getVisibleTableColumnsSelector } =
useRecordTableStates();
const hiddenTableColumns = useRecoilValue(hiddenTableColumnsSelector);
const scrollWrapper = useScrollWrapperScopedRef();
const isTableWiderThanScreen =
(scrollWrapper.current?.clientWidth ?? 0) <
(scrollWrapper.current?.scrollWidth ?? 0);
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector);
const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector());
const hiddenTableColumns = useRecoilValue(getHiddenTableColumnsSelector());
const theme = useTheme();

View File

@ -83,8 +83,8 @@ export const RecordTableHeaderCell = ({
const {
getResizeFieldOffsetState,
getTableColumnsState,
tableColumnsByKeySelector,
visibleTableColumnsSelector,
getTableColumnsByKeySelector,
getVisibleTableColumnsSelector,
} = useRecordTableStates();
const [resizeFieldOffset, setResizeFieldOffset] = useRecoilState(
@ -92,8 +92,8 @@ export const RecordTableHeaderCell = ({
);
const tableColumns = useRecoilValue(getTableColumnsState());
const tableColumnsByKey = useRecoilValue(tableColumnsByKeySelector);
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector);
const tableColumnsByKey = useRecoilValue(getTableColumnsByKeySelector());
const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector());
const [initialPointerPositionX, setInitialPointerPositionX] = useState<
number | null

View File

@ -18,9 +18,9 @@ import { ColumnDefinition } from '../types/ColumnDefinition';
export const RecordTableHeaderPlusButtonContent = () => {
const { closeDropdown } = useDropdown();
const { hiddenTableColumnsSelector } = useRecordTableStates();
const { getHiddenTableColumnsSelector } = useRecordTableStates();
const hiddenTableColumns = useRecoilValue(hiddenTableColumnsSelector);
const hiddenTableColumns = useRecoilValue(getHiddenTableColumnsSelector());
const { getIcon } = useIcons();
const { handleColumnVisibilityChange } = useTableColumns();

View File

@ -26,9 +26,9 @@ const StyledPlaceholder = styled.td`
`;
export const RecordTableRow = ({ rowId }: RecordTableRowProps) => {
const { visibleTableColumnsSelector } = useRecordTableStates();
const { getVisibleTableColumnsSelector } = useRecordTableStates();
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector);
const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector());
const { currentRowSelected } = useCurrentRowSelected();

View File

@ -16,9 +16,11 @@ const StyledContainer = styled.div`
`;
export const SelectAllCheckbox = () => {
const { allRowsSelectedStatusSelector } = useRecordTableStates();
const { getAllRowsSelectedStatusSelector } = useRecordTableStates();
const allRowsSelectedStatus = useRecoilValue(allRowsSelectedStatusSelector);
const allRowsSelectedStatus = useRecoilValue(
getAllRowsSelectedStatusSelector(),
);
const { selectAllRows } = useRecordTable();
const checked = allRowsSelectedStatus === 'all';

View File

@ -8,9 +8,9 @@ export const RecordTableContextMenu = ({
}: {
recordTableId: string;
}) => {
const { selectedRowIdsSelector } = useRecordTableStates(recordTableId);
const { getSelectedRowIdsSelector } = useRecordTableStates(recordTableId);
const selectedRowIds = useRecoilValue(selectedRowIdsSelector);
const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector());
return <ContextMenu selectedIds={selectedRowIds} />;
};

View File

@ -94,27 +94,27 @@ export const useRecordTableStates = (recordTableId?: string) => {
isRowSelectedFamilyStateScopeMap,
scopeId,
),
allRowsSelectedStatusSelector: getSelector(
getAllRowsSelectedStatusSelector: getSelector(
allRowsSelectedStatusSelectorScopeMap,
scopeId,
),
hiddenTableColumnsSelector: getSelector(
getHiddenTableColumnsSelector: getSelector(
hiddenTableColumnsSelectorScopeMap,
scopeId,
),
numberOfTableColumnsSelector: getSelector(
getNumberOfTableColumnsSelector: getSelector(
numberOfTableColumnsSelectorScopeMap,
scopeId,
),
selectedRowIdsSelector: getSelector(
getSelectedRowIdsSelector: getSelector(
selectedRowIdsSelectorScopeMap,
scopeId,
),
tableColumnsByKeySelector: getSelector(
getTableColumnsByKeySelector: getSelector(
tableColumnsByKeySelectorScopeMap,
scopeId,
),
visibleTableColumnsSelector: getSelector(
getVisibleTableColumnsSelector: getSelector(
visibleTableColumnsSelectorScopeMap,
scopeId,
),

View File

@ -5,7 +5,7 @@ import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotV
export const useSelectAllRows = (recordTableId?: string) => {
const {
allRowsSelectedStatusSelector,
getAllRowsSelectedStatusSelector,
getTableRowIdsState,
isRowSelectedFamilyState,
} = useRecordTableStates(recordTableId);
@ -15,7 +15,7 @@ export const useSelectAllRows = (recordTableId?: string) => {
() => {
const allRowsSelectedStatus = getSnapshotValue(
snapshot,
allRowsSelectedStatusSelector,
getAllRowsSelectedStatusSelector(),
);
const tableRowIds = getSnapshotValue(snapshot, getTableRowIdsState());
@ -34,7 +34,7 @@ export const useSelectAllRows = (recordTableId?: string) => {
}
},
[
allRowsSelectedStatusSelector,
getAllRowsSelectedStatusSelector,
getTableRowIdsState,
isRowSelectedFamilyState,
],

View File

@ -1,6 +1,6 @@
import { useRecoilCallback } from 'recoil';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
@ -23,11 +23,11 @@ export const useSetRecordTableData = ({
for (const entity of newEntityArray) {
// TODO: refactor with scoped state later
const currentEntity = snapshot
.getLoadable(entityFieldsFamilyState(entity.id))
.getLoadable(recordStoreFamilyState(entity.id))
.valueOrThrow();
if (JSON.stringify(currentEntity) !== JSON.stringify(entity)) {
set(entityFieldsFamilyState(entity.id), entity);
set(recordStoreFamilyState(entity.id), entity);
}
}
const currentRowIds = getSnapshotValue(snapshot, getTableRowIdsState());

View File

@ -40,8 +40,8 @@ export const useRecordTable = (props?: useRecordTableProps) => {
getOnColumnsChangeState,
getIsRecordTableInitialLoadingState,
getTableLastRowVisibleState,
numberOfTableColumnsSelector,
selectedRowIdsSelector,
getNumberOfTableColumnsSelector,
getSelectedRowIdsSelector,
} = useRecordTableStates(recordTableId);
const setAvailableTableColumns = useSetRecoilState(
@ -176,7 +176,7 @@ export const useRecordTable = (props?: useRecordTableProps) => {
const numberOfTableColumns = getSnapshotValue(
snapshot,
numberOfTableColumnsSelector,
getNumberOfTableColumnsSelector(),
);
const numberOfTableRows = getSnapshotValue(
@ -215,7 +215,7 @@ export const useRecordTable = (props?: useRecordTableProps) => {
},
[
getSoftFocusPositionState,
numberOfTableColumnsSelector,
getNumberOfTableColumnsSelector,
getNumberOfTableRowsState,
setSoftFocusPosition,
],
@ -231,7 +231,7 @@ export const useRecordTable = (props?: useRecordTableProps) => {
const numberOfTableColumns = getSnapshotValue(
snapshot,
numberOfTableColumnsSelector,
getNumberOfTableColumnsSelector(),
);
const currentColumnNumber = softFocusPosition.column;
@ -262,8 +262,8 @@ export const useRecordTable = (props?: useRecordTableProps) => {
}
},
[
getNumberOfTableColumnsSelector,
getSoftFocusPositionState,
numberOfTableColumnsSelector,
setSoftFocusPosition,
],
);
@ -352,6 +352,6 @@ export const useRecordTable = (props?: useRecordTableProps) => {
setRecordTableLastRowVisible,
setSoftFocusPosition,
isSomeCellInEditModeState,
selectedRowIdsSelector,
getSelectedRowIdsSelector,
};
};

View File

@ -20,13 +20,13 @@ export const useTableColumns = (props?: useRecordTableProps) => {
const {
getAvailableTableColumnsState,
getTableColumnsState,
visibleTableColumnsSelector,
getVisibleTableColumnsSelector,
} = useRecordTableStates(props?.recordTableId);
const availableTableColumns = useRecoilValue(getAvailableTableColumnsState());
const tableColumns = useRecoilValue(getTableColumnsState());
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector);
const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector());
const { handleColumnMove } = useMoveViewColumns();

View File

@ -42,11 +42,11 @@ export const TableOptionsDropdownContent = ({
const viewEditInputRef = useRef<HTMLInputElement>(null);
const { hiddenTableColumnsSelector, visibleTableColumnsSelector } =
const { getHiddenTableColumnsSelector, getVisibleTableColumnsSelector } =
useRecordTableStates(recordTableId);
const hiddenTableColumns = useRecoilValue(hiddenTableColumnsSelector);
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector);
const hiddenTableColumns = useRecoilValue(getHiddenTableColumnsSelector());
const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector());
const { handleColumnVisibilityChange, handleColumnReorder } = useTableColumns(
{ recordTableId },

View File

@ -1,7 +1,7 @@
import { useEffect } from 'react';
import { useRecoilState } from 'recoil';
import { useSetRecoilState } from 'recoil';
import { entityFieldsFamilySelector } from '@/object-record/field/states/selectors/entityFieldsFamilySelector';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
type SettingsObjectFieldPreviewValueEffectProps = {
entityId: string;
@ -14,9 +14,9 @@ export const SettingsObjectFieldPreviewValueEffect = ({
fieldName,
value,
}: SettingsObjectFieldPreviewValueEffectProps) => {
const [, setFieldValue] = useRecoilState(
entityFieldsFamilySelector({
entityId,
const setFieldValue = useSetRecoilState(
recordStoreFamilySelector({
recordId: entityId,
fieldName,
}),
);

View File

@ -8,5 +8,5 @@ export const getSelector = <StateType>(
) => RecoilValueReadOnly<StateType>,
scopeId: string,
) => {
return stateScopeMap({ scopeId });
return () => stateScopeMap({ scopeId });
};

View File

@ -4,8 +4,8 @@ import { useSetRecoilState } from 'recoil';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { IconBuildingSkyscraper } from '@/ui/display/icon';
import { PageBody } from '@/ui/layout/page/PageBody';
import { PageContainer } from '@/ui/layout/page/PageContainer';
@ -39,7 +39,7 @@ export const RecordShowPage = () => {
const { favorites, createFavorite, deleteFavorite } = useFavorites();
const setEntityFields = useSetRecoilState(
entityFieldsFamilyState(objectRecordId ?? ''),
recordStoreFamilyState(objectRecordId),
);
const { record } = useFindOneRecord({

View File

@ -12,6 +12,12 @@ const getRandomProbability = () => {
const getRandomPipelineStepId = (pipelineStepIds: { id: string }[]) =>
pipelineStepIds[Math.floor(Math.random() * pipelineStepIds.length)].id;
const getRandomStage = () => {
const stages = ['new', 'screening', 'meeting', 'proposal', 'customer'];
return stages[Math.floor(Math.random() * stages.length)];
};
const generateRandomAmountMicros = () => {
const firstDigit = Math.floor(Math.random() * 9) + 1;
@ -31,6 +37,7 @@ const generateOpportunities = (
amountAmountMicros: generateRandomAmountMicros(),
amountCurrencyCode: 'USD',
closeDate: new Date(),
stage: getRandomStage(),
probability: getRandomProbability(),
pipelineStepId: getRandomPipelineStepId(pipelineStepIds),
pointOfContactId: company.personId,
@ -65,6 +72,7 @@ export const seedDemoOpportunity = async (
'amountAmountMicros',
'amountCurrencyCode',
'closeDate',
'stage',
'probability',
'pipelineStepId',
'pointOfContactId',