diff --git a/.github/stale.yml b/.github/stale.yml
index 0827505..394a813 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -7,7 +7,7 @@ exemptLabels:
- pinned
- security
- bug
- - enchantment
+ - enhancement
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
diff --git a/frontend/src/components/MessagesList/index.js b/frontend/src/components/Ticket/index.js
similarity index 77%
rename from frontend/src/components/MessagesList/index.js
rename to frontend/src/components/Ticket/index.js
index 5db3271..841d81b 100644
--- a/frontend/src/components/MessagesList/index.js
+++ b/frontend/src/components/Ticket/index.js
@@ -30,6 +30,9 @@ import whatsBackground from "../../assets/wa-background.png";
import LinkifyWithTargetBlank from "../LinkifyWithTargetBlank";
import MessageInput from "../MessageInput/";
import TicketOptionsMenu from "../TicketOptionsMenu";
+import TicketHeader from "../TicketHeader";
+import TicketInfo from "../TicketInfo";
+import TicketActionButtons from "../TicketActionButtons";
const drawerWidth = 320;
@@ -67,24 +70,6 @@ const useStyles = makeStyles(theme => ({
marginRight: 0,
},
- messagesHeader: {
- display: "flex",
- // cursor: "pointer",
- backgroundColor: "#eee",
- flex: "none",
- borderBottom: "1px solid rgba(0, 0, 0, 0.12)",
- },
-
- actionButtons: {
- marginRight: 6,
- flex: "none",
- alignSelf: "center",
- marginLeft: "auto",
- "& > *": {
- margin: theme.spacing(1),
- },
- },
-
messagesListWrapper: {
overflow: "hidden",
position: "relative",
@@ -262,14 +247,13 @@ const reducer = (state, action) => {
}
};
-const MessagesList = () => {
+const Ticket = () => {
const { ticketId } = useParams();
const history = useHistory();
const classes = useStyles();
- const userId = +localStorage.getItem("userId");
-
const [loading, setLoading] = useState(true);
+ const [ticketLoading, setTicketLoading] = useState(true);
const [contact, setContact] = useState({});
const [ticket, setTicket] = useState({});
const [drawerOpen, setDrawerOpen] = useState(false);
@@ -279,12 +263,10 @@ const MessagesList = () => {
const [hasMore, setHasMore] = useState(false);
const [pageNumber, setPageNumber] = useState(1);
- const [anchorEl, setAnchorEl] = useState(null);
- const moreMenuOpen = Boolean(anchorEl);
-
useEffect(() => {
dispatch({ type: "RESET" });
setPageNumber(1);
+ setTicketLoading(true);
}, [ticketId]);
useEffect(() => {
@@ -301,6 +283,7 @@ const MessagesList = () => {
dispatch({ type: "LOAD_MESSAGES", payload: data.messages });
setHasMore(data.hasMore);
setLoading(false);
+ setTicketLoading(false);
if (pageNumber === 1 && data.messages.length > 1) {
scrollToBottom();
@@ -420,29 +403,6 @@ const MessagesList = () => {
}
};
- const handleOpenTicketOptionsMenu = e => {
- setAnchorEl(e.currentTarget);
- };
-
- const handleCloseTicketOptionsMenu = e => {
- setAnchorEl(null);
- };
-
- const handleUpdateTicketStatus = async (e, status, userId) => {
- try {
- await api.put(`/tickets/${ticketId}`, {
- status: status,
- userId: userId || null,
- });
- } catch (err) {
- console.log(err);
- if (err.response && err.response.data && err.response.data.error) {
- toast.error(err.response.data.error);
- }
- }
- history.push("/tickets");
- };
-
const handleDrawerOpen = () => {
setDrawerOpen(true);
};
@@ -575,81 +535,14 @@ const MessagesList = () => {
[classes.mainWrapperShift]: drawerOpen,
})}
>
-
-
+
-
-
- ) : (
-
- )
- }
- title={
- loading ? (
-
- ) : (
- `${contact.name} #${ticket.id}`
- )
- }
- subheader={
- loading ? (
-
- ) : ticket.user ? (
- `${i18n.t("messagesList.header.assignedTo")} ${
- ticket.user.name
- }`
- ) : (
- "Pending"
- )
- }
/>
- {!loading && (
-
- {ticket.status === "closed" ? (
- }
- size="small"
- onClick={e => handleUpdateTicketStatus(e, "open", userId)}
- >
- {i18n.t("messagesList.header.buttons.reopen")}
-
- ) : (
- <>
- }
- size="small"
- onClick={e => handleUpdateTicketStatus(e, "pending", null)}
- >
- {i18n.t("messagesList.header.buttons.return")}
-
-
- >
- )}
-
-
-
-
-
- )}
-
+
+
);
};
-export default MessagesList;
+export default Ticket;
diff --git a/frontend/src/components/TicketActionButtons/index.js b/frontend/src/components/TicketActionButtons/index.js
new file mode 100644
index 0000000..2a0c774
--- /dev/null
+++ b/frontend/src/components/TicketActionButtons/index.js
@@ -0,0 +1,113 @@
+import React, { useState } from "react";
+import { useHistory } from "react-router-dom";
+import { toast } from "react-toastify";
+
+import { makeStyles } from "@material-ui/core/styles";
+import { Button, IconButton } from "@material-ui/core";
+import { MoreVert, Replay } from "@material-ui/icons";
+
+import { i18n } from "../../translate/i18n";
+import api from "../../services/api";
+import TicketOptionsMenu from "../TicketOptionsMenu";
+
+const useStyles = makeStyles(theme => ({
+ actionButtons: {
+ marginRight: 6,
+ flex: "none",
+ alignSelf: "center",
+ marginLeft: "auto",
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+}));
+
+const TicketActionButtons = ({ ticket }) => {
+ const classes = useStyles();
+ const history = useHistory();
+ const userId = +localStorage.getItem("userId");
+ const [anchorEl, setAnchorEl] = useState(null);
+ const ticketOptionsMenuOpen = Boolean(anchorEl);
+
+ const handleOpenTicketOptionsMenu = e => {
+ setAnchorEl(e.currentTarget);
+ };
+
+ const handleCloseTicketOptionsMenu = e => {
+ setAnchorEl(null);
+ };
+
+ const handleUpdateTicketStatus = async (e, status, userId) => {
+ try {
+ await api.put(`/tickets/${ticket.id}`, {
+ status: status,
+ userId: userId || null,
+ });
+
+ if (status === "open") {
+ history.push(`/tickets/${ticket.id}`);
+ } else {
+ history.push("/tickets");
+ }
+ } catch (err) {
+ console.log(err);
+ if (err.response && err.response.data && err.response.data.error) {
+ toast.error(err.response.data.error);
+ }
+ }
+ };
+
+ return (
+
+ {ticket.status === "closed" && (
+ }
+ size="small"
+ onClick={e => handleUpdateTicketStatus(e, "open", userId)}
+ >
+ {i18n.t("messagesList.header.buttons.reopen")}
+
+ )}
+ {ticket.status === "open" && (
+ <>
+ }
+ size="small"
+ onClick={e => handleUpdateTicketStatus(e, "pending", null)}
+ >
+ {i18n.t("messagesList.header.buttons.return")}
+
+
+
+
+
+
+ >
+ )}
+ {ticket.status === "pending" && (
+
+ )}
+
+ );
+};
+
+export default TicketActionButtons;
diff --git a/frontend/src/components/TicketHeader/index.js b/frontend/src/components/TicketHeader/index.js
new file mode 100644
index 0000000..8725042
--- /dev/null
+++ b/frontend/src/components/TicketHeader/index.js
@@ -0,0 +1,28 @@
+import React from "react";
+
+import { Card } from "@material-ui/core";
+import { makeStyles } from "@material-ui/core/styles";
+import TicketHeaderSkeleton from "../TicketHeaderSkeleton";
+
+const useStyles = makeStyles(theme => ({
+ ticketHeader: {
+ display: "flex",
+ backgroundColor: "#eee",
+ flex: "none",
+ borderBottom: "1px solid rgba(0, 0, 0, 0.12)",
+ },
+}));
+
+const TicketHeader = ({ loading, children }) => {
+ const classes = useStyles();
+
+ if (loading) return ;
+
+ return (
+
+ {children}
+
+ );
+};
+
+export default TicketHeader;
diff --git a/frontend/src/components/TicketHeader/old.js b/frontend/src/components/TicketHeader/old.js
new file mode 100644
index 0000000..0cbdb0f
--- /dev/null
+++ b/frontend/src/components/TicketHeader/old.js
@@ -0,0 +1,272 @@
+import React from "react";
+
+import {
+ Avatar,
+ Button,
+ Card,
+ CardHeader,
+ IconButton,
+} from "@material-ui/core";
+import { makeStyles } from "@material-ui/core/styles";
+import { green } from "@material-ui/core/colors";
+import Skeleton from "@material-ui/lab/Skeleton";
+import { Replay } from "@material-ui/icons";
+
+import TicketOptionsMenu from "../TicketOptionsMenu";
+import { i18n } from "../../translate/i18n";
+
+const drawerWidth = 320;
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ display: "flex",
+ height: "100%",
+ position: "relative",
+ overflow: "hidden",
+ },
+
+ mainWrapper: {
+ flex: 1,
+ height: "100%",
+ display: "flex",
+ flexDirection: "column",
+ overflow: "hidden",
+ borderTopLeftRadius: 0,
+ borderBottomLeftRadius: 0,
+ borderLeft: "0",
+ marginRight: -drawerWidth,
+ transition: theme.transitions.create("margin", {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ },
+
+ mainWrapperShift: {
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
+ transition: theme.transitions.create("margin", {
+ easing: theme.transitions.easing.easeOut,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ marginRight: 0,
+ },
+
+ messagesHeader: {
+ display: "flex",
+ // cursor: "pointer",
+ backgroundColor: "#eee",
+ flex: "none",
+ borderBottom: "1px solid rgba(0, 0, 0, 0.12)",
+ },
+
+ actionButtons: {
+ marginRight: 6,
+ flex: "none",
+ alignSelf: "center",
+ marginLeft: "auto",
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+
+ messagesListWrapper: {
+ overflow: "hidden",
+ position: "relative",
+ display: "flex",
+ flexDirection: "column",
+ flexGrow: 1,
+ },
+
+ circleLoading: {
+ color: green[500],
+ position: "absolute",
+ opacity: "70%",
+ top: 0,
+ left: "50%",
+ marginTop: 12,
+ },
+
+ messageLeft: {
+ marginRight: 20,
+ marginTop: 2,
+ minWidth: 100,
+ maxWidth: 600,
+ height: "auto",
+ display: "block",
+ position: "relative",
+
+ whiteSpace: "pre-wrap",
+ backgroundColor: "#ffffff",
+ color: "#303030",
+ alignSelf: "flex-start",
+ borderTopLeftRadius: 0,
+ borderTopRightRadius: 8,
+ borderBottomLeftRadius: 8,
+ borderBottomRightRadius: 8,
+ paddingLeft: 5,
+ paddingRight: 5,
+ paddingTop: 5,
+ paddingBottom: 0,
+ boxShadow: "0 1px 1px #b3b3b3",
+ },
+
+ messageRight: {
+ marginLeft: 20,
+ marginTop: 2,
+ minWidth: 100,
+ maxWidth: 600,
+ height: "auto",
+ display: "block",
+ position: "relative",
+
+ whiteSpace: "pre-wrap",
+ backgroundColor: "#dcf8c6",
+ color: "#303030",
+ alignSelf: "flex-end",
+ borderTopLeftRadius: 8,
+ borderTopRightRadius: 8,
+ borderBottomLeftRadius: 8,
+ borderBottomRightRadius: 0,
+ paddingLeft: 5,
+ paddingRight: 5,
+ paddingTop: 5,
+ paddingBottom: 0,
+ boxShadow: "0 1px 1px #b3b3b3",
+ },
+
+ textContentItem: {
+ overflowWrap: "break-word",
+ padding: "3px 80px 6px 6px",
+ },
+
+ messageMedia: {
+ objectFit: "cover",
+ width: 250,
+ height: 200,
+ borderTopLeftRadius: 8,
+ borderTopRightRadius: 8,
+ borderBottomLeftRadius: 8,
+ borderBottomRightRadius: 8,
+ },
+
+ timestamp: {
+ fontSize: 11,
+ position: "absolute",
+ bottom: 0,
+ right: 5,
+ color: "#999",
+ },
+
+ dailyTimestamp: {
+ alignItems: "center",
+ textAlign: "center",
+ alignSelf: "center",
+ width: "110px",
+ backgroundColor: "#e1f3fb",
+ margin: "10px",
+ borderRadius: "10px",
+ boxShadow: "0 1px 1px #b3b3b3",
+ },
+
+ dailyTimestampText: {
+ color: "#808888",
+ padding: 8,
+ alignSelf: "center",
+ marginLeft: "0px",
+ },
+
+ ackIcons: {
+ fontSize: 18,
+ verticalAlign: "middle",
+ marginLeft: 4,
+ },
+
+ ackDoneAllIcon: {
+ color: green[500],
+ fontSize: 18,
+ verticalAlign: "middle",
+ marginLeft: 4,
+ },
+}));
+
+const TicketHeader = ({ loading, contact, ticket }) => {
+ const classes = useStyles();
+
+ return (
+
+
+
+
+ ) : (
+
+ )
+ }
+ title={
+ loading ? (
+
+ ) : (
+ `${contact.name} #${ticket.id}`
+ )
+ }
+ subheader={
+ loading ? (
+
+ ) : ticket.user ? (
+ `${i18n.t("messagesList.header.assignedTo")} ${ticket.user.name}`
+ ) : (
+ "Pending"
+ )
+ }
+ />
+ {!loading && (
+
+ {ticket.status === "closed" ? (
+ }
+ size="small"
+ // onClick={e => handleUpdateTicketStatus(e, "open", userId)}
+ >
+ {i18n.t("messagesList.header.buttons.reopen")}
+
+ ) : (
+ <>
+ }
+ size="small"
+ // onClick={e => handleUpdateTicketStatus(e, "pending", null)}
+ >
+ {i18n.t("messagesList.header.buttons.return")}
+
+
+ >
+ )}
+ {/*
+
+
+ */}
+
+ )}
+
+ );
+};
+
+export default TicketHeader;
diff --git a/frontend/src/components/TicketHeaderSkeleton/index.js b/frontend/src/components/TicketHeaderSkeleton/index.js
new file mode 100644
index 0000000..1bd583c
--- /dev/null
+++ b/frontend/src/components/TicketHeaderSkeleton/index.js
@@ -0,0 +1,36 @@
+import React from "react";
+
+import { makeStyles } from "@material-ui/core/styles";
+import { Avatar, Card, CardHeader } from "@material-ui/core";
+import Skeleton from "@material-ui/lab/Skeleton";
+
+const useStyles = makeStyles(theme => ({
+ ticketHeader: {
+ display: "flex",
+ backgroundColor: "#eee",
+ flex: "none",
+ borderBottom: "1px solid rgba(0, 0, 0, 0.12)",
+ },
+}));
+
+const TicketHeaderSkeleton = () => {
+ const classes = useStyles();
+
+ return (
+
+
+
+
+ }
+ title={}
+ subheader={}
+ />
+
+ );
+};
+
+export default TicketHeaderSkeleton;
diff --git a/frontend/src/components/TicketInfo/index.js b/frontend/src/components/TicketInfo/index.js
new file mode 100644
index 0000000..914e261
--- /dev/null
+++ b/frontend/src/components/TicketInfo/index.js
@@ -0,0 +1,24 @@
+import React from "react";
+
+import { Avatar, CardHeader } from "@material-ui/core";
+
+import { i18n } from "../../translate/i18n";
+
+const TicketInfo = ({ contact, ticket, onClick }) => {
+ return (
+ }
+ title={`${contact.name} #${ticket.id}`}
+ subheader={
+ ticket.user &&
+ `${i18n.t("messagesList.header.assignedTo")} ${ticket.user.name}`
+ }
+ />
+ );
+};
+
+export default TicketInfo;
diff --git a/frontend/src/components/TicketsList/index.js b/frontend/src/components/TicketsList/index.js
index 0aa075a..db4d845 100644
--- a/frontend/src/components/TicketsList/index.js
+++ b/frontend/src/components/TicketsList/index.js
@@ -6,7 +6,7 @@ import List from "@material-ui/core/List";
import Paper from "@material-ui/core/Paper";
import TicketListItem from "../TicketListItem";
-import TicketsSkeleton from "../TicketsSkeleton";
+import TicketsListSkeleton from "../TicketsListSkeleton";
import useTickets from "../../hooks/useTickets";
import { i18n } from "../../translate/i18n";
@@ -276,7 +276,7 @@ const TicketsList = ({ status, searchParam, showAll }) => {
))}
>
)}
- {loading && }
+ {loading && }
diff --git a/frontend/src/components/TicketsSkeleton/index.js b/frontend/src/components/TicketsListSkeleton/index.js
similarity index 100%
rename from frontend/src/components/TicketsSkeleton/index.js
rename to frontend/src/components/TicketsListSkeleton/index.js
diff --git a/frontend/src/components/Tickets/index.js b/frontend/src/components/TicketsManager/index.js
similarity index 94%
rename from frontend/src/components/Tickets/index.js
rename to frontend/src/components/TicketsManager/index.js
index 18236a2..31286fe 100644
--- a/frontend/src/components/Tickets/index.js
+++ b/frontend/src/components/TicketsManager/index.js
@@ -81,7 +81,7 @@ const useStyles = makeStyles(theme => ({
},
}));
-const Tickets = () => {
+const TicketsManager = () => {
const classes = useStyles();
const [searchParam, setSearchParam] = useState("");
@@ -186,4 +186,4 @@ const Tickets = () => {
);
};
-export default Tickets;
+export default TicketsManager;
diff --git a/frontend/src/pages/Tickets/index.js b/frontend/src/pages/Tickets/index.js
index bc77923..9e6ea20 100644
--- a/frontend/src/pages/Tickets/index.js
+++ b/frontend/src/pages/Tickets/index.js
@@ -4,8 +4,8 @@ import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import { makeStyles } from "@material-ui/core/styles";
-import Tickets from "../../components/Tickets/";
-import MessagesList from "../../components/MessagesList/";
+import TicketsManager from "../../components/TicketsManager/";
+import Ticket from "../../components/Ticket/";
import { i18n } from "../../translate/i18n";
@@ -54,12 +54,12 @@ const Chat = () => {
-
+
{ticketId ? (
<>
-
+
>
) : (