feat: set primary link in Links field (#5429)

Closes #5375

<img width="381" alt="image"
src="https://github.com/twentyhq/twenty/assets/3098428/d87773df-c685-466b-ae35-a8349f79df48">

_____

~~Note that I ugraded `@apollo/client` to v3.10.4 because current
version is causing an error when trying to write the Links field in the
cache in `updateRecordFromCache` (`TypeError: Cannot convert object to
primitive value`). After upgrade, the error is gone but console still
prints a warning (here the custom object name is `Listing` and the Links
field name is `website`):~~

<img width="964" alt="image"
src="https://github.com/twentyhq/twenty/assets/3098428/834b8909-e8dc-464a-8c5a-6b7e4c964a7f">

~~It might be because the Links field seems to somehow have a
`__typename` property in Apollo's cache, so Apollo considers it as a
record and tries to match the object's cache with an id, but the Links
field value has no id so it can't find it.
We might want to find where this `__typename` is added and remove it
from the Links object in the cache.~~

Edit: will fix this in another PR as upgrading `@apollo/client` +
`apollo-upload-client` seems to break types and/or tests. Related issue:
[#5437](https://github.com/twentyhq/twenty/issues/5437)
This commit is contained in:
Thaïs
2024-05-22 10:32:37 +02:00
committed by GitHub
parent 2386191d8e
commit 47a6146dd0
3 changed files with 33 additions and 1 deletions

View File

@ -14,6 +14,7 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { moveArrayItem } from '~/utils/array/moveArrayItem';
import { toSpliced } from '~/utils/array/toSpliced';
import { isDefined } from '~/utils/isDefined';
@ -86,6 +87,19 @@ export const LinksFieldInput = ({
);
};
const handleSetPrimaryLink = (index: number) => {
const nextLinks = moveArrayItem(links, { fromIndex: index, toIndex: 0 });
const [nextPrimaryLink, ...nextSecondaryLinks] = nextLinks;
onSubmit?.(() =>
persistLinksField({
primaryLinkUrl: nextPrimaryLink.url ?? '',
primaryLinkLabel: nextPrimaryLink.label ?? '',
secondaryLinks: nextSecondaryLinks,
}),
);
};
const handleDeleteLink = (index: number) => {
onSubmit?.(() =>
persistLinksField({
@ -110,6 +124,7 @@ export const LinksFieldInput = ({
dropdownId={`${hotkeyScope}-links-${index}`}
isPrimary={index === 0}
label={label}
onSetAsPrimary={() => handleSetPrimaryLink(index)}
onDelete={() => handleDeleteLink(index)}
url={url}
/>

View File

@ -1,6 +1,8 @@
import { useEffect } from 'react';
import styled from '@emotion/styled';
import {
IconBookmark,
IconBookmarkPlus,
IconComponent,
IconDotsVertical,
IconTrash,
@ -16,6 +18,7 @@ type LinksFieldMenuItemProps = {
dropdownId: string;
isPrimary?: boolean;
label: string;
onSetAsPrimary: () => void;
onDelete: () => void;
url: string;
};
@ -30,10 +33,18 @@ export const LinksFieldMenuItem = ({
dropdownId,
isPrimary,
label,
onSetAsPrimary,
onDelete,
url,
}: LinksFieldMenuItemProps) => {
const { isDropdownOpen } = useDropdown(dropdownId);
const { isDropdownOpen, closeDropdown } = useDropdown(dropdownId);
// Make sure dropdown closes on unmount.
useEffect(() => {
if (isDropdownOpen) {
return () => closeDropdown();
}
}, [closeDropdown, isDropdownOpen]);
return (
<MenuItem
@ -55,6 +66,11 @@ export const LinksFieldMenuItem = ({
clickableComponent={iconButton}
dropdownComponents={
<DropdownMenuItemsContainer>
<MenuItem
LeftIcon={IconBookmarkPlus}
text="Set as Primary"
onClick={onSetAsPrimary}
/>
<MenuItem
accent="danger"
LeftIcon={IconTrash}

View File

@ -20,6 +20,7 @@ export {
IconBolt,
IconBook2,
IconBookmark,
IconBookmarkPlus,
IconBox,
IconBrandGithub,
IconBrandGoogle,