168 lines
4.5 KiB
TypeScript
168 lines
4.5 KiB
TypeScript
import clsx from "clsx";
|
|
import { useState } from "react";
|
|
import {
|
|
LoaderFunctionArgs,
|
|
useLoaderData,
|
|
useNavigate,
|
|
} from "react-router-dom";
|
|
import { createImporterStatusPageURL } from "#lib/urls";
|
|
import { fetchHasPendingDMs } from "#api/dms";
|
|
import { fetchImportLogs } from "#api/imports";
|
|
import { getLocalStorageItem, setLocalStorageItem } from "#storage/local";
|
|
import { useInterval } from "#hooks";
|
|
import { PageSkeleton } from "#components/pages";
|
|
import { LoadingIcon } from "#components/loading";
|
|
import { Button } from "#components/buttons";
|
|
|
|
interface IProps {
|
|
importID: string;
|
|
isDMS?: boolean;
|
|
logs: string[];
|
|
}
|
|
|
|
export function ImporterStatusPage() {
|
|
const { importID, isDMS, logs } = useLoaderData() as IProps;
|
|
const navigate = useNavigate();
|
|
const [isReversed, switchReversed] = useState(false);
|
|
const title = `Import ${importID}`;
|
|
const heading = `Importer logs for ${importID}`;
|
|
const status = logs.length === 0 ? "Fetching" : "In Progress";
|
|
const cooldown = 120_000;
|
|
|
|
useInterval(() => {
|
|
navigate(String(createImporterStatusPageURL(importID)));
|
|
}, cooldown);
|
|
|
|
return (
|
|
<PageSkeleton name="importer-status" title={title} heading={heading}>
|
|
{isDMS && (
|
|
<div className="jumbo no-posts">
|
|
<strong>Hey!</strong>
|
|
<p>
|
|
You gave the importer permission to access your messages. To protect
|
|
your anonymity, you must manually approve each one. Wait until{" "}
|
|
<i>after</i> the importer says <code>Done importing DMs</code>, then
|
|
go <a href="/account/review_dms">here</a> to choose which ones you
|
|
wish to import.
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
<div className="import">
|
|
<div className="import__info">
|
|
<div className="import__stats">
|
|
<div className="import__status">
|
|
<span>Status: </span>
|
|
<span>{status}</span>
|
|
</div>
|
|
|
|
<div
|
|
className={clsx(
|
|
"import__count",
|
|
logs.length === 0 && "import__count--invisible"
|
|
)}
|
|
>
|
|
<span>Total: </span>
|
|
<span>{logs.length}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="import__buttons">
|
|
<Button
|
|
className="import__reverse"
|
|
onClick={() => switchReversed((old) => !old)}
|
|
>
|
|
Reverse order
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
<p
|
|
className={clsx(
|
|
"loading-placeholder",
|
|
logs.length !== 0 && "loading-placeholder--complete"
|
|
)}
|
|
>
|
|
<LoadingIcon /> <span>Wait until logs load...</span>
|
|
</p>
|
|
|
|
<ol
|
|
id="log-list"
|
|
className={clsx(
|
|
"log-list",
|
|
logs.length !== 0 && "log-list--loaded",
|
|
isReversed && "log-list--reversed"
|
|
)}
|
|
>
|
|
{logs.length !== 0 &&
|
|
logs.map((message, index) => (
|
|
<li key={`${index}-${message}`} className="log-list__item">
|
|
{message}
|
|
</li>
|
|
))}
|
|
</ol>
|
|
</div>
|
|
</PageSkeleton>
|
|
);
|
|
}
|
|
|
|
async function initPendingReviewDms(
|
|
forceReload = false,
|
|
minutesForRecheck = 30
|
|
) {
|
|
let hasPendingReviewDms =
|
|
getLocalStorageItem("has_pending_review_dms") === "true";
|
|
const lastCheckedHasPendingReviewDms = parseInt(
|
|
getLocalStorageItem("last_checked_has_pending_review_dms") ?? "0",
|
|
10
|
|
);
|
|
|
|
if (
|
|
forceReload ||
|
|
!lastCheckedHasPendingReviewDms ||
|
|
lastCheckedHasPendingReviewDms < Date.now() - minutesForRecheck * 60 * 1000
|
|
) {
|
|
/**
|
|
* @type {string}
|
|
*/
|
|
hasPendingReviewDms = await fetchHasPendingDMs();
|
|
setLocalStorageItem("has_pending_review_dms", String(hasPendingReviewDms));
|
|
localStorage.setItem(
|
|
"last_checked_has_pending_review_dms",
|
|
Date.now().toString()
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function loader({
|
|
params,
|
|
request,
|
|
}: LoaderFunctionArgs): Promise<IProps> {
|
|
const searchparams = new URL(request.url).searchParams;
|
|
|
|
const importID = params.import_id?.trim();
|
|
if (!importID) {
|
|
throw new Error("Import ID is required.");
|
|
}
|
|
|
|
let isDMS: boolean | undefined = undefined;
|
|
{
|
|
const inputValue = Boolean(searchparams.get("dms")?.trim());
|
|
if (inputValue) {
|
|
isDMS = inputValue;
|
|
}
|
|
}
|
|
|
|
const logs = await fetchImportLogs(importID);
|
|
|
|
if (logs.length !== 0) {
|
|
initPendingReviewDms(true);
|
|
}
|
|
|
|
return {
|
|
importID,
|
|
isDMS,
|
|
logs,
|
|
};
|
|
}
|