Fix: Replace styled logo with Avatar component for workspace logo in NavigationDrawerHeader (#9093)

This PR addresses issue #9042

- Replaced the styled logo with the `Avatar` component.
- `Avatar` now handles the case when no `logo` is uploaded by using the
workspace name's first character as the `placeholder`.
- This ensures a consistent fallback when the `logo` is undefined.

---------

Co-authored-by: guillim <guigloo@msn.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Murali Singh 2024-12-18 01:12:06 +05:30 committed by GitHub
parent 07bde4883e
commit fb8d193238
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 15 additions and 44 deletions

View File

@ -14,22 +14,12 @@ import { useTheme } from '@emotion/react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useState } from 'react'; import { useState } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil'; import { useRecoilState, useRecoilValue } from 'recoil';
import { getImageAbsoluteURI } from 'twenty-shared';
import { import {
Avatar,
IconChevronDown, IconChevronDown,
MenuItemSelectAvatar, MenuItemSelectAvatar,
UndecoratedLink, UndecoratedLink,
} from 'twenty-ui'; } from 'twenty-ui';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
const StyledLogo = styled.div<{ logo: string }>`
background: url(${({ logo }) => logo});
background-position: center;
background-size: cover;
border-radius: ${({ theme }) => theme.border.radius.xs};
height: 16px;
width: 16px;
`;
const StyledContainer = styled.div<{ isNavigationDrawerExpanded: boolean }>` const StyledContainer = styled.div<{ isNavigationDrawerExpanded: boolean }>`
align-items: center; align-items: center;
@ -102,13 +92,9 @@ export const MultiWorkspaceDropdownButton = ({
data-testid="workspace-dropdown" data-testid="workspace-dropdown"
isNavigationDrawerExpanded={isNavigationDrawerExpanded} isNavigationDrawerExpanded={isNavigationDrawerExpanded}
> >
<StyledLogo <Avatar
logo={ placeholder={currentWorkspace?.displayName || ''}
getImageAbsoluteURI({ avatarUrl={currentWorkspace?.logo ?? DEFAULT_WORKSPACE_LOGO}
imageUrl: currentWorkspace?.logo ?? '',
baseUrl: REACT_APP_SERVER_BASE_URL,
}) ?? ''
}
/> />
<NavigationDrawerAnimatedCollapseWrapper> <NavigationDrawerAnimatedCollapseWrapper>
<StyledLabel>{currentWorkspace?.displayName ?? ''}</StyledLabel> <StyledLabel>{currentWorkspace?.displayName ?? ''}</StyledLabel>
@ -135,13 +121,9 @@ export const MultiWorkspaceDropdownButton = ({
<MenuItemSelectAvatar <MenuItemSelectAvatar
text={workspace.displayName ?? '(No name)'} text={workspace.displayName ?? '(No name)'}
avatar={ avatar={
<StyledLogo <Avatar
logo={ placeholder={workspace.displayName || ''}
getImageAbsoluteURI({ avatarUrl={workspace.logo ?? DEFAULT_WORKSPACE_LOGO}
imageUrl: workspace.logo ?? DEFAULT_WORKSPACE_LOGO,
baseUrl: REACT_APP_SERVER_BASE_URL,
}) ?? ''
}
/> />
} }
selected={currentWorkspace?.id === workspace.id} selected={currentWorkspace?.id === workspace.id}

View File

@ -7,11 +7,11 @@ import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/consta
import { DEFAULT_WORKSPACE_NAME } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceName'; import { DEFAULT_WORKSPACE_NAME } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceName';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWorkspaceEnabledState';
import { NavigationDrawerAnimatedCollapseWrapper } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerAnimatedCollapseWrapper'; import { NavigationDrawerAnimatedCollapseWrapper } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerAnimatedCollapseWrapper';
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded'; import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
import { isNonEmptyString } from '@sniptt/guards'; import { Avatar } from 'twenty-ui';
import { NavigationDrawerCollapseButton } from './NavigationDrawerCollapseButton'; import { NavigationDrawerCollapseButton } from './NavigationDrawerCollapseButton';
import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWorkspaceEnabledState';
const StyledContainer = styled.div` const StyledContainer = styled.div`
align-items: center; align-items: center;
@ -19,20 +19,12 @@ const StyledContainer = styled.div`
height: ${({ theme }) => theme.spacing(8)}; height: ${({ theme }) => theme.spacing(8)};
user-select: none; user-select: none;
`; `;
const StyledSingleWorkspaceContainer = styled(StyledContainer)` const StyledSingleWorkspaceContainer = styled(StyledContainer)`
gap: ${({ theme }) => theme.spacing(2)}; gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(1)}; padding: ${({ theme }) => theme.spacing(1)};
`; `;
const StyledLogo = styled.div<{ logo: string }>`
background: url(${({ logo }) => logo});
background-position: center;
background-size: cover;
border-radius: ${({ theme }) => theme.border.radius.xs};
height: 16px;
width: 16px;
`;
const StyledName = styled.div` const StyledName = styled.div`
color: ${({ theme }) => theme.font.color.primary}; color: ${({ theme }) => theme.font.color.primary};
font-family: 'Inter'; font-family: 'Inter';
@ -75,9 +67,7 @@ export const NavigationDrawerHeader = ({
<MultiWorkspaceDropdownButton workspaces={workspaces} /> <MultiWorkspaceDropdownButton workspaces={workspaces} />
) : ( ) : (
<StyledSingleWorkspaceContainer> <StyledSingleWorkspaceContainer>
<StyledLogo <Avatar placeholder={name} avatarUrl={logo} />
logo={isNonEmptyString(logo) ? logo : DEFAULT_WORKSPACE_LOGO}
/>
<NavigationDrawerAnimatedCollapseWrapper> <NavigationDrawerAnimatedCollapseWrapper>
<StyledName>{name}</StyledName> <StyledName>{name}</StyledName>
</NavigationDrawerAnimatedCollapseWrapper> </NavigationDrawerAnimatedCollapseWrapper>

View File

@ -1,4 +1,5 @@
import { workspacePublicDataState } from '@/auth/states/workspacePublicDataState'; import { workspacePublicDataState } from '@/auth/states/workspacePublicDataState';
import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo';
import { Helmet } from 'react-helmet-async'; import { Helmet } from 'react-helmet-async';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { getImageAbsoluteURI } from 'twenty-shared'; import { getImageAbsoluteURI } from 'twenty-shared';
@ -16,7 +17,7 @@ export const PageFavicon = () => {
getImageAbsoluteURI({ getImageAbsoluteURI({
imageUrl: workspacePublicData.logo, imageUrl: workspacePublicData.logo,
baseUrl: REACT_APP_SERVER_BASE_URL, baseUrl: REACT_APP_SERVER_BASE_URL,
}) ?? '' }) ?? DEFAULT_WORKSPACE_LOGO
} }
/> />
)} )}

View File

@ -1,5 +1,5 @@
import { styled } from '@linaria/react'; import { styled } from '@linaria/react';
import { isNonEmptyString, isUndefined } from '@sniptt/guards'; import { isNonEmptyString, isNull, isUndefined } from '@sniptt/guards';
import { useContext } from 'react'; import { useContext } from 'react';
import { useRecoilState } from 'recoil'; import { useRecoilState } from 'recoil';
@ -90,12 +90,10 @@ export const Avatar = ({
}) })
: null; : null;
const noAvatarUrl = !isNonEmptyString(avatarImageURI);
const placeholderChar = placeholder?.[0]?.toLocaleUpperCase(); const placeholderChar = placeholder?.[0]?.toLocaleUpperCase();
const showPlaceholder = const showPlaceholder =
noAvatarUrl || invalidAvatarUrls.includes(avatarImageURI); isNull(avatarImageURI) || invalidAvatarUrls.includes(avatarImageURI);
const handleImageError = () => { const handleImageError = () => {
if (isNonEmptyString(avatarImageURI)) { if (isNonEmptyString(avatarImageURI)) {