Skip to content

Commit

Permalink
feat(frontend): update diff page (#90)
Browse files Browse the repository at this point in the history
* feat(frontend): paginate alerts

* feat(hasura): order v1 schema views

* fix(frontend): hide pagination if not needed
  • Loading branch information
lionelB committed Aug 27, 2020
1 parent 3955dfa commit b2efaa4
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 80 deletions.
13 changes: 7 additions & 6 deletions targets/frontend/src/components/button/index.js
Expand Up @@ -37,7 +37,6 @@ const defaultButtonStyles = {
lineHeight: "inherit",
m: 0,
minWidth: 0,
p: 1,
textAlign: "center",
textDecoration: "none",
};
Expand All @@ -51,11 +50,13 @@ const smallSize = {
};
// function _Button({ outline = false, ...props }) {}

export const Button = React.forwardRef(({ outline, ...props }, ref) => (
<div ref={ref}>
{outline ? <OutlineButton {...props} /> : <SolidButton {...props} />}
</div>
));
export const Button = React.forwardRef(({ outline, ...props }, ref) =>
outline ? (
<OutlineButton ref={ref} {...props} />
) : (
<SolidButton ref={ref} {...props} />
)
);
Button.propTypes = {
outline: PropTypes.bool,
...buttonPropTypes,
Expand Down
4 changes: 2 additions & 2 deletions targets/frontend/src/components/changes/ViewDiff.js
Expand Up @@ -44,15 +44,15 @@ export const ViewDiff = ({ sx, type, inputA, inputB }) => {
<input
type="radio"
name={groupName}
onClick={() => setMode("words")}
onChange={() => setMode("words")}
style={{ marginLeft: 10 }}
checked={mode === "words"}
/>{" "}
Mots
<input
type="radio"
name={groupName}
onClick={() => setMode("sentences")}
onChange={() => setMode("sentences")}
style={{ marginLeft: 10 }}
checked={mode === "sentences"}
/>{" "}
Expand Down
80 changes: 41 additions & 39 deletions targets/frontend/src/components/changes/index.js
Expand Up @@ -130,45 +130,47 @@ export function DilaDiffChange({ change }) {
{isVisible ? <IoIosArrowDown /> : <IoIosArrowForward />}
</TButton>
)}
<Card id={id} hidden={!isVisible}>
<Stack>
{showDiff && (
<>
<strong>Modification du texte</strong>
<ViewDiff
inputA={previousContent}
inputB={content}
type={"words"}
style={{
background: "#fff",
border: "1px solid silver",
borderRadius: 3,
padding: 5,
whiteSpace: "pre-line",
}}
/>
</>
)}
{showDiff && showNotaDiff && <Divider />}
{showNotaDiff && (
<>
<strong>Modification du Nota</strong>
<ViewDiff
inputA={previous.data.nota}
inputB={data.nota}
type={"words"}
style={{
background: "#fff",
border: "1px solid silver",
borderRadius: 3,
padding: 5,
whiteSpace: "pre-line",
}}
/>
</>
)}
</Stack>
</Card>
{isVisible && (
<Card id={id}>
<Stack>
{showDiff && (
<>
<strong>Modification du texte</strong>
<ViewDiff
inputA={previousContent}
inputB={content}
type={"words"}
style={{
background: "#fff",
border: "1px solid silver",
borderRadius: 3,
padding: 5,
whiteSpace: "pre-line",
}}
/>
</>
)}
{showDiff && showNotaDiff && <Divider />}
{showNotaDiff && (
<>
<strong>Modification du Nota</strong>
<ViewDiff
inputA={previous.data.nota}
inputB={data.nota}
type={"words"}
style={{
background: "#fff",
border: "1px solid silver",
borderRadius: 3,
padding: 5,
whiteSpace: "pre-line",
}}
/>
</>
)}
</Stack>
</Card>
)}
</li>
);
}
Expand Down
87 changes: 87 additions & 0 deletions targets/frontend/src/components/pagination/index.js
@@ -0,0 +1,87 @@
/** @jsx jsx */
import PropTypes from "prop-types";
import { Flex, jsx } from "theme-ui";

import { Button } from "../button";
import { Inline } from "../layout/Inline";
import { Li, List } from "../list";

export function Pagination({
count,
onChange,
offset = 0,
pageSize = 10,
visibleRange = 2,
}) {
const nbPage = Math.ceil(count / pageSize);
const currentPage = Math.floor(offset / pageSize);

const allPages = Array.from(Array(nbPage))
.map((_, page) => ({
index: page,
label: `${page + 1}`,
offset: pageSize * page,
}))
.map((page) => (
<Li key={page.label}>
<Button
variant={page.index === currentPage ? "accent" : "secondary"}
sx={{
py: "xxsmall",
}}
onClick={() => onChange({ offset: page.offset })}
>
{page.label}
</Button>
</Li>
));
const rangeStartIndex = Math.min(
Math.max(0, currentPage - visibleRange),
nbPage - visibleRange * 2 - 1
);
const rangeEndIndex = Math.min(
rangeStartIndex + 1 + visibleRange * 2,
nbPage
);

let startPagination = [];
if (rangeStartIndex > 2) {
startPagination = allPages
.slice(0, 1)
.concat(<Li key="start-range">...</Li>);
} else {
startPagination = allPages.slice(0, 2);
}

let endPagination = [];
if (nbPage - rangeEndIndex > 2) {
endPagination = [<Li key="end-range">...</Li>].concat(allPages.slice(-1));
} else {
endPagination = allPages.slice(-2);
}

const pages = allPages.slice(
Math.max(rangeStartIndex, 2),
Math.min(rangeEndIndex, nbPage - 2)
);
if (nbPage === 1) {
return null;
}
return (
<Flex sx={{ justifyContent: "center" }}>
<List sx={{ display: "flex", fontSize: "xxsmall" }}>
<Inline space="xxsmall">
{startPagination.concat(pages, endPagination)}
</Inline>
</List>
</Flex>
);
}

Pagination.propTypes = {
count: PropTypes.number.isRequired,
offset: PropTypes.number,
onChange: PropTypes.func.isRequired,
pageSize: PropTypes.number,
visibleRange: PropTypes.number,
};
1 change: 0 additions & 1 deletion targets/frontend/src/hoc/UserProvider.js
Expand Up @@ -35,7 +35,6 @@ function withUserProvider(WrappedComponent) {
const componentProps =
WrappedComponent.getInitialProps &&
(await WrappedComponent.getInitialProps(ctx));

return { ...componentProps };
}
render() {
Expand Down
37 changes: 32 additions & 5 deletions targets/frontend/src/pages/alerts/[[...params]].js
Expand Up @@ -5,12 +5,13 @@ import slugify from "@socialgouv/cdtn-slugify";
import { getRouteBySource } from "@socialgouv/cdtn-sources";
import Link from "next/link";
import { useRouter } from "next/router";
import { useMemo } from "react";
import { useMemo, useState } from "react";
import { AlertTitle } from "src/components/alerts/AlertTitle";
import { DiffChange } from "src/components/changes";
import { ChangesGroup } from "src/components/changes/ChangeGroup";
import { Layout } from "src/components/layout/auth.layout";
import { Stack } from "src/components/layout/Stack";
import { Pagination } from "src/components/pagination";
import { TabItem, Tabs } from "src/components/tabs";
import { withCustomUrqlClient } from "src/hoc/CustomUrqlClient";
import { withUserProvider } from "src/hoc/UserProvider";
Expand All @@ -19,7 +20,7 @@ import { Card, Container, Divider, jsx, Message, NavLink } from "theme-ui";
import { useQuery } from "urql";

const getAlertQuery = `
query getAlerts($status: String!, $repository: String!) {
query getAlerts($status: String!, $repository: String!, $limit: Int!, $offset: Int!) {
statuses: alert_status {
name
alerts: alerts_aggregate(where: {
Expand All @@ -31,7 +32,7 @@ query getAlerts($status: String!, $repository: String!) {
__typename
}
}
alerts(where: {
alerts(limit: $limit, offset: $offset, where: {
_and: [
{status: {_eq: $status}},
{repository: {_eq: $repository}},
Expand All @@ -50,6 +51,8 @@ query getAlerts($status: String!, $repository: String!) {

export function AlertPage() {
const router = useRouter();
const [offset, setOffset] = useState(0);
const pageSize = 10;

const [repo, activeStatus = "todo"] = router.query.params;
const repository = repo.replace(/_/, "/");
Expand All @@ -58,11 +61,15 @@ export function AlertPage() {
const [result] = useQuery({
context,
query: getAlertQuery,
variables: { repository, status: activeStatus },
variables: {
limit: pageSize,
offset,
repository,
status: activeStatus,
},
});

const { fetching, error, data } = result;
console.log("<AlertPage> render", result, repository, activeStatus);

if (fetching) {
return <Layout title="Gestion des alertes">Chargement...</Layout>;
Expand Down Expand Up @@ -93,6 +100,7 @@ export function AlertPage() {
).toLocaleDateString()} (${alert.ref})`;
}
}

return (
<Layout title="Gestion des alertes">
<Tabs id="statustab">
Expand Down Expand Up @@ -186,8 +194,27 @@ export function AlertPage() {
</Card>
</Container>
))}
<Pagination
count={
statuses.find(({ name }) => name === activeStatus).alerts.aggregate
.count
}
pageSize={pageSize}
offset={offset}
onChange={({ offset }) => setOffset(offset)}
/>
</Layout>
);
}
/**
* This getInitialProps ensure useState to reset while page url change
* @see https://github.com/vercel/next.js/issues/9992
*/
AlertPage.getInitialProps = async function ({ query }) {
const [repo, activeStatus = "todo"] = query.params;
return {
key: `${repo}/${activeStatus}`,
};
};

export default withCustomUrqlClient(withUserProvider(AlertPage));

0 comments on commit b2efaa4

Please sign in to comment.