From 6a84bb4a74cb05b7e8e81acf2e208a8585de85c7 Mon Sep 17 00:00:00 2001 From: Jack Andrews Date: Sat, 9 Nov 2024 15:48:39 +0000 Subject: [PATCH 01/22] chore: improve sidebar --- .../@/shadcn/components/app-sidebar.tsx | 19 +++++++---- apps/client/@/shadcn/components/nav-main.tsx | 19 +++++++---- apps/client/@/shadcn/ui/sidebar.tsx | 7 ++-- .../components/CreateTicketModal/index.tsx | 34 +++---------------- 4 files changed, 34 insertions(+), 45 deletions(-) diff --git a/apps/client/@/shadcn/components/app-sidebar.tsx b/apps/client/@/shadcn/components/app-sidebar.tsx index 4094c683e..a41e43616 100644 --- a/apps/client/@/shadcn/components/app-sidebar.tsx +++ b/apps/client/@/shadcn/components/app-sidebar.tsx @@ -1,11 +1,11 @@ -import * as React from "react"; import { Building, FileText, - GalleryVerticalEnd, + ListPlus, Settings, - SquareKanban, + SquareKanban } from "lucide-react"; +import * as React from "react"; import { NavMain } from "@/shadcn/components/nav-main"; import { @@ -16,12 +16,12 @@ import { SidebarRail, useSidebar, } from "@/shadcn/ui/sidebar"; -import ThemeSettings from "../../../components/ThemeSettings"; +import useTranslation from "next-translate/useTranslation"; import { useRouter } from "next/router"; -import { useUser } from "../../../store/session"; import { useEffect, useState } from "react"; -import useTranslation from "next-translate/useTranslation"; import CreateTicketModal from "../../../components/CreateTicketModal"; +import ThemeSettings from "../../../components/ThemeSettings"; +import { useUser } from "../../../store/session"; export function AppSidebar({ ...props }: React.ComponentProps) { const location = useRouter(); @@ -55,6 +55,13 @@ export function AppSidebar({ ...props }: React.ComponentProps) { }, ], navMain: [ + { + title: "New Issue", + url: ``, + icon: ListPlus, + isActive: location.pathname === "/" ? true : false, + initial: "c", + }, { title: t("sl_dashboard"), url: `/${locale}/`, diff --git a/apps/client/@/shadcn/components/nav-main.tsx b/apps/client/@/shadcn/components/nav-main.tsx index ca63f6295..d2d1005a2 100644 --- a/apps/client/@/shadcn/components/nav-main.tsx +++ b/apps/client/@/shadcn/components/nav-main.tsx @@ -1,9 +1,8 @@ -import { ChevronRight, type LucideIcon } from "lucide-react"; -import { useState, useEffect } from "react"; +import { type LucideIcon } from "lucide-react"; +import { useEffect, useState } from "react"; import { SidebarGroup, - SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, @@ -59,7 +58,6 @@ export function NavMain({ router.push(item.url)} >
@@ -84,7 +82,6 @@ export function NavMain({ {item.items?.map((subItem) => ( router.push(subItem.url)} className="cursor-pointer flex flex-row items-center justify-between w-full px-0 pl-2.5" > @@ -102,9 +99,17 @@ export function NavMain({ ) : ( router.push(item.url)} + onClick={() => { + if (item.url) { + router.push(item.url); + } else { + const event = new KeyboardEvent("keydown", { + key: item.initial, + }); + document.dispatchEvent(event); + } + }} >
diff --git a/apps/client/@/shadcn/ui/sidebar.tsx b/apps/client/@/shadcn/ui/sidebar.tsx index d5a588326..25a22d1f3 100644 --- a/apps/client/@/shadcn/ui/sidebar.tsx +++ b/apps/client/@/shadcn/ui/sidebar.tsx @@ -1,8 +1,8 @@ //@ts-nocheck -import * as React from "react" import { Slot } from "@radix-ui/react-slot" import { VariantProps, cva } from "class-variance-authority" import { PanelLeft } from "lucide-react" +import * as React from "react" import { useIsMobile } from "@/shadcn/hooks/use-mobile" import { cn } from "@/shadcn/lib/utils" @@ -534,7 +534,7 @@ const sidebarMenuButtonVariants = cva( "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]", }, size: { - default: "h-8 text-sm", + default: "h-8 text-xs text-foreground", sm: "h-7 text-xs", lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0", }, @@ -772,5 +772,6 @@ export { SidebarRail, SidebarSeparator, SidebarTrigger, - useSidebar, + useSidebar } + diff --git a/apps/client/components/CreateTicketModal/index.tsx b/apps/client/components/CreateTicketModal/index.tsx index 68fb88761..332739122 100644 --- a/apps/client/components/CreateTicketModal/index.tsx +++ b/apps/client/components/CreateTicketModal/index.tsx @@ -1,16 +1,15 @@ -import React, { useState, useEffect, Fragment } from "react"; -import { Dialog, Transition, Listbox } from "@headlessui/react"; +import { Dialog, Listbox, Transition } from "@headlessui/react"; import { CheckIcon } from "@heroicons/react/20/solid"; -import useTranslation from "next-translate/useTranslation"; import { ChevronUpDownIcon, XMarkIcon } from "@heroicons/react/24/outline"; +import { getCookie } from "cookies-next"; +import useTranslation from "next-translate/useTranslation"; import { useRouter } from "next/router"; +import { Fragment, useEffect, useState } from "react"; import { useUser } from "../../store/session"; -import { getCookie } from "cookies-next"; -import dynamic from "next/dynamic"; -import { ListPlus } from "lucide-react"; import { toast } from "@/shadcn/hooks/use-toast"; import { useSidebar } from "@/shadcn/ui/sidebar"; +import dynamic from "next/dynamic"; const Editor = dynamic(() => import("../BlockEditor"), { ssr: false }); @@ -179,29 +178,6 @@ export default function CreateTicketModal({ keypress, setKeyPressDown }) { return ( <> - -
From bd78d1741455ece3f3f1dde3fc484df2294a3016 Mon Sep 17 00:00:00 2001 From: Jack Andrews Date: Sat, 9 Nov 2024 15:50:39 +0000 Subject: [PATCH 02/22] chore: fix font size --- apps/client/@/shadcn/components/nav-main.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/@/shadcn/components/nav-main.tsx b/apps/client/@/shadcn/components/nav-main.tsx index d2d1005a2..76cde71e0 100644 --- a/apps/client/@/shadcn/components/nav-main.tsx +++ b/apps/client/@/shadcn/components/nav-main.tsx @@ -61,7 +61,7 @@ export function NavMain({ onClick={() => router.push(item.url)} >
-
+
{item.icon && } router.push(subItem.url)} - className="cursor-pointer flex flex-row items-center justify-between w-full px-0 pl-2.5" + className="cursor-pointer flex flex-row items-center justify-between w-full px-0 pl-2.5 text-xs" > {subItem.title} From 55bd461597fc9eb41d2fb3b682024a9b42f8e25a Mon Sep 17 00:00:00 2001 From: Jack Andrews Date: Sat, 9 Nov 2024 15:52:59 +0000 Subject: [PATCH 03/22] fix: delete issue right click --- apps/client/components/TicketDetails/index.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/client/components/TicketDetails/index.tsx b/apps/client/components/TicketDetails/index.tsx index b07f60d1c..bfac55564 100644 --- a/apps/client/components/TicketDetails/index.tsx +++ b/apps/client/components/TicketDetails/index.tsx @@ -1276,14 +1276,7 @@ export default function Ticket() { onClick={(e) => { e.preventDefault(); if (confirm("Are you sure you want to delete this ticket?")) { - fetch(`/api/v1/ticket/delete`, { - method: "POST", - headers: { - Authorization: `Bearer ${token}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ id: data.ticket.id }), - }); + deleteIssue(data.ticket.id); } }} > From f7b96e62079284db099060c6014b1726832604c3 Mon Sep 17 00:00:00 2001 From: Jack Andrews Date: Mon, 11 Nov 2024 22:52:10 +0000 Subject: [PATCH 04/22] chore: improve error message when its DB related --- apps/client/pages/auth/login.tsx | 56 +++++++++++++++++++------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/apps/client/pages/auth/login.tsx b/apps/client/pages/auth/login.tsx index 79603f7ee..e683b24db 100644 --- a/apps/client/pages/auth/login.tsx +++ b/apps/client/pages/auth/login.tsx @@ -14,33 +14,43 @@ export default function Login({}) { const [url, setUrl] = useState(""); async function postData() { - await fetch(`/api/v1/auth/login`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ email, password }), - }) - .then((res) => res.json()) - .then(async (res) => { - if (res.user) { - setCookie("session", res.token); - if (res.user.external_user) { - router.push("/portal"); - } else { - if (res.user.firstLogin) { - router.push("/onboarding"); + try { + await fetch(`/api/v1/auth/login`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ email, password }), + }) + .then((res) => res.json()) + .then(async (res) => { + if (res.user) { + setCookie("session", res.token); + if (res.user.external_user) { + router.push("/portal"); } else { - router.push("/"); + if (res.user.firstLogin) { + router.push("/onboarding"); + } else { + router.push("/"); + } } + } else { + toast({ + variant: "destructive", + title: "Error", + description: + "There was an error logging in, please try again. If this issue persists, please contact support via the discord.", + }); } - } else { - toast({ - variant: "destructive", - title: "Error", - description: - "There was an error logging in, please try again. If this issue persists, please contact support via the discord.", - }); - } + }); + } catch (error) { + console.error(error); + toast({ + variant: "destructive", + title: "Database Error", + description: + "This is an issue with the database, please check the docker logs or contact support via discord.", }); + } } async function oidcLogin() { From 1d493ec37618439b3b423d573c5055dc58ed509f Mon Sep 17 00:00:00 2001 From: Jack Andrews Date: Mon, 11 Nov 2024 22:52:25 +0000 Subject: [PATCH 05/22] feat: logs in the ui --- apps/api/src/controllers/data.ts | 20 +++++++ apps/client/layouts/adminLayout.tsx | 7 +++ apps/client/pages/admin/logs.tsx | 82 +++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 apps/client/pages/admin/logs.tsx diff --git a/apps/api/src/controllers/data.ts b/apps/api/src/controllers/data.ts index dc07d860e..af578e7fb 100644 --- a/apps/api/src/controllers/data.ts +++ b/apps/api/src/controllers/data.ts @@ -74,4 +74,24 @@ export function dataRoutes(fastify: FastifyInstance) { } } ); + + // Get all logs + fastify.get( + "/api/v1/data/logs", + async (request: FastifyRequest, reply: FastifyReply) => { + const bearer = request.headers.authorization!.split(" ")[1]; + const token = checkToken(bearer); + + if (token) { + try { + const logs = await import("fs/promises").then((fs) => + fs.readFile("logs.log", "utf-8") + ); + reply.send({ logs: logs }); + } catch (error) { + reply.code(500).send({ error: "Failed to read logs file" }); + } + } + } + ); } diff --git a/apps/client/layouts/adminLayout.tsx b/apps/client/layouts/adminLayout.tsx index 9141a306e..371c9421e 100644 --- a/apps/client/layouts/adminLayout.tsx +++ b/apps/client/layouts/adminLayout.tsx @@ -9,6 +9,7 @@ import { import { Button } from "@radix-ui/themes"; import { ContactIcon, + FileText, KeyRound, Mail, Mailbox, @@ -81,6 +82,12 @@ export default function AdminLayout({ children }: any) { current: location.pathname === "/admin/authentication", icon: KeyRound, }, + { + name: "Logs", + href: "/admin/logs", + current: location.pathname === "/admin/logs", + icon: FileText, + }, ]; return ( diff --git a/apps/client/pages/admin/logs.tsx b/apps/client/pages/admin/logs.tsx new file mode 100644 index 000000000..745bfead1 --- /dev/null +++ b/apps/client/pages/admin/logs.tsx @@ -0,0 +1,82 @@ +import { Card, CardContent, CardHeader, CardTitle } from "@/shadcn/ui/card"; +import { getCookie } from "cookies-next"; +import { useEffect, useState } from "react"; + +const Logs = () => { + const [logs, setLogs] = useState([]); + const [loading, setLoading] = useState(true); + + const fetchLogs = async () => { + const response = await fetch("/api/v1/data/logs", { + headers: { + Authorization: `Bearer ${getCookie("session")}`, + }, + }); + const data = await response.json(); + + // Split logs by newline and parse each line as JSON + const parsedLogs = data.logs + .split("\n") + .filter((line) => line.trim()) // Remove empty lines + .map((line) => { + try { + return JSON.parse(line); + } catch (e) { + console.error("Failed to parse log line:", e); + return null; + } + }) + .filter((log) => log !== null) // Remove any + .sort((a, b) => b.time - a.time); + + setLogs(parsedLogs); + setLoading(false); + }; + + useEffect(() => { + fetchLogs(); + }, []); + + if (loading) { + return
Loading...
; + } + + return ( +
+ + + + Logs + + + {logs.length === 0 ? ( +
No logs available
+ ) : ( +
    + {logs.map((log, index) => ( +
  • +
    + + {new Date(log.time).toLocaleString()} + + {log.msg} +
    +
  • + ))} +
+ )} +
+
+
+ ); +}; + +export default Logs; From d59518bd77c70f597888bc3a037a943cad1e35ba Mon Sep 17 00:00:00 2001 From: Jack Andrews Date: Mon, 11 Nov 2024 22:54:35 +0000 Subject: [PATCH 06/22] fix: issue api call --- apps/client/pages/issues/open.tsx | 36 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/apps/client/pages/issues/open.tsx b/apps/client/pages/issues/open.tsx index 3d84bd0a3..8196f0a8e 100644 --- a/apps/client/pages/issues/open.tsx +++ b/apps/client/pages/issues/open.tsx @@ -1,40 +1,40 @@ import useTranslation from "next-translate/useTranslation"; import { useRouter } from "next/router"; +import { useEffect, useMemo, useState } from "react"; import Loader from "react-spinners/ClipLoader"; -import { useState, useMemo, useEffect } from "react"; +import { toast } from "@/shadcn/hooks/use-toast"; +import { cn } from "@/shadcn/lib/utils"; +import { Button } from "@/shadcn/ui/button"; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, +} from "@/shadcn/ui/command"; import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, - ContextMenuTrigger, ContextMenuSub, - ContextMenuSubTrigger, ContextMenuSubContent, + ContextMenuSubTrigger, + ContextMenuTrigger, } from "@/shadcn/ui/context-menu"; +import { Popover, PopoverContent, PopoverTrigger } from "@/shadcn/ui/popover"; import { getCookie } from "cookies-next"; +import { CheckIcon, Filter, X } from "lucide-react"; import moment from "moment"; import Link from "next/link"; import { useQuery } from "react-query"; import { useUser } from "../../store/session"; -import { Popover, PopoverContent, PopoverTrigger } from "@/shadcn/ui/popover"; -import { CheckIcon, Filter, X } from "lucide-react"; -import { Button } from "@/shadcn/ui/button"; -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, - CommandSeparator, -} from "@/shadcn/ui/command"; -import { cn } from "@/shadcn/lib/utils"; -import { toast } from "@/shadcn/hooks/use-toast"; async function getUserTickets(token: any) { - const res = await fetch(`/api/v1/tickets/open`, { + const res = await fetch(`/api/v1/tickets/user/open`, { headers: { Authorization: `Bearer ${token}`, }, From 804c021907e1de0c60e517a0b6c0864f906ec8b9 Mon Sep 17 00:00:00 2001 From: Jack Andrews Date: Mon, 11 Nov 2024 22:57:37 +0000 Subject: [PATCH 07/22] feat: save filters to local storage --- apps/client/pages/issues/closed.tsx | 61 +++++++++++++++++++---------- apps/client/pages/issues/index.tsx | 25 ++++++++++-- apps/client/pages/issues/open.tsx | 42 ++++++++++++++++---- 3 files changed, 97 insertions(+), 31 deletions(-) diff --git a/apps/client/pages/issues/closed.tsx b/apps/client/pages/issues/closed.tsx index f9033c8e2..38f410f43 100644 --- a/apps/client/pages/issues/closed.tsx +++ b/apps/client/pages/issues/closed.tsx @@ -1,37 +1,37 @@ import useTranslation from "next-translate/useTranslation"; import { useRouter } from "next/router"; +import { useEffect, useMemo, useState } from "react"; import Loader from "react-spinners/ClipLoader"; -import { useState, useMemo, useEffect } from "react"; +import { toast } from "@/shadcn/hooks/use-toast"; +import { cn } from "@/shadcn/lib/utils"; +import { Button } from "@/shadcn/ui/button"; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, +} from "@/shadcn/ui/command"; import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, - ContextMenuTrigger, ContextMenuSub, - ContextMenuSubTrigger, ContextMenuSubContent, + ContextMenuSubTrigger, + ContextMenuTrigger, } from "@/shadcn/ui/context-menu"; +import { Popover, PopoverContent, PopoverTrigger } from "@/shadcn/ui/popover"; import { getCookie } from "cookies-next"; +import { CheckIcon, Filter, X } from "lucide-react"; import moment from "moment"; import Link from "next/link"; import { useQuery } from "react-query"; import { useUser } from "../../store/session"; -import { Popover, PopoverContent, PopoverTrigger } from "@/shadcn/ui/popover"; -import { CheckIcon, Filter, X } from "lucide-react"; -import { Button } from "@/shadcn/ui/button"; -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, - CommandSeparator, -} from "@/shadcn/ui/command"; -import { cn } from "@/shadcn/lib/utils"; -import { toast } from "@/shadcn/hooks/use-toast"; async function getUserTickets(token: any) { const res = await fetch(`/api/v1/tickets/completed`, { @@ -83,11 +83,32 @@ export default function Tickets() { const normal = "bg-green-100 text-green-800"; const [filterSelected, setFilterSelected] = useState(); - const [selectedPriorities, setSelectedPriorities] = useState([]); - const [selectedStatuses, setSelectedStatuses] = useState([]); - const [selectedAssignees, setSelectedAssignees] = useState([]); + const [selectedPriorities, setSelectedPriorities] = useState(() => { + const saved = localStorage.getItem('closed_selectedPriorities'); + return saved ? JSON.parse(saved) : []; + }); + const [selectedStatuses, setSelectedStatuses] = useState(() => { + const saved = localStorage.getItem('closed_selectedStatuses'); + return saved ? JSON.parse(saved) : []; + }); + const [selectedAssignees, setSelectedAssignees] = useState(() => { + const saved = localStorage.getItem('closed_selectedAssignees'); + return saved ? JSON.parse(saved) : []; + }); const [users, setUsers] = useState([]); + useEffect(() => { + localStorage.setItem('closed_selectedPriorities', JSON.stringify(selectedPriorities)); + }, [selectedPriorities]); + + useEffect(() => { + localStorage.setItem('closed_selectedStatuses', JSON.stringify(selectedStatuses)); + }, [selectedStatuses]); + + useEffect(() => { + localStorage.setItem('closed_selectedAssignees', JSON.stringify(selectedAssignees)); + }, [selectedAssignees]); + const handlePriorityToggle = (priority: string) => { setSelectedPriorities((prev) => prev.includes(priority) diff --git a/apps/client/pages/issues/index.tsx b/apps/client/pages/issues/index.tsx index ae9388e88..a487ba404 100644 --- a/apps/client/pages/issues/index.tsx +++ b/apps/client/pages/issues/index.tsx @@ -82,9 +82,28 @@ export default function Tickets() { const low = "bg-blue-100 text-blue-800"; const normal = "bg-green-100 text-green-800"; - const [selectedPriorities, setSelectedPriorities] = useState([]); - const [selectedStatuses, setSelectedStatuses] = useState([]); - const [selectedAssignees, setSelectedAssignees] = useState([]); + const [selectedPriorities, setSelectedPriorities] = useState(() => { + const saved = localStorage.getItem('all_selectedPriorities'); + return saved ? JSON.parse(saved) : []; + }); + + const [selectedStatuses, setSelectedStatuses] = useState(() => { + const saved = localStorage.getItem('all_selectedStatuses'); + return saved ? JSON.parse(saved) : []; + }); + + const [selectedAssignees, setSelectedAssignees] = useState(() => { + const saved = localStorage.getItem('all_selectedAssignees'); + return saved ? JSON.parse(saved) : []; + }); + + // Update local storage when filters change + useEffect(() => { + localStorage.setItem('all_selectedPriorities', JSON.stringify(selectedPriorities)); + localStorage.setItem('all_selectedStatuses', JSON.stringify(selectedStatuses)); + localStorage.setItem('all_selectedAssignees', JSON.stringify(selectedAssignees)); + }, [selectedPriorities, selectedStatuses, selectedAssignees]); + const [users, setUsers] = useState([]); const handlePriorityToggle = (priority: string) => { diff --git a/apps/client/pages/issues/open.tsx b/apps/client/pages/issues/open.tsx index 8196f0a8e..6604e0ab2 100644 --- a/apps/client/pages/issues/open.tsx +++ b/apps/client/pages/issues/open.tsx @@ -83,11 +83,41 @@ export default function Tickets() { const normal = "bg-green-100 text-green-800"; const [filterSelected, setFilterSelected] = useState(); - const [selectedPriorities, setSelectedPriorities] = useState([]); - const [selectedStatuses, setSelectedStatuses] = useState([]); - const [selectedAssignees, setSelectedAssignees] = useState([]); + const [selectedPriorities, setSelectedPriorities] = useState(() => { + const saved = localStorage.getItem('open_selectedPriorities'); + return saved ? JSON.parse(saved) : []; + }); + const [selectedStatuses, setSelectedStatuses] = useState(() => { + const saved = localStorage.getItem('open_selectedStatuses'); + return saved ? JSON.parse(saved) : []; + }); + const [selectedAssignees, setSelectedAssignees] = useState(() => { + const saved = localStorage.getItem('open_selectedAssignees'); + return saved ? JSON.parse(saved) : []; + }); const [users, setUsers] = useState([]); + useEffect(() => { + localStorage.setItem('open_selectedPriorities', JSON.stringify(selectedPriorities)); + }, [selectedPriorities]); + + useEffect(() => { + localStorage.setItem('open_selectedStatuses', JSON.stringify(selectedStatuses)); + }, [selectedStatuses]); + + useEffect(() => { + localStorage.setItem('open_selectedAssignees', JSON.stringify(selectedAssignees)); + }, [selectedAssignees]); + + const clearAllFilters = () => { + setSelectedPriorities([]); + setSelectedStatuses([]); + setSelectedAssignees([]); + localStorage.removeItem('open_selectedPriorities'); + localStorage.removeItem('open_selectedStatuses'); + localStorage.removeItem('open_selectedAssignees'); + }; + const handlePriorityToggle = (priority: string) => { setSelectedPriorities((prev) => prev.includes(priority) @@ -480,11 +510,7 @@ export default function Tickets() { variant="ghost" size="sm" className="h-6 px-2 text-xs" - onClick={() => { - setSelectedPriorities([]); - setSelectedStatuses([]); - setSelectedAssignees([]); - }} + onClick={clearAllFilters} > Clear all From 3ee96dcab407bc371218d533f0dfe179ef25ca0a Mon Sep 17 00:00:00 2001 From: Jack Andrews Date: Mon, 11 Nov 2024 23:16:49 +0000 Subject: [PATCH 08/22] chore: improve ticket widthing --- .../@/shadcn/components/app-sidebar.tsx | 2 +- .../client/components/TicketDetails/index.tsx | 437 +++++++++--------- apps/client/layouts/shad.tsx | 4 +- 3 files changed, 217 insertions(+), 226 deletions(-) diff --git a/apps/client/@/shadcn/components/app-sidebar.tsx b/apps/client/@/shadcn/components/app-sidebar.tsx index a41e43616..3f9c97e13 100644 --- a/apps/client/@/shadcn/components/app-sidebar.tsx +++ b/apps/client/@/shadcn/components/app-sidebar.tsx @@ -163,7 +163,7 @@ export function AppSidebar({ ...props }: React.ComponentProps) { }, [handleKeyPress, location]); return ( - + {/* */}
diff --git a/apps/client/components/TicketDetails/index.tsx b/apps/client/components/TicketDetails/index.tsx index bfac55564..02f3b9b28 100644 --- a/apps/client/components/TicketDetails/index.tsx +++ b/apps/client/components/TicketDetails/index.tsx @@ -567,255 +567,246 @@ export default function Ticket() {
-
-
-
-
-
-
-

- #{data.ticket.Number} - -

- setTitle(e.target.value)} - key={data.ticket.id} - disabled={data.ticket.locked} - /> -
-
-
- {data.ticket.client && ( -
- - {data.ticket.client.name} - -
- )} -
- {!data.ticket.isComplete ? ( -
- - {t("open_issue")} - -
- ) : ( -
- - {t("closed_issue")} - -
- )} -
+
+
+
+
+
+

+ #{data.ticket.Number} - +

+ setTitle(e.target.value)} + key={data.ticket.id} + disabled={data.ticket.locked} + /> +
+
+
+ {data.ticket.client && (
- {data.ticket.type} + {data.ticket.client.name}
- {data.ticket.hidden && ( -
- - Hidden + )} +
+ {!data.ticket.isComplete ? ( +
+ + {t("open_issue")}
- )} - {data.ticket.locked && ( -
- - Locked + ) : ( +
+ + {t("closed_issue")}
)}
- {user.isAdmin && ( - - - - - - - Issue Actions - - - {data.ticket.hidden ? ( - hide(false)} - > - - Show Issue - - ) : ( - hide(true)} - > - - Hide Issue - - )} - {data.ticket.locked ? ( - lock(false)} - > - - Unlock Issue - - ) : ( - lock(true)} - > - - Lock Issue - - )} - +
+ + {data.ticket.type} + +
+ {data.ticket.hidden && ( +
+ + Hidden + +
+ )} + {data.ticket.locked && ( +
+ + Locked + +
+ )} +
+ {user.isAdmin && ( + + + + + + + Issue Actions + + + {data.ticket.hidden ? ( deleteIssue()} + className="flex flex-row space-x-3 items-center" + onClick={() => hide(false)} > - - Delete Issue + + Show Issue - - - )} -
+ ) : ( + hide(true)} + > + + Hide Issue + + )} + {data.ticket.locked ? ( + lock(false)} + > + + Unlock Issue + + ) : ( + lock(true)} + > + + Lock Issue + + )} + + deleteIssue()} + > + + Delete Issue + + + + )}
- +
+
+ {data.ticket.fromImap ? ( + <> + {data.ticket.email} + created via email at + + {moment(data.ticket.createdAt).format("DD/MM/YYYY")} + + + ) : ( + <> + {data.ticket.createdBy ? ( +
+ + Created by + + {data.ticket.createdBy.name} + at{" "} + + + {moment(data.ticket.createdAt).format("LLL")} + + {data.ticket.name && ( + + for {data.ticket.name} + )} - - - ) : ( - <> - {data.ticket.createdBy ? ( -
+ {data.ticket.email && ( - Created by - - {data.ticket.createdBy.name} - {" "} - at{" "} + ( {data.ticket.email} ) - + )} +
+ ) : ( +
+ Created at + + {moment(data.ticket.createdAt).format("LLL")} - - {data.ticket.name && ( - - for {data.ticket.name} - - )} - {data.ticket.email && ( + + {data.ticket.client && ( - ( {data.ticket.email} ) + for{" "} + {data.ticket.client.name} )} -
- ) : ( -
- Created at - - - {moment(data.ticket.createdAt).format( - "LLL" - )} - - {data.ticket.client && ( - - for{" "} - {data.ticket.client.name} - - )} - -
- )} - - )} -
-
- {!data.ticket.fromImap ? ( - <> - - - ) : ( -
-
- +
+ )} + + )} +
+
+ {!data.ticket.fromImap ? ( + <> + + + ) : ( +
+
+
- )} -
+
+ )}
-
+

{t("details")}

-
+
{users && ( +
@@ -54,7 +54,7 @@ export default function ShadLayout({ children }: any) { )}
-
+
-
-
- {data.ticket.fromImap ? ( - <> - {data.ticket.email} - created via email at - - {moment(data.ticket.createdAt).format("DD/MM/YYYY")} - - - ) : ( - <> - {data.ticket.createdBy ? ( -
- - Created by - - {data.ticket.createdBy.name} - at{" "} - - - {moment(data.ticket.createdAt).format("LLL")} - - {data.ticket.name && ( - - for {data.ticket.name} - - )} - {data.ticket.email && ( - - ( {data.ticket.email} ) - - )} -
- ) : ( -
- Created at - - - {moment(data.ticket.createdAt).format("LLL")} - - {data.ticket.client && ( - - for{" "} - {data.ticket.client.name} - - )} - -
- )} - - )} -
+
{!data.ticket.fromImap ? ( <> @@ -810,205 +759,230 @@ export default function Ticket() {
-
-
-
- - {t("comments")} - -
-
- {/* Activity feed*/} -
-
    - {data.ticket.comments.length > 0 && - data.ticket.comments.map( - (item: any, itemIdx: any) => ( -
  • -
    - {itemIdx !== - data.ticket.comments.length - 1 ? ( -
    -
  • - ) +
    +
    + + Activity + +
    +
    +
    + {data.ticket.fromImap ? ( + <> + + {data.ticket.email} + + created via email at + + {moment(data.ticket.createdAt).format( + "DD/MM/YYYY" )} -
-
-
-
-
-
-
- -