Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve demo #4831

Merged
merged 18 commits into from
May 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/List.md
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,7 @@ Normally, `showFilter()` adds one input to the `displayedFilters` list. As the f

Next is the form component, based on `react-final-form`. The form inputs appear directly in the form, and the form submission triggers the `setFilters()` callback passed as parameter:

{% raw %}
```jsx
import React from "react";
import { Form } from "react-final-form";
Expand Down Expand Up @@ -1050,6 +1051,7 @@ return (
);
};
```
{% endraw %}

To finish, we pass the `<PostFilter>` component to the `<List>` component using the `filters` prop:

Expand Down
3 changes: 3 additions & 0 deletions examples/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"dependencies": {
"@material-ui/core": "^4.9.0",
"@material-ui/icons": "^4.5.1",
"@types/inflection": "^1.5.28",
"@types/recharts": "^1.8.10",
"data-generator-retail": "^3.0.0",
"fakerest": "~2.1.0",
"fetch-mock": "~6.3.0",
Expand All @@ -25,6 +27,7 @@
"react-router": "^5.1.0",
"react-router-dom": "^5.1.0",
"react-scripts": "^3.0.0",
"recharts": "^1.8.5",
"recompose": "~0.26.0",
"redux-saga": "^1.0.0"
},
Expand Down
3 changes: 2 additions & 1 deletion examples/demo/src/categories/CategoryEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ const CategoryEdit = (props: any) => (
reference="products"
target="category_id"
label="resources.categories.fields.products"
perPage={5}
perPage={20}
fullWidth
>
<Datagrid>
<ThumbnailField />
Expand Down
88 changes: 80 additions & 8 deletions examples/demo/src/categories/CategoryList.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,87 @@
import React from 'react';
import { Datagrid, EditButton, List, TextField } from 'react-admin';
import React, { FC } from 'react';
import { EditButton, List } from 'react-admin';
import { ListControllerProps } from 'ra-core';
import inflection from 'inflection';
import {
Grid,
Card,
CardMedia,
CardContent,
CardActions,
Typography,
makeStyles,
} from '@material-ui/core';

import LinkToRelatedProducts from './LinkToRelatedProducts';
import { Category } from '../types';

const useStyles = makeStyles({
root: {
marginTop: '1em',
},
media: {
height: 140,
},
title: {
paddingBottom: '0.5em',
},
actionSpacer: {
display: 'flex',
justifyContent: 'space-around',
},
});

const CategoryGrid: FC<ListControllerProps<Category>> = props => {
const classes = useStyles(props);
const { data, ids } = props;
return ids ? (
<Grid container spacing={2} className={classes.root}>
{ids.map(id => (
<Grid key={id} xs={12} sm={6} md={4} lg={3} xl={2} item>
<Card>
<CardMedia
image={`https://marmelab.com/posters/${
data[id].name
}-1.jpeg`}
className={classes.media}
/>
<CardContent className={classes.title}>
<Typography
variant="h5"
component="h2"
align="center"
>
{inflection.humanize(data[id].name)}
</Typography>
</CardContent>
<CardActions
classes={{ spacing: classes.actionSpacer }}
>
<LinkToRelatedProducts record={data[id]} />
<EditButton
basePath="/categories"
record={data[id]}
/>
</CardActions>
</Card>
</Grid>
))}
</Grid>
) : null;
};

const CategoryList = (props: any) => (
<List {...props} sort={{ field: 'name', order: 'ASC' }}>
<Datagrid>
<TextField source="name" />
<LinkToRelatedProducts />
<EditButton />
</Datagrid>
<List
{...props}
sort={{ field: 'name', order: 'ASC' }}
perPage={20}
pagination={false}
component="div"
actions={false}
>
{/*
// @ts-ignore */}
<CategoryGrid />
</List>
);

Expand Down
13 changes: 13 additions & 0 deletions examples/demo/src/dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import NbNewOrders from './NbNewOrders';
import PendingOrders from './PendingOrders';
import PendingReviews from './PendingReviews';
import NewCustomers from './NewCustomers';
import OrderChart from './OrderChart';

import { Customer, Order, Review } from '../types';

Expand All @@ -34,6 +35,7 @@ interface State {
pendingOrdersCustomers?: CustomerData;
pendingReviews?: Review[];
pendingReviewsCustomers?: CustomerData;
recentOrders?: Order[];
revenue?: number;
}

Expand Down Expand Up @@ -85,6 +87,7 @@ const Dashboard: FC = () => {
);
setState(state => ({
...state,
recentOrders,
revenue: aggregations.revenue.toLocaleString(undefined, {
style: 'currency',
currency: 'USD',
Expand Down Expand Up @@ -148,6 +151,7 @@ const Dashboard: FC = () => {
pendingReviews,
pendingReviewsCustomers,
revenue,
recentOrders,
} = state;
return isXSmall ? (
<div>
Expand All @@ -160,6 +164,9 @@ const Dashboard: FC = () => {
<NbNewOrders value={nbNewOrders} />
</div>
<div style={styles.singleCol}>
<OrderChart orders={recentOrders} />
</div>
<div style={styles.flex}>
<PendingOrders
orders={pendingOrders}
customers={pendingOrdersCustomers}
Expand All @@ -177,6 +184,9 @@ const Dashboard: FC = () => {
<NbNewOrders value={nbNewOrders} />
</div>
<div style={styles.singleCol}>
<OrderChart orders={recentOrders} />
</div>
<div style={styles.flex}>
<PendingOrders
orders={pendingOrders}
customers={pendingOrdersCustomers}
Expand All @@ -193,6 +203,9 @@ const Dashboard: FC = () => {
<div style={styles.singleCol}>
<Welcome />
</div>
<div style={styles.singleCol}>
<OrderChart orders={recentOrders} />
</div>
<div style={styles.singleCol}>
<PendingOrders
orders={pendingOrders}
Expand Down
99 changes: 99 additions & 0 deletions examples/demo/src/dashboard/OrderChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React, { FC } from 'react';
import { Card, CardHeader, CardContent } from '@material-ui/core';
import {
ResponsiveContainer,
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
} from 'recharts';
import { useTranslate } from 'react-admin';

import { Order } from '../types';

const lastDay = new Date(new Date().toDateString()).getTime();
const oneDay = 24 * 60 * 60 * 1000;
const lastMonthDays = Array.from(
{ length: 30 },
(_, i) => lastDay - i * oneDay
).reverse();
const aMonthAgo = new Date();
aMonthAgo.setDate(aMonthAgo.getDate() - 30);

const dateFormatter = (date: number): string =>
new Date(date).toLocaleDateString();

const aggregateOrdersByDay = (orders: Order[]): { [key: number]: number } =>
orders
.filter((order: Order) => order.status !== 'cancelled')
.reduce(
(acc, curr) => {
const day = new Date(
new Date(curr.date).toDateString()
).getTime();
if (!acc[day]) {
acc[day] = 0;
}
acc[day] += curr.total;
return acc;
},
{} as { [key: string]: number }
);

const getRevenuePerDay = (orders: Order[]): TotalByDay[] => {
const daysWithRevenue = aggregateOrdersByDay(orders);
return lastMonthDays.map(date => ({
date,
total: daysWithRevenue[date] || 0,
}));
};

const OrderChart: FC<{ orders?: Order[] }> = ({ orders }) => {
const translate = useTranslate();
if (!orders) return null;

return (
<Card>
<CardHeader title={translate('pos.dashboard.month_history')} />
<CardContent>
<ResponsiveContainer width="100%" height={300}>
<BarChart data={getRevenuePerDay(orders)}>
<XAxis
dataKey="date"
name="Date"
type="number"
scale="time"
domain={[aMonthAgo.getTime(), new Date().getTime()]}
tickFormatter={dateFormatter}
reversed
/>
<YAxis dataKey="total" name="Revenue" unit="€" />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip
cursor={{ strokeDasharray: '3 3' }}
formatter={value =>
new Intl.NumberFormat(undefined, {
style: 'currency',
currency: 'USD',
}).format(value as any)
}
labelFormatter={(label: any) =>
dateFormatter(label)
}
/>
<Bar dataKey="total" fill="#31708f" />
</BarChart>
</ResponsiveContainer>
</CardContent>
</Card>
);
};

interface TotalByDay {
date: number;
total: number;
}

export default OrderChart;
2 changes: 1 addition & 1 deletion examples/demo/src/dashboard/Welcome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useTranslate } from 'react-admin';

const useStyles = makeStyles({
media: {
height: '18em',
height: '16em',
},
});

Expand Down
13 changes: 13 additions & 0 deletions examples/demo/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const customEnglishMessages: TranslationMessages = {
},
dashboard: {
monthly_revenue: 'Monthly Revenue',
month_history: '30 Day Revenue History',
new_orders: 'New Orders',
pending_reviews: 'Pending Reviews',
new_customers: 'New Customers',
Expand Down Expand Up @@ -50,6 +51,18 @@ const customEnglishMessages: TranslationMessages = {
password: 'Password',
confirm_password: 'Confirm password',
},
filters: {
last_visited: 'Last visited',
today: 'Today',
this_week: 'This week',
last_week: 'Last week',
this_month: 'This month',
last_month: 'Last month',
earlier: 'Earlier',
has_ordered: 'Has ordered',
has_newsletter: 'Has newsletter',
group: 'Segment',
},
fieldGroups: {
identity: 'Identity',
address: 'Address',
Expand Down
13 changes: 13 additions & 0 deletions examples/demo/src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const customFrenchMessages: TranslationMessages = {
},
dashboard: {
monthly_revenue: 'CA à 30 jours',
month_history: "Chiffre d'affaire sur 30 jours",
new_orders: 'Nouvelles commandes',
pending_reviews: 'Commentaires à modérer',
new_customers: 'Nouveaux clients',
Expand Down Expand Up @@ -59,6 +60,18 @@ const customFrenchMessages: TranslationMessages = {
password: 'Mot de passe',
confirm_password: 'Confirmez le mot de passe',
},
filters: {
last_visited: 'Dernière visite',
today: "Aujourd'hui",
this_week: 'Cette semaine',
last_week: 'La semaine dernière',
this_month: 'Ce mois-ci',
last_month: 'Le mois dernier',
earlier: 'Plus tôt',
has_ordered: 'A déjà commandé',
has_newsletter: 'Abonné newsletter',
group: 'Segment',
},
fieldGroups: {
identity: 'Identité',
address: 'Adresse',
Expand Down
Loading