Skip to content

Commit

Permalink
More progress on moderation ticket pane 😭
Browse files Browse the repository at this point in the history
  • Loading branch information
SupertigerDev committed Nov 26, 2023
1 parent d7cab69 commit fb6cd39
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 56 deletions.
1 change: 1 addition & 0 deletions src/chat-api/RawData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export interface RawTicket {
status: TicketStatus;
lastUpdatedAt: number;
openedById: string;
openedBy?: RawUser;
openedAt: Date;
}

Expand Down
6 changes: 4 additions & 2 deletions src/components/moderation-pane/ModerationPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { Notice } from "../ui/Notice";
import SettingsBlock from "../ui/settings-block/SettingsBlock";

const UserPage = lazy(() => import("./UserPage"));
const TicketsPage = lazy(() => import("./TicketsPage"));
const ServerPage = lazy(() => import("./ServerPage"));

const [stats, setStats] = createSignal<ModerationStats | null>(null);
Expand Down Expand Up @@ -155,12 +156,12 @@ export default function ModerationPane() {
}
});

const show = useMatch(() => "/app/moderation");
const isModerationRoute = useMatch(() => "/app/moderation");

return (
<Show when={load()}>
<ModerationPage />
<Show when={!show()}>
<Show when={!isModerationRoute()}>
<div
style={{
position: "absolute",
Expand All @@ -178,6 +179,7 @@ export default function ModerationPane() {
<Routes>
<Route path="/servers/:serverId" element={<ServerPage />} />
<Route path="/users/:userId" element={<UserPage />} />
<Route path="/tickets" element={<TicketsPage/>} />
</Routes>
</div>
</Show>
Expand Down
64 changes: 64 additions & 0 deletions src/components/moderation-pane/TicketsPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { USER_BADGES, addBit, hasBit, removeBit } from "@/chat-api/Bitwise";
import {
ModerationUser,
getTickets,
getUser,
getUsersWithSameIPAddress,
updateUser,
} from "@/chat-api/services/ModerationService";
import { createUpdatedSignal } from "@/common/createUpdatedSignal";
import { useWindowProperties } from "@/common/useWindowProperties";
import { A, useParams } from "@solidjs/router";
import { For, Show, createEffect, createSignal, on, onMount } from "solid-js";
import { css, styled } from "solid-styled-components";
import { FlexColumn, FlexRow } from "../ui/Flexbox";
import { Banner } from "../ui/Banner";
import Avatar from "../ui/Avatar";
import RouterEndpoints from "@/common/RouterEndpoints";
import { bannerUrl } from "@/chat-api/store/useUsers";
import Breadcrumb, { BreadcrumbItem } from "../ui/Breadcrumb";
import SettingsBlock from "../ui/settings-block/SettingsBlock";
import Input from "../ui/input/Input";
import Checkbox from "../ui/Checkbox";
import { formatTimestamp } from "@/common/date";
import UnsuspendUsersModal from "./UnsuspendUsersModal";
import SuspendUsersModal from "./SuspendUsersModal";
import { useCustomPortal } from "../ui/custom-portal/CustomPortal";
import Button from "../ui/Button";
import env from "@/common/env";
import Text from "../ui/Text";
import { RawServer, RawTicket, RawUser } from "@/chat-api/RawData";
import { Server, User } from "./ModerationPane";
import { TicketItem } from "../settings/TicketSettings";

const PageContainer = styled(FlexColumn)`
height: 100%;
width: 100%;
max-width: 900px;
align-self: center;
margin-top: 10px;
`;

const TicketListContainer = styled(FlexColumn)`
padding: 10px;
gap: 8px;
`;

export default function TicketPage() {
const [tickets, setTickets] = createSignal<RawTicket[]>([]);

onMount(async () => {
const tickets = await getTickets({ limit: 30 });
setTickets(tickets);
});

return (
<PageContainer>
<TicketListContainer>
<For each={tickets()}>
{(ticket) => <TicketItem as="mod" ticket={ticket} />}
</For>
</TicketListContainer>
</PageContainer>
);
}
133 changes: 79 additions & 54 deletions src/components/settings/TicketSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -283,32 +283,33 @@ const TableRowStyle = css`

const StatusText = styled("div")<{ bgColor: string }>`
background-color: ${(props) => props.bgColor};
border-radius: 12px;
padding: 4px;
padding-left: 8px;
padding-right: 8px;
font-size: 14px;
border-radius: 6px;
padding: 2px;
padding-left: 6px;
padding-right: 6px;
font-size: 16px;
color: black;
`;

const StatusToName = (as: "mod" | "user") => ({
[TicketStatus.CLOSED_AS_DONE]: {
text: "Resolved",
color: "var(--primary-color)",
},
[TicketStatus.CLOSED_AS_INVALID]: {
text: "Closed",
color: "gray",
},
[TicketStatus.WAITING_FOR_MODERATOR_RESPONSE]: {
text: as === "user" ? "Reply Sent" : "Action Required",
color: as === "user" ? "var(--success-color)" : "var(--warn-color)",
},
[TicketStatus.WAITING_FOR_USER_RESPONSE]: {
text: as === "user" ? "Action Required" : "Reply Sent",
color: as === "user" ? "var(--warn-color)" : 'var(--success-color)',
},
} as const);
const StatusToName = (as: "mod" | "user") =>
({
[TicketStatus.CLOSED_AS_DONE]: {
text: "Resolved",
color: "var(--primary-color)",
},
[TicketStatus.CLOSED_AS_INVALID]: {
text: "Closed",
color: "gray",
},
[TicketStatus.WAITING_FOR_MODERATOR_RESPONSE]: {
text: as === "user" ? "Reply Sent" : "Action Required",
color: as === "user" ? "var(--success-color)" : "var(--warn-color)",
},
[TicketStatus.WAITING_FOR_USER_RESPONSE]: {
text: as === "user" ? "Action Required" : "Reply Sent",
color: as === "user" ? "var(--warn-color)" : "var(--success-color)",
},
} as const);

const CategoryToName = {
[TicketCategory.QUESTION]: "Question",
Expand All @@ -317,7 +318,7 @@ const CategoryToName = {
[TicketCategory.OTHER]: "Other",
} as const;

const TicketItemTable = (props: { ticket: RawTicket, as: "mod" | "user" }) => {
const TicketItemTable = (props: { ticket: RawTicket; as: "mod" | "user" }) => {
return (
<CustomLink href={`./${props.ticket.id}`} class={TableRowStyle}>
<td class="firstCol">
Expand Down Expand Up @@ -351,10 +352,12 @@ const TicketItemTable = (props: { ticket: RawTicket, as: "mod" | "user" }) => {
padding-bottom: 4px;
`}
>
<StatusText bgColor={StatusToName(props.as)[props.ticket.status].color}>
<StatusText
bgColor={StatusToName(props.as)[props.ticket.status].color}
>
{StatusToName(props.as)[props.ticket.status].text}
</StatusText>
<Text color="white" size={14}>
<Text color="white" size={12}>
{formatTimestamp(props.ticket.lastUpdatedAt)}
</Text>
</FlexColumn>
Expand All @@ -365,48 +368,70 @@ const TicketItemTable = (props: { ticket: RawTicket, as: "mod" | "user" }) => {

const TicketItemStyle = css`
display: flex;
flex-direction: column;
flex-direction: row;
user-select: none;
background-color: rgba(0, 0, 0, 0.2);
border-radius: 6px;
gap: 4px;
padding: 6px;
`;

const TicketItem = (props: { ticket: RawTicket; disableClick?: boolean, as: "mod" | "user" }) => {
export const TicketItem = (props: {
ticket: RawTicket;
disableClick?: boolean;
as: "mod" | "user";
}) => {
return (
<Dynamic
component={!props.disableClick ? CustomLink : "div"}
href={`./${props.ticket.id}`}
class={TicketItemStyle}
>
<FlexRow itemsCenter gap={4}>
<Text opacity={0.4}>#{props.ticket.id}</Text>
<Text size={14}>{props.ticket.title}</Text>
</FlexRow>
<Text
size={12}
opacity={0.4}
class={css`
margin-left: 22px;
`}
>
{CategoryToName[props.ticket.category]}
<Text opacity={0.4} class={css`width`}>
#{props.ticket.id}
</Text>

<FlexColumn
gap={4}
class={css`
align-items: flex-start;
margin-top: 4px;
margin-left: 22px;
`}
>
<StatusText bgColor={StatusToName(props.as)[props.ticket.status].color}>
{StatusToName(props.as)[props.ticket.status].text}
</StatusText>
<Text color="white" size={14}>
{formatTimestamp(props.ticket.lastUpdatedAt)}
<FlexColumn>
<FlexRow gap={4} itemsCenter>
<StatusText
bgColor={StatusToName(props.as)[props.ticket.status].color}
>
{StatusToName(props.as)[props.ticket.status].text}
</StatusText>
</FlexRow>
<FlexRow
class={css`
margin-top: 2px;
`}
>
<Text size={14}>{props.ticket.title}</Text>
</FlexRow>
<Text
size={12}
opacity={0.4}
>
{CategoryToName[props.ticket.category]}
</Text>

<Show when={props.ticket.openedBy}>
<CustomLink href={RouterEndpoints.PROFILE(props.ticket.openedBy?.id!)}>
<FlexRow itemsCenter gap={4} class={css`margin-top: 4px; margin-bottom: 4px;`}>
<Avatar user={props.ticket.openedBy} size={18} />
<Text size={12}>{props.ticket.openedBy?.username}:{props.ticket.openedBy?.tag}</Text>
</FlexRow>
</CustomLink>
</Show>

<FlexColumn
gap={4}
class={css`
align-items: flex-start;
margin-top: 4px;
`}
>
<Text color="white" size={12}>
{formatTimestamp(props.ticket.lastUpdatedAt)}
</Text>
</FlexColumn>
</FlexColumn>
</Dynamic>
);
Expand Down

0 comments on commit fb6cd39

Please sign in to comment.