Skip to content

Commit

Permalink
Fixes Empty Label Identifer Preview in Settings/DataModel/Object/Edit (
Browse files Browse the repository at this point in the history
…twentyhq#6370)

fixes twentyhq#6143

---------

Co-authored-by: Félix Malfait <[email protected]>
  • Loading branch information
Faisal-imtiyaz123 and FelixMalfait authored Aug 8, 2024
1 parent 320742c commit b4e2ada
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ export const SettingsDataModelFieldPreview = ({
return (
<>
{previewRecord ? (
<SettingsDataModelSetRecordEffect record={previewRecord} />
<SettingsDataModelSetRecordEffect
fieldName={fieldName}
record={previewRecord}
/>
) : (
<SettingsDataModelSetFieldValueEffect
recordId={recordId}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { useEffect } from 'react';
import { useSetRecoilState } from 'recoil';

import { useSetRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { previewRecordIdState } from '@/settings/data-model/fields/preview/states/previewRecordIdState';
import { useEffect } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { isDefined } from '~/utils/isDefined';

type SettingsDataModelSetFieldValueEffectProps = {
recordId: string;
Expand All @@ -15,19 +17,43 @@ export const SettingsDataModelSetFieldValueEffect = ({
fieldName,
value,
}: SettingsDataModelSetFieldValueEffectProps) => {
const previewRecordId = useRecoilValue(previewRecordIdState);

const upsertedPreviewRecord = useRecoilValue(
recordStoreFamilyState(previewRecordId ?? ''),
);

const setFieldValue = useSetRecoilState(
recordStoreFamilySelector({
recordId,
fieldName,
}),
);

const setRecordFieldValue = useSetRecordFieldValue();

useEffect(() => {
setFieldValue(value);
setRecordFieldValue(recordId, fieldName, value);
}, [value, setFieldValue, setRecordFieldValue, recordId, fieldName]);
if (
isDefined(upsertedPreviewRecord) &&
!!upsertedPreviewRecord[fieldName]
) {
setFieldValue(upsertedPreviewRecord[fieldName]);
setRecordFieldValue(
recordId,
fieldName,
upsertedPreviewRecord[fieldName],
);
} else {
setFieldValue(value);
setRecordFieldValue(recordId, fieldName, value);
}
}, [
value,
setFieldValue,
setRecordFieldValue,
recordId,
fieldName,
upsertedPreviewRecord,
]);

return null;
};
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
import { useEffect } from 'react';

import { useSetRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { previewRecordIdState } from '@/settings/data-model/fields/preview/states/previewRecordIdState';
import { useEffect } from 'react';
import { useSetRecoilState } from 'recoil';

type SettingsDataModelSetRecordEffectProps = {
record: ObjectRecord;
fieldName: string;
};

export const SettingsDataModelSetRecordEffect = ({
record,
fieldName,
}: SettingsDataModelSetRecordEffectProps) => {
const { upsertRecords: upsertRecordsInStore } = useUpsertRecordsInStore();
const setRecordFieldValue = useSetRecordFieldValue();

const setPreviewRecordId = useSetRecoilState(previewRecordIdState);

useEffect(() => {
upsertRecordsInStore([record]);
}, [record, upsertRecordsInStore]);
setRecordFieldValue(record.id, fieldName, record[fieldName]);
setPreviewRecordId(record.id);
}, [
record,
upsertRecordsInStore,
setRecordFieldValue,
fieldName,
setPreviewRecordId,
]);

return null;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createState } from 'twenty-ui';

export const previewRecordIdState = createState<string | null>({
key: 'previewRecordId',
defaultValue: null,
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import styled from '@emotion/styled';
import { useMemo } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import styled from '@emotion/styled';
import { IconCircleOff, useIcons } from 'twenty-ui';
import { IconCircleOff, isDefined, useIcons } from 'twenty-ui';
import { z } from 'zod';

import { LABEL_IDENTIFIER_FIELD_METADATA_TYPES } from '@/object-metadata/constants/LabelIdentifierFieldMetadataTypes';
Expand All @@ -22,6 +22,7 @@ export type SettingsDataModelObjectIdentifiersFormValues = z.infer<

type SettingsDataModelObjectIdentifiersFormProps = {
objectMetadataItem: ObjectMetadataItem;
defaultLabelIdentifierFieldMetadataId: string;
};

const StyledContainer = styled.div`
Expand All @@ -31,6 +32,7 @@ const StyledContainer = styled.div`

export const SettingsDataModelObjectIdentifiersForm = ({
objectMetadataItem,
defaultLabelIdentifierFieldMetadataId,
}: SettingsDataModelObjectIdentifiersFormProps) => {
const { control } =
useFormContext<SettingsDataModelObjectIdentifiersFormValues>();
Expand Down Expand Up @@ -58,7 +60,6 @@ export const SettingsDataModelObjectIdentifiersForm = ({
label: 'None',
value: null,
};

return (
<StyledContainer>
{[
Expand All @@ -77,7 +78,13 @@ export const SettingsDataModelObjectIdentifiersForm = ({
key={fieldName}
name={fieldName}
control={control}
defaultValue={objectMetadataItem[fieldName]}
defaultValue={
fieldName === 'labelIdentifierFieldMetadataId'
? isDefined(objectMetadataItem[fieldName])
? objectMetadataItem[fieldName]
: defaultLabelIdentifierFieldMetadataId
: objectMetadataItem[fieldName]
}
render={({ field: { onBlur, onChange, value } }) => {
return (
<Select
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styled from '@emotion/styled';
import { useMemo } from 'react';
import { useFormContext } from 'react-hook-form';
import styled from '@emotion/styled';

import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
Expand Down Expand Up @@ -78,6 +78,9 @@ export const SettingsDataModelObjectSettingsFormCard = ({
<CardContent>
<SettingsDataModelObjectIdentifiersForm
objectMetadataItem={objectMetadataItem}
defaultLabelIdentifierFieldMetadataId={
labelIdentifierFieldMetadataItem?.id
}
/>
</CardContent>
</Card>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMemo, useRef, useState } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useMemo, useRef, useState } from 'react';
import { IconChevronDown, IconComponent } from 'twenty-ui';

import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable react/jsx-props-no-spreading */

import { zodResolver } from '@hookform/resolvers/zod';
import pick from 'lodash.pick';
import { useEffect } from 'react';
Expand Down Expand Up @@ -28,6 +30,7 @@ import { Button } from '@/ui/input/button/components/Button';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';

const objectEditFormSchema = z
.object({})
Expand Down Expand Up @@ -103,66 +106,67 @@ export const SettingsObjectEdit = () => {
};

return (
// eslint-disable-next-line react/jsx-props-no-spreading
<FormProvider {...formConfig}>
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{
children: 'Objects',
href: settingsObjectsPagePath,
},
{
children: activeObjectMetadataItem.labelPlural,
href: `${settingsObjectsPagePath}/${objectSlug}`,
},
{ children: 'Edit' },
]}
/>
{activeObjectMetadataItem.isCustom && (
<SaveAndCancelButtons
isSaveDisabled={!canSave}
isCancelDisabled={isSubmitting}
onCancel={() =>
navigate(`${settingsObjectsPagePath}/${objectSlug}`)
}
onSave={formConfig.handleSubmit(handleSave)}
<RecordFieldValueSelectorContextProvider>
<FormProvider {...formConfig}>
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{
children: 'Objects',
href: settingsObjectsPagePath,
},
{
children: activeObjectMetadataItem.labelPlural,
href: `${settingsObjectsPagePath}/${objectSlug}`,
},
{ children: 'Edit' },
]}
/>
{activeObjectMetadataItem.isCustom && (
<SaveAndCancelButtons
isSaveDisabled={!canSave}
isCancelDisabled={isSubmitting}
onCancel={() =>
navigate(`${settingsObjectsPagePath}/${objectSlug}`)
}
onSave={formConfig.handleSubmit(handleSave)}
/>
)}
</SettingsHeaderContainer>
<Section>
<H2Title
title="About"
description="Name in both singular (e.g., 'Invoice') and plural (e.g., 'Invoices') forms."
/>
<SettingsDataModelObjectAboutForm
disabled={!activeObjectMetadataItem.isCustom}
disableNameEdit
objectMetadataItem={activeObjectMetadataItem}
/>
</Section>
<Section>
<H2Title
title="Settings"
description="Choose the fields that will identify your records"
/>
<SettingsDataModelObjectSettingsFormCard
objectMetadataItem={activeObjectMetadataItem}
/>
</Section>
<Section>
<H2Title title="Danger zone" description="Deactivate object" />
<Button
Icon={IconArchive}
title="Deactivate"
size="small"
onClick={handleDisable}
/>
)}
</SettingsHeaderContainer>
<Section>
<H2Title
title="About"
description="Name in both singular (e.g., 'Invoice') and plural (e.g., 'Invoices') forms."
/>
<SettingsDataModelObjectAboutForm
disabled={!activeObjectMetadataItem.isCustom}
disableNameEdit
objectMetadataItem={activeObjectMetadataItem}
/>
</Section>
<Section>
<H2Title
title="Settings"
description="Choose the fields that will identify your records"
/>
<SettingsDataModelObjectSettingsFormCard
objectMetadataItem={activeObjectMetadataItem}
/>
</Section>
<Section>
<H2Title title="Danger zone" description="Deactivate object" />
<Button
Icon={IconArchive}
title="Deactivate"
size="small"
onClick={handleDisable}
/>
</Section>
</SettingsPageContainer>
</SubMenuTopBarContainer>
</FormProvider>
</Section>
</SettingsPageContainer>
</SubMenuTopBarContainer>
</FormProvider>
</RecordFieldValueSelectorContextProvider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import {
SaveOptions,
UpdateResult,
} from 'typeorm';
import { PickKeysByType } from 'typeorm/common/PickKeysByType';
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { UpsertOptions } from 'typeorm/repository/UpsertOptions';
import { PickKeysByType } from 'typeorm/common/PickKeysByType';

import { WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Injectable } from '@nestjs/common';

import axios, { AxiosInstance } from 'axios';
import { EntityManager, ILike } from 'typeorm';
import uniqBy from 'lodash.uniqby';
import { EntityManager, ILike } from 'typeorm';

import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { extractDomainFromLink } from 'src/modules/contact-creation-manager/utils/extract-domain-from-link.util';
import { getCompanyNameFromDomainName } from 'src/modules/contact-creation-manager/utils/get-company-name-from-domain-name.util';
import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { computeDisplayName } from 'src/utils/compute-display-name';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';

type CompanyToCreate = {
domainName: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { Injectable } from '@nestjs/common';
import { EntityManager } from 'typeorm';
import { v4 } from 'uuid';

import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { getFirstNameAndLastNameFromHandleAndDisplayName } from 'src/modules/contact-creation-manager/utils/get-first-name-and-last-name-from-handle-and-display-name.util';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { computeDisplayName } from 'src/utils/compute-display-name';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';

type ContactToCreate = {
handle: string;
Expand Down

0 comments on commit b4e2ada

Please sign in to comment.