Skip to content
This repository was archived by the owner on May 13, 2025. It is now read-only.

Commit a704184

Browse files
authored
fix: home screen loading & error state fixes (#347) (#348)
fixes #347
1 parent b773e4b commit a704184

File tree

3 files changed

+106
-58
lines changed

3 files changed

+106
-58
lines changed

src/hooks/useGetStreamMetadata.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { LogStreamRetention, LogStreamStat } from '@/@types/parseable/api/stream
22
import { getLogStreamRetention, getLogStreamStats } from '@/api/logStream';
33
import { getStreamsSepcificAccess } from '@/components/Navbar/rolesHandler';
44
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
5+
import { notifyError } from '@/utils/notification';
56
import _ from 'lodash';
67
import { useCallback, useState } from 'react';
78

@@ -14,7 +15,7 @@ type MetaData = {
1415

1516
// until dedicated endpoint been provided - fetch one by one
1617
export const useGetStreamMetadata = () => {
17-
const [isLoading, setLoading] = useState<Boolean>(false);
18+
const [isLoading, setLoading] = useState<Boolean>(true);
1819
const [error, setError] = useState<Boolean>(false);
1920
const [metaData, setMetadata] = useState<MetaData | null>(null);
2021
const [userRoles] = useAppStore((store) => store.userRoles);
@@ -43,6 +44,9 @@ export const useGetStreamMetadata = () => {
4344
} catch {
4445
setError(true);
4546
setMetadata(null);
47+
notifyError({
48+
message: 'Unable to fetch stream data',
49+
});
4650
} finally {
4751
setLoading(false);
4852
}

src/pages/Home/index.tsx

Lines changed: 100 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { EmptySimple } from '@/components/Empty';
2-
import { Text, Button, Center, Box, Group, ActionIcon, Stack, Tooltip, ScrollArea } from '@mantine/core';
2+
import { Text, Button, Center, Box, Group, ActionIcon, Stack, Tooltip, ScrollArea, Loader, Flex } from '@mantine/core';
33
import { IconChevronRight, IconExternalLink, IconPlus } from '@tabler/icons-react';
4-
import { useEffect, type FC, useCallback } from 'react';
4+
import { useEffect, type FC, useCallback, useMemo } from 'react';
55
import { useNavigate } from 'react-router-dom';
66
import { useDocumentTitle } from '@mantine/hooks';
77
import { useGetStreamMetadata } from '@/hooks/useGetStreamMetadata';
@@ -13,34 +13,58 @@ import CreateStreamModal from './CreateStreamModal';
1313
import { useAppStore, appStoreReducers } from '@/layouts/MainLayout/providers/AppProvider';
1414
import { getStreamsSepcificAccess } from '@/components/Navbar/rolesHandler';
1515
import _ from 'lodash';
16+
import { heights } from '@/components/Mantine/sizing';
17+
import { PRIMARY_HEADER_HEIGHT } from '@/constants/theme';
1618

1719
const { changeStream, toggleCreateStreamModal } = appStoreReducers;
1820

19-
const EmptyStreamsView: FC = () => {
21+
type NoStreamsViewProps = {
22+
hasCreateStreamAccess: boolean;
23+
openCreateStreamModal: () => void;
24+
};
25+
26+
const NoStreamsView: FC<NoStreamsViewProps> = ({
27+
hasCreateStreamAccess,
28+
openCreateStreamModal,
29+
}: {
30+
hasCreateStreamAccess: boolean;
31+
openCreateStreamModal: () => void;
32+
}) => {
2033
const classes = homeStyles;
21-
const { messageStyle, btnStyle, noDataViewContainer } = classes;
34+
const { messageStyle, btnStyle, noDataViewContainer, createStreamButton } = classes;
2235
return (
2336
<Center className={noDataViewContainer}>
2437
<EmptySimple height={70} width={100} />
2538
<Text className={messageStyle}>No Stream found on this account</Text>
26-
<Button
27-
target="_blank"
28-
component="a"
29-
href="https://www.parseable.io/docs/category/log-ingestion"
30-
className={btnStyle}
31-
leftSection={<IconExternalLink size="0.9rem" />}>
32-
Documentation
33-
</Button>
39+
<Flex gap="md">
40+
<Button
41+
target="_blank"
42+
component="a"
43+
href="https://www.parseable.io/docs/category/log-ingestion"
44+
className={btnStyle}
45+
leftSection={<IconExternalLink size="0.9rem" />}>
46+
Documentation
47+
</Button>
48+
{hasCreateStreamAccess && (
49+
<Button
50+
style={{ marginTop: '1rem' }}
51+
className={createStreamButton}
52+
onClick={openCreateStreamModal}
53+
leftSection={<IconPlus stroke={2} size={'1rem'} />}>
54+
Create Stream
55+
</Button>
56+
)}
57+
</Flex>
3458
</Center>
3559
);
3660
};
3761

3862
const Home: FC = () => {
3963
useDocumentTitle('Parseable | Streams');
4064
const classes = homeStyles;
41-
const { container, createStreamButton } = classes;
65+
const { container, createStreamButton, noDataViewContainer } = classes;
4266
const navigate = useNavigate();
43-
const { getStreamMetadata, metaData } = useGetStreamMetadata();
67+
const { getStreamMetadata, metaData, isLoading, error } = useGetStreamMetadata();
4468
const [userSpecificStreams, setAppStore] = useAppStore((store) => store.userSpecificStreams);
4569
const [userRoles] = useAppStore((store) => store.userRoles);
4670
const [userAccessMap] = useAppStore((store) => store.userAccessMap);
@@ -60,50 +84,72 @@ const Home: FC = () => {
6084
setAppStore((store) => toggleCreateStreamModal(store));
6185
}, []);
6286

87+
const hasCreateStreamAccess = useMemo(() => userAccessMap?.hasCreateStreamAccess, [userAccessMap]);
88+
89+
const shouldDisplayEmptyPlaceholder = displayEmptyPlaceholder || isLoading || error;
90+
6391
return (
6492
<>
65-
<Stack
66-
style={{
67-
margin: '1rem',
68-
alignItems: 'center',
69-
justifyContent: 'space-between',
70-
flexDirection: 'row',
71-
}}>
72-
<Text style={{ fontSize: '0.8rem' }} fw={500}>
73-
All Streams
74-
</Text>
75-
<Box>
76-
{userAccessMap.hasCreateStreamAccess && (
77-
<Button
78-
variant="outline"
79-
className={createStreamButton}
80-
onClick={openCreateStreamModal}
81-
leftSection={<IconPlus stroke={2} size={'1rem'} />}>
82-
Create Stream
83-
</Button>
84-
)}
85-
</Box>
86-
</Stack>
87-
<ScrollArea>
88-
<Box className={container} style={{ display: 'flex', flex: 1, paddingBottom: '3rem' }}>
93+
{!shouldDisplayEmptyPlaceholder && (
94+
<Stack
95+
style={{
96+
padding: '1rem',
97+
alignItems: 'center',
98+
justifyContent: 'space-between',
99+
flexDirection: 'row',
100+
borderBottom: '1px solid var(--mantine-color-gray-3)',
101+
}}>
102+
<Text style={{ fontSize: '0.8rem' }} fw={500}>
103+
All Streams ({metaData && Object.keys(metaData).length})
104+
</Text>
105+
<Box>
106+
{hasCreateStreamAccess && (
107+
<Button
108+
variant="outline"
109+
className={createStreamButton}
110+
onClick={openCreateStreamModal}
111+
leftSection={<IconPlus stroke={2} size={'1rem'} />}>
112+
Create Stream
113+
</Button>
114+
)}
115+
</Box>
116+
</Stack>
117+
)}
118+
<ScrollArea style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
119+
<Box
120+
className={container}
121+
style={{
122+
display: 'flex',
123+
paddingTop: shouldDisplayEmptyPlaceholder ? '0rem' : '1rem',
124+
paddingBottom: shouldDisplayEmptyPlaceholder ? '0rem' : '3rem',
125+
height: shouldDisplayEmptyPlaceholder ? `calc(${heights.screen} - ${PRIMARY_HEADER_HEIGHT}px)` : 'auto',
126+
}}>
89127
<CreateStreamModal />
90-
{displayEmptyPlaceholder ? (
91-
<EmptyStreamsView />
128+
{isLoading ? (
129+
<Center className={noDataViewContainer}>
130+
<Loader type="parseable" />
131+
</Center>
92132
) : (
93-
<Group style={{ marginRight: '1rem', marginLeft: '1rem', gap: '1rem' }}>
94-
{Object.entries(metaData || {}).map(([stream, data]) => {
95-
const hasSettingsAccess = _.includes(getStreamsSepcificAccess(userRoles, stream), 'StreamSettings');
96-
return (
97-
<StreamInfo
98-
key={stream}
99-
stream={stream}
100-
data={data}
101-
navigateToStream={navigateToStream}
102-
hasSettingsAccess={hasSettingsAccess}
103-
/>
104-
);
105-
})}
106-
</Group>
133+
<>
134+
{displayEmptyPlaceholder || error ? (
135+
<NoStreamsView
136+
hasCreateStreamAccess={hasCreateStreamAccess}
137+
openCreateStreamModal={openCreateStreamModal}
138+
/>
139+
) : (
140+
<Group style={{ margin: '0 1rem', gap: '1rem' }}>
141+
{Object.entries(metaData || {}).map(([stream, data]) => (
142+
<StreamInfo
143+
key={stream}
144+
stream={stream}
145+
data={data}
146+
navigateToStream={navigateToStream}
147+
hasSettingsAccess={_.includes(getStreamsSepcificAccess(userRoles, stream), 'StreamSettings')}
148+
/>
149+
))}
150+
</Group>
151+
)}
152+
</>
107153
)}
108154
</Box>
109155
</ScrollArea>

src/pages/Home/styles/Home.module.css

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
}
77

88
.noDataViewContainer {
9-
height: 100%;
10-
width: calc(100% - 200px);
11-
padding-top: 2rem;
9+
height: 100%;
1210
flex-direction: column;
1311
justify-content: center;
1412
align-items: center;

0 commit comments

Comments
 (0)