Skip to content

Commit b45617a

Browse files
Laurie T. Malauroboquat
Laurie T. Malau
authored andcommitted
[pat] Show list of tokens
1 parent a5a7d64 commit b45617a

File tree

2 files changed

+104
-12
lines changed

2 files changed

+104
-12
lines changed

components/dashboard/src/settings/PersonalAccessTokens.tsx

+29-12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { Timestamp } from "@bufbuild/protobuf";
1818
import Alert from "../components/Alert";
1919
import { InputWithCopy } from "../components/InputWithCopy";
2020
import { copyToClipboard } from "../utils";
21+
import TokenEntry from "./TokenEntry";
2122

2223
function PersonalAccessTokens() {
2324
const { enablePersonalAccessTokens } = useContext(FeatureFlagContext);
@@ -197,14 +198,16 @@ function ListAccessTokensView() {
197198

198199
return (
199200
<>
200-
<div className="flex items-center sm:justify-between mb-2">
201+
<div className="flex items-center sm:justify-between mb-4">
201202
<div>
202203
<h3>Personal Access Tokens</h3>
203204
<h2 className="text-gray-500">Create or regenerate active personal access tokens.</h2>
204205
</div>
205-
<Link to={settingsPathPersonalAccessTokenCreate}>
206-
<button>New Personal Access Token</button>
207-
</Link>
206+
{tokens.length > 0 && (
207+
<Link to={settingsPathPersonalAccessTokenCreate}>
208+
<button>New Personal Access Token</button>
209+
</Link>
210+
)}
208211
</div>
209212
<>
210213
{tokenInfo && (
@@ -251,16 +254,30 @@ function ListAccessTokensView() {
251254
</>
252255
)}
253256
</>
254-
{tokens.length > 0 && (
255-
<ul>
257+
{tokens.length === 0 ? (
258+
<div className="bg-gray-100 dark:bg-gray-800 rounded-xl w-full py-28 flex flex-col items-center">
259+
<h3 className="text-center pb-3 text-gray-500 dark:text-gray-400">
260+
No Personal Access Tokens (PAT)
261+
</h3>
262+
<p className="text-center pb-6 text-gray-500 text-base w-96">
263+
Generate a personal access token (PAT) for applications that need access to the Gitpod API.{" "}
264+
</p>
265+
<Link to={settingsPathPersonalAccessTokenCreate}>
266+
<button>New Personal Access Token</button>
267+
</Link>
268+
</div>
269+
) : (
270+
<>
271+
<div className="px-6 py-3 flex justify-between space-x-2 text-sm text-gray-400 mb-2 bg-gray-100 rounded-xl">
272+
<h2 className="w-3/12">Token Name</h2>
273+
<h2 className="w-3/12">Permissions</h2>
274+
<h2 className="w-3/12">Expires</h2>
275+
<div className="w-3/12"></div>
276+
</div>
256277
{tokens.map((t: PersonalAccessToken) => {
257-
return (
258-
<li>
259-
{t.id} - {t.name} - {t.value}
260-
</li>
261-
);
278+
return <TokenEntry token={t} />;
262279
})}
263-
</ul>
280+
</>
264281
)}
265282
</>
266283
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License-AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { PersonalAccessToken } from "@gitpod/public-api/lib/gitpod/experimental/v1/tokens_pb";
8+
import { ContextMenuEntry } from "../components/ContextMenu";
9+
import { ItemFieldContextMenu } from "../components/ItemsList";
10+
11+
const menuEntries: ContextMenuEntry[] = [
12+
{
13+
title: "Edit",
14+
href: "",
15+
onClick: () => {},
16+
},
17+
{
18+
title: "Regenerate",
19+
href: "",
20+
onClick: () => {},
21+
},
22+
{
23+
title: "Delete",
24+
href: "",
25+
onClick: () => {},
26+
},
27+
];
28+
29+
function TokenEntry(t: { token: PersonalAccessToken }) {
30+
if (!t) {
31+
return <></>;
32+
}
33+
34+
const getDate = () => {
35+
if (!t.token.expirationTime) {
36+
return "";
37+
}
38+
const date = t.token.expirationTime?.toDate();
39+
return date.toDateString();
40+
};
41+
42+
const defaultAllScope = ["function:*", "resource:default"];
43+
44+
const getScopes = () => {
45+
if (!t.token.scopes) {
46+
return "";
47+
}
48+
if (t.token.scopes.every((v) => defaultAllScope.includes(v))) {
49+
return "Access the user's API";
50+
} else {
51+
return "No access";
52+
}
53+
};
54+
55+
return (
56+
<>
57+
<div className="rounded-xl whitespace-nowrap flex space-x-2 py-4 px-4 w-full justify-between hover:bg-gray-100 dark:hover:bg-gray-800 focus:bg-gitpod-kumquat-light group">
58+
<div className="pr-3 self-center w-3/12">
59+
<span>{t.token.name || ""}</span>
60+
</div>
61+
<div className="flex flex-col w-3/12 text-gray-400 font-medium">
62+
<span>{getScopes()}</span>
63+
</div>
64+
<div className="flex flex-col w-3/12 text-gray-400">
65+
<span>{getDate()}</span>
66+
</div>
67+
<div className="flex flex-col w-3/12">
68+
<ItemFieldContextMenu menuEntries={menuEntries} />
69+
</div>
70+
</div>
71+
</>
72+
);
73+
}
74+
75+
export default TokenEntry;

0 commit comments

Comments
 (0)