Skip to content

Commit

Permalink
fix(frontend): add text diff view (#89)
Browse files Browse the repository at this point in the history
* fix(frontend): add text diff view

* fix(frontend): fiw warnin
  • Loading branch information
lionelB authored Aug 26, 2020
1 parent 7d38bbd commit 3955dfa
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 94 deletions.
29 changes: 14 additions & 15 deletions targets/frontend/src/components/button/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from "theme-ui";

const buttonPropTypes = {
size: PropTypes.oneOf(["small", "normal"]),
size: PropTypes.oneOf(["xsmall", "small", "normal"]),
variant: PropTypes.oneOf(["secondary", "primary", "link"]),
};

Expand Down Expand Up @@ -49,7 +49,6 @@ const smallSize = {
px: "xxsmall",
py: "xxsmall",
};

// function _Button({ outline = false, ...props }) {}

export const Button = React.forwardRef(({ outline, ...props }, ref) => (
Expand All @@ -70,17 +69,17 @@ function SolidButton({ variant = "primary", size = "normal", ...props }) {
...defaultButtonStyles,
...(size === "small" ? smallSize : normalSize),
"&:hover:not([disabled])": {
bg: (theme) => theme.buttons[variant].colorHover,
borderColor: (theme) => theme.buttons[variant].colorHover,
bg: (theme) => theme.buttons[variant].bgHover,
borderColor: (theme) => theme.buttons[variant].bgHover,
},
"&[disabled]": {
bg: "muted",
borderColor: "muted",
},
bg: (theme) => theme.buttons[variant].color,
borderColor: (theme) => theme.buttons[variant].color,
bg: (theme) => theme.buttons[variant].bg,
borderColor: (theme) => theme.buttons[variant].bg,
borderRadius: "small",
color: (theme) => theme.buttons[variant].text,
color: (theme) => theme.buttons[variant].color,
}}
/>
);
Expand All @@ -95,16 +94,16 @@ function OutlineButton({ variant = "primary", size = "normal", ...props }) {
...defaultButtonStyles,
...(size === "small" ? smallSize : normalSize),
"&:hover:not([disabled])": {
borderColor: (theme) => theme.buttons[variant].colorHover,
color: (theme) => theme.buttons[variant].colorHover,
borderColor: (theme) => theme.buttons[variant].bgHover,
color: (theme) => theme.buttons[variant].bgHover,
},
"&[disabled]": {
borderColor: "muted",
color: "muted",
},
bg: (theme) => theme.buttons[variant].text,
borderColor: (theme) => theme.buttons[variant].color,
color: (theme) => theme.buttons[variant].color,
bg: (theme) => theme.buttons[variant].color,
borderColor: (theme) => theme.buttons[variant].bg,
color: (theme) => theme.buttons[variant].bg,
}}
/>
);
Expand All @@ -119,7 +118,7 @@ export function IconButton({ variant = "primary", size = "large", ...props }) {
...defaultButtonStyles,
"&:hover:not([disabled])": {
bg: (theme) => theme.buttons.icon.bgHover,
color: (theme) => theme.buttons[variant].text,
color: (theme) => theme.buttons[variant].color,
},
"&[disabled]": {
bg: "neutral",
Expand All @@ -145,7 +144,7 @@ export function MenuButton({ variant = "primary", size = "large", children }) {
...defaultButtonStyles,
"&:hover:not([disabled])": {
bg: (theme) => theme.buttons.icon.bgHover,
color: (theme) => theme.buttons[variant].text,
color: (theme) => theme.buttons[variant].color,
},
"&[disabled]": {
bg: "neutral",
Expand All @@ -154,7 +153,7 @@ export function MenuButton({ variant = "primary", size = "large", children }) {
bg: "transparent",
border: "none",
borderRadius: 32,
color: (theme) => theme.buttons[variant].color,
color: (theme) => theme.buttons[variant].bg,
fontSize: size,
height: 32,
justifyContent: "center",
Expand Down
5 changes: 3 additions & 2 deletions targets/frontend/src/components/changes/ChangeGroup.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/** @jsx jsx */
import { AccordionItem, AccordionPanel } from "@reach/accordion";
import PropTypes from "prop-types";
import React from "react";
import { AccordionButton } from "src/components/button";
import { jsx } from "theme-ui";

export const ChangesGroup = ({ changes, label, renderChange }) => {
return changes && changes.length > 0 ? (
<AccordionItem>
<AccordionButton>{label}</AccordionButton>
<AccordionPanel>
<ul>{changes.map(renderChange)}</ul>
<ul sx={{ margin: 0, px: "large" }}>{changes.map(renderChange)}</ul>
</AccordionPanel>
</AccordionItem>
) : null;
Expand Down
162 changes: 104 additions & 58 deletions targets/frontend/src/components/changes/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
/** @jsx jsx */
import PropTypes from "prop-types";
import { Badge, Card, jsx, Text } from "theme-ui";
import { useState } from "react";
import { IoIosArrowDown, IoIosArrowForward } from "react-icons/io";
import {
Badge,
Box,
Button as TButton,
Card,
Divider,
Flex,
jsx,
Text,
} from "theme-ui";

import { Collapsible } from "../collapsible";
import { Stack } from "../layout/Stack";
import { ViewDiff } from "./ViewDiff";

export function DilaLink({ info, children }) {
Expand Down Expand Up @@ -56,73 +67,108 @@ DilaLink.propTypes = {
}),
};

let COLLAPSIBLE_ID = 1;

export function DilaDiffChange({ change }) {
const { data, previous } = change;
const textFieldname =
change.context.containerId === "LEGITEXT000006072050" ? "text" : "content";
change.context.containerId === "LEGITEXT000006072050" ? "texte" : "content";
const content = data[textFieldname] || "";
const previousContent = previous?.data[textFieldname] || "";
const showDiff = previous && content !== previousContent;
const showNotaDiff = previous && previous.data.nota !== data.nota;
const [isVisible, setVisible] = useState(false);
const id = `collapsible-component-${COLLAPSIBLE_ID++}`;

return (
<li>
{change.type === "section" && (
<>
{change.context.parents.slice(-3, -1).join(" › ")} -
<DilaLink info={change}>{change.data.title}</DilaLink>
</>
)}
{change.type === "article" && (
<DilaLink info={change}>Article {data.num}</DilaLink>
)}
{previous?.data.etat && previous?.data.etat !== data.etat && (
<>
<Badge sx={{ bg: getBadgeColor(previous.data.etat), px: "xxsmall" }}>
{previous.data.etat}
</Badge>{" "}
{" "}
</>
)}
<Badge sx={{ bg: getBadgeColor(data.etat), px: "xxsmall" }}>
{data.etat}
</Badge>
{showDiff && (
<Collapsible label="voir les modifications">
<Card>
<ViewDiff
inputA={previousContent}
inputB={content}
type={"words"}
style={{
background: "#fff",
border: "1px solid silver",
borderRadius: 3,
padding: 5,
whiteSpace: "pre-line",
}}
/>
</Card>
</Collapsible>
)}
{showNotaDiff && (
<Collapsible label="voir le changement de nota">
<Card>
<ViewDiff
inputA={previous.data.nota}
inputB={data.nota}
type={"words"}
style={{
background: "#fff",
border: "1px solid silver",
borderRadius: 3,
padding: 5,
whiteSpace: "pre-line",
}}
/>
</Card>
</Collapsible>
<Flex sx={{ alignItems: "center" }}>
<Box>
{change.type === "section" && (
<>
{change.context.parents.slice(-3, -1).join(" › ")} -
<DilaLink info={change}>{change.data.title}</DilaLink>
</>
)}
{change.type === "article" && (
<DilaLink info={change}>Article {data.num}</DilaLink>
)}
</Box>

<Box px="xxsmall">
{previous?.data.etat && previous?.data.etat !== data.etat && (
<>
<Badge
sx={{ bg: getBadgeColor(previous.data.etat), px: "xxsmall" }}
>
{previous.data.etat}
</Badge>{" "}
{" "}
</>
)}
<Badge sx={{ bg: getBadgeColor(data.etat), px: "xxsmall" }}>
{data.etat}
</Badge>
</Box>
</Flex>
{(showDiff || showNotaDiff) && (
<TButton
aria-controls={id}
aria-expanded={isVisible}
size="small"
variant="link"
sx={{
"&:hover": {
color: "link",
},
cursor: "pointer",
px: 0,
}}
onClick={() => setVisible(!isVisible)}
>
Voir les modifications{" "}
{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>
</li>
);
}
Expand Down
31 changes: 25 additions & 6 deletions targets/frontend/src/components/collapsible/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,41 @@
import PropTypes from "prop-types";
import React, { useState } from "react";
import { IoMdGitNetwork } from "react-icons/io";
import React, { useRef, useState } from "react";
import { IoIosArrowDown, IoIosArrowUp, IoMdGitCompare } from "react-icons/io";

import { Button } from "../button";
import { Inline } from "../layout/Inline";

export function Collapsible({ label, children, ...props }) {
const COLLAPSIBLE_ID = 1;

export function Collapsible({ label, children, id, ...props }) {
const [isVisible, setVisible] = useState(false);
const collapsibleRef = useRef(COLLAPSIBLE_ID);
if (!id) {
id = `collapsible-component-${collapsibleRef.current++}`;
}
return (
<div {...props}>
<Button variant="link" onClick={() => setVisible(!isVisible)}>
<IoMdGitNetwork /> {label}
<Button
aria-controls={id}
aria-expanded={isVisible}
size="small"
variant="link"
onClick={() => setVisible(!isVisible)}
>
<Inline space="xxsmall">
<IoMdGitCompare /> {label}
{isVisible ? <IoIosArrowUp /> : <IoIosArrowDown />}
</Inline>
</Button>
{isVisible && children}
<div id={id} tabIndex="-1" hidden={!isVisible}>
{children}
</div>
</div>
);
}

Collapsible.propTypes = {
children: PropTypes.node,
id: PropTypes.string,
label: PropTypes.string,
};
2 changes: 1 addition & 1 deletion targets/frontend/src/components/layout/auth.layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function Layout({ children, title }) {
<Nav />
<Box as="main" sx={{ flex: "1 1 auto" }} padding="large">
<Stack>
<Heading>{title}</Heading>
<Heading as="h1">{title}</Heading>
{children}
</Stack>
</Box>
Expand Down
9 changes: 7 additions & 2 deletions targets/frontend/src/components/list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@
import PropTypes from "prop-types";
import { jsx } from "theme-ui";

export function List({ children }) {
return <ul sx={{ margin: 0, px: 0 }}>{children}</ul>;
export function List({ className, children }) {
return (
<ul className={className} sx={{ margin: 0, px: 0 }}>
{children}
</ul>
);
}
List.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
};

export function Li({ children }) {
Expand Down
Loading

0 comments on commit 3955dfa

Please sign in to comment.