-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCredentialsPanel.tsx
More file actions
152 lines (145 loc) · 5.42 KB
/
Copy pathCredentialsPanel.tsx
File metadata and controls
152 lines (145 loc) · 5.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import { type FormEvent, useState } from "react";
import { reportRegistry } from "../domain/reportRegistry";
import type { InstanceType, ReportId, SessionCredentials } from "../domain/types";
interface CredentialsPanelProps {
selectedReportId: ReportId;
credentials: SessionCredentials | null;
onSave: (credentials: SessionCredentials) => void;
}
interface CredentialsDraft {
instanceType: InstanceType;
baseUrl: string;
apiKey: string;
accessToken: string;
pat: string;
}
const credentialLabels: Record<string, string> = {
"api-key": "API key",
"access-token": "Access token",
pat: "Personal access token",
"community-access": "Community access",
"enterprise-admin": "Enterprise admin access",
};
export function CredentialsPanel({ selectedReportId, credentials, onSave }: CredentialsPanelProps) {
const report = reportRegistry.find((candidate) => candidate.id === selectedReportId)!;
const [draft, setDraft] = useState<CredentialsDraft>({
instanceType: credentials?.instanceType ?? "basic-business",
baseUrl: credentials?.baseUrl ?? "",
apiKey: credentials?.apiKey ?? "",
accessToken: credentials?.accessToken ?? "",
pat: credentials?.pat ?? "",
});
const [saved, setSaved] = useState(false);
function updateDraft<Field extends keyof CredentialsDraft>(
field: Field,
value: CredentialsDraft[Field],
) {
setSaved(false);
setDraft((current) => ({ ...current, [field]: value }));
}
function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
onSave({
instanceType: draft.instanceType,
baseUrl: draft.baseUrl.trim(),
apiKey: draft.apiKey.trim() || undefined,
accessToken: draft.accessToken.trim() || undefined,
pat: draft.pat.trim() || undefined,
});
setSaved(true);
}
return (
<section className="workspace-panel" aria-labelledby="credentials-heading">
<div className="workspace-header">
<div>
<p className="workspace-kicker">Browser session</p>
<h2 className="workspace-heading" id="credentials-heading">
Session Credentials
</h2>
</div>
</div>
<p className="workspace-copy credential-session-copy">
Credentials are kept in memory for this browser session only.
</p>
<div className="credential-notes" role="note">
<p className="scope-label">Scope notes for selected report</p>
<h3 className="fs-body2 mb8">{report.title} credential notes</h3>
<ul className="m0">
<li>Basic/Business: provide your team URL and either an access token or PAT.</li>
<li>
Enterprise: provide your site URL
{report.credentialRequirements.includes("api-key") ? ", API key," : ""} and access
token.
</li>
<li>
Required scope notes:{" "}
{report.credentialRequirements
.map((requirement) => credentialLabels[requirement] ?? requirement)
.join(", ")}
.
</li>
<li>Credential acquisition guidance placeholder: add internal steps here.</li>
</ul>
</div>
<form className="credentials-form" onSubmit={handleSubmit}>
<label className="d-block">
<span className="d-block fs-caption tt-uppercase fc-light mb4">Instance type</span>
<select
className="s-select"
value={draft.instanceType}
onChange={(event) =>
updateDraft("instanceType", event.currentTarget.value as InstanceType)
}
>
<option value="basic-business">Basic / Business</option>
<option value="enterprise">Enterprise</option>
</select>
</label>
<label className="d-block">
<span className="d-block fs-caption tt-uppercase fc-light mb4">Instance URL</span>
<input
className="s-input"
value={draft.baseUrl}
onChange={(event) => updateDraft("baseUrl", event.currentTarget.value)}
placeholder="https://stackoverflowteams.com/c/team-name"
required
/>
</label>
<label className="d-block">
<span className="d-block fs-caption tt-uppercase fc-light mb4">API key</span>
<input
className="s-input"
value={draft.apiKey}
onChange={(event) => updateDraft("apiKey", event.currentTarget.value)}
/>
</label>
<label className="d-block">
<span className="d-block fs-caption tt-uppercase fc-light mb4">Access token</span>
<input
className="s-input"
type="password"
value={draft.accessToken}
onChange={(event) => updateDraft("accessToken", event.currentTarget.value)}
/>
</label>
<label className="d-block">
<span className="d-block fs-caption tt-uppercase fc-light mb4">Personal access token</span>
<input
className="s-input"
type="password"
value={draft.pat}
onChange={(event) => updateDraft("pat", event.currentTarget.value)}
/>
</label>
<button className="s-btn s-btn__primary" type="submit">
Save session credentials
</button>
</form>
{saved && (
<div className="s-notice s-notice__success mt16" role="status">
Credentials saved for this browser session.
</div>
)}
</section>
);
}