Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default address country 🗺️ & Phone prefix ☎️ #8614

Merged
merged 31 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6291ca5
Adding the DefaultCountry in the backend
guillim Nov 19, 2024
1352706
adding the frontend settings option to select countries by default
guillim Nov 19, 2024
03e0459
Merge branch 'main' of https://github.com/twentyhq/twenty into featur…
guillim Nov 19, 2024
47c79be
new design
guillim Nov 19, 2024
a454623
Default country in the input
guillim Nov 20, 2024
5ab4f71
fix
guillim Nov 20, 2024
c89a07a
lint
guillim Nov 20, 2024
a7d472e
Merge branch 'main' of https://github.com/twentyhq/twenty into featur…
guillim Nov 20, 2024
a7739d1
lint
guillim Nov 20, 2024
74691d3
moving towards defaultValue
guillim Nov 21, 2024
0420d3b
Merge branch 'main' of https://github.com/twentyhq/twenty into featur…
guillim Nov 25, 2024
18ccbd3
bugfix on quoting
guillim Nov 25, 2024
c6d01fc
request from thomas 2d
guillim Nov 25, 2024
47825a5
Address Field null in preview
guillim Nov 25, 2024
eaee2a0
end of coutrues
guillim Nov 26, 2024
c47f928
better typing
guillim Nov 26, 2024
dab6cf9
Charles feedback
guillim Nov 26, 2024
85fa685
Merge branch 'main' of https://github.com/twentyhq/twenty into featur…
guillim Nov 26, 2024
04d75ed
most fixes from charles feedback
guillim Nov 27, 2024
7ede48b
removing useless fct
guillim Nov 27, 2024
dc6f3d8
console log removal
guillim Nov 27, 2024
129223d
Fix typing
charlesBochet Nov 27, 2024
0d51f4c
Fix
charlesBochet Nov 27, 2024
6ba2fdf
Merge branch 'main' of https://github.com/twentyhq/twenty into featur…
guillim Nov 28, 2024
dc2a060
slamost done
guillim Nov 28, 2024
8b1f027
Merge branch 'main' of https://github.com/twentyhq/twenty into featur…
guillim Dec 2, 2024
daa8c1b
good phone default country
guillim Dec 2, 2024
8e006fb
fix display numbers
guillim Dec 2, 2024
c55d567
Merge branch 'main' of https://github.com/twentyhq/twenty into featur…
guillim Dec 2, 2024
a77b569
better typing 1
guillim Dec 2, 2024
cfd7eed
better typing usecountries
guillim Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import { FieldMetadataType } from '~/generated-metadata/graphql';

export const FIELD_NOT_OVERWRITTEN_AT_DRAFT = [
FieldMetadataType.Address,
FieldMetadataType.Phones,
FieldMetadataType.Links,
];
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export const useNumberField = () => {

const persistNumberField = (newValue: string) => {
if (fieldDefinition?.metadata?.settings?.type === 'percentage') {
newValue = newValue.replaceAll('%', '');
if (!canBeCastAsNumberOrNull(newValue)) {
const newValueEscaped = newValue.replaceAll('%', '');
if (!canBeCastAsNumberOrNull(newValueEscaped)) {
return;
}
const castedValue = castAsNumberOrNull(newValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export const MultiItemFieldInput = <T,>({
break;
case FieldMetadataType.Phones:
item = items[index] as PhoneRecord;
setInputValue(item.countryCode + item.number);
setInputValue(`+${item.callingCode}` + item.number);
break;
case FieldMetadataType.Emails:
item = items[index] as string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { usePhonesField } from '@/object-record/record-field/meta-types/hooks/usePhonesField';
import { PhonesFieldMenuItem } from '@/object-record/record-field/meta-types/input/components/PhonesFieldMenuItem';
import styled from '@emotion/styled';
import { E164Number, parsePhoneNumber } from 'libphonenumber-js';
import { CountryCode, E164Number, parsePhoneNumber } from 'libphonenumber-js';
import { useMemo } from 'react';
import ReactPhoneNumberInput from 'react-phone-number-input';
import 'react-phone-number-input/style.css';
import { isDefined, TEXT_INPUT_STYLE } from 'twenty-ui';
import { TEXT_INPUT_STYLE, isDefined } from 'twenty-ui';

import { MultiItemFieldInput } from './MultiItemFieldInput';

import { useCountries } from '@/ui/input/components/internal/hooks/useCountries';
import { PhoneCountryPickerDropdownButton } from '@/ui/input/components/internal/phone/components/PhoneCountryPickerDropdownButton';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { stripSimpleQuotesFromString } from '~/utils/string/stripSimpleQuotesFromString';

const StyledCustomPhoneInput = styled(ReactPhoneNumberInput)`
font-family: ${({ theme }) => theme.font.family};
Expand Down Expand Up @@ -48,33 +50,44 @@ type PhonesFieldInputProps = {
};

export const PhonesFieldInput = ({ onCancel }: PhonesFieldInputProps) => {
const { persistPhonesField, hotkeyScope, fieldValue } = usePhonesField();
const { persistPhonesField, hotkeyScope, draftValue, fieldDefinition } =
usePhonesField();

const phones = useMemo<{ number: string; countryCode: string }[]>(
const phones = useMemo<{ number: string; callingCode: string }[]>(
() =>
[
fieldValue.primaryPhoneNumber
draftValue?.primaryPhoneNumber
guillim marked this conversation as resolved.
Show resolved Hide resolved
? {
number: fieldValue.primaryPhoneNumber,
countryCode: fieldValue.primaryPhoneCountryCode,
number: draftValue.primaryPhoneNumber,
callingCode: draftValue.primaryPhoneCountryCode,
}
: null,
...(fieldValue.additionalPhones ?? []),
...(draftValue?.additionalPhones ?? []),
].filter(isDefined),
[
fieldValue.primaryPhoneNumber,
fieldValue.primaryPhoneCountryCode,
fieldValue.additionalPhones,
draftValue?.primaryPhoneNumber,
draftValue?.primaryPhoneCountryCode,
draftValue?.additionalPhones,
],
);

const defaultCallingCode =
stripSimpleQuotesFromString(
fieldDefinition?.defaultValue?.primaryPhoneCountryCode,
) ?? '+1';

// TODO : improve once we store the real country code
const defaultCountry = useCountries().find(
(obj) => obj.callingCode === defaultCallingCode,
)?.countryCode as CountryCode;
guillim marked this conversation as resolved.
Show resolved Hide resolved

const handlePersistPhones = (
updatedPhones: { number: string; countryCode: string }[],
updatedPhones: { number: string; callingCode: string }[],
) => {
const [nextPrimaryPhone, ...nextAdditionalPhones] = updatedPhones;
persistPhonesField({
primaryPhoneNumber: nextPrimaryPhone?.number ?? '',
primaryPhoneCountryCode: nextPrimaryPhone?.countryCode ?? '',
primaryPhoneCountryCode: nextPrimaryPhone?.callingCode ?? '',
additionalPhones: nextAdditionalPhones,
});
};
Expand All @@ -93,12 +106,12 @@ export const PhonesFieldInput = ({ onCancel }: PhonesFieldInputProps) => {
if (phone !== undefined) {
return {
number: phone.nationalNumber,
countryCode: `+${phone.countryCallingCode}`,
callingCode: `${phone.countryCallingCode}`,
};
}
return {
number: '',
countryCode: '',
callingCode: '',
};
}}
renderItem={({
Expand Down Expand Up @@ -128,6 +141,7 @@ export const PhonesFieldInput = ({ onCancel }: PhonesFieldInputProps) => {
international={true}
withCountryCallingCode={true}
countrySelectComponent={PhoneCountryPickerDropdownButton}
defaultCountry={defaultCountry}
/>
);
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type PhonesFieldMenuItemProps = {
onEdit?: () => void;
onSetAsPrimary?: () => void;
onDelete?: () => void;
phone: { number: string; countryCode: string };
phone: { number: string; callingCode: string };
};

export const PhonesFieldMenuItem = ({
Expand All @@ -22,7 +22,7 @@ export const PhonesFieldMenuItem = ({
<MultiItemFieldMenuItem
dropdownId={dropdownId}
isPrimary={isPrimary}
value={phone.countryCode + phone.number}
value={{ number: phone.number, callingCode: phone.callingCode }}
onEdit={onEdit}
onSetAsPrimary={onSetAsPrimary}
onDelete={onDelete}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import { CurrencyCode } from './CurrencyCode';
export type FieldUuidMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldBooleanMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldTextMetadata = {
Expand Down Expand Up @@ -61,80 +61,80 @@ export type FieldLinkMetadata = {
objectMetadataNameSingular?: string;
placeHolder: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldLinksMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldCurrencyMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
placeHolder: string;
isPositive?: boolean;
settings?: Record<string, never>;
settings?: null;
};

export type FieldFullNameMetadata = {
objectMetadataNameSingular?: string;
placeHolder: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldEmailMetadata = {
objectMetadataNameSingular?: string;
placeHolder: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldEmailsMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldPhoneMetadata = {
objectMetadataNameSingular?: string;
placeHolder: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldRatingMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldAddressMetadata = {
objectMetadataNameSingular?: string;
placeHolder: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldRawJsonMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
placeHolder: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldRichTextMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldPositionMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldRelationMetadata = {
Expand All @@ -146,47 +146,47 @@ export type FieldRelationMetadata = {
relationType?: RelationDefinitionType;
targetFieldMetadataName?: string;
useEditButton?: boolean;
settings?: Record<string, never>;
settings?: null;
};

export type FieldSelectMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
options: { label: string; color: ThemeColor; value: string }[];
isNullable: boolean;
settings?: Record<string, never>;
settings?: null;
};

export type FieldMultiSelectMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
options: { label: string; color: ThemeColor; value: string }[];
settings?: Record<string, never>;
settings?: null;
};

export type FieldActorMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldArrayMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
values: { label: string; value: string }[];
settings?: Record<string, never>;
settings?: null;
};

export type FieldPhonesMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldTsVectorMetadata = {
objectMetadataNameSingular?: string;
fieldName: string;
settings?: Record<string, never>;
settings?: null;
};

export type FieldMetadata =
Expand Down Expand Up @@ -265,7 +265,7 @@ export type FieldActorValue = {

export type FieldArrayValue = string[];

export type PhoneRecord = { number: string; countryCode: string };
export type PhoneRecord = { number: string; callingCode: string };

export type FieldPhonesValue = {
primaryPhoneNumber: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { z } from 'zod';

import { FieldAddressValue } from '../FieldMetadata';

const addressSchema = z.object({
export const addressSchema = z.object({
addressStreet1: z.string(),
addressStreet2: z.string().nullable(),
addressCity: z.string().nullable(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const phonesSchema = z.object({
primaryPhoneNumber: z.string(),
primaryPhoneCountryCode: z.string(),
additionalPhones: z
.array(z.object({ number: z.string(), countryCode: z.string() }))
.array(z.object({ number: z.string(), callingCode: z.string() }))
.nullable(),
}) satisfies z.ZodType<FieldPhonesValue>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { isFieldAddress } from '@/object-record/record-field/types/guards/isFieldAddress';
import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency';
import { isFieldCurrencyValue } from '@/object-record/record-field/types/guards/isFieldCurrencyValue';
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
import { isFieldNumberValue } from '@/object-record/record-field/types/guards/isFieldNumberValue';
import { isFieldPhones } from '@/object-record/record-field/types/guards/isFieldPhones';
import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson';
import { isFieldRawJsonValue } from '@/object-record/record-field/types/guards/isFieldRawJsonValue';
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
import { computeEmptyDraftValue } from '@/object-record/record-field/utils/computeEmptyDraftValue';
import { isFieldValueEmpty } from '@/object-record/record-field/utils/isFieldValueEmpty';
import { isDefined } from '~/utils/isDefined';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
import { stripSimpleQuotesFromString } from '~/utils/string/stripSimpleQuotesFromString';

type computeDraftValueFromFieldValueParams<FieldValue> = {
fieldDefinition: Pick<FieldDefinition<FieldMetadata>, 'type' | 'metadata'>;
Expand Down Expand Up @@ -42,6 +45,38 @@ export const computeDraftValueFromFieldValue = <FieldValue>({
} as unknown as FieldInputDraftValue<FieldValue>;
}

if (isFieldAddress(fieldDefinition)) {
guillim marked this conversation as resolved.
Show resolved Hide resolved
if (
isFieldValueEmpty({ fieldValue, fieldDefinition }) &&
!!fieldDefinition?.defaultValue?.addressCountry
) {
return {
...fieldValue,
addressCountry: stripSimpleQuotesFromString(
fieldDefinition?.defaultValue?.addressCountry,
),
} as unknown as FieldInputDraftValue<FieldValue>;
}

return fieldValue as FieldInputDraftValue<FieldValue>;
}

if (isFieldPhones(fieldDefinition)) {
if (
isFieldValueEmpty({ fieldValue, fieldDefinition }) &&
!!fieldDefinition?.defaultValue?.primaryPhoneCountryCode
) {
return {
...fieldValue,
primaryPhoneCountryCode: stripSimpleQuotesFromString(
fieldDefinition?.defaultValue?.primaryPhoneCountryCode,
),
} as unknown as FieldInputDraftValue<FieldValue>;
}

return fieldValue as FieldInputDraftValue<FieldValue>;
}

if (
isFieldNumber(fieldDefinition) &&
isFieldNumberValue(fieldValue) &&
Expand Down
Loading
Loading