mirror of https://github.com/usememos/memos.git
Update CreateAccessTokenDialog and AccessTokenSection; improve handling
This commit is contained in:
parent
1684b78cd3
commit
c7b53930cc
|
|
@ -8,12 +8,13 @@ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||||
import { userServiceClient } from "@/grpcweb";
|
import { userServiceClient } from "@/grpcweb";
|
||||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||||
import useLoading from "@/hooks/useLoading";
|
import useLoading from "@/hooks/useLoading";
|
||||||
|
import { UserAccessToken } from "@/types/proto/api/v1/user_service";
|
||||||
import { useTranslate } from "@/utils/i18n";
|
import { useTranslate } from "@/utils/i18n";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
onSuccess: () => void;
|
onSuccess: (created: UserAccessToken) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
|
@ -72,7 +73,7 @@ function CreateAccessTokenDialog({ open, onOpenChange, onSuccess }: Props) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
requestState.setLoading();
|
requestState.setLoading();
|
||||||
await userServiceClient.createUserAccessToken({
|
const created = await userServiceClient.createUserAccessToken({
|
||||||
parent: currentUser.name,
|
parent: currentUser.name,
|
||||||
accessToken: {
|
accessToken: {
|
||||||
description: state.description,
|
description: state.description,
|
||||||
|
|
@ -81,7 +82,7 @@ function CreateAccessTokenDialog({ open, onOpenChange, onSuccess }: Props) {
|
||||||
});
|
});
|
||||||
|
|
||||||
requestState.setFinish();
|
requestState.setFinish();
|
||||||
onSuccess();
|
onSuccess(created);
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.error(error.details);
|
toast.error(error.details);
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,13 @@ const AccessTokenSection = () => {
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleCreateAccessTokenDialogConfirm = async () => {
|
const handleCreateAccessTokenDialogConfirm = async (created?: UserAccessToken) => {
|
||||||
const prevTokensSet = new Set(userAccessTokens.map((token) => token.accessToken));
|
// Refresh list to reflect server state and include stable fields like issuedAt/expiresAt
|
||||||
const accessTokens = await listAccessTokens(currentUser.name);
|
const accessTokens = await listAccessTokens(currentUser.name);
|
||||||
setUserAccessTokens(accessTokens);
|
setUserAccessTokens(accessTokens);
|
||||||
const newToken = accessTokens.find((token) => !prevTokensSet.has(token.accessToken));
|
|
||||||
toast.success(
|
toast.success(
|
||||||
t("setting.access-token-section.create-dialog.access-token-created", {
|
t("setting.access-token-section.create-dialog.access-token-created", {
|
||||||
description: newToken?.description ?? t("setting.access-token-section.create-dialog.access-token-created-default"),
|
description: created?.description ?? t("setting.access-token-section.create-dialog.access-token-created-default"),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -56,9 +55,10 @@ const AccessTokenSection = () => {
|
||||||
|
|
||||||
const confirmDeleteAccessToken = async () => {
|
const confirmDeleteAccessToken = async () => {
|
||||||
if (!deleteTarget) return;
|
if (!deleteTarget) return;
|
||||||
const { name, accessToken, description } = deleteTarget;
|
const { name: tokenName, description } = deleteTarget;
|
||||||
await userServiceClient.deleteUserAccessToken({ name });
|
await userServiceClient.deleteUserAccessToken({ name: tokenName });
|
||||||
setUserAccessTokens((prev) => prev.filter((token) => token.accessToken !== accessToken));
|
// Filter by stable resource name to avoid ambiguity with duplicate token strings
|
||||||
|
setUserAccessTokens((prev) => prev.filter((token) => token.name !== tokenName));
|
||||||
setDeleteTarget(undefined);
|
setDeleteTarget(undefined);
|
||||||
toast.success(t("setting.access-token-section.access-token-deleted", { description }));
|
toast.success(t("setting.access-token-section.access-token-deleted", { description }));
|
||||||
};
|
};
|
||||||
|
|
@ -108,7 +108,7 @@ const AccessTokenSection = () => {
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y divide-border">
|
<tbody className="divide-y divide-border">
|
||||||
{userAccessTokens.map((userAccessToken) => (
|
{userAccessTokens.map((userAccessToken) => (
|
||||||
<tr key={userAccessToken.accessToken}>
|
<tr key={userAccessToken.name}>
|
||||||
<td className="whitespace-nowrap px-3 py-2 text-sm text-foreground flex flex-row justify-start items-center gap-x-1">
|
<td className="whitespace-nowrap px-3 py-2 text-sm text-foreground flex flex-row justify-start items-center gap-x-1">
|
||||||
<span className="font-mono">{getFormatedAccessToken(userAccessToken.accessToken)}</span>
|
<span className="font-mono">{getFormatedAccessToken(userAccessToken.accessToken)}</span>
|
||||||
<Button variant="ghost" onClick={() => copyAccessToken(userAccessToken.accessToken)}>
|
<Button variant="ghost" onClick={() => copyAccessToken(userAccessToken.accessToken)}>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue