Skip to content

Commit

Permalink
Merge pull request #386 from middlewarehq/feat/skeletal-loader
Browse files Browse the repository at this point in the history
Fix sync-loader animation and create loading state card
  • Loading branch information
shivam-bit committed May 23, 2024
2 parents 69fc3cc + 5c5227b commit c2ef409
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 23 deletions.
182 changes: 182 additions & 0 deletions web-server/src/content/DoraMetrics/DoraCards/SkeletalCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import { Paper, Grid, Divider, useTheme } from '@mui/material';
import Link from 'next/link';
import { FC, useEffect } from 'react';

import { FlexBox } from '@/components/FlexBox';
import { Line } from '@/components/Text';
import { useBoolState } from '@/hooks/useEasyState';
import { OPEN_IN_NEW_TAB_PROPS } from '@/utils/url';

import { LoaderCore } from '../DoraMetricsBody';

const ANIMATON_DURATION = 1000;

export const DataStillSyncing = () => {
const flickerAnimation = useBoolState();

useEffect(() => {
const flickerInterval = setInterval(
flickerAnimation.toggle,
ANIMATON_DURATION
);

return () => {
clearInterval(flickerInterval);
};
}, [flickerAnimation.toggle]);
return (
<FlexBox col gap2>
<ScoreSkeleton />
<LoaderCore />
<Divider />
<Grid container spacing={4}>
<Grid item xs={12} md={6} order={1}>
<SkeletalCard animation={flickerAnimation.value} />
</Grid>
<Grid item xs={12} md={6} order={2}>
<SkeletalCard animation={flickerAnimation.value} />
</Grid>
<Grid item xs={12} md={6} order={3}>
<SkeletalCard animation={flickerAnimation.value} />
</Grid>
<Grid item xs={12} md={6} order={4}>
<SkeletalCard animation={flickerAnimation.value} />
</Grid>
</Grid>
</FlexBox>
);
};

const SkeletalCard: FC<{ animation?: boolean }> = ({ animation }) => {
return (
<FlexBox
minHeight={'15em'}
component={Paper}
col
relative
width={'100%'}
flexGrow={1}
overflow={'hidden'}
height={'100%'}
p={2}
>
<FlexBox
col
justifyBetween
height={'100%'}
sx={{
filter: `brightness(${animation ? 0.7 : 1})`,
transition: `all ${ANIMATON_DURATION}ms linear`
}}
>
<FlexBox fullWidth justifyBetween>
<FlexBox gap1>
<Skeleton width="200px" />
<Skeleton width="30px" />
</FlexBox>
<Skeleton width="75px" />
</FlexBox>
<FlexBox col gap2>
<Skeleton width="100px" height="20px" />
<Skeleton width="200px" />
<Skeleton width="100px" height="20px" />
</FlexBox>
</FlexBox>
</FlexBox>
);
};

const ScoreSkeleton: FC<{ animation?: boolean }> = ({ animation }) => {
const theme = useTheme();
const stats = {
avg: 2,
standard: 6.3,
lt: 4,
df: 5,
cfr: 6,
mttr: 7
};

return (
<FlexBox>
<FlexBox centered gap={1.5}>
<FlexBox col>
<Line bigish bold white>
Your DORA
</Line>
<Line bigish bold white>
Performance
</Line>
</FlexBox>

<FlexBox
col
height={'50px'}
centered
gap={'14px'}
ml={1}
sx={{
filter: `brightness(${animation ? 0.7 : 1})`,
transition: `all ${ANIMATON_DURATION}ms linear`
}}
>
<Skeleton height="12px" width="90px" />
<Skeleton height="12px" width="90px" />
</FlexBox>

<FlexBox col ml={4}>
<Line bigish bold white>
Industry
</Line>
<Line bigish bold white>
Standard
</Line>
</FlexBox>

<FlexBox
corner={theme.spacing(1)}
px={1.5}
sx={{
background: `linear-gradient(30deg,#8C7CF0, #3E2EA4)`
}}
>
<Line fontSize={'2.4em'} bold white>
{stats.standard}{' '}
<Line fontSize="0.8rem" ml="-4px">
/ 10
</Line>
</Line>
</FlexBox>

<FlexBox col>
<Line bigish medium>
Based on data available
</Line>
<Line bigish>
at{' '}
<Line info semibold>
<Link
href="https://dora.dev/quickcheck"
{...OPEN_IN_NEW_TAB_PROPS}
>
dora.dev
</Link>
</Line>
</Line>
</FlexBox>
</FlexBox>
</FlexBox>
);
};

const Skeleton: FC<{ width?: string; height?: string }> = ({
width = '150px',
height = '30px'
}) => (
<FlexBox
height={height}
bgcolor={'#262E5E'}
width={width}
borderRadius={'20px'}
/>
);
47 changes: 24 additions & 23 deletions web-server/src/content/DoraMetrics/DoraMetricsBody.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Grid, Divider, Button } from '@mui/material';
import Link from 'next/link';
import { useEffect, useMemo } from 'react';
import { FC, useEffect, useMemo } from 'react';

import { DoraMetricsConfigurationSettings } from '@/components/DoraMetricsConfigurationSettings';
import { DoraScore } from '@/components/DoraScore';
Expand Down Expand Up @@ -30,6 +30,7 @@ import { ClassificationPills } from './ClassificationPills';
import { ChangeFailureRateCard } from './DoraCards/ChangeFailureRateCard';
import { ChangeTimeCard } from './DoraCards/ChangeTimeCard';
import { MeanTimeToRestoreCard } from './DoraCards/MeanTimeToRestoreCard';
import { DataStillSyncing } from './DoraCards/SkeletalCard';
import { WeeklyDeliveryVolumeCard } from './DoraCards/WeeklyDeliveryVolumeCard';

export const DoraMetricsBody = () => {
Expand Down Expand Up @@ -103,22 +104,7 @@ export const DoraMetricsBody = () => {
);
if (!firstLoadDone) return <MiniLoader label={getRandomLoadMsg()} />;
if (isTeamInsightsEmpty)
if (isSyncing)
return (
<EmptyState
type="SYNC_IN_PROGRESS"
title="Sync in progress"
desc={
<FlexBox gap={1}>
<MiniLoader
label={'Your repos are syncing, please wait for a few minutes'}
/>
</FlexBox>
}
>
<FixedContentRefreshLoader show={isLoading} />
</EmptyState>
);
if (isSyncing) return <DataStillSyncing />;
else
return (
<EmptyState
Expand Down Expand Up @@ -224,9 +210,9 @@ export const useSyncedRepos = () => {
};
};

const ANIMATON_DURATION = 700;
const ANIMATON_DURATION = 1000;

const Syncing = () => {
export const Syncing = () => {
const flickerAnimation = useBoolState(false);
const { isSyncing } = useSyncedRepos();

Expand All @@ -240,11 +226,26 @@ const Syncing = () => {

return (
<FlexBox
gap={4}
sx={{
height: isSyncing ? '66px' : '0px',
opacity: flickerAnimation.value ? 1 : 0.6,
transition: `all ${isSyncing ? ANIMATON_DURATION : 200}ms linear`
mb: isSyncing ? 0 : -2,
transition: `opacity ${ANIMATON_DURATION}ms linear, height 300ms ease, margin 300ms ease`
}}
>
<LoaderCore animation={flickerAnimation.value} />
</FlexBox>
);
};

export const LoaderCore: FC<{
animation?: boolean;
}> = ({ animation }) => {
return (
<FlexBox
gap={4}
sx={{
transition: `opacity ${ANIMATON_DURATION}ms linear, height 300ms ease, margin 300ms ease`,
opacity: !animation ? 1 : 0.6
}}
overflow={'hidden'}
>
Expand All @@ -267,7 +268,7 @@ const Syncing = () => {
height={'100%'}
/>
<FlexBox height={'25px'} centered>
{isSyncing && <LoadingWrapper />}
{<LoadingWrapper />}
</FlexBox>
<Line color={'#1AE579'} medium big>
Calculating Dora
Expand Down
15 changes: 15 additions & 0 deletions web-server/src/slices/dora_metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ export const doraMetricsSlice = createSlice({
'deploymentPrs',
(state, action) => (state.deploymentPrs = action.payload)
);
addFetchCasesToReducer(
builder,
getSyncedRepos,
'bookmarkedRepos',
(state, action) => (state.bookmarkedRepos = action.payload)
);
}
});

Expand Down Expand Up @@ -207,3 +213,12 @@ export const fetchDeploymentPRs = createAsyncThunk(
return await handleApi<PR[]>(`/internal/deployments/prs`, { params });
}
);

export const getSyncedRepos = createAsyncThunk(
'dora_metrics/getSyncedRepos',
async (params: { team_id: ID }) => {
return await handleApi<ID[]>(
`/resources/teams/${params.team_id}/bookmarked_repos`
);
}
);

0 comments on commit c2ef409

Please sign in to comment.