feat: introduce notifications page
This commit is contained in:

committed by
Ömer Faruk Aydın

parent
db021c06c7
commit
d373d04cdf
@@ -7,6 +7,7 @@ import AppsIcon from '@mui/icons-material/Apps';
|
||||
import SwapCallsIcon from '@mui/icons-material/SwapCalls';
|
||||
import HistoryIcon from '@mui/icons-material/History';
|
||||
import ExploreIcon from '@mui/icons-material/Explore';
|
||||
import NotificationsIcon from '@mui/icons-material/Notifications';
|
||||
|
||||
import * as URLS from 'config/urls';
|
||||
import AppBar from 'components/AppBar';
|
||||
@@ -39,6 +40,14 @@ const drawerLinks = [
|
||||
},
|
||||
];
|
||||
|
||||
const drawerBottomLinks = [
|
||||
{
|
||||
Icon: NotificationsIcon,
|
||||
primary: 'settingsDrawer.notifications',
|
||||
to: URLS.UPDATES,
|
||||
},
|
||||
]
|
||||
|
||||
export default function PublicLayout({ children }: PublicLayoutProps): React.ReactElement {
|
||||
const theme = useTheme();
|
||||
const matchSmallScreens = useMediaQuery(theme.breakpoints.down('lg'), { noSsr: true });
|
||||
@@ -54,6 +63,7 @@ export default function PublicLayout({ children }: PublicLayoutProps): React.Rea
|
||||
<Box sx={{ display: 'flex', }}>
|
||||
<Drawer
|
||||
links={drawerLinks}
|
||||
bottomLinks={drawerBottomLinks}
|
||||
open={isDrawerOpen}
|
||||
onOpen={openDrawer}
|
||||
onClose={closeDrawer}
|
||||
|
56
packages/web/src/components/NotificationCard/index.tsx
Normal file
56
packages/web/src/components/NotificationCard/index.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import * as React from 'react';
|
||||
import Card from '@mui/material/Card';
|
||||
import CardHeader from '@mui/material/CardHeader';
|
||||
import CardActionArea from '@mui/material/CardActionArea';
|
||||
import CardContent from '@mui/material/CardContent';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
||||
interface NotificationCardProps {
|
||||
name: string;
|
||||
createdAt: string;
|
||||
documentationUrl: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
const getHumanlyDate = (timestamp: number) => DateTime.fromMillis(timestamp).toRelative();
|
||||
|
||||
export default function NotificationCard(props: NotificationCardProps) {
|
||||
const {
|
||||
name,
|
||||
createdAt,
|
||||
documentationUrl,
|
||||
description,
|
||||
} = props;
|
||||
|
||||
const formatMessage = useFormatMessage();
|
||||
const relativeCreatedAt = getHumanlyDate((new Date(createdAt)).getTime());
|
||||
const subheader = formatMessage('notification.releasedAt', { relativeDate: relativeCreatedAt });
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardActionArea
|
||||
component={'a'}
|
||||
href={documentationUrl}
|
||||
target="_blank"
|
||||
>
|
||||
<CardHeader
|
||||
title={name}
|
||||
titleTypographyProps={{ variant: 'h6' }}
|
||||
subheader={subheader}
|
||||
sx={{ borderBottom: '1px solid', borderColor: 'divider'}}
|
||||
/>
|
||||
|
||||
<CardContent>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color="text.secondary"
|
||||
dangerouslySetInnerHTML={{ __html: description }}
|
||||
/>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
);
|
||||
}
|
@@ -1,16 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Typography, { TypographyProps } from '@mui/material/Typography';
|
||||
|
||||
type PageTitleProps = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
type PageTitleProps = TypographyProps;
|
||||
|
||||
export default function PageTitle(props: PageTitleProps): React.ReactElement {
|
||||
const { children } = props;
|
||||
|
||||
return (
|
||||
<Typography variant="h3">
|
||||
{children}
|
||||
</Typography>
|
||||
<Typography variant="h3" {...props} />
|
||||
);
|
||||
}
|
@@ -5,6 +5,7 @@ type Config = {
|
||||
const config: Config = {
|
||||
baseUrl: process.env.REACT_APP_BASE_URL as string,
|
||||
graphqlUrl: process.env.REACT_APP_GRAPHQL_URL as string,
|
||||
notificationsUrl: process.env.REACT_APP_NOTIFICATIONS_URL as string,
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
@@ -31,8 +31,8 @@ export const FLOW_PATTERN = '/flows/:flowId';
|
||||
|
||||
export const SETTINGS = '/settings';
|
||||
export const SETTINGS_DASHBOARD = SETTINGS;
|
||||
export const SETTINGS_PROFILE = '/settings/profile';
|
||||
export const PROFILE = 'profile';
|
||||
|
||||
export const UPDATES = '/updates';
|
||||
export const SETTINGS_PROFILE = `${SETTINGS}/${PROFILE}`;
|
||||
|
||||
export const DASHBOARD = FLOWS;
|
||||
|
@@ -10,6 +10,7 @@
|
||||
"drawer.explore": "Explore",
|
||||
"settingsDrawer.myProfile": "My Profile",
|
||||
"settingsDrawer.goBack": "Go to the dashboard",
|
||||
"settingsDrawer.notifications": "Notifications",
|
||||
"app.connectionCount": "{count} connections",
|
||||
"app.flowCount": "{count} flows",
|
||||
"app.addConnection": "Add connection",
|
||||
@@ -49,5 +50,7 @@
|
||||
"profileSettings.confirmNewPassword": "Confirm new password",
|
||||
"profileSettings.updatedEmail": "Your email has been updated.",
|
||||
"profileSettings.updatedPassword": "Your password has been updated.",
|
||||
"profileSettings.updatePassword": "Update password"
|
||||
"profileSettings.updatePassword": "Update password",
|
||||
"notifications.title": "Notifications",
|
||||
"notification.releasedAt": "Released {relativeDate}"
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ export default function CreateFlow(): React.ReactElement {
|
||||
});
|
||||
const flowId = response.data?.createFlow?.id;
|
||||
|
||||
navigate(URLS.FLOW_EDITOR(flowId));
|
||||
navigate(URLS.FLOW_EDITOR(flowId), { replace: true });
|
||||
}
|
||||
|
||||
initiate();
|
||||
|
56
packages/web/src/pages/Notifications/index.tsx
Normal file
56
packages/web/src/pages/Notifications/index.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Stack from '@mui/material/Stack';
|
||||
|
||||
import appConfig from 'config/app';
|
||||
import Container from 'components/Container';
|
||||
import NotificationCard from 'components/NotificationCard';
|
||||
import PageTitle from 'components/PageTitle';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
||||
interface IUpdate {
|
||||
name: string;
|
||||
createdAt: string;
|
||||
documentationUrl: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export default function Updates(): React.ReactElement {
|
||||
const formatMessage = useFormatMessage();
|
||||
const [updates, setUpdates] = React.useState<IUpdate[]>([]);
|
||||
|
||||
React.useEffect(() => {
|
||||
fetch(`${appConfig.notificationsUrl}/notifications.json`)
|
||||
.then((response) => response.json())
|
||||
.then((updates) => {
|
||||
if (Array.isArray(updates) && updates.length) {
|
||||
setUpdates(updates);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box sx={{ py: 3 }}>
|
||||
<Container>
|
||||
<PageTitle sx={{ mb: [2, 5] }}>
|
||||
{formatMessage('notifications.title')}
|
||||
</PageTitle>
|
||||
|
||||
<Stack
|
||||
gap={2}
|
||||
>
|
||||
{updates.map((update: IUpdate) => (
|
||||
<NotificationCard
|
||||
key={update.name}
|
||||
name={`Version ${update.name}`}
|
||||
description={update.description}
|
||||
createdAt={update.createdAt}
|
||||
documentationUrl={update.documentationUrl}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</Container>
|
||||
</Box>
|
||||
);
|
||||
};
|
@@ -12,6 +12,8 @@ import Login from 'pages/Login';
|
||||
import EditorRoutes from 'pages/Editor/routes';
|
||||
import * as URLS from 'config/urls';
|
||||
import settingsRoutes from './settingsRoutes';
|
||||
import Notifications from 'pages/Notifications';
|
||||
|
||||
|
||||
export default (
|
||||
<Routes>
|
||||
@@ -33,6 +35,8 @@ export default (
|
||||
|
||||
<Route path={URLS.LOGIN} element={<PublicLayout><Login /></PublicLayout>} />
|
||||
|
||||
<Route path={URLS.UPDATES} element={<Layout><Notifications /></Layout>} />
|
||||
|
||||
<Route path="/" element={<Navigate to={URLS.FLOWS} />} />
|
||||
|
||||
<Route path={`${URLS.SETTINGS}`}>
|
||||
|
Reference in New Issue
Block a user