From 155b37e81fb3a5f463ddcc0c39790ea9b755d57b Mon Sep 17 00:00:00 2001
From: Sascha <GlancingMind@outlook.com>
Date: Fri, 19 Mar 2021 14:20:54 +0100
Subject: Use dialog with accordion for message history menu

---
 webui/src/pages/bug/MessageHistoryDialog.tsx | 215 +++++++++++++++++++++++++++
 1 file changed, 215 insertions(+)
 create mode 100644 webui/src/pages/bug/MessageHistoryDialog.tsx

(limited to 'webui/src/pages/bug/MessageHistoryDialog.tsx')

diff --git a/webui/src/pages/bug/MessageHistoryDialog.tsx b/webui/src/pages/bug/MessageHistoryDialog.tsx
new file mode 100644
index 000000000..c49ac6614
--- /dev/null
+++ b/webui/src/pages/bug/MessageHistoryDialog.tsx
@@ -0,0 +1,215 @@
+import moment from 'moment';
+import React from 'react';
+import Moment from 'react-moment';
+
+import MuiAccordion from '@material-ui/core/Accordion';
+import MuiAccordionDetails from '@material-ui/core/AccordionDetails';
+import MuiAccordionSummary from '@material-ui/core/AccordionSummary';
+import CircularProgress from '@material-ui/core/CircularProgress';
+import Dialog from '@material-ui/core/Dialog';
+import MuiDialogContent from '@material-ui/core/DialogContent';
+import MuiDialogTitle from '@material-ui/core/DialogTitle';
+import Grid from '@material-ui/core/Grid';
+import IconButton from '@material-ui/core/IconButton';
+import Tooltip from '@material-ui/core/Tooltip/Tooltip';
+import Typography from '@material-ui/core/Typography';
+import {
+  createStyles,
+  Theme,
+  withStyles,
+  WithStyles,
+} from '@material-ui/core/styles';
+import CloseIcon from '@material-ui/icons/Close';
+
+import { AddCommentFragment } from './MessageCommentFragment.generated';
+import { CreateFragment } from './MessageCreateFragment.generated';
+import { useMessageEditHistoryQuery } from './MessageEditHistory.generated';
+
+const styles = (theme: Theme) =>
+  createStyles({
+    root: {
+      margin: 0,
+      padding: theme.spacing(2),
+    },
+    closeButton: {
+      position: 'absolute',
+      right: theme.spacing(1),
+      top: theme.spacing(1),
+    },
+  });
+
+export interface DialogTitleProps extends WithStyles<typeof styles> {
+  id: string;
+  children: React.ReactNode;
+  onClose: () => void;
+}
+
+const DialogTitle = withStyles(styles)((props: DialogTitleProps) => {
+  const { children, classes, onClose, ...other } = props;
+  return (
+    <MuiDialogTitle disableTypography className={classes.root} {...other}>
+      <Typography variant="h6">{children}</Typography>
+      {onClose ? (
+        <IconButton
+          aria-label="close"
+          className={classes.closeButton}
+          onClick={onClose}
+        >
+          <CloseIcon />
+        </IconButton>
+      ) : null}
+    </MuiDialogTitle>
+  );
+});
+
+const DialogContent = withStyles((theme: Theme) => ({
+  root: {
+    padding: theme.spacing(2),
+  },
+}))(MuiDialogContent);
+
+const Accordion = withStyles({
+  root: {
+    border: '1px solid rgba(0, 0, 0, .125)',
+    boxShadow: 'none',
+    '&:not(:last-child)': {
+      borderBottom: 0,
+    },
+    '&:before': {
+      display: 'none',
+    },
+    '&$expanded': {
+      margin: 'auto',
+    },
+  },
+  expanded: {},
+})(MuiAccordion);
+
+const AccordionSummary = withStyles((theme) => ({
+  root: {
+    backgroundColor: theme.palette.primary.light,
+    borderBottomWidth: '1px',
+    borderBottomStyle: 'solid',
+    borderBottomColor: theme.palette.divider,
+    marginBottom: -1,
+    minHeight: 56,
+    '&$expanded': {
+      minHeight: 56,
+    },
+  },
+  content: {
+    '&$expanded': {
+      margin: '12px 0',
+    },
+  },
+  expanded: {},
+}))(MuiAccordionSummary);
+
+const AccordionDetails = withStyles((theme) => ({
+  root: {
+    padding: theme.spacing(2),
+  },
+}))(MuiAccordionDetails);
+
+type Props = {
+  bugId: string;
+  commentId: string;
+  open: boolean;
+  onClose: () => void;
+};
+function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
+  const [expanded, setExpanded] = React.useState<string | false>('panel0');
+
+  const { loading, error, data } = useMessageEditHistoryQuery({
+    variables: { bugIdPrefix: bugId },
+  });
+  if (loading) {
+    return (
+      <Dialog
+        onClose={onClose}
+        aria-labelledby="customized-dialog-title"
+        open={open}
+        fullWidth
+        maxWidth="sm"
+      >
+        <DialogTitle id="customized-dialog-title" onClose={onClose}>
+          Loading...
+        </DialogTitle>
+        <DialogContent dividers>
+          <Grid container justify="center">
+            <CircularProgress />
+          </Grid>
+        </DialogContent>
+      </Dialog>
+    );
+  }
+  if (error) {
+    return (
+      <Dialog
+        onClose={onClose}
+        aria-labelledby="customized-dialog-title"
+        open={open}
+        fullWidth
+        maxWidth="sm"
+      >
+        <DialogTitle id="customized-dialog-title" onClose={onClose}>
+          Something went wrong...
+        </DialogTitle>
+        <DialogContent dividers>
+          <p>Error: {error}</p>
+        </DialogContent>
+      </Dialog>
+    );
+  }
+
+  const comments = data?.repository?.bug?.timeline.comments as (
+    | AddCommentFragment
+    | CreateFragment
+  )[];
+  // NOTE Searching for the changed comment could be dropped if GraphQL get
+  // filter by id argument for timelineitems
+  const comment = comments.find((elem) => elem.id === commentId);
+  const history = comment?.history;
+
+  const handleChange = (panel: string) => (
+    event: React.ChangeEvent<{}>,
+    newExpanded: boolean
+  ) => {
+    setExpanded(newExpanded ? panel : false);
+  };
+
+  return (
+    <Dialog
+      onClose={onClose}
+      aria-labelledby="customized-dialog-title"
+      open={open}
+      fullWidth
+      maxWidth="md"
+    >
+      <DialogTitle id="customized-dialog-title" onClose={onClose}>
+        Edited {history?.length} times.
+      </DialogTitle>
+      <DialogContent dividers>
+        {history?.map((edit, index) => (
+          <Accordion
+            square
+            expanded={expanded === 'panel' + index}
+            onChange={handleChange('panel' + index)}
+          >
+            <AccordionSummary
+              aria-controls="panel1d-content"
+              id="panel1d-header"
+            >
+              <Tooltip title={moment(edit.date).format('LLLL')}>
+                <Moment date={edit.date} format="on ll" />
+              </Tooltip>
+            </AccordionSummary>
+            <AccordionDetails>{edit.message}</AccordionDetails>
+          </Accordion>
+        ))}
+      </DialogContent>
+    </Dialog>
+  );
+}
+
+export default MessageHistoryDialog;
-- 
cgit v1.2.3


From dfb039a9361a1a0d19a31e25130c89f70828ef00 Mon Sep 17 00:00:00 2001
From: Sascha <GlancingMind@outlook.com>
Date: Fri, 19 Mar 2021 14:25:42 +0100
Subject: Rename MessageEditHistoryQuery

---
 webui/src/pages/bug/MessageEditHistory.graphql | 15 ---------------
 webui/src/pages/bug/MessageHistory.graphql     | 15 +++++++++++++++
 webui/src/pages/bug/MessageHistoryDialog.tsx   |  4 ++--
 3 files changed, 17 insertions(+), 17 deletions(-)
 delete mode 100644 webui/src/pages/bug/MessageEditHistory.graphql
 create mode 100644 webui/src/pages/bug/MessageHistory.graphql

(limited to 'webui/src/pages/bug/MessageHistoryDialog.tsx')

diff --git a/webui/src/pages/bug/MessageEditHistory.graphql b/webui/src/pages/bug/MessageEditHistory.graphql
deleted file mode 100644
index 6fde8d452..000000000
--- a/webui/src/pages/bug/MessageEditHistory.graphql
+++ /dev/null
@@ -1,15 +0,0 @@
-#import "./MessageCommentFragment.graphql"
-#import "./MessageCreateFragment.graphql"
-
-query MessageEditHistory($bugIdPrefix: String!) {
-  repository {
-    bug(prefix: $bugIdPrefix) {
-      timeline {
-        comments: nodes {
-          ...Create
-          ...AddComment
-        }
-      }
-    }
-  }
-}
diff --git a/webui/src/pages/bug/MessageHistory.graphql b/webui/src/pages/bug/MessageHistory.graphql
new file mode 100644
index 000000000..e90eb4595
--- /dev/null
+++ b/webui/src/pages/bug/MessageHistory.graphql
@@ -0,0 +1,15 @@
+#import "./MessageCommentFragment.graphql"
+#import "./MessageCreateFragment.graphql"
+
+query MessageHistory($bugIdPrefix: String!) {
+  repository {
+    bug(prefix: $bugIdPrefix) {
+      timeline {
+        comments: nodes {
+          ...Create
+          ...AddComment
+        }
+      }
+    }
+  }
+}
diff --git a/webui/src/pages/bug/MessageHistoryDialog.tsx b/webui/src/pages/bug/MessageHistoryDialog.tsx
index c49ac6614..9857f2729 100644
--- a/webui/src/pages/bug/MessageHistoryDialog.tsx
+++ b/webui/src/pages/bug/MessageHistoryDialog.tsx
@@ -23,7 +23,7 @@ import CloseIcon from '@material-ui/icons/Close';
 
 import { AddCommentFragment } from './MessageCommentFragment.generated';
 import { CreateFragment } from './MessageCreateFragment.generated';
-import { useMessageEditHistoryQuery } from './MessageEditHistory.generated';
+import { useMessageHistoryQuery } from './MessageHistory.generated';
 
 const styles = (theme: Theme) =>
   createStyles({
@@ -120,7 +120,7 @@ type Props = {
 function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
   const [expanded, setExpanded] = React.useState<string | false>('panel0');
 
-  const { loading, error, data } = useMessageEditHistoryQuery({
+  const { loading, error, data } = useMessageHistoryQuery({
     variables: { bugIdPrefix: bugId },
   });
   if (loading) {
-- 
cgit v1.2.3


From de9dd698917f905946c5b0e19039e4202375721d Mon Sep 17 00:00:00 2001
From: Sascha <GlancingMind@outlook.com>
Date: Fri, 19 Mar 2021 14:57:11 +0100
Subject: Sort history from most recent edit to old

---
 webui/src/pages/bug/MessageHistoryDialog.tsx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'webui/src/pages/bug/MessageHistoryDialog.tsx')

diff --git a/webui/src/pages/bug/MessageHistoryDialog.tsx b/webui/src/pages/bug/MessageHistoryDialog.tsx
index 9857f2729..dc0e09cb5 100644
--- a/webui/src/pages/bug/MessageHistoryDialog.tsx
+++ b/webui/src/pages/bug/MessageHistoryDialog.tsx
@@ -169,7 +169,9 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
   // NOTE Searching for the changed comment could be dropped if GraphQL get
   // filter by id argument for timelineitems
   const comment = comments.find((elem) => elem.id === commentId);
-  const history = comment?.history;
+  // Sort by most recent edit. Must create a copy of constant history as
+  // reverse() modifies inplace.
+  const history = comment?.history.slice().reverse();
 
   const handleChange = (panel: string) => (
     event: React.ChangeEvent<{}>,
@@ -203,6 +205,7 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
               <Tooltip title={moment(edit.date).format('LLLL')}>
                 <Moment date={edit.date} format="on ll" />
               </Tooltip>
+              {index === 0 && '• (most recent edit)'}
             </AccordionSummary>
             <AccordionDetails>{edit.message}</AccordionDetails>
           </Accordion>
-- 
cgit v1.2.3


From bd316ef9efc5485513d8f2ceeca3938eb0c5b30f Mon Sep 17 00:00:00 2001
From: Sascha <GlancingMind@outlook.com>
Date: Fri, 19 Mar 2021 15:03:27 +0100
Subject: Improve readability of accordion summary

---
 webui/src/pages/bug/MessageHistoryDialog.tsx | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

(limited to 'webui/src/pages/bug/MessageHistoryDialog.tsx')

diff --git a/webui/src/pages/bug/MessageHistoryDialog.tsx b/webui/src/pages/bug/MessageHistoryDialog.tsx
index dc0e09cb5..c359873b9 100644
--- a/webui/src/pages/bug/MessageHistoryDialog.tsx
+++ b/webui/src/pages/bug/MessageHistoryDialog.tsx
@@ -202,10 +202,12 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
               aria-controls="panel1d-content"
               id="panel1d-header"
             >
-              <Tooltip title={moment(edit.date).format('LLLL')}>
-                <Moment date={edit.date} format="on ll" />
-              </Tooltip>
-              {index === 0 && '• (most recent edit)'}
+              <Typography>
+                <Tooltip title={moment(edit.date).format('LLLL')}>
+                  <Moment date={edit.date} format="on ll" />
+                </Tooltip>
+                {index === 0 && '• (most recent edit)'}
+              </Typography>
             </AccordionSummary>
             <AccordionDetails>{edit.message}</AccordionDetails>
           </Accordion>
-- 
cgit v1.2.3


From 6f26afb74f169a56270d8667a4092901324df2e3 Mon Sep 17 00:00:00 2001
From: Sascha <GlancingMind@outlook.com>
Date: Fri, 19 Mar 2021 17:17:03 +0100
Subject: Number accordion elements

---
 webui/src/pages/bug/MessageHistoryDialog.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'webui/src/pages/bug/MessageHistoryDialog.tsx')

diff --git a/webui/src/pages/bug/MessageHistoryDialog.tsx b/webui/src/pages/bug/MessageHistoryDialog.tsx
index c359873b9..9d1578b28 100644
--- a/webui/src/pages/bug/MessageHistoryDialog.tsx
+++ b/webui/src/pages/bug/MessageHistoryDialog.tsx
@@ -203,10 +203,11 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
               id="panel1d-header"
             >
               <Typography>
+                {`#${index + 1} • Edited `}
                 <Tooltip title={moment(edit.date).format('LLLL')}>
                   <Moment date={edit.date} format="on ll" />
                 </Tooltip>
-                {index === 0 && '• (most recent edit)'}
+                {index === 0 && ' (most recent edit)'}
               </Typography>
             </AccordionSummary>
             <AccordionDetails>{edit.message}</AccordionDetails>
-- 
cgit v1.2.3


From 4c5a0f37f7979d29fa077c0cfcd9be936c8fc0bd Mon Sep 17 00:00:00 2001
From: Sascha <GlancingMind@outlook.com>
Date: Sat, 20 Mar 2021 11:04:17 +0100
Subject: Improve message history accordions

- Add unfold icon to edit history accordions
- Change order of edit number. Most recent should have highest id and initial
  description should always have "#1 Edit"
- Add "(Initial description)' to title of the first comment version
---
 webui/src/pages/bug/MessageHistoryDialog.tsx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'webui/src/pages/bug/MessageHistoryDialog.tsx')

diff --git a/webui/src/pages/bug/MessageHistoryDialog.tsx b/webui/src/pages/bug/MessageHistoryDialog.tsx
index 9d1578b28..139eb4a59 100644
--- a/webui/src/pages/bug/MessageHistoryDialog.tsx
+++ b/webui/src/pages/bug/MessageHistoryDialog.tsx
@@ -20,6 +20,7 @@ import {
   WithStyles,
 } from '@material-ui/core/styles';
 import CloseIcon from '@material-ui/icons/Close';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
 
 import { AddCommentFragment } from './MessageCommentFragment.generated';
 import { CreateFragment } from './MessageCreateFragment.generated';
@@ -199,15 +200,17 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
             onChange={handleChange('panel' + index)}
           >
             <AccordionSummary
+              expandIcon={<ExpandMoreIcon />}
               aria-controls="panel1d-content"
               id="panel1d-header"
             >
               <Typography>
-                {`#${index + 1} • Edited `}
+                {`#${history?.length - index} • Edited `}
                 <Tooltip title={moment(edit.date).format('LLLL')}>
                   <Moment date={edit.date} format="on ll" />
                 </Tooltip>
                 {index === 0 && ' (most recent edit)'}
+                {index === history?.length - 1 && ' (Initial description)'}
               </Typography>
             </AccordionSummary>
             <AccordionDetails>{edit.message}</AccordionDetails>
-- 
cgit v1.2.3


From bd6159a25b548f8f939f137b70dcf77a722e70dc Mon Sep 17 00:00:00 2001
From: Sascha <GlancingMind@outlook.com>
Date: Mon, 22 Mar 2021 13:47:44 +0100
Subject: Treat description not as edit

---
 webui/src/pages/bug/MessageHistoryDialog.tsx | 29 +++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

(limited to 'webui/src/pages/bug/MessageHistoryDialog.tsx')

diff --git a/webui/src/pages/bug/MessageHistoryDialog.tsx b/webui/src/pages/bug/MessageHistoryDialog.tsx
index 139eb4a59..0ed33642c 100644
--- a/webui/src/pages/bug/MessageHistoryDialog.tsx
+++ b/webui/src/pages/bug/MessageHistoryDialog.tsx
@@ -173,6 +173,7 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
   // Sort by most recent edit. Must create a copy of constant history as
   // reverse() modifies inplace.
   const history = comment?.history.slice().reverse();
+  const editCount = history?.length === undefined ? 0 : history?.length - 1;
 
   const handleChange = (panel: string) => (
     event: React.ChangeEvent<{}>,
@@ -181,6 +182,23 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
     setExpanded(newExpanded ? panel : false);
   };
 
+  const getSummary = (index: number, date: Date) => {
+    const desc =
+      index === editCount ? 'Created ' : `#${editCount - index} • Edited `;
+    const mostRecent = index === 0 ? ' (most recent)' : '';
+    return (
+      <>
+        <Tooltip title={moment(date).format('LLLL')}>
+          <span>
+            {desc}
+            <Moment date={date} format="on ll" />
+            {mostRecent}
+          </span>
+        </Tooltip>
+      </>
+    );
+  };
+
   return (
     <Dialog
       onClose={onClose}
@@ -190,7 +208,7 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
       maxWidth="md"
     >
       <DialogTitle id="customized-dialog-title" onClose={onClose}>
-        Edited {history?.length} times.
+        {`Edited ${editCount} ${editCount > 1 ? 'times' : 'time'}.`}
       </DialogTitle>
       <DialogContent dividers>
         {history?.map((edit, index) => (
@@ -204,14 +222,7 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) {
               aria-controls="panel1d-content"
               id="panel1d-header"
             >
-              <Typography>
-                {`#${history?.length - index} • Edited `}
-                <Tooltip title={moment(edit.date).format('LLLL')}>
-                  <Moment date={edit.date} format="on ll" />
-                </Tooltip>
-                {index === 0 && ' (most recent edit)'}
-                {index === history?.length - 1 && ' (Initial description)'}
-              </Typography>
+              <Typography>{getSummary(index, edit.date)}</Typography>
             </AccordionSummary>
             <AccordionDetails>{edit.message}</AccordionDetails>
           </Accordion>
-- 
cgit v1.2.3

