tangled
alpha
login
or
join now
futur.blue
/
pegasus
57
fork
atom
objective categorical abstract machine language personal data server
57
fork
atom
overview
issues
2
pulls
pipelines
Fix account switcher, admin pages sizing
futur.blue
2 months ago
f0e70709
51cda44f
verified
This commit was signed with the committer's
known signature
.
futur.blue
SSH Key Fingerprint:
SHA256:QHGqHWNpqYyw9bt8KmPuJIyeZX9SZewBZ0PR1COtKQ0=
+40
-32
4 changed files
expand all
collapse all
unified
split
frontend
src
components
AccountSwitcher.mlx
Sidebar.mlx
templates
AdminInvitesPage.mlx
AdminUsersPage.mlx
+8
-4
frontend/src/components/AccountSwitcher.mlx
···
10
active:bg-mist-20/40"
11
12
let button_class_default =
13
-
"group min-w-48 flex flex-row items-center gap-x-1 px-2 py-1.5 -mx-2 \
14
rounded-lg focus-visible:outline-none hover:bg-mist-20/40 \
15
active:bg-mist-20/40"
16
···
44
[%browser_only
45
fun newDid ->
46
if newDid <> current_user.did then
47
-
let formData = Fetch.FormData.make () in
48
-
Fetch.FormData.set "did" newDid formData ;
0
0
0
49
let _ =
50
Fetch.fetchWithInit "/account/switch"
51
(Fetch.RequestInit.make ~method_:Fetch.Post
52
-
~body:(Fetch.BodyInit.makeWithFormData formData)
0
53
() )
54
|> Js.Promise.then_ (fun response ->
55
if Fetch.Response.ok response then (
···
10
active:bg-mist-20/40"
11
12
let button_class_default =
13
+
"group w-64 flex flex-row items-center gap-x-1 px-2 py-1.5 -mx-2 \
14
rounded-lg focus-visible:outline-none hover:bg-mist-20/40 \
15
active:bg-mist-20/40"
16
···
44
[%browser_only
45
fun newDid ->
46
if newDid <> current_user.did then
47
+
let body =
48
+
Fetch.BodyInit.make
49
+
(Webapi.Url.URLSearchParams.makeWithArray [|("did", newDid)|]
50
+
|> Webapi.Url.URLSearchParams.toString )
51
+
in
52
let _ =
53
Fetch.fetchWithInit "/account/switch"
54
(Fetch.RequestInit.make ~method_:Fetch.Post
55
+
~headers:(Fetch.HeadersInit.makeWithArray [|("Content-Type", "application/x-www-form-urlencoded")|])
56
+
~body
57
() )
58
|> Js.Promise.then_ (fun response ->
59
if Fetch.Response.ok response then (
+1
-1
frontend/src/components/Sidebar.mlx
···
5
let[@react.component] make ~pages ~active_page ?header () =
6
let selected_class = "text-mana-100 font-medium" in
7
let unselected_class = "text-mist-100 hover:text-mana-100" in
8
-
<aside className="flex flex-col gap-y-2 min-w-24 max-w-3xs">
9
(match header with Some h -> h | None -> null)
10
<nav className="flex flex-col gap-y-1 mt-2">
11
( List.map
···
5
let[@react.component] make ~pages ~active_page ?header () =
6
let selected_class = "text-mana-100 font-medium" in
7
let unselected_class = "text-mist-100 hover:text-mana-100" in
8
+
<aside className="flex flex-col gap-y-2 w-auto min-w-32">
9
(match header with Some h -> h | None -> null)
10
<nav className="flex flex-col gap-y-1 mt-2">
11
( List.map
+12
-10
frontend/src/templates/AdminInvitesPage.mlx
···
38
let editRemaining, setEditRemaining = useState (fun () -> "") in
39
(* delete confirmation state *)
40
let deleteConfirmFor, setDeleteConfirmFor = useState (fun () -> (None : invite option)) in
41
-
<div className="w-full max-w-3xl h-full px-4 sm:px-0 pt-16 mx-auto flex flex-col md:flex-row gap-12">
42
<Sidebar pages=admin_pages active_page="/admin/invites" />
43
<main className="flex-1 w-full max-w-2xl">
44
<h1 className="text-2xl font-serif text-mana-200 mb-1">
···
138
</div>
139
| None -> null )
140
<div className="overflow-x-auto">
141
-
<table className="w-full min-w-xl text-sm">
142
-
<thead>
143
-
<tr className="text-left text-mist-80">
144
-
<th className="pb-2 font-normal">(string "Code")</th>
145
-
<th className="pb-2 font-normal">(string "For")</th>
146
-
<th className="pb-2 font-normal">(string "Remaining")</th>
147
-
<th className="pb-2 font-normal w-20"></th>
0
0
148
</tr>
149
</thead>
150
-
<tbody>
151
( List.map
152
(fun (invite : invite) ->
153
-
<tr key=invite.code className="border-t border-mist-60/50">
154
<td className="py-3 pr-4">
155
<span className="font-mono text-mana-100">
156
(string invite.code)
···
38
let editRemaining, setEditRemaining = useState (fun () -> "") in
39
(* delete confirmation state *)
40
let deleteConfirmFor, setDeleteConfirmFor = useState (fun () -> (None : invite option)) in
41
+
<div className="w-auto h-full max-w-full px-4 pt-16 mx-auto flex flex-1 flex-col md:flex-row justify-center gap-12">
42
<Sidebar pages=admin_pages active_page="/admin/invites" />
43
<main className="flex-1 w-full max-w-2xl">
44
<h1 className="text-2xl font-serif text-mana-200 mb-1">
···
138
</div>
139
| None -> null )
140
<div className="overflow-x-auto">
141
+
<table
142
+
className="w-full grid border-collapse text-sm"
143
+
style=(ReactDOM.Style.make ~gridTemplateColumns:"minmax(6rem, 1fr) 1fr minmax(2rem, 1fr) 4rem" ())>
144
+
<thead className="contents">
145
+
<tr className="contents text-left text-mist-80">
146
+
<th className="border-b border-mist-60/50 pb-2 font-normal">(string "Code")</th>
147
+
<th className="border-b border-mist-60/50 pb-2 font-normal">(string "For")</th>
148
+
<th className="border-b border-mist-60/50 pb-2 font-normal">(string "Remaining")</th>
149
+
<th className="border-b border-mist-60/50 pb-2 font-normal w-20"></th>
150
</tr>
151
</thead>
152
+
<tbody className="contents">
153
( List.map
154
(fun (invite : invite) ->
155
+
<tr key=invite.code className="contents">
156
<td className="py-3 pr-4">
157
<span className="font-mono text-mana-100">
158
(string invite.code)
+19
-17
frontend/src/templates/AdminUsersPage.mlx
···
62
let editValue, setEditValue = useState (fun () -> "") in
63
(* delete confirmation state *)
64
let deleteConfirmFor, setDeleteConfirmFor = useState (fun () -> (None : actor option)) in
65
-
<div className="w-full max-w-3xl h-full px-4 sm:px-0 pt-16 mx-auto flex flex-col md:flex-row gap-12">
66
<Sidebar pages=admin_pages active_page="/admin/users" />
67
<main className="flex-1 w-full max-w-2xl">
68
<h1 className="text-2xl font-serif text-mana-200 mb-1">
···
169
</div>
170
| None -> null )
171
<div className="overflow-x-auto">
172
-
<table className="w-full min-w-xl text-sm">
173
-
<thead>
174
-
<tr className="text-left text-mist-80">
175
-
<th className="pb-2 font-normal">(string "Handle")</th>
176
-
<th className="pb-2 font-normal">(string "Email")</th>
177
-
<th className="pb-2 font-normal">(string "Created at")</th>
178
-
<th className="pb-2 font-normal w-8"></th>
0
0
179
</tr>
180
</thead>
181
-
<tbody>
182
( List.map
183
(fun (actor : actor) ->
184
if filter <> ""
···
187
&& not (contains_str actor.email filter) then null else
188
let handleClasses = "font-medium truncate " ^
189
(if actor.deactivated then "text-phoenix-100" else "text-mana-100") in
190
-
<tr key=actor.did className="border-t border-mist-60/50">
191
<td className="py-3 pr-4">
192
<div className="flex items-center gap-3">
193
-
<div className="max-w-54">
194
<p className=handleClasses ?title=(if actor.deactivated then Some "Deactivated" else None)>
195
(string actor.handle)
196
</p>
···
202
</td>
203
<td className="py-3 pr-4">
204
<div className="flex items-center gap-1">
205
-
<span className="text-mist-100">(string actor.email)</span>
206
( if actor.email_confirmed then
207
-
<CheckmarkIcon className="w-4 h-4 text-mana-100" />
208
else
209
-
<XIcon className="w-4 h-4 text-phoenix-100" /> )
210
</div>
211
</td>
212
-
<td className="py-3 pr-4 text-mist-100">
213
(string actor.created_at)
214
</td>
215
<td className="py-3">
216
<ClientOnly fallback=(
217
-
<button className="p-1 text-mist-80 hover:text-mana-100">
218
<EllipsisIcon className="w-5 h-5" />
219
</button>
220
)>
···
228
setMenuOpenFor (fun _ -> if o then Some actor.did else None))>
229
<Aria.Pressable>
230
<button
231
-
className="p-1 text-mist-80 hover:text-mana-100 cursor-pointer"
232
onClick=(fun _ -> setMenuOpenFor (fun _ -> Some actor.did))>
233
<EllipsisIcon className="w-5 h-5" />
234
</button>
···
62
let editValue, setEditValue = useState (fun () -> "") in
63
(* delete confirmation state *)
64
let deleteConfirmFor, setDeleteConfirmFor = useState (fun () -> (None : actor option)) in
65
+
<div className="w-auto h-full max-w-full px-4 pt-16 mx-auto flex flex-col md:flex-row gap-12">
66
<Sidebar pages=admin_pages active_page="/admin/users" />
67
<main className="flex-1 w-full max-w-2xl">
68
<h1 className="text-2xl font-serif text-mana-200 mb-1">
···
169
</div>
170
| None -> null )
171
<div className="overflow-x-auto">
172
+
<table
173
+
className="w-full min-w-xl grid border-collapse text-sm"
174
+
style=(ReactDOM.Style.make ~gridTemplateColumns:"minmax(200px, 2fr) minmax(160px, 2fr) minmax(160px, 1.5fr) 1.25rem" ())>
175
+
<thead className="contents">
176
+
<tr className="contents text-left text-mist-80">
177
+
<th className="border-b border-mist-60/50 pb-2 font-normal">(string "Handle")</th>
178
+
<th className="border-b border-mist-60/50 pb-2 font-normal">(string "Email")</th>
179
+
<th className="border-b border-mist-60/50 pb-2 font-normal">(string "Created at")</th>
180
+
<th className="border-b border-mist-60/50 pb-2 font-normal w-8"></th>
181
</tr>
182
</thead>
183
+
<tbody className="contents">
184
( List.map
185
(fun (actor : actor) ->
186
if filter <> ""
···
189
&& not (contains_str actor.email filter) then null else
190
let handleClasses = "font-medium truncate " ^
191
(if actor.deactivated then "text-phoenix-100" else "text-mana-100") in
192
+
<tr key=actor.did className="contents">
193
<td className="py-3 pr-4">
194
<div className="flex items-center gap-3">
195
+
<div className="max-w-54 truncate">
196
<p className=handleClasses ?title=(if actor.deactivated then Some "Deactivated" else None)>
197
(string actor.handle)
198
</p>
···
204
</td>
205
<td className="py-3 pr-4">
206
<div className="flex items-center gap-1">
207
+
<span className="text-mist-100 truncate">(string actor.email)</span>
208
( if actor.email_confirmed then
209
+
<CheckmarkIcon className="flex-shrink-0 w-4 h-4 text-mana-100" />
210
else
211
+
<XIcon className="flex-shrink-0 w-4 h-4 text-phoenix-100" /> )
212
</div>
213
</td>
214
+
<td className="py-3 pr-4 text-mist-100 truncate">
215
(string actor.created_at)
216
</td>
217
<td className="py-3">
218
<ClientOnly fallback=(
219
+
<button className="text-mist-80 hover:text-mana-100">
220
<EllipsisIcon className="w-5 h-5" />
221
</button>
222
)>
···
230
setMenuOpenFor (fun _ -> if o then Some actor.did else None))>
231
<Aria.Pressable>
232
<button
233
+
className="text-mist-80 hover:text-mana-100 cursor-pointer"
234
onClick=(fun _ -> setMenuOpenFor (fun _ -> Some actor.did))>
235
<EllipsisIcon className="w-5 h-5" />
236
</button>