diff --git a/packages/twenty-emails/src/emails/send-invite-link.email.tsx b/packages/twenty-emails/src/emails/send-invite-link.email.tsx index 36e712acf9..e1c3e70ca3 100644 --- a/packages/twenty-emails/src/emails/send-invite-link.email.tsx +++ b/packages/twenty-emails/src/emails/send-invite-link.email.tsx @@ -9,7 +9,7 @@ import { MainText } from 'src/components/MainText'; import { Title } from 'src/components/Title'; import { WhatIsTwenty } from 'src/components/WhatIsTwenty'; import { capitalize } from 'src/utils/capitalize'; -import { getImageAbsoluteURIOrBase64 } from 'src/utils/getImageAbsoluteURIOrBase64'; +import { getImageAbsoluteURI } from 'src/utils/getImageAbsoluteURI'; type SendInviteLinkEmailProps = { link: string; @@ -27,7 +27,7 @@ export const SendInviteLinkEmail = ({ sender, serverUrl, }: SendInviteLinkEmailProps) => { - const workspaceLogo = getImageAbsoluteURIOrBase64(workspace.logo, serverUrl); + const workspaceLogo = getImageAbsoluteURI(workspace.logo, serverUrl); return ( diff --git a/packages/twenty-emails/src/utils/getImageAbsoluteURIOrBase64.ts b/packages/twenty-emails/src/utils/getImageAbsoluteURI.ts similarity index 70% rename from packages/twenty-emails/src/utils/getImageAbsoluteURIOrBase64.ts rename to packages/twenty-emails/src/utils/getImageAbsoluteURI.ts index cab930f765..28a6e637a3 100644 --- a/packages/twenty-emails/src/utils/getImageAbsoluteURIOrBase64.ts +++ b/packages/twenty-emails/src/utils/getImageAbsoluteURI.ts @@ -1,4 +1,4 @@ -export const getImageAbsoluteURIOrBase64 = ( +export const getImageAbsoluteURI = ( imageUrl?: string | null, serverUrl?: string, ) => { @@ -6,7 +6,7 @@ export const getImageAbsoluteURIOrBase64 = ( return null; } - if (imageUrl?.startsWith('data:') || imageUrl?.startsWith('https:')) { + if (imageUrl?.startsWith('https:')) { return imageUrl; } diff --git a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx index e5ad988d31..bdaf54830d 100644 --- a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx @@ -16,7 +16,6 @@ import { Card } from '@/ui/layout/card/components/Card'; import { CardContent } from '@/ui/layout/card/components/CardContent'; import { TimelineCalendarEvent } from '~/generated-metadata/graphql'; import { CalendarChannelVisibility } from '~/generated/graphql'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; import { isDefined } from '~/utils/isDefined'; type CalendarEventRowProps = { @@ -163,7 +162,7 @@ export const CalendarEventRow = ({ key={[participant.workspaceMemberId, participant.displayName] .filter(isDefined) .join('-')} - avatarUrl={getImageAbsoluteURIOrBase64(participant.avatarUrl)} + avatarUrl={participant.avatarUrl} placeholder={ participant.firstName && participant.lastName ? `${participant.firstName} ${participant.lastName}` diff --git a/packages/twenty-front/src/modules/activities/comment/CommentHeader.tsx b/packages/twenty-front/src/modules/activities/comment/CommentHeader.tsx index d48f114e9d..c40cd8f26a 100644 --- a/packages/twenty-front/src/modules/activities/comment/CommentHeader.tsx +++ b/packages/twenty-front/src/modules/activities/comment/CommentHeader.tsx @@ -6,7 +6,6 @@ import { beautifyExactDateTime, beautifyPastDateRelativeToNow, } from '~/utils/date-utils'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; const StyledContainer = styled.div` align-items: center; @@ -60,7 +59,7 @@ export const CommentHeader = ({ comment, actionBar }: CommentHeaderProps) => { <StyledContainer> <StyledLeftContainer> <Avatar - avatarUrl={getImageAbsoluteURIOrBase64(avatarUrl)} + avatarUrl={avatarUrl} size="md" placeholderColorSeed={author?.id} placeholder={authorName} diff --git a/packages/twenty-front/src/modules/activities/components/ParticipantChip.tsx b/packages/twenty-front/src/modules/activities/components/ParticipantChip.tsx index a69c2cfb7f..82d48531db 100644 --- a/packages/twenty-front/src/modules/activities/components/ParticipantChip.tsx +++ b/packages/twenty-front/src/modules/activities/components/ParticipantChip.tsx @@ -4,7 +4,6 @@ import { Avatar } from 'twenty-ui'; import { getDisplayNameFromParticipant } from '@/activities/emails/utils/getDisplayNameFromParticipant'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { RecordChip } from '@/object-record/components/RecordChip'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; const StyledAvatar = styled(Avatar)` margin-right: ${({ theme }) => theme.spacing(1)}; @@ -74,7 +73,7 @@ export const ParticipantChip = ({ ) : ( <StyledChip> <StyledAvatar - avatarUrl={getImageAbsoluteURIOrBase64(avatarUrl)} + avatarUrl={avatarUrl} type="rounded" placeholder={displayName} size="sm" diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx index b9daf483a2..e381b1bac3 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx @@ -10,7 +10,6 @@ import { CardContent } from '@/ui/layout/card/components/CardContent'; import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { MessageChannelVisibility, TimelineThread } from '~/generated/graphql'; import { formatToHumanReadableDate } from '~/utils/date-utils'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; const StyledCardContent = styled(CardContent)<{ visibility: MessageChannelVisibility; @@ -154,24 +153,20 @@ export const EmailThreadPreview = ({ <StyledHeading unread={!thread.read}> <StyledParticipantsContainer> <Avatar - avatarUrl={getImageAbsoluteURIOrBase64( - thread?.firstParticipant?.avatarUrl, - )} + avatarUrl={thread?.firstParticipant?.avatarUrl} placeholder={thread.firstParticipant.displayName} type="rounded" /> {thread?.lastTwoParticipants?.[0] && ( <StyledAvatar - avatarUrl={getImageAbsoluteURIOrBase64( - thread.lastTwoParticipants[0].avatarUrl, - )} + avatarUrl={thread.lastTwoParticipants[0].avatarUrl} placeholder={thread.lastTwoParticipants[0].displayName} type="rounded" /> )} {finalDisplayedName && ( <StyledAvatar - avatarUrl={getImageAbsoluteURIOrBase64(finalAvatarUrl)} + avatarUrl={finalAvatarUrl} placeholder={finalDisplayedName} type="rounded" color={isCountIcon ? GRAY_SCALE.gray50 : undefined} diff --git a/packages/twenty-front/src/modules/activities/timeline/components/TimelineActivity.tsx b/packages/twenty-front/src/modules/activities/timeline/components/TimelineActivity.tsx index fc915a1ce1..819bcc73d7 100644 --- a/packages/twenty-front/src/modules/activities/timeline/components/TimelineActivity.tsx +++ b/packages/twenty-front/src/modules/activities/timeline/components/TimelineActivity.tsx @@ -11,7 +11,6 @@ import { beautifyExactDateTime, beautifyPastDateRelativeToNow, } from '~/utils/date-utils'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; const StyledAvatarContainer = styled.div` align-items: center; @@ -154,9 +153,7 @@ export const TimelineActivity = ({ <StyledTimelineItemContainer> <StyledAvatarContainer> <Avatar - avatarUrl={getImageAbsoluteURIOrBase64( - activityForTimeline.author?.avatarUrl, - )} + avatarUrl={activityForTimeline.author?.avatarUrl} placeholder={activityForTimeline.author?.name.firstName ?? ''} size="sm" type="rounded" diff --git a/packages/twenty-front/src/modules/auth/components/Logo.tsx b/packages/twenty-front/src/modules/auth/components/Logo.tsx index a1bbc54beb..34ddf069cd 100644 --- a/packages/twenty-front/src/modules/auth/components/Logo.tsx +++ b/packages/twenty-front/src/modules/auth/components/Logo.tsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; +import { getImageAbsoluteURI } from '~/utils/image/getImageAbsoluteURI'; type LogoProps = { workspaceLogo?: string | null; @@ -58,7 +58,7 @@ export const Logo = ({ workspaceLogo }: LogoProps) => { return ( <StyledContainer> - <StyledMainLogo logo={getImageAbsoluteURIOrBase64(workspaceLogo)} /> + <StyledMainLogo logo={getImageAbsoluteURI(workspaceLogo)} /> <StyledTwentyLogoContainer> <StyledTwentyLogo src="/icons/android/android-launchericon-192-192.png" /> </StyledTwentyLogoContainer> diff --git a/packages/twenty-front/src/modules/favorites/components/Favorites.tsx b/packages/twenty-front/src/modules/favorites/components/Favorites.tsx index 9835a860b4..1c14dc8b3c 100644 --- a/packages/twenty-front/src/modules/favorites/components/Favorites.tsx +++ b/packages/twenty-front/src/modules/favorites/components/Favorites.tsx @@ -10,7 +10,6 @@ import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/componen import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle'; import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; import { useFavorites } from '../hooks/useFavorites'; @@ -81,7 +80,7 @@ export const Favorites = () => { Icon={() => ( <StyledAvatar placeholderColorSeed={recordId} - avatarUrl={getImageAbsoluteURIOrBase64(avatarUrl)} + avatarUrl={avatarUrl} type={avatarType} placeholder={labelIdentifier} className="fav-avatar" diff --git a/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx b/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx index 522f76f3e3..1dbe04bad6 100644 --- a/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx +++ b/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx @@ -11,7 +11,7 @@ import { } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer'; import { isNavigationDrawerOpenState } from '@/ui/navigation/states/isNavigationDrawerOpenState'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; +import { getImageAbsoluteURI } from '~/utils/image/getImageAbsoluteURI'; import { useIsSettingsPage } from '../hooks/useIsSettingsPage'; import { currentMobileNavigationDrawerState } from '../states/currentMobileNavigationDrawerState'; @@ -49,7 +49,7 @@ export const AppNavigationDrawer = ({ : { logo: (currentWorkspace?.logo && - getImageAbsoluteURIOrBase64(currentWorkspace.logo)) ?? + getImageAbsoluteURI(currentWorkspace.logo)) ?? undefined, title: currentWorkspace?.displayName ?? undefined, children: <MainNavigationDrawerItems />, diff --git a/packages/twenty-front/src/modules/object-metadata/utils/getAvatarUrl.ts b/packages/twenty-front/src/modules/object-metadata/utils/getAvatarUrl.ts index 7965b905b4..97ffc4e384 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/getAvatarUrl.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/getAvatarUrl.ts @@ -2,7 +2,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { getLogoUrlFromDomainName } from '~/utils'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; +import { getImageAbsoluteURI } from '~/utils/image/getImageAbsoluteURI'; import { isDefined } from '~/utils/isDefined'; import { getImageIdentifierFieldValue } from './getImageIdentifierFieldValue'; @@ -21,7 +21,7 @@ export const getAvatarUrl = ( } if (objectNameSingular === CoreObjectNameSingular.Person) { - return getImageAbsoluteURIOrBase64(record.avatarUrl) ?? ''; + return getImageAbsoluteURI(record.avatarUrl) ?? ''; } const imageIdentifierFieldValue = getImageIdentifierFieldValue( diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/GenericEntityFilterChip.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/GenericEntityFilterChip.tsx index fae9454c18..2815490a20 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/GenericEntityFilterChip.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/GenericEntityFilterChip.tsx @@ -1,7 +1,5 @@ import { AvatarChip, IconComponent } from 'twenty-ui'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; - import { Filter } from '../types/Filter'; type GenericEntityFilterChipProps = { @@ -17,7 +15,7 @@ export const GenericEntityFilterChip = ({ placeholderColorSeed={filter.value} name={filter.displayValue} avatarType="rounded" - avatarUrl={getImageAbsoluteURIOrBase64(filter.displayAvatarUrl) || ''} + avatarUrl={filter.displayAvatarUrl} LeftIcon={Icon} /> ); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx index af92fedd19..fc4061cfc9 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx @@ -10,7 +10,6 @@ import { SelectableItem } from '@/ui/layout/selectable-list/components/Selectabl import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { MenuItemMultiSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar'; import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; import { isDefined } from '~/utils/isDefined'; export const StyledSelectableItem = styled(SelectableItem)` @@ -65,7 +64,7 @@ export const MultipleObjectRecordSelectItem = ({ selected={selected} avatar={ <Avatar - avatarUrl={getImageAbsoluteURIOrBase64(recordIdentifier.avatarUrl)} + avatarUrl={recordIdentifier.avatarUrl} placeholderColorSeed={objectRecordId} placeholder={recordIdentifier.name} size="md" diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SelectableMenuItemSelect.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/SelectableMenuItemSelect.tsx index 16eb58fad2..2044670627 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SelectableMenuItemSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/SelectableMenuItemSelect.tsx @@ -6,7 +6,6 @@ import { EntityForSelect } from '@/object-record/relation-picker/types/EntityFor import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { MenuItemSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemSelectAvatar'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; type SelectableMenuItemSelectProps = { entity: EntityForSelect; @@ -40,7 +39,7 @@ export const SelectableMenuItemSelect = ({ hovered={isSelectedItemId} avatar={ <Avatar - avatarUrl={getImageAbsoluteURIOrBase64(entity.avatarUrl)} + avatarUrl={entity.avatarUrl} placeholderColorSeed={entity.id} placeholder={entity.name} size="md" diff --git a/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx b/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx index af608e0077..86e9ef5aa2 100644 --- a/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx +++ b/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx @@ -6,7 +6,6 @@ import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItemMultiSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; export const MultipleRecordSelectDropdown = ({ recordsToSelect, @@ -69,7 +68,7 @@ export const MultipleRecordSelectDropdown = ({ } avatar={ <Avatar - avatarUrl={getImageAbsoluteURIOrBase64(record.avatarUrl)} + avatarUrl={record.avatarUrl} placeholderColorSeed={record.id} placeholder={record.name} size="md" diff --git a/packages/twenty-front/src/modules/settings/profile/components/ProfilePictureUploader.tsx b/packages/twenty-front/src/modules/settings/profile/components/ProfilePictureUploader.tsx index 6bc475de5a..cef17405c1 100644 --- a/packages/twenty-front/src/modules/settings/profile/components/ProfilePictureUploader.tsx +++ b/packages/twenty-front/src/modules/settings/profile/components/ProfilePictureUploader.tsx @@ -6,7 +6,6 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { ImageInput } from '@/ui/input/components/ImageInput'; import { useUploadProfilePictureMutation } from '~/generated/graphql'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; import { isDefined } from '~/utils/isDefined'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; @@ -101,7 +100,7 @@ export const ProfilePictureUploader = () => { return ( <ImageInput - picture={getImageAbsoluteURIOrBase64(currentWorkspaceMember?.avatarUrl)} + picture={currentWorkspaceMember?.avatarUrl} onUpload={handleUpload} onRemove={handleRemove} onAbort={handleAbort} diff --git a/packages/twenty-front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx b/packages/twenty-front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx index 3a3699c9b0..4cff974765 100644 --- a/packages/twenty-front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx +++ b/packages/twenty-front/src/modules/settings/workspace/components/WorkspaceLogoUploader.tsx @@ -6,7 +6,6 @@ import { useUpdateWorkspaceMutation, useUploadWorkspaceLogoMutation, } from '~/generated/graphql'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; export const WorkspaceLogoUploader = () => { @@ -57,7 +56,7 @@ export const WorkspaceLogoUploader = () => { return ( <ImageInput - picture={getImageAbsoluteURIOrBase64(currentWorkspace?.logo)} + picture={currentWorkspace?.logo} onUpload={onUpload} onRemove={onRemove} /> diff --git a/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx b/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx index c992e53811..df318dd3b6 100644 --- a/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx @@ -1,9 +1,10 @@ -import React from 'react'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; +import React, { useMemo } from 'react'; import { IconFileUpload, IconTrash, IconUpload, IconX } from 'twenty-ui'; import { Button } from '@/ui/input/button/components/Button'; +import { getImageAbsoluteURI } from '~/utils/image/getImageAbsoluteURI'; import { isDefined } from '~/utils/isDefined'; const StyledContainer = styled.div` @@ -105,16 +106,18 @@ export const ImageInput = ({ hiddenFileInput.current?.click(); }; + const pictureURI = useMemo(() => getImageAbsoluteURI(picture), [picture]); + return ( <StyledContainer className={className}> <StyledPicture - withPicture={!!picture} + withPicture={!!pictureURI} disabled={disabled} onClick={onUploadButtonClick} > - {picture ? ( + {pictureURI ? ( <img - src={picture || '/images/default-profile-picture.png'} + src={pictureURI || '/images/default-profile-picture.png'} alt="profile" /> ) : ( @@ -139,7 +142,7 @@ export const ImageInput = ({ onClick={onAbort} variant="secondary" title="Abort" - disabled={!picture || disabled} + disabled={!pictureURI || disabled} fullWidth /> ) : ( @@ -157,7 +160,7 @@ export const ImageInput = ({ onClick={onRemove} variant="secondary" title="Remove" - disabled={!picture || disabled} + disabled={!pictureURI || disabled} fullWidth /> </StyledButtonContainer> diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdownButton.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdownButton.tsx index 23d356aa4f..07be1ee8bf 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdownButton.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdownButton.tsx @@ -14,7 +14,7 @@ import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/consta import { MULTI_WORKSPACE_DROPDOWN_ID } from '@/ui/navigation/navigation-drawer/constants/MulitWorkspaceDropdownId'; import { useWorkspaceSwitching } from '@/ui/navigation/navigation-drawer/hooks/useWorkspaceSwitching'; import { NavigationDrawerHotKeyScope } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerHotKeyScope'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; +import { getImageAbsoluteURI } from '~/utils/image/getImageAbsoluteURI'; const StyledLogo = styled.div<{ logo: string }>` background: url(${({ logo }) => logo}); @@ -88,7 +88,7 @@ export const MultiWorkspaceDropdownButton = ({ <StyledContainer> <StyledLogo logo={ - getImageAbsoluteURIOrBase64( + getImageAbsoluteURI( currentWorkspace?.logo === null ? DEFAULT_WORKSPACE_LOGO : currentWorkspace?.logo, @@ -111,7 +111,7 @@ export const MultiWorkspaceDropdownButton = ({ avatar={ <StyledLogo logo={ - getImageAbsoluteURIOrBase64( + getImageAbsoluteURI( workspace.logo === null ? DEFAULT_WORKSPACE_LOGO : workspace.logo, diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo.ts b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo.ts index 7f58ca06ba..7428bf82b1 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo.ts +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo.ts @@ -1,2 +1,2 @@ export const DEFAULT_WORKSPACE_LOGO = - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACb0lEQVR4nO2VO4taQRTHr3AblbjxEVlwCwVhg7BoqqCIjy/gAyyFWNlYBOxsfH0KuxgQGwXRUkGuL2S7i1barGAgiwbdW93SnGOc4BonPiKahf3DwXFmuP/fPM4ZlvmlTxAhCBdzHnEQWYiv7Mr4C3NeuVYhQYDPzOUUQgDLBQGcLHNhvQK8DACPx8PTxiqVyvISG43GbyaT6Qfpn06n0m63e/tPAPF4vJ1MJu8kEsnWTCkWi1yr1RKGw+GDRqPBOTfr44vFQvD7/Q/lcpmaaVQAr9fLp1IpO22c47hGOBz+MB6PH+Vy+VYDAL8qlUoGtVotzOfzq4MAgsHgE/6KojiQyWR/bKVSqbSszHFM8Pl8z1YK48JsNltCOBwOnrYLO+8AAIjb+nHbycoTiUQfDJ7tFq4YAHiVSmXBxcD41u8flQU8z7fhzO0r83atVns3Go3u9Xr9x0O/RQXo9/tsIBBg6vX606a52Wz+bZ7P5/WwG29gxSJzhKgA6XTaDoFNF+krFAocmC//4yWEcSf2wTm7mCO19xFgSsKOLI16vV7b7XY7mRNoLwA0JymJ5uQIzgIAuX5PzDElT2m+E8BqtQ4ymcx7Yq7T6a6ZE4sKgOadTucaCwkxp1UzlEKh0GDxIXOwDWHAdi6Xe3swQDQa/Q7mywoolUpvsaptymazDWKxmBHTlWXZm405BFZoNpuGgwEmk4mE2SGtVivii4f1AO7J3ZopkQCQj7Ar1FeRChCJRJzVapX6DKNIfSc1Ax+wtQWQ55h6bH8FWDfYV4fO3wlwDr0C/BcADYiTPCxHqIEA2QsCZAkAKnRGkMbKN/sTX5YHPQ1e7SkAAAAASUVORK5CYII='; + 'https://twentyhq.github.io/placeholder-images/workspaces/twenty-logo.png'; diff --git a/packages/twenty-front/src/modules/users/components/UserChip.tsx b/packages/twenty-front/src/modules/users/components/UserChip.tsx index 5f4fbc94eb..58460c4d1d 100644 --- a/packages/twenty-front/src/modules/users/components/UserChip.tsx +++ b/packages/twenty-front/src/modules/users/components/UserChip.tsx @@ -1,7 +1,5 @@ import { AvatarChip } from 'twenty-ui'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; - export type UserChipProps = { id: string; name: string; @@ -13,6 +11,6 @@ export const UserChip = ({ id, name, avatarUrl }: UserChipProps) => ( placeholderColorSeed={id} name={name} avatarType="rounded" - avatarUrl={getImageAbsoluteURIOrBase64(avatarUrl) || ''} + avatarUrl={avatarUrl} /> ); diff --git a/packages/twenty-front/src/modules/workspace/components/WorkspaceMemberCard.tsx b/packages/twenty-front/src/modules/workspace/components/WorkspaceMemberCard.tsx index 2fc774905a..6ed05ce15f 100644 --- a/packages/twenty-front/src/modules/workspace/components/WorkspaceMemberCard.tsx +++ b/packages/twenty-front/src/modules/workspace/components/WorkspaceMemberCard.tsx @@ -2,7 +2,6 @@ import styled from '@emotion/styled'; import { Avatar, OverflowingTextWithTooltip } from 'twenty-ui'; import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; -import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64'; const StyledContainer = styled.div` background: ${({ theme }) => theme.background.secondary}; @@ -39,7 +38,7 @@ export const WorkspaceMemberCard = ({ }: WorkspaceMemberCardProps) => ( <StyledContainer> <Avatar - avatarUrl={getImageAbsoluteURIOrBase64(workspaceMember.avatarUrl)} + avatarUrl={workspaceMember.avatarUrl} placeholderColorSeed={workspaceMember.id} placeholder={workspaceMember.name.firstName || ''} type="squared" diff --git a/packages/twenty-front/src/utils/image/__tests__/getImageAbsoluteURI.test.ts b/packages/twenty-front/src/utils/image/__tests__/getImageAbsoluteURI.test.ts new file mode 100644 index 0000000000..aea54c1648 --- /dev/null +++ b/packages/twenty-front/src/utils/image/__tests__/getImageAbsoluteURI.test.ts @@ -0,0 +1,21 @@ +import { getImageAbsoluteURI } from '../getImageAbsoluteURI'; + +describe('getImageAbsoluteURI', () => { + it('should return null if imageUrl is null', () => { + const imageUrl = null; + const result = getImageAbsoluteURI(imageUrl); + expect(result).toBeNull(); + }); + + it('should return absolute url if the imageUrl is an absolute url', () => { + const imageUrl = 'https://XXX'; + const result = getImageAbsoluteURI(imageUrl); + expect(result).toBe(imageUrl); + }); + + it('should return fully formed url if imageUrl is a relative url', () => { + const imageUrl = 'XXX'; + const result = getImageAbsoluteURI(imageUrl); + expect(result).toBe('http://localhost:3000/files/XXX'); + }); +}); diff --git a/packages/twenty-front/src/utils/image/__tests__/getImageAbsoluteURIOrBase64.test.ts b/packages/twenty-front/src/utils/image/__tests__/getImageAbsoluteURIOrBase64.test.ts deleted file mode 100644 index 226aa6a0e5..0000000000 --- a/packages/twenty-front/src/utils/image/__tests__/getImageAbsoluteURIOrBase64.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { getImageAbsoluteURIOrBase64 } from '../getImageAbsoluteURIOrBase64'; - -describe('getImageAbsoluteURIOrBase64', () => { - it('should return null if imageUrl is null', () => { - const imageUrl = null; - const result = getImageAbsoluteURIOrBase64(imageUrl); - expect(result).toBeNull(); - }); - - it('should return base64 encoded string if prefixed with data', () => { - const imageUrl = 'data:XXX'; - const result = getImageAbsoluteURIOrBase64(imageUrl); - expect(result).toBe(imageUrl); - }); - - it('should return absolute url if the imageUrl is an absolute url', () => { - const imageUrl = 'https://XXX'; - const result = getImageAbsoluteURIOrBase64(imageUrl); - expect(result).toBe(imageUrl); - }); - - it('should return fully formed url if imageUrl is a relative url', () => { - const imageUrl = 'XXX'; - const result = getImageAbsoluteURIOrBase64(imageUrl); - expect(result).toBe('http://localhost:3000/files/XXX'); - }); -}); diff --git a/packages/twenty-front/src/utils/image/getImageAbsoluteURIOrBase64.ts b/packages/twenty-front/src/utils/image/getImageAbsoluteURI.ts similarity index 60% rename from packages/twenty-front/src/utils/image/getImageAbsoluteURIOrBase64.ts rename to packages/twenty-front/src/utils/image/getImageAbsoluteURI.ts index 7f4ad3b352..6237813b78 100644 --- a/packages/twenty-front/src/utils/image/getImageAbsoluteURIOrBase64.ts +++ b/packages/twenty-front/src/utils/image/getImageAbsoluteURI.ts @@ -1,11 +1,11 @@ import { REACT_APP_SERVER_BASE_URL } from '~/config'; -export const getImageAbsoluteURIOrBase64 = (imageUrl?: string | null) => { +export const getImageAbsoluteURI = (imageUrl?: string | null) => { if (!imageUrl) { return null; } - if (imageUrl?.startsWith('data:') || imageUrl?.startsWith('https:')) { + if (imageUrl?.startsWith('https:')) { return imageUrl; } diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/demo/workspaces.ts b/packages/twenty-server/src/database/typeorm-seeds/core/demo/workspaces.ts index 8778e721a3..bc0b3c93b1 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/demo/workspaces.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/demo/workspaces.ts @@ -24,7 +24,7 @@ export const seedWorkspaces = async ( displayName: 'Demo', domainName: 'demo.dev', inviteHash: 'demo.dev-invite-hash', - logo: 'data:image/png;base64,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', + logo: 'https://twentyhq.github.io/placeholder-images/workspaces/apple-logo.png', }, ]) .execute(); diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/workspaces.ts b/packages/twenty-server/src/database/typeorm-seeds/core/workspaces.ts index 71fcea2d4b..54b2f4a85f 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/workspaces.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/workspaces.ts @@ -23,14 +23,14 @@ export const seedWorkspaces = async ( displayName: 'Apple', domainName: 'apple.dev', inviteHash: 'apple.dev-invite-hash', - logo: 'data:image/png;base64,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', + logo: 'https://twentyhq.github.io/placeholder-images/workspaces/apple-logo.png', }, [SEED_TWENTY_WORKSPACE_ID]: { id: workspaceId, displayName: 'Twenty', domainName: 'twenty.dev', inviteHash: 'twenty.dev-invite-hash', - logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACb0lEQVR4nO2VO4taQRTHr3AblbjxEVlwCwVhg7BoqqCIjy/gAyyFWNlYBOxsfH0KuxgQGwXRUkGuL2S7i1barGAgiwbdW93SnGOc4BonPiKahf3DwXFmuP/fPM4ZlvmlTxAhCBdzHnEQWYiv7Mr4C3NeuVYhQYDPzOUUQgDLBQGcLHNhvQK8DACPx8PTxiqVyvISG43GbyaT6Qfpn06n0m63e/tPAPF4vJ1MJu8kEsnWTCkWi1yr1RKGw+GDRqPBOTfr44vFQvD7/Q/lcpmaaVQAr9fLp1IpO22c47hGOBz+MB6PH+Vy+VYDAL8qlUoGtVotzOfzq4MAgsHgE/6KojiQyWR/bKVSqbSszHFM8Pl8z1YK48JsNltCOBwOnrYLO+8AAIjb+nHbycoTiUQfDJ7tFq4YAHiVSmXBxcD41u8flQU8z7fhzO0r83atVns3Go3u9Xr9x0O/RQXo9/tsIBBg6vX606a52Wz+bZ7P5/WwG29gxSJzhKgA6XTaDoFNF+krFAocmC//4yWEcSf2wTm7mCO19xFgSsKOLI16vV7b7XY7mRNoLwA0JymJ5uQIzgIAuX5PzDElT2m+E8BqtQ4ymcx7Yq7T6a6ZE4sKgOadTucaCwkxp1UzlEKh0GDxIXOwDWHAdi6Xe3swQDQa/Q7mywoolUpvsaptymazDWKxmBHTlWXZm405BFZoNpuGgwEmk4mE2SGtVivii4f1AO7J3ZopkQCQj7Ar1FeRChCJRJzVapX6DKNIfSc1Ax+wtQWQ55h6bH8FWDfYV4fO3wlwDr0C/BcADYiTPCxHqIEA2QsCZAkAKnRGkMbKN/sTX5YHPQ1e7SkAAAAASUVORK5CYII=', + logo: 'https://twentyhq.github.io/placeholder-images/workspaces/twenty-logo.png', }, }; diff --git a/packages/twenty-ui/src/display/avatar/components/Avatar.tsx b/packages/twenty-ui/src/display/avatar/components/Avatar.tsx index b0373b8cb8..81c3a80219 100644 --- a/packages/twenty-ui/src/display/avatar/components/Avatar.tsx +++ b/packages/twenty-ui/src/display/avatar/components/Avatar.tsx @@ -1,6 +1,6 @@ import { styled } from '@linaria/react'; import { isNonEmptyString, isUndefined } from '@sniptt/guards'; -import { useContext } from 'react'; +import { useContext, useMemo } from 'react'; import { useRecoilState } from 'recoil'; import { invalidAvatarUrlsState } from '@ui/display/avatar/components/states/isInvalidAvatarUrlState'; @@ -8,7 +8,7 @@ import { AVATAR_PROPERTIES_BY_SIZE } from '@ui/display/avatar/constants/AvatarPr import { AvatarSize } from '@ui/display/avatar/types/AvatarSize'; import { AvatarType } from '@ui/display/avatar/types/AvatarType'; import { ThemeContext } from '@ui/theme'; -import { Nullable, stringToHslColor } from '@ui/utilities'; +import { Nullable, getImageAbsoluteURI, stringToHslColor } from '@ui/utilities'; const StyledAvatar = styled.div<{ size: AvatarSize; @@ -73,15 +73,21 @@ export const Avatar = ({ invalidAvatarUrlsState, ); - const noAvatarUrl = !isNonEmptyString(avatarUrl); + const avatarImageURI = useMemo( + () => getImageAbsoluteURI(avatarUrl), + [avatarUrl], + ); + + const noAvatarUrl = !isNonEmptyString(avatarImageURI); const placeholderChar = placeholder?.[0]?.toLocaleUpperCase(); - const showPlaceholder = noAvatarUrl || invalidAvatarUrls.includes(avatarUrl); + const showPlaceholder = + noAvatarUrl || invalidAvatarUrls.includes(avatarImageURI); const handleImageError = () => { - if (isNonEmptyString(avatarUrl)) { - setInvalidAvatarUrls((prev) => [...prev, avatarUrl]); + if (isNonEmptyString(avatarImageURI)) { + setInvalidAvatarUrls((prev) => [...prev, avatarImageURI]); } }; @@ -105,7 +111,7 @@ export const Avatar = ({ {showPlaceholder ? ( placeholderChar ) : ( - <StyledImage src={avatarUrl} onError={handleImageError} alt="" /> + <StyledImage src={avatarImageURI} onError={handleImageError} alt="" /> )} </StyledAvatar> ); diff --git a/packages/twenty-ui/src/utilities/config/index.ts b/packages/twenty-ui/src/utilities/config/index.ts new file mode 100644 index 0000000000..4525e814d6 --- /dev/null +++ b/packages/twenty-ui/src/utilities/config/index.ts @@ -0,0 +1,30 @@ +declare global { + interface Window { + _env_?: Record<string, string>; + __APOLLO_CLIENT__?: any; + } +} + +const getDefaultUrl = () => { + if ( + window.location.hostname === 'localhost' || + window.location.hostname === '127.0.0.1' + ) { + // In development environment front and backend usually run on separate ports + // we set the default value to localhost:3000. + // It dev context, we use env vars to overwrite it + return 'http://localhost:3000'; + } else { + // Outside of localhost we assume that they run on the same port + // because the backend will serve the frontend + // It prod context, we use env-config.js + window var to ovewrite it + return `${window.location.protocol}//${window.location.hostname}${ + window.location.port ? `:${window.location.port}` : '' + }`; + } +}; + +export const REACT_APP_SERVER_BASE_URL = + window._env_?.REACT_APP_SERVER_BASE_URL || + process.env.REACT_APP_SERVER_BASE_URL || + getDefaultUrl(); diff --git a/packages/twenty-ui/src/utilities/image/getImageAbsoluteURI.ts b/packages/twenty-ui/src/utilities/image/getImageAbsoluteURI.ts new file mode 100644 index 0000000000..879447d302 --- /dev/null +++ b/packages/twenty-ui/src/utilities/image/getImageAbsoluteURI.ts @@ -0,0 +1,15 @@ +import { REACT_APP_SERVER_BASE_URL } from '@ui/utilities/config'; + +export const getImageAbsoluteURI = (imageUrl?: string | null) => { + if (!imageUrl) { + return null; + } + + if (imageUrl?.startsWith('https:')) { + return imageUrl; + } + + const serverFilesUrl = REACT_APP_SERVER_BASE_URL; + + return `${serverFilesUrl}/files/${imageUrl}`; +}; diff --git a/packages/twenty-ui/src/utilities/index.ts b/packages/twenty-ui/src/utilities/index.ts index 3d99deafee..38cd4a1b60 100644 --- a/packages/twenty-ui/src/utilities/index.ts +++ b/packages/twenty-ui/src/utilities/index.ts @@ -1,4 +1,5 @@ export * from './color/utils/stringToHslColor'; +export * from './image/getImageAbsoluteURI'; export * from './isDefined'; export * from './state/utils/createState'; export * from './types/Nullable';