From 47a6146dd013a4d7cfe6b1dfc4fca1479fd42780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tha=C3=AFs?= Date: Wed, 22 May 2024 10:32:37 +0200 Subject: [PATCH] feat: set primary link in Links field (#5429) Closes #5375 image _____ ~~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`):~~ image ~~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) --- .../input/components/LinksFieldInput.tsx | 15 +++++++++++++++ .../input/components/LinksFieldMenuItem.tsx | 18 +++++++++++++++++- .../src/display/icon/components/TablerIcons.ts | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldInput.tsx index 158b25152..449603794 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldInput.tsx @@ -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} /> diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldMenuItem.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldMenuItem.tsx index b4f1f2fac..19f3041a6 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldMenuItem.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldMenuItem.tsx @@ -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 ( +