From 10abd7f0ad4dd1e06d22e47e43370880abd856ac Mon Sep 17 00:00:00 2001 From: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com> Date: Mon, 27 May 2024 16:38:37 +0800 Subject: [PATCH] User & Metadata Loading (#5347) ### Description User & Metadata Loading ### Refs #4456 ### Demo https://github.com/twentyhq/twenty/assets/140154534/4c20fca6-feaf-45f6-ac50-6532d2ebf050 Fixes #4456 --------- Co-authored-by: gitstart-twenty Co-authored-by: v1b3m Co-authored-by: Thiago Nascimbeni Co-authored-by: Charles Bochet --- .../components/LeftPanelSkeletonLoader.tsx | 74 +++++++++++++++ ...ainNavigationDrawerItemsSkeletonLoader.tsx | 34 +++++++ .../components/RightPanelSkeletonLoader.tsx | 92 +++++++++++++++++++ .../components/UserOrMetadataLoader.tsx | 32 +++++++ .../loading/hooks/useUserOrMetadataLoading.ts | 11 +++ .../ObjectMetadataItemsProvider.tsx | 5 +- .../modules/users/components/UserProvider.tsx | 3 +- 7 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 packages/twenty-front/src/loading/components/LeftPanelSkeletonLoader.tsx create mode 100644 packages/twenty-front/src/loading/components/MainNavigationDrawerItemsSkeletonLoader.tsx create mode 100644 packages/twenty-front/src/loading/components/RightPanelSkeletonLoader.tsx create mode 100644 packages/twenty-front/src/loading/components/UserOrMetadataLoader.tsx create mode 100644 packages/twenty-front/src/loading/hooks/useUserOrMetadataLoading.ts diff --git a/packages/twenty-front/src/loading/components/LeftPanelSkeletonLoader.tsx b/packages/twenty-front/src/loading/components/LeftPanelSkeletonLoader.tsx new file mode 100644 index 000000000000..9920568fca3a --- /dev/null +++ b/packages/twenty-front/src/loading/components/LeftPanelSkeletonLoader.tsx @@ -0,0 +1,74 @@ +import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; +import styled from '@emotion/styled'; +import { motion } from 'framer-motion'; +import { ANIMATION, BACKGROUND_LIGHT, GRAY_SCALE } from 'twenty-ui'; + +import { DESKTOP_NAV_DRAWER_WIDTHS } from '@/ui/navigation/navigation-drawer/constants/DesktopNavDrawerWidths'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; +import { MainNavigationDrawerItemsSkeletonLoader } from '~/loading/components/MainNavigationDrawerItemsSkeletonLoader'; + +const StyledAnimatedContainer = styled(motion.div)` + display: flex; + justify-content: end; +`; + +const StyledItemsContainer = styled.div` + display: flex; + flex-direction: column; + gap: 32px; + margin-bottom: auto; + overflow-y: auto; + height: calc(100vh - 32px); + min-width: 216px; + max-width: 216px; +`; + +const StyledSkeletonContainer = styled.div` + display: flex; + flex-direction: column; + gap: 32px; +`; + +const StyledSkeletonTitleContainer = styled.div` + display: flex; + flex-direction: column; + gap: 6px; + margin-left: 12px; + margin-top: 8px; +`; + +export const LeftPanelSkeletonLoader = () => { + const isMobile = useIsMobile(); + const mobileWidth = isMobile ? 0 : '100%'; + const desktopWidth = !mobileWidth ? 12 : DESKTOP_NAV_DRAWER_WIDTHS.menu; + + return ( + + + + + + + + + + + + + + + ); +}; diff --git a/packages/twenty-front/src/loading/components/MainNavigationDrawerItemsSkeletonLoader.tsx b/packages/twenty-front/src/loading/components/MainNavigationDrawerItemsSkeletonLoader.tsx new file mode 100644 index 000000000000..b13b1bb884d6 --- /dev/null +++ b/packages/twenty-front/src/loading/components/MainNavigationDrawerItemsSkeletonLoader.tsx @@ -0,0 +1,34 @@ +import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; +import styled from '@emotion/styled'; +import { BACKGROUND_LIGHT, GRAY_SCALE } from 'twenty-ui'; + +const StyledSkeletonContainer = styled.div` + display: flex; + flex-direction: column; + gap: 6px; + margin-left: 12px; + margin-top: 8px; +`; + +export const MainNavigationDrawerItemsSkeletonLoader = ({ + title, + length, +}: { + title?: boolean; + length: number; +}) => { + return ( + + + {title && } + {Array.from({ length }).map((_, index) => ( + + ))} + + + ); +}; diff --git a/packages/twenty-front/src/loading/components/RightPanelSkeletonLoader.tsx b/packages/twenty-front/src/loading/components/RightPanelSkeletonLoader.tsx new file mode 100644 index 000000000000..e42dc5fec01e --- /dev/null +++ b/packages/twenty-front/src/loading/components/RightPanelSkeletonLoader.tsx @@ -0,0 +1,92 @@ +import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; +import styled from '@emotion/styled'; +import { + BACKGROUND_LIGHT, + BORDER_COMMON, + BORDER_LIGHT, + GRAY_SCALE, + MOBILE_VIEWPORT, +} from 'twenty-ui'; + +const StyledMainContainer = styled.div` + background: ${BACKGROUND_LIGHT.noisy}; + box-sizing: border-box; + display: flex; + flex: 1 1 auto; + flex-direction: row; + gap: 8px; + min-height: 0; + padding-left: 0; + width: 100%; + + @media (max-width: ${MOBILE_VIEWPORT}px) { + padding-left: 12px; + padding-bottom: 0; + } +`; + +const StyledPanel = styled.div` + background: ${BACKGROUND_LIGHT.primary}; + border: 1px solid ${BORDER_LIGHT.color.medium}; + border-radius: ${BORDER_COMMON.radius.md}; + height: 100%; + overflow: auto; + width: 100%; +`; + +const StyledHeaderContainer = styled.div` + flex: 1; +`; +const StyledRightPanelContainer = styled.div` + display: flex; + flex-direction: column; + width: 100%; +`; + +const StyledRightPanelFlexContainer = styled.div` + display: flex; + margin-top: 12px; + margin-bottom: 14px; +`; + +const StyledSkeletonHeaderLoader = () => { + return ( + + + + + + ); +}; + +const StyledSkeletonAddLoader = () => { + return ( + + + + ); +}; + +const RightPanelSkeleton = () => ( + + + +); + +export const RightPanelSkeletonLoader = () => ( + + + + + + + +); diff --git a/packages/twenty-front/src/loading/components/UserOrMetadataLoader.tsx b/packages/twenty-front/src/loading/components/UserOrMetadataLoader.tsx new file mode 100644 index 000000000000..d4d078619bb9 --- /dev/null +++ b/packages/twenty-front/src/loading/components/UserOrMetadataLoader.tsx @@ -0,0 +1,32 @@ +import styled from '@emotion/styled'; +import { BACKGROUND_LIGHT, MOBILE_VIEWPORT } from 'twenty-ui'; + +import { DESKTOP_NAV_DRAWER_WIDTHS } from '@/ui/navigation/navigation-drawer/constants/DesktopNavDrawerWidths'; +import { LeftPanelSkeletonLoader } from '~/loading/components/LeftPanelSkeletonLoader'; +import { RightPanelSkeletonLoader } from '~/loading/components/RightPanelSkeletonLoader'; + +const StyledContainer = styled.div` + background: ${BACKGROUND_LIGHT.noisy}; + box-sizing: border-box; + display: flex; + flex-direction: row; + gap: 12px; + height: 100vh; + min-width: ${DESKTOP_NAV_DRAWER_WIDTHS.menu}px; + width: 100%; + padding: 12px 8px 12px; + overflow: hidden; + + @media (max-width: ${MOBILE_VIEWPORT}px) { + width: 100%; + } +`; + +export const UserOrMetadataLoader = () => { + return ( + + + + + ); +}; diff --git a/packages/twenty-front/src/loading/hooks/useUserOrMetadataLoading.ts b/packages/twenty-front/src/loading/hooks/useUserOrMetadataLoading.ts new file mode 100644 index 000000000000..b35cdb3dd02d --- /dev/null +++ b/packages/twenty-front/src/loading/hooks/useUserOrMetadataLoading.ts @@ -0,0 +1,11 @@ +import { useRecoilValue } from 'recoil'; + +import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadingState'; +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; + +export const useUserOrMetadataLoading = () => { + const isCurrentUserLoaded = useRecoilValue(isCurrentUserLoadedState); + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); + + return !isCurrentUserLoaded || objectMetadataItems.length === 0; +}; diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx index 85f240db9e7a..b374d13e1d6d 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx @@ -4,6 +4,7 @@ import { useRecoilValue } from 'recoil'; import { ObjectMetadataItemsLoadEffect } from '@/object-metadata/components/ObjectMetadataItemsLoadEffect'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope'; +import { UserOrMetadataLoader } from '~/loading/components/UserOrMetadataLoader'; export const ObjectMetadataItemsProvider = ({ children, @@ -15,10 +16,12 @@ export const ObjectMetadataItemsProvider = ({ return ( <> - {shouldDisplayChildren && ( + {shouldDisplayChildren ? ( {children} + ) : ( + )} ); diff --git a/packages/twenty-front/src/modules/users/components/UserProvider.tsx b/packages/twenty-front/src/modules/users/components/UserProvider.tsx index 5287cb4e24f4..806bcf35ebf1 100644 --- a/packages/twenty-front/src/modules/users/components/UserProvider.tsx +++ b/packages/twenty-front/src/modules/users/components/UserProvider.tsx @@ -2,9 +2,10 @@ import React from 'react'; import { useRecoilValue } from 'recoil'; import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadingState'; +import { UserOrMetadataLoader } from '~/loading/components/UserOrMetadataLoader'; export const UserProvider = ({ children }: React.PropsWithChildren) => { const isCurrentUserLoaded = useRecoilValue(isCurrentUserLoadedState); - return !isCurrentUserLoaded ? <> : <>{children}; + return !isCurrentUserLoaded ? : <>{children}; };