Prefetch Skeleton Loading on Indexes and Shows (#5545)
### Description Prefetch Skeleton Loading on Indexes and Shows ### Refs #4458 ### Demo https://jam.dev/c/a1ad04e1-80b6-4b2a-b7df-373f52f4b169 https://jam.dev/c/c5038b97-2f18-4c29-8dee-18c09376e5ee Fixes: #4458 --------- Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com> Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: Matheus <matheus_benini@hotmail.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -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';
|
||||
@ -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) {
|
||||
|
||||
@ -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>
|
||||
);
|
||||
};
|
||||
@ -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';
|
||||
@ -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 <></>;
|
||||
|
||||
|
||||
@ -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>
|
||||
);
|
||||
};
|
||||
@ -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';
|
||||
@ -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 (
|
||||
<>
|
||||
|
||||
@ -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>
|
||||
);
|
||||
};
|
||||
@ -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';
|
||||
|
||||
@ -20,6 +21,7 @@ const meta: Meta<typeof ObjectMetadataNavItems> = {
|
||||
ComponentWithRouterDecorator,
|
||||
ComponentWithRecoilScopeDecorator,
|
||||
SnackBarDecorator,
|
||||
PrefetchLoadingDecorator,
|
||||
],
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -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>
|
||||
);
|
||||
};
|
||||
@ -12,6 +12,7 @@ import {
|
||||
} from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell';
|
||||
import { PropertyBox } from '@/object-record/record-inline-cell/property-box/components/PropertyBox';
|
||||
import { PropertyBoxSkeletonLoader } from '@/object-record/record-inline-cell/property-box/components/PropertyBoxSkeletonLoader';
|
||||
import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
|
||||
import { RecordDetailDuplicatesSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailDuplicatesSection';
|
||||
import { RecordDetailRelationSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationSection';
|
||||
@ -19,6 +20,7 @@ import { recordLoadingFamilyState } from '@/object-record/record-store/states/re
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { recordStoreIdentifierFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreIdentifierSelector';
|
||||
import { isFieldCellSupported } from '@/object-record/utils/isFieldCellSupported';
|
||||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||
import { ShowPageContainer } from '@/ui/layout/page/ShowPageContainer';
|
||||
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
|
||||
import { ShowPageRightContainer } from '@/ui/layout/show-page/components/ShowPageRightContainer';
|
||||
@ -127,6 +129,7 @@ export const RecordShowContainer = ({
|
||||
);
|
||||
|
||||
const isReadOnly = objectMetadataItem.isRemote;
|
||||
const isPrefetchLoading = useIsPrefetchLoading();
|
||||
|
||||
return (
|
||||
<RecoilScope CustomRecoilScopeContext={ShowPageRecoilScopeContext}>
|
||||
@ -139,7 +142,7 @@ export const RecordShowContainer = ({
|
||||
logoOrAvatar={recordIdentifier?.avatarUrl ?? ''}
|
||||
avatarPlaceholder={recordIdentifier?.name ?? ''}
|
||||
date={recordFromStore.createdAt ?? ''}
|
||||
loading={loading || recordLoading}
|
||||
loading={isPrefetchLoading || loading || recordLoading}
|
||||
title={
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
@ -176,32 +179,36 @@ export const RecordShowContainer = ({
|
||||
}
|
||||
/>
|
||||
<PropertyBox>
|
||||
{inlineFieldMetadataItems.map((fieldMetadataItem, index) => (
|
||||
<FieldContext.Provider
|
||||
key={objectRecordId + fieldMetadataItem.id}
|
||||
value={{
|
||||
entityId: objectRecordId,
|
||||
maxWidth: 200,
|
||||
recoilScopeId: objectRecordId + fieldMetadataItem.id,
|
||||
isLabelIdentifier: false,
|
||||
fieldDefinition:
|
||||
formatFieldMetadataItemAsColumnDefinition({
|
||||
field: fieldMetadataItem,
|
||||
position: index,
|
||||
objectMetadataItem,
|
||||
showLabel: true,
|
||||
labelWidth: 90,
|
||||
}),
|
||||
useUpdateRecord: useUpdateOneObjectRecordMutation,
|
||||
hotkeyScope: InlineCellHotkeyScope.InlineCell,
|
||||
}}
|
||||
>
|
||||
<RecordInlineCell
|
||||
loading={loading || recordLoading}
|
||||
readonly={isReadOnly}
|
||||
/>
|
||||
</FieldContext.Provider>
|
||||
))}
|
||||
{isPrefetchLoading ? (
|
||||
<PropertyBoxSkeletonLoader />
|
||||
) : (
|
||||
inlineFieldMetadataItems.map((fieldMetadataItem, index) => (
|
||||
<FieldContext.Provider
|
||||
key={objectRecordId + fieldMetadataItem.id}
|
||||
value={{
|
||||
entityId: objectRecordId,
|
||||
maxWidth: 200,
|
||||
recoilScopeId: objectRecordId + fieldMetadataItem.id,
|
||||
isLabelIdentifier: false,
|
||||
fieldDefinition:
|
||||
formatFieldMetadataItemAsColumnDefinition({
|
||||
field: fieldMetadataItem,
|
||||
position: index,
|
||||
objectMetadataItem,
|
||||
showLabel: true,
|
||||
labelWidth: 90,
|
||||
}),
|
||||
useUpdateRecord: useUpdateOneObjectRecordMutation,
|
||||
hotkeyScope: InlineCellHotkeyScope.InlineCell,
|
||||
}}
|
||||
>
|
||||
<RecordInlineCell
|
||||
loading={loading || recordLoading}
|
||||
readonly={isReadOnly}
|
||||
/>
|
||||
</FieldContext.Provider>
|
||||
))
|
||||
)}
|
||||
</PropertyBox>
|
||||
<RecordDetailDuplicatesSection
|
||||
objectRecordId={objectRecordId}
|
||||
@ -224,7 +231,7 @@ export const RecordShowContainer = ({
|
||||
}}
|
||||
>
|
||||
<RecordDetailRelationSection
|
||||
loading={loading || recordLoading}
|
||||
loading={isPrefetchLoading || loading || recordLoading}
|
||||
/>
|
||||
</FieldContext.Provider>
|
||||
))}
|
||||
@ -241,7 +248,7 @@ export const RecordShowContainer = ({
|
||||
tasks
|
||||
notes
|
||||
emails
|
||||
loading={loading || recordLoading}
|
||||
loading={isPrefetchLoading || loading || recordLoading}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { useCallback, useContext } from 'react';
|
||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import qs from 'qs';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@ -13,6 +11,7 @@ import { usePersistField } from '@/object-record/record-field/hooks/usePersistFi
|
||||
import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { RecordDetailRelationRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsList';
|
||||
import { RecordDetailRelationRecordsListEmptyState } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListEmptyState';
|
||||
import { RecordDetailRelationSectionSkeletonLoader } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationSectionSkeletonLoader';
|
||||
import { RecordDetailSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailSection';
|
||||
import { RecordDetailSectionHeader } from '@/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
@ -37,25 +36,6 @@ const StyledAddDropdown = styled(Dropdown)`
|
||||
margin-left: auto;
|
||||
`;
|
||||
|
||||
const StyledSkeletonDiv = styled.div`
|
||||
height: 40px;
|
||||
`;
|
||||
|
||||
const StyledRecordDetailRelationSectionSkeletonLoader = () => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.tertiary}
|
||||
highlightColor={theme.background.transparent.lighter}
|
||||
borderRadius={4}
|
||||
>
|
||||
<StyledSkeletonDiv>
|
||||
<Skeleton width={129} height={16} />
|
||||
</StyledSkeletonDiv>
|
||||
</SkeletonTheme>
|
||||
);
|
||||
};
|
||||
|
||||
export const RecordDetailRelationSection = ({
|
||||
loading,
|
||||
}: RecordDetailRelationSectionProps) => {
|
||||
@ -142,7 +122,11 @@ export const RecordDetailRelationSection = ({
|
||||
|
||||
const showContent = () => {
|
||||
if (loading) {
|
||||
return <StyledRecordDetailRelationSectionSkeletonLoader />;
|
||||
return (
|
||||
<RecordDetailRelationSectionSkeletonLoader
|
||||
numSkeletons={fieldName === 'people' ? 2 : 1}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return relationRecords.length ? (
|
||||
|
||||
@ -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`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
height: 40px;
|
||||
`;
|
||||
|
||||
export const RecordDetailRelationSectionSkeletonLoader = ({
|
||||
numSkeletons = 1,
|
||||
}: {
|
||||
numSkeletons?: number;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.tertiary}
|
||||
highlightColor={theme.background.transparent.lighter}
|
||||
borderRadius={4}
|
||||
>
|
||||
<StyledSkeletonDiv>
|
||||
{Array.from({ length: numSkeletons }).map((_, index) => (
|
||||
<Skeleton key={index} width={129} height={16} />
|
||||
))}
|
||||
</StyledSkeletonDiv>
|
||||
</SkeletonTheme>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,14 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
|
||||
export const useIsPrefetchLoading = () => {
|
||||
const areViewsPrefetched = useRecoilValue(
|
||||
prefetchIsLoadedFamilyState(PrefetchKey.AllViews),
|
||||
);
|
||||
const areFavoritesPrefetched = useRecoilValue(
|
||||
prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites),
|
||||
);
|
||||
return !areViewsPrefetched || !areFavoritesPrefetched;
|
||||
};
|
||||
@ -7,6 +7,8 @@ import { IconHelpCircle } from 'twenty-ui';
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { supportChatState } from '@/client-config/states/supportChatState';
|
||||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||
import { SupportChatSkeletonLoader } from '@/support/components/SupportChatSkeletonLoader';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||
import { User } from '~/generated/graphql';
|
||||
@ -37,6 +39,7 @@ export const SupportChat = () => {
|
||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||
const supportChat = useRecoilValue(supportChatState);
|
||||
const [isFrontChatLoaded, setIsFrontChatLoaded] = useState(false);
|
||||
const loading = useIsPrefetchLoading();
|
||||
|
||||
const configureFront = useCallback(
|
||||
(
|
||||
@ -98,6 +101,10 @@ export const SupportChat = () => {
|
||||
currentWorkspaceMember,
|
||||
]);
|
||||
|
||||
if (loading) {
|
||||
return <SupportChatSkeletonLoader />;
|
||||
}
|
||||
|
||||
return isFrontChatLoaded ? (
|
||||
<StyledButtonContainer>
|
||||
<Button
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
||||
import { useTheme } from '@emotion/react';
|
||||
|
||||
export const SupportChatSkeletonLoader = () => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.tertiary}
|
||||
highlightColor={theme.background.transparent.lighter}
|
||||
borderRadius={4}
|
||||
>
|
||||
<Skeleton width={84} height={24} />
|
||||
</SkeletonTheme>
|
||||
);
|
||||
};
|
||||
@ -7,6 +7,7 @@ import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { supportChatState } from '@/client-config/states/supportChatState';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import {
|
||||
mockDefaultWorkspace,
|
||||
@ -35,6 +36,7 @@ const meta: Meta<typeof SupportChat> = {
|
||||
|
||||
return <Story />;
|
||||
},
|
||||
PrefetchLoadingDecorator,
|
||||
],
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -12,6 +12,9 @@ const meta: Meta = {
|
||||
maxWidth: 100,
|
||||
children: 'This is a long text that should be truncated',
|
||||
},
|
||||
parameters: {
|
||||
chromatic: { disableSnapshot: true },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@ -53,7 +53,7 @@ type ShowPageRightContainerProps = {
|
||||
tasks?: boolean;
|
||||
notes?: boolean;
|
||||
emails?: boolean;
|
||||
loading?: boolean;
|
||||
loading: boolean;
|
||||
};
|
||||
|
||||
export const ShowPageRightContainer = ({
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||
import { NavigationDrawerSectionTitleSkeletonLoader } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitleSkeletonLoader';
|
||||
|
||||
type NavigationDrawerSectionTitleProps = {
|
||||
label: string;
|
||||
};
|
||||
@ -15,4 +18,11 @@ const StyledTitle = styled.div`
|
||||
|
||||
export const NavigationDrawerSectionTitle = ({
|
||||
label,
|
||||
}: NavigationDrawerSectionTitleProps) => <StyledTitle>{label}</StyledTitle>;
|
||||
}: NavigationDrawerSectionTitleProps) => {
|
||||
const loading = useIsPrefetchLoading();
|
||||
return loading ? (
|
||||
<NavigationDrawerSectionTitleSkeletonLoader />
|
||||
) : (
|
||||
<StyledTitle>{label}</StyledTitle>
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const StyledSkeletonTitle = styled.div`
|
||||
margin-bottom: ${(props) => props.theme.spacing(2)};
|
||||
padding-left: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
export const NavigationDrawerSectionTitleSkeletonLoader = () => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.tertiary}
|
||||
highlightColor={theme.background.transparent.lighter}
|
||||
borderRadius={4}
|
||||
>
|
||||
<StyledSkeletonTitle>
|
||||
<Skeleton width={56} height={13} />
|
||||
</StyledSkeletonTitle>
|
||||
</SkeletonTheme>
|
||||
);
|
||||
};
|
||||
@ -4,12 +4,14 @@ import { useParams } from 'react-router-dom';
|
||||
import { ObjectFilterDropdownButton } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownButton';
|
||||
import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
|
||||
import { ObjectSortDropdownButton } from '@/object-record/object-sort-dropdown/components/ObjectSortDropdownButton';
|
||||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||
import { TopBar } from '@/ui/layout/top-bar/TopBar';
|
||||
import { QueryParamsFiltersEffect } from '@/views/components/QueryParamsFiltersEffect';
|
||||
import { QueryParamsViewIdEffect } from '@/views/components/QueryParamsViewIdEffect';
|
||||
import { ViewBarEffect } from '@/views/components/ViewBarEffect';
|
||||
import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
|
||||
import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle';
|
||||
import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader';
|
||||
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
|
||||
import { ViewScope } from '@/views/scopes/ViewScope';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
@ -38,6 +40,8 @@ export const ViewBar = ({
|
||||
const filterDropdownId = 'view-filter';
|
||||
const sortDropdownId = 'view-sort';
|
||||
|
||||
const loading = useIsPrefetchLoading();
|
||||
|
||||
if (!objectNamePlural) {
|
||||
return;
|
||||
}
|
||||
@ -57,9 +61,7 @@ export const ViewBar = ({
|
||||
<TopBar
|
||||
className={className}
|
||||
leftComponent={
|
||||
<>
|
||||
<ViewPickerDropdown />
|
||||
</>
|
||||
loading ? <ViewBarSkeletonLoader /> : <ViewPickerDropdown />
|
||||
}
|
||||
displayBottomBorder={false}
|
||||
rightComponent={
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
||||
import { useTheme } from '@emotion/react';
|
||||
|
||||
export const ViewBarSkeletonLoader = () => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.tertiary}
|
||||
highlightColor={theme.background.transparent.lighter}
|
||||
borderRadius={4}
|
||||
>
|
||||
<Skeleton width={140} height={16} />
|
||||
</SkeletonTheme>
|
||||
);
|
||||
};
|
||||
@ -9,6 +9,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockedOnboardingUsersData } from '~/testing/mock-data/users';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
@ -18,7 +19,7 @@ import { ChooseYourPlan } from '../ChooseYourPlan';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Auth/ChooseYourPlan',
|
||||
component: ChooseYourPlan,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: AppPath.PlanRequired },
|
||||
parameters: {
|
||||
msw: {
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockedOnboardingUsersData } from '~/testing/mock-data/users';
|
||||
|
||||
@ -17,7 +18,7 @@ import { CreateProfile } from '../CreateProfile';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Auth/CreateProfile',
|
||||
component: CreateProfile,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: AppPath.CreateProfile },
|
||||
parameters: {
|
||||
msw: {
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockedOnboardingUsersData } from '~/testing/mock-data/users';
|
||||
|
||||
@ -25,6 +26,7 @@ const meta: Meta<PageDecoratorArgs> = {
|
||||
setCurrentWorkspace(mockedOnboardingUsersData[1].defaultWorkspace);
|
||||
return <Story />;
|
||||
},
|
||||
PrefetchLoadingDecorator,
|
||||
PageDecorator,
|
||||
],
|
||||
args: { routePath: AppPath.CreateWorkspace },
|
||||
|
||||
@ -10,13 +10,14 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockedOnboardingUsersData } from '~/testing/mock-data/users';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Auth/PasswordReset',
|
||||
component: PasswordReset,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/reset-password/:passwordResetToken',
|
||||
routeParams: { ':passwordResetToken': 'MOCKED_TOKEN' },
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockedOnboardingUsersData } from '~/testing/mock-data/users';
|
||||
|
||||
@ -17,7 +18,7 @@ import { PaymentSuccess } from '../PaymentSuccess';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Auth/PaymentSuccess',
|
||||
component: PaymentSuccess,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: AppPath.PlanRequiredSuccess },
|
||||
parameters: {
|
||||
msw: {
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SignInUp } from '../SignInUp';
|
||||
@ -16,7 +17,7 @@ import { SignInUp } from '../SignInUp';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Auth/SignInUp',
|
||||
component: SignInUp,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: AppPath.SignInUp },
|
||||
parameters: {
|
||||
msw: {
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
@ -13,7 +14,7 @@ import { ImpersonateEffect } from '../ImpersonateEffect';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Impersonate/Impersonate',
|
||||
component: ImpersonateEffect,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: AppPath.Impersonate,
|
||||
routeParams: { ':userId': '1' },
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { expect } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { within } from '@storybook/test';
|
||||
|
||||
import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { RecordIndexPage } from '../RecordIndexPage';
|
||||
@ -27,4 +30,26 @@ export default meta;
|
||||
|
||||
export type Story = StoryObj<typeof RecordIndexPage>;
|
||||
|
||||
export const Default: Story = {};
|
||||
export const Default: Story = {
|
||||
decorators: [PrefetchLoadingDecorator],
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
await canvas.findByText('People');
|
||||
await canvas.findAllByText('Companies');
|
||||
await canvas.findByText('Opportunities');
|
||||
await canvas.findByText('Listings');
|
||||
await canvas.findByText('My Customs');
|
||||
},
|
||||
};
|
||||
|
||||
export const Loading: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
expect(canvas.queryByText('People')).toBeNull();
|
||||
expect(canvas.queryByText('Opportunities')).toBeNull();
|
||||
expect(canvas.queryByText('Listings')).toBeNull();
|
||||
expect(canvas.queryByText('My Customs')).toBeNull();
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { expect } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { within } from '@storybook/test';
|
||||
import { graphql, HttpResponse } from 'msw';
|
||||
@ -6,6 +7,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockedPeopleData } from '~/testing/mock-data/people';
|
||||
import { mockedWorkspaceMemberData } from '~/testing/mock-data/users';
|
||||
@ -15,7 +17,6 @@ import { RecordShowPage } from '../RecordShowPage';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/ObjectRecord/RecordShowPage',
|
||||
component: RecordShowPage,
|
||||
decorators: [PageDecorator],
|
||||
args: {
|
||||
routePath: '/object/:objectNameSingular/:objectRecordId',
|
||||
routeParams: {
|
||||
@ -81,6 +82,9 @@ export default meta;
|
||||
export type Story = StoryObj<typeof RecordShowPage>;
|
||||
|
||||
export const Default: Story = {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
@ -88,3 +92,15 @@ export const Default: Story = {
|
||||
await canvas.findByText('Add your first Activity');
|
||||
},
|
||||
};
|
||||
|
||||
export const Loading: Story = {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
decorators: [PageDecorator],
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
expect(canvas.queryByText('Alexandre Prot')).toBeNull();
|
||||
expect(canvas.queryByText('Add your first Activity')).toBeNull();
|
||||
},
|
||||
};
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsAppearance } from '../SettingsAppearance';
|
||||
@ -11,7 +12,7 @@ import { SettingsAppearance } from '../SettingsAppearance';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/SettingsAppearance',
|
||||
component: SettingsAppearance,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: '/settings/appearance' },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
@ -15,7 +16,7 @@ import { SettingsBilling } from '../SettingsBilling';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/SettingsBilling',
|
||||
component: SettingsBilling,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: getSettingsPagePath(SettingsPath.Billing) },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsProfile } from '../SettingsProfile';
|
||||
@ -12,7 +13,7 @@ import { SettingsProfile } from '../SettingsProfile';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/SettingsProfile',
|
||||
component: SettingsProfile,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/profile',
|
||||
additionalRoutes: ['/welcome'],
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsWorkspace } from '../SettingsWorkspace';
|
||||
@ -11,7 +12,7 @@ import { SettingsWorkspace } from '../SettingsWorkspace';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/SettingsWorkspace',
|
||||
component: SettingsWorkspace,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: '/settings/workspace' },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
@ -13,7 +14,7 @@ import { SettingsWorkspaceMembers } from '../SettingsWorkspaceMembers';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/SettingsWorkspaceMembers',
|
||||
component: SettingsWorkspaceMembers,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: '/settings/workspace-members' },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsAccounts } from '../SettingsAccounts';
|
||||
@ -12,7 +13,7 @@ import { SettingsAccounts } from '../SettingsAccounts';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Accounts/SettingsAccounts',
|
||||
component: SettingsAccounts,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/accounts',
|
||||
},
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
@ -15,7 +16,7 @@ import { SettingsAccountsCalendars } from '../SettingsAccountsCalendars';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Accounts/SettingsAccountsCalendars',
|
||||
component: SettingsAccountsCalendars,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: getSettingsPagePath(SettingsPath.AccountsCalendars),
|
||||
},
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockedConnectedAccounts } from '~/testing/mock-data/accounts';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
@ -17,7 +18,7 @@ import { SettingsAccountsCalendarsSettings } from '../SettingsAccountsCalendarsS
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Accounts/SettingsAccountsCalendarsSettings',
|
||||
component: SettingsAccountsCalendarsSettings,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: getSettingsPagePath(SettingsPath.AccountsCalendarsSettings),
|
||||
routeParams: { ':accountUuid': mockedConnectedAccounts[0].id },
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsAccountsEmails } from '../SettingsAccountsEmails';
|
||||
@ -11,7 +12,7 @@ import { SettingsAccountsEmails } from '../SettingsAccountsEmails';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Accounts/SettingsAccountsEmails',
|
||||
component: SettingsAccountsEmails,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/accounts/emails',
|
||||
},
|
||||
|
||||
@ -7,12 +7,13 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Accounts/SettingsAccountsEmailsInboxSettings',
|
||||
component: SettingsAccountsEmailsInboxSettings,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/accounts/emails/:accountUuid',
|
||||
routeParams: { ':accountUuid': '123' },
|
||||
|
||||
@ -5,12 +5,13 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Accounts/SettingsNewAccount',
|
||||
component: SettingsNewAccount,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/accounts/new',
|
||||
},
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsNewObject } from '../SettingsNewObject';
|
||||
@ -12,7 +13,7 @@ import { SettingsNewObject } from '../SettingsNewObject';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/DataModel/SettingsNewObject',
|
||||
component: SettingsNewObject,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/objects/new',
|
||||
},
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
@ -13,7 +14,7 @@ import { SettingsObjectDetail } from '../SettingsObjectDetail';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/DataModel/SettingsObjectDetail',
|
||||
component: SettingsObjectDetail,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/objects/:objectSlug',
|
||||
routeParams: { ':objectSlug': 'companies' },
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
@ -12,7 +13,7 @@ import { SettingsObjectEdit } from '../SettingsObjectEdit';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/DataModel/SettingsObjectEdit',
|
||||
component: SettingsObjectEdit,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/objects/:objectSlug/edit',
|
||||
routeParams: { ':objectSlug': 'companies' },
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsObjectFieldEdit } from '../SettingsObjectFieldEdit';
|
||||
@ -11,7 +12,7 @@ import { SettingsObjectFieldEdit } from '../SettingsObjectFieldEdit';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/DataModel/SettingsObjectFieldEdit',
|
||||
component: SettingsObjectFieldEdit,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/objects/:objectSlug/:fieldSlug',
|
||||
routeParams: { ':objectSlug': 'companies', ':fieldSlug': 'name' },
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsObjectNewFieldStep1 } from '../../SettingsObjectNewField/SettingsObjectNewFieldStep1';
|
||||
@ -13,7 +14,7 @@ const meta: Meta<PageDecoratorArgs> = {
|
||||
title:
|
||||
'Pages/Settings/DataModel/SettingsObjectNewField/SettingsObjectNewFieldStep1',
|
||||
component: SettingsObjectNewFieldStep1,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/objects/:objectSlug/new-field/step-1',
|
||||
routeParams: { ':objectSlug': 'companies' },
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { SettingsObjectNewFieldStep2 } from '../../SettingsObjectNewField/SettingsObjectNewFieldStep2';
|
||||
@ -13,7 +14,7 @@ const meta: Meta<PageDecoratorArgs> = {
|
||||
title:
|
||||
'Pages/Settings/DataModel/SettingsObjectNewField/SettingsObjectNewFieldStep2',
|
||||
component: SettingsObjectNewFieldStep2,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/objects/:objectSlug/new-field/step-2',
|
||||
routeParams: { ':objectSlug': 'companies' },
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
@ -13,7 +14,7 @@ import { SettingsObjects } from '../SettingsObjects';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/DataModel/SettingsObjects',
|
||||
component: SettingsObjects,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: '/settings/objects' },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -6,13 +6,14 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Developers/SettingsDevelopers',
|
||||
component: SettingsDevelopers,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: '/settings/developers' },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -7,12 +7,13 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Developers/ApiKeys/SettingsDevelopersApiKeyDetail',
|
||||
component: SettingsDevelopersApiKeyDetail,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/developers/api-keys/:apiKeyId',
|
||||
routeParams: {
|
||||
|
||||
@ -6,12 +6,13 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Developers/ApiKeys/SettingsDevelopersApiKeysNew',
|
||||
component: SettingsDevelopersApiKeysNew,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: '/settings/developers/api-keys/new' },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -7,12 +7,13 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Developers/Webhooks/SettingsDevelopersWebhooksDetail',
|
||||
component: SettingsDevelopersWebhooksDetail,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/developers/webhooks/:webhookId',
|
||||
routeParams: { ':webhookId': '1234' },
|
||||
|
||||
@ -6,12 +6,13 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Developers/Webhooks/SettingsDevelopersWebhooksNew',
|
||||
component: SettingsDevelopersWebhooksNew,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: '/settings/developers' },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -8,13 +8,14 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Integrations/SettingsIntegrationDatabase',
|
||||
component: SettingsIntegrationDatabase,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: getSettingsPagePath(SettingsPath.IntegrationDatabase),
|
||||
routeParams: { ':databaseKey': 'postgresql' },
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
@ -13,7 +14,7 @@ const meta: Meta<PageDecoratorArgs> = {
|
||||
title:
|
||||
'Pages/Settings/Integrations/SettingsIntegrationEditDatabaseConnection',
|
||||
component: SettingsIntegrationEditDatabaseConnection,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/integrations/:databaseKey/edit',
|
||||
routeParams: {
|
||||
|
||||
@ -6,13 +6,14 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Integrations/SettingsIntegrationNewDatabaseConnection',
|
||||
component: SettingsIntegrationNewDatabaseConnection,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: '/settings/integrations/:databaseKey/new',
|
||||
routeParams: { ':databaseKey': 'postgresql' },
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
@ -15,7 +16,7 @@ const meta: Meta<PageDecoratorArgs> = {
|
||||
title:
|
||||
'Pages/Settings/Integrations/SettingsIntegrationShowDatabaseConnection',
|
||||
component: SettingsIntegrationShowDatabaseConnection,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: {
|
||||
routePath: getSettingsPagePath(SettingsPath.IntegrationDatabaseConnection),
|
||||
routeParams: {
|
||||
|
||||
@ -8,13 +8,14 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Settings/Integrations/SettingsIntegrations',
|
||||
component: SettingsIntegrations,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: getSettingsPagePath(SettingsPath.Integrations) },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
PageDecorator,
|
||||
PageDecoratorArgs,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
import { PrefetchLoadingDecorator } from '~/testing/decorators/PrefetchLoadingDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockedWorkspaceMemberData } from '~/testing/mock-data/users';
|
||||
import { sleep } from '~/testing/sleep';
|
||||
@ -15,7 +16,7 @@ import { Tasks } from '../Tasks';
|
||||
const meta: Meta<PageDecoratorArgs> = {
|
||||
title: 'Pages/Tasks/Default',
|
||||
component: Tasks,
|
||||
decorators: [PageDecorator],
|
||||
decorators: [PrefetchLoadingDecorator, PageDecorator],
|
||||
args: { routePath: AppPath.TasksPage },
|
||||
parameters: {
|
||||
msw: {
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
import { Decorator } from '@storybook/react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
|
||||
export const PrefetchLoadingDecorator: Decorator = (Story) => {
|
||||
const setAreViewsPrefetched = useSetRecoilState(
|
||||
prefetchIsLoadedFamilyState(PrefetchKey.AllViews),
|
||||
);
|
||||
const setAreFavoritesPrefetched = useSetRecoilState(
|
||||
prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites),
|
||||
);
|
||||
|
||||
setAreViewsPrefetched(true);
|
||||
setAreFavoritesPrefetched(true);
|
||||
|
||||
return <Story />;
|
||||
};
|
||||
Reference in New Issue
Block a user