import { format, formatDistanceToNow } from "date-fns";
import React, { FormEvent, useCallback, useMemo, useState } from "react";
import { ApiToken, NewApiToken } from "../api/entities/api-token";
import { useApiTokens } from "../hooks/use-api";
import { useAuthProtection } from "../hooks/use-auth-protection";
import { SpinnerIcon } from "../icons/Spinner";
import TrashcanIcon from "../icons/Trashcan";
import { Spinner } from "./Spinner";
export const AuthApiTokens: React.FC = () => {
const { requireUser } = useAuthProtection();
const { apiTokens, isLoading, createToken, revokeToken } = useApiTokens();
const sortedTokens = useMemo(
() => apiTokens.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1)),
[apiTokens],
);
requireUser();
return (
You can use API Tokens to access the Listory API directly. You can
find the API docs{" "}
here
.
Manage Existing Tokens
{isLoading &&
}
{sortedTokens.length === 0 && (
Could not find any api tokens!
)}
{sortedTokens.length > 0 && (
{sortedTokens.map((apiToken) => (
))}
)}
);
};
const NewTokenForm: React.FC<{
createToken: (description: string) => Promise;
}> = ({ createToken }) => {
const [newTokenDescription, setNewTokenDescription] = useState("");
const [newToken, setNewToken] = useState(null);
const [isLoading, setLoading] = useState(false);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [error, setError] = useState(null);
const submitForm = useCallback(
async (event: FormEvent) => {
event.preventDefault();
setLoading(true);
setError(null);
try {
const newToken = await createToken(newTokenDescription);
setNewToken(newToken);
setNewTokenDescription("");
} catch (err: any) {
setError(err);
}
setLoading(false);
},
[
setLoading,
setError,
newTokenDescription,
createToken,
setNewToken,
setNewTokenDescription,
],
);
return (
);
};
const NewApiTokenItem: React.FC<{ apiToken: NewApiToken }> = ({ apiToken }) => {
const copyToken = useCallback(() => {
navigator.clipboard.writeText(apiToken.token);
}, [apiToken]);
return (
Your new API Token:
{apiToken.token}
The token will only be visible once, so make sure to save it!
);
};
const ApiTokenItem: React.FC<{
apiToken: ApiToken;
revokeToken: (id: string) => Promise;
}> = ({ apiToken, revokeToken }) => {
const [isBeingRevoked, setIsBeingRevoked] = useState(false);
const revokeTokenButton = useCallback(async () => {
setIsBeingRevoked(true);
await revokeToken(apiToken.id);
setIsBeingRevoked(false);
}, [setIsBeingRevoked, revokeToken, apiToken]);
const description = apiToken.description;
const prefix = apiToken.prefix;
const timeAgo = formatDistanceToNow(new Date(apiToken.createdAt), {
addSuffix: true,
});
const dateTime = format(new Date(apiToken.createdAt), "PP p");
const displayRevokeButton = apiToken.revokedAt == null && !isBeingRevoked;
const displaySpinner = isBeingRevoked;
return (
{description}
{prefix}...
{timeAgo}
{displayRevokeButton && (
)}
{displaySpinner && (
)}
);
};