Skip to content

Commit

Permalink
Home Screen-Loading & error state fixes (#347)
Browse files Browse the repository at this point in the history
  • Loading branch information
praveen5959 committed Oct 27, 2024
1 parent 51c1fc1 commit e495565
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 56 deletions.
6 changes: 5 additions & 1 deletion src/hooks/useGetStreamMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { LogStreamRetention, LogStreamStat } from '@/@types/parseable/api/stream
import { getLogStreamRetention, getLogStreamStats } from '@/api/logStream';
import { getStreamsSepcificAccess } from '@/components/Navbar/rolesHandler';
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
import { notifyError } from '@/utils/notification';
import _ from 'lodash';
import { useCallback, useState } from 'react';

Expand All @@ -14,7 +15,7 @@ type MetaData = {

// until dedicated endpoint been provided - fetch one by one
export const useGetStreamMetadata = () => {
const [isLoading, setLoading] = useState<Boolean>(false);
const [isLoading, setLoading] = useState<Boolean>(true);
const [error, setError] = useState<Boolean>(false);
const [metaData, setMetadata] = useState<MetaData | null>(null);
const [userRoles] = useAppStore((store) => store.userRoles);
Expand Down Expand Up @@ -43,6 +44,9 @@ export const useGetStreamMetadata = () => {
} catch {
setError(true);
setMetadata(null);
notifyError({
message: 'Unable to fetch stream data',
});
} finally {
setLoading(false);
}
Expand Down
147 changes: 94 additions & 53 deletions src/pages/Home/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EmptySimple } from '@/components/Empty';
import { Text, Button, Center, Box, Group, ActionIcon, Stack, Tooltip, ScrollArea } from '@mantine/core';
import { Text, Button, Center, Box, Group, ActionIcon, Stack, Tooltip, ScrollArea, Loader, Flex } from '@mantine/core';
import { IconChevronRight, IconExternalLink, IconPlus } from '@tabler/icons-react';
import { useEffect, type FC, useCallback } from 'react';
import { useEffect, type FC, useCallback, useState, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { useDocumentTitle } from '@mantine/hooks';
import { useGetStreamMetadata } from '@/hooks/useGetStreamMetadata';
Expand All @@ -16,31 +16,53 @@ import _ from 'lodash';

const { changeStream, toggleCreateStreamModal } = appStoreReducers;

const EmptyStreamsView: FC = () => {
type NoStreamsViewProps = {
hasCreateStreamAccess: boolean;
openCreateStreamModal: () => void;
};

const NoStreamsView: FC<NoStreamsViewProps> = ({
hasCreateStreamAccess,
openCreateStreamModal,
}: {
hasCreateStreamAccess: boolean;
openCreateStreamModal: () => void;
}) => {
const classes = homeStyles;
const { messageStyle, btnStyle, noDataViewContainer } = classes;
const { messageStyle, btnStyle, noDataViewContainer, createStreamButton } = classes;
return (
<Center className={noDataViewContainer}>
<EmptySimple height={70} width={100} />
<Text className={messageStyle}>No Stream found on this account</Text>
<Button
target="_blank"
component="a"
href="https://www.parseable.io/docs/category/log-ingestion"
className={btnStyle}
leftSection={<IconExternalLink size="0.9rem" />}>
Documentation
</Button>
<Flex gap="md">
<Button
target="_blank"
component="a"
href="https://www.parseable.io/docs/category/log-ingestion"
className={btnStyle}
leftSection={<IconExternalLink size="0.9rem" />}>
Documentation
</Button>
{hasCreateStreamAccess && (
<Button
style={{ marginTop: '1rem' }}
className={createStreamButton}
onClick={openCreateStreamModal}
leftSection={<IconPlus stroke={2} size={'1rem'} />}>
Create Stream
</Button>
)}
</Flex>
</Center>
);
};

const Home: FC = () => {
useDocumentTitle('Parseable | Streams');
const classes = homeStyles;
const { container, createStreamButton } = classes;
const { container, createStreamButton, noDataViewContainer } = classes;
const navigate = useNavigate();
const { getStreamMetadata, metaData } = useGetStreamMetadata();
const { getStreamMetadata, metaData, isLoading, error } = useGetStreamMetadata();
const [userSpecificStreams, setAppStore] = useAppStore((store) => store.userSpecificStreams);
const [userRoles] = useAppStore((store) => store.userRoles);
const [userAccessMap] = useAppStore((store) => store.userAccessMap);
Expand All @@ -60,50 +82,69 @@ const Home: FC = () => {
setAppStore((store) => toggleCreateStreamModal(store));
}, []);

const [isScrolled, setIsScrolled] = useState(false);
const handleScroll = ({ y }: { y: number }) => {
setIsScrolled(y > 0);
};

const hasCreateStreamAccess = useMemo(() => userAccessMap?.hasCreateStreamAccess, [userAccessMap]);

return (
<>
<Stack
style={{
margin: '1rem',
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<Text style={{ fontSize: '0.8rem' }} fw={500}>
All Streams
</Text>
<Box>
{userAccessMap.hasCreateStreamAccess && (
<Button
variant="outline"
className={createStreamButton}
onClick={openCreateStreamModal}
leftSection={<IconPlus stroke={2} size={'1rem'} />}>
Create Stream
</Button>
)}
</Box>
</Stack>
<ScrollArea>
{!displayEmptyPlaceholder && !isLoading && !error && (
<Stack
style={{
padding: '1rem',
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
boxShadow: isScrolled ? '0px 4px 10px rgba(0, 0, 0, 0.1)' : 'none',
transition: 'box-shadow 0.2s ease',
}}>
<Text style={{ fontSize: '0.8rem' }} fw={500}>
All Streams ({metaData && Object.keys(metaData).length})
</Text>
<Box>
{hasCreateStreamAccess && (
<Button
variant="outline"
className={createStreamButton}
onClick={openCreateStreamModal}
leftSection={<IconPlus stroke={2} size={'1rem'} />}>
Create Stream
</Button>
)}
</Box>
</Stack>
)}
<ScrollArea onScrollPositionChange={handleScroll}>
<Box className={container} style={{ display: 'flex', flex: 1, paddingBottom: '3rem' }}>
<CreateStreamModal />
{displayEmptyPlaceholder ? (
<EmptyStreamsView />
{isLoading ? (
<Center className={noDataViewContainer}>
<Loader />
</Center>
) : (
<Group style={{ marginRight: '1rem', marginLeft: '1rem', gap: '1rem' }}>
{Object.entries(metaData || {}).map(([stream, data]) => {
const hasSettingsAccess = _.includes(getStreamsSepcificAccess(userRoles, stream), 'StreamSettings');
return (
<StreamInfo
key={stream}
stream={stream}
data={data}
navigateToStream={navigateToStream}
hasSettingsAccess={hasSettingsAccess}
/>
);
})}
</Group>
<>
{displayEmptyPlaceholder || error ? (
<NoStreamsView
hasCreateStreamAccess={hasCreateStreamAccess}
openCreateStreamModal={openCreateStreamModal}
/>
) : (
<Group style={{ margin: '0 1rem', gap: '1rem' }}>
{Object.entries(metaData || {}).map(([stream, data]) => (
<StreamInfo
key={stream}
stream={stream}
data={data}
navigateToStream={navigateToStream}
hasSettingsAccess={_.includes(getStreamsSepcificAccess(userRoles, stream), 'StreamSettings')}
/>
))}
</Group>
)}
</>
)}
</Box>
</ScrollArea>
Expand Down
3 changes: 1 addition & 2 deletions src/pages/Home/styles/Home.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

.noDataViewContainer {
height: 100%;
width: calc(100% - 200px);
padding-top: 2rem;
padding-top: 2rem;
flex-direction: column;
justify-content: center;
align-items: center;
Expand Down

0 comments on commit e495565

Please sign in to comment.