Skip to content

Commit 5b4c9e0

Browse files
committed
move banner under details
1 parent 6d3116c commit 5b4c9e0

15 files changed

Lines changed: 172 additions & 257 deletions

src/views/schedule-page/schedule-page-paused-banner/__tests__/schedule-page-paused-banner.test.tsx renamed to src/views/schedule-details/schedule-details-paused-banner/__tests__/schedule-details-paused-banner.test.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ import {
1010
} from '@/route-handlers/describe-schedule/__fixtures__/mock-describe-schedule-response';
1111
import { type DescribeScheduleResponse } from '@/views/shared/hooks/use-describe-schedule/use-describe-schedule.types';
1212

13-
import formatPausedAtTimestamp from '../helpers/format-paused-at-timestamp';
14-
import SchedulePagePausedBanner from '../schedule-page-paused-banner';
13+
import { formatScheduleTimestamp } from '../../helpers/format-schedule-timestamp';
1514

16-
describe(SchedulePagePausedBanner.name, () => {
17-
it('shows paused banner with mailto link when schedule is paused', async () => {
15+
import ScheduleDetailsPausedBanner from '../schedule-details-paused-banner';
16+
17+
describe(ScheduleDetailsPausedBanner.name, () => {
18+
it('shows paused banner when schedule is paused', async () => {
1819
const pausedAt = { seconds: '1704112496', nanos: 0 };
1920
const response = getMockPausedDescribeScheduleResponse({
2021
state: {
@@ -32,13 +33,10 @@ describe(SchedulePagePausedBanner.name, () => {
3233
expect(await screen.findByText(/Schedule was paused/)).toBeInTheDocument();
3334
expect(
3435
screen.getByText((content) =>
35-
content.includes(formatPausedAtTimestamp(pausedAt)!)
36+
content.includes(formatScheduleTimestamp(pausedAt)!)
3637
)
3738
).toBeInTheDocument();
38-
expect(screen.getByRole('link', { name: 'operator@example.com' })).toHaveAttribute(
39-
'href',
40-
'mailto:operator@example.com'
41-
);
39+
expect(screen.getByText(/operator@example.com/)).toBeInTheDocument();
4240
expect(document.body.textContent).toMatch(/Reason: "Paused for maintenance"/);
4341
});
4442

@@ -77,7 +75,7 @@ function setup({
7775
}) {
7876
return render(
7977
<Suspense fallback={null}>
80-
<SchedulePagePausedBanner
78+
<ScheduleDetailsPausedBanner
8179
domain="test-domain"
8280
cluster="test-cluster"
8381
scheduleId="test-schedule"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { styled as createStyled, type Theme } from 'baseui';
2+
import type { BannerOverrides } from 'baseui/banner';
3+
import { type StyleObject } from 'styletron-react';
4+
5+
export const PAUSED_BANNER_ICON_SIZE = 20;
6+
7+
export const styled = {
8+
ValueText: createStyled(
9+
'span',
10+
({ $theme }: { $theme: Theme }): StyleObject => ({
11+
fontWeight: $theme.typography.LabelSmall.fontWeight,
12+
})
13+
),
14+
};
15+
16+
export const overrides = {
17+
banner: {
18+
Root: {
19+
style: ({ $theme }: { $theme: Theme }): StyleObject => ({
20+
marginLeft: 0,
21+
marginRight: 0,
22+
marginTop: 0,
23+
marginBottom: $theme.sizing.scale500,
24+
}),
25+
},
26+
Message: {
27+
style: ({ $theme }: { $theme: Theme }): StyleObject => ({
28+
...$theme.typography.LabelSmall,
29+
fontWeight: 'normal',
30+
}),
31+
},
32+
} satisfies BannerOverrides,
33+
};
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
'use client';
2+
import React, { useMemo } from 'react';
3+
4+
import { Banner, HIERARCHY, KIND } from 'baseui/banner';
5+
import { MdInfoOutline } from 'react-icons/md';
6+
7+
import PageSection from '@/components/page-section/page-section';
8+
import useDescribeSchedule from '@/views/shared/hooks/use-describe-schedule/use-describe-schedule';
9+
10+
import { formatScheduleTimestamp } from '../helpers/format-schedule-timestamp';
11+
12+
import {
13+
overrides,
14+
PAUSED_BANNER_ICON_SIZE,
15+
styled,
16+
} from './schedule-details-paused-banner.styles';
17+
import { type Props } from './schedule-details-paused-banner.types';
18+
19+
export default function ScheduleDetailsPausedBanner(props: Props) {
20+
const {
21+
data: scheduleDetails,
22+
isLoading,
23+
isError,
24+
} = useDescribeSchedule(props);
25+
26+
const isPaused =
27+
!isLoading && !isError && Boolean(scheduleDetails?.state?.paused);
28+
const pauseInfo = scheduleDetails?.state?.pauseInfo;
29+
30+
const message = useMemo(() => {
31+
if (!isPaused) {
32+
return null;
33+
}
34+
35+
const pausedAt = formatScheduleTimestamp(pauseInfo?.pausedAt);
36+
const pausedBy = pauseInfo?.pausedBy?.trim() || null;
37+
const reason = pauseInfo?.reason?.trim() || null;
38+
39+
return (
40+
<>
41+
Schedule was paused
42+
{pausedAt ? (
43+
<>
44+
{' '}
45+
<styled.ValueText>{pausedAt}</styled.ValueText>
46+
</>
47+
) : null}
48+
{pausedBy ? (
49+
<>
50+
{' by '}
51+
<styled.ValueText>{pausedBy}</styled.ValueText>
52+
</>
53+
) : null}
54+
{reason ? (
55+
<>
56+
{'. Reason: "'}
57+
<styled.ValueText>{reason}</styled.ValueText>
58+
{'"'}
59+
</>
60+
) : null}
61+
</>
62+
);
63+
}, [isPaused, pauseInfo]);
64+
65+
if (!isPaused) {
66+
return null;
67+
}
68+
69+
return (
70+
<PageSection>
71+
<Banner
72+
hierarchy={HIERARCHY.low}
73+
kind={KIND.warning}
74+
artwork={{
75+
icon: () => (
76+
<MdInfoOutline size={PAUSED_BANNER_ICON_SIZE} aria-hidden />
77+
),
78+
}}
79+
overrides={overrides.banner}
80+
>
81+
{message}
82+
</Banner>
83+
</PageSection>
84+
);
85+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { type SchedulePageTabsParams } from '@/views/schedule-page/schedule-page-tabs/schedule-page-tabs.types';
2+
3+
export type Props = Pick<
4+
SchedulePageTabsParams,
5+
'domain' | 'cluster' | 'scheduleId'
6+
>;

src/views/schedule-details/schedule-details.styles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ export const styled = {
44
DetailsSectionsContainer: createStyled('div', ({ $theme }) => ({
55
display: 'flex',
66
flexDirection: 'column',
7-
gap: $theme.sizing.scale900,
7+
gap: $theme.sizing.scale950,
88
})),
99
};

src/views/schedule-details/schedule-details.tsx

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import useDescribeSchedule from '@/views/shared/hooks/use-describe-schedule/use-
77

88
import scheduleDetailsSectionsConfig from './config/schedule-details-sections.config';
99
import { getRowsFromConfig } from './helpers/get-rows-from-config';
10+
import ScheduleDetailsPausedBanner from './schedule-details-paused-banner/schedule-details-paused-banner';
1011
import ScheduleDetailsSection from './schedule-details-section/schedule-details-section';
1112
import { styled } from './schedule-details.styles';
1213
import { type Props } from './schedule-details.types';
@@ -20,7 +21,16 @@ export default function ScheduleDetails({ params }: Props) {
2021
});
2122

2223
if (isLoading || isPending) {
23-
return <SectionLoadingIndicator />;
24+
return (
25+
<>
26+
<ScheduleDetailsPausedBanner
27+
domain={params.domain}
28+
cluster={params.cluster}
29+
scheduleId={params.scheduleId}
30+
/>
31+
<SectionLoadingIndicator />
32+
</>
33+
);
2434
}
2535

2636
// Should never happen as we have throwOnError set to true but it is for better type safety below
@@ -29,27 +39,34 @@ export default function ScheduleDetails({ params }: Props) {
2939
}
3040

3141
return (
32-
<PageSection>
33-
<styled.DetailsSectionsContainer>
34-
{scheduleDetailsSectionsConfig.map((section) => {
35-
const rows = getRowsFromConfig(
36-
section.rowsConfig,
37-
data,
38-
params.scheduleId
39-
);
40-
if (!rows.length) {
41-
return null;
42-
}
42+
<>
43+
<ScheduleDetailsPausedBanner
44+
domain={params.domain}
45+
cluster={params.cluster}
46+
scheduleId={params.scheduleId}
47+
/>
48+
<PageSection>
49+
<styled.DetailsSectionsContainer>
50+
{scheduleDetailsSectionsConfig.map((section) => {
51+
const rows = getRowsFromConfig(
52+
section.rowsConfig,
53+
data,
54+
params.scheduleId
55+
);
56+
if (!rows.length) {
57+
return null;
58+
}
4359

44-
return (
45-
<ScheduleDetailsSection
46-
key={section.key}
47-
title={section.title}
48-
rows={rows}
49-
/>
50-
);
51-
})}
52-
</styled.DetailsSectionsContainer>
53-
</PageSection>
60+
return (
61+
<ScheduleDetailsSection
62+
key={section.key}
63+
title={section.title}
64+
rows={rows}
65+
/>
66+
);
67+
})}
68+
</styled.DetailsSectionsContainer>
69+
</PageSection>
70+
</>
5471
);
5572
}

src/views/schedule-page/schedule-page-paused-banner/helpers/__tests__/build-paused-banner-message.test.tsx

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/views/schedule-page/schedule-page-paused-banner/helpers/__tests__/format-paused-at-timestamp.test.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/views/schedule-page/schedule-page-paused-banner/helpers/build-paused-banner-message.tsx

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/views/schedule-page/schedule-page-paused-banner/helpers/format-paused-at-timestamp.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)