Skip to content

Commit

Permalink
Prefetch Skeleton Loading on Indexes and Shows (twentyhq#5545)
Browse files Browse the repository at this point in the history
### Description
Prefetch Skeleton Loading on Indexes and Shows

### Refs
twentyhq#4458

### Demo

https://jam.dev/c/a1ad04e1-80b6-4b2a-b7df-373f52f4b169

https://jam.dev/c/c5038b97-2f18-4c29-8dee-18c09376e5ee

Fixes: twentyhq#4458

---------

Co-authored-by: gitstart-twenty <[email protected]>
Co-authored-by: v1b3m <[email protected]>
Co-authored-by: Matheus <[email protected]>
Co-authored-by: Charles Bochet <[email protected]>
  • Loading branch information
5 people authored May 27, 2024
1 parent cfd83d6 commit 9c046dc
Show file tree
Hide file tree
Showing 60 changed files with 490 additions and 161 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';

import { TimelineCreateButtonGroup } from '@/activities/timeline/components/TimelineCreateButtonGroup';
import { TimelineSkeletonLoader } from '@/activities/timeline/components/TimelineSkeletonLoader';
import { timelineActivitiesForGroupState } from '@/activities/timeline/states/timelineActivitiesForGroupState';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import AnimatedPlaceholder from '@/ui/layout/animated-placeholder/components/AnimatedPlaceholder';
Expand All @@ -29,82 +28,19 @@ const StyledMainContainer = styled.div`
justify-content: center;
`;

const StyledSkeletonContainer = styled.div`
align-items: center;
width: 100%;
padding: ${({ theme }) => theme.spacing(8)};
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(4)};
flex-wrap: wrap;
align-content: flex-start;
`;

const StyledSkeletonSubSection = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
`;

const StyledSkeletonColumn = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(3)};
justify-content: center;
`;

const StyledSkeletonLoader = () => {
const theme = useTheme();
return (
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.lighter}
borderRadius={80}
>
<Skeleton width={24} height={84} />
</SkeletonTheme>
);
};

const StyledTimelineSkeletonLoader = () => {
const theme = useTheme();
const skeletonItems = Array.from({ length: 3 }).map((_, index) => ({
id: `skeleton-item-${index}`,
}));
return (
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.lighter}
borderRadius={4}
>
<StyledSkeletonContainer>
<Skeleton width={440} height={16} />
{skeletonItems.map(({ id }) => (
<StyledSkeletonSubSection key={id}>
<StyledSkeletonLoader />
<StyledSkeletonColumn>
<Skeleton width={400} height={24} />
<Skeleton width={400} height={24} />
</StyledSkeletonColumn>
</StyledSkeletonSubSection>
))}
</StyledSkeletonContainer>
</SkeletonTheme>
);
};

export const Timeline = ({
targetableObject,
loading,
}: {
targetableObject: ActivityTargetableObject;
loading?: boolean;
loading: boolean;
}) => {
const timelineActivitiesForGroup = useRecoilValue(
timelineActivitiesForGroupState,
);

if (loading === true) {
return <StyledTimelineSkeletonLoader />;
if (loading) {
return <TimelineSkeletonLoader />;
}

if (timelineActivitiesForGroup.length === 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';

const StyledSkeletonContainer = styled.div`
align-items: center;
width: 100%;
padding: ${({ theme }) => theme.spacing(8)};
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(4)};
flex-wrap: wrap;
align-content: flex-start;
`;

const StyledSkeletonSubSection = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
`;

const StyledSkeletonColumn = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(3)};
justify-content: center;
`;

const StyledSkeletonLoader = ({
isSecondColumn,
}: {
isSecondColumn: boolean;
}) => {
const theme = useTheme();
return (
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.lighter}
borderRadius={80}
>
<Skeleton width={24} height={isSecondColumn ? 120 : 84} />
</SkeletonTheme>
);
};

export const TimelineSkeletonLoader = () => {
const theme = useTheme();
const skeletonItems = Array.from({ length: 3 }).map((_, index) => ({
id: `skeleton-item-${index}`,
}));

return (
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.lighter}
borderRadius={4}
>
<StyledSkeletonContainer>
<Skeleton width={440} height={16} />
{skeletonItems.map(({ id }, index) => (
<StyledSkeletonSubSection key={id}>
<StyledSkeletonLoader isSecondColumn={index === 1} />
<StyledSkeletonColumn>
<Skeleton width={400} height={24} />
<Skeleton width={400} height={24} />
{index === 1 && <Skeleton width={400} height={24} />}
</StyledSkeletonColumn>
</StyledSkeletonSubSection>
))}
</StyledSkeletonContainer>
</SkeletonTheme>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import styled from '@emotion/styled';
import { Avatar } from 'twenty-ui';

import { FavoritesSkeletonLoader } from '@/favorites/components/FavoritesSkeletonLoader';
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem';
import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableList';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
Expand Down Expand Up @@ -32,6 +34,11 @@ const StyledNavigationDrawerItem = styled(NavigationDrawerItem)`

export const Favorites = () => {
const { favorites, handleReorderFavorite } = useFavorites();
const loading = useIsPrefetchLoading();

if (loading) {
return <FavoritesSkeletonLoader />;
}

if (!favorites || favorites.length === 0) return <></>;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';

const StyledSkeletonContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
height: 71px;
padding-left: ${({ theme }) => theme.spacing(1)};
`;

const StyledSkeletonColumn = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
`;

export const FavoritesSkeletonLoader = () => {
const theme = useTheme();
return (
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.lighter}
borderRadius={4}
>
<StyledSkeletonContainer>
<Skeleton width={56} height={13} />
<StyledSkeletonColumn>
<Skeleton width={196} height={16} />
<Skeleton width={196} height={16} />
</StyledSkeletonColumn>
</StyledSkeletonContainer>
</SkeletonTheme>
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useLocation } from 'react-router-dom';
import { useIcons } from 'twenty-ui';

import { ObjectMetadataNavItemsSkeletonLoader } from '@/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
Expand All @@ -14,6 +16,11 @@ export const ObjectMetadataNavItems = () => {
const currentPath = useLocation().pathname;

const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const loading = useIsPrefetchLoading();

if (loading) {
return <ObjectMetadataNavItemsSkeletonLoader />;
}

return (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';

const StyledSkeletonColumn = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(1)};
height: 76px;
padding-left: ${({ theme }) => theme.spacing(1)};
`;

export const ObjectMetadataNavItemsSkeletonLoader: React.FC = () => {
const theme = useTheme();
return (
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.light}
borderRadius={4}
>
<StyledSkeletonColumn>
<Skeleton width={196} height={16} />
<Skeleton width={196} height={16} />
<Skeleton width={196} height={16} />
</StyledSkeletonColumn>
</SkeletonTheme>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/Componen
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';

Expand All @@ -20,6 +21,7 @@ const meta: Meta<typeof ObjectMetadataNavItems> = {
ComponentWithRouterDecorator,
ComponentWithRecoilScopeDecorator,
SnackBarDecorator,
PrefetchLoadingDecorator,
],
parameters: {
msw: graphqlMocks,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';

const StyledSkeletonDiv = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
width: 100%;
height: 24px;
`;
export const PropertyBoxSkeletonLoader = () => {
const theme = useTheme();
const skeletonItems = Array.from({ length: 4 }).map((_, index) => ({
id: `skeleton-item-${index}`,
}));
return (
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.lighter}
borderRadius={4}
>
{skeletonItems.map(({ id }) => (
<StyledSkeletonDiv key={id}>
<Skeleton width={92} height={16} />
<Skeleton width={154} height={16} />
</StyledSkeletonDiv>
))}
</SkeletonTheme>
);
};
Loading

0 comments on commit 9c046dc

Please sign in to comment.