objective categorical abstract machine language personal data server
65
fork

Configure Feed

Select the types of activity you want to include in your feed.

Styling tweaks

futurGH 21bdcf1a e8abd4ae

+240 -249
+5 -14
frontend/src/components/AccountSidebar.mlx
··· 4 4 5 5 type actor = AccountSwitcher.actor 6 6 7 - type active_page = Account | Permissions 8 - 9 7 let pages = 10 - [ (Account, "Account", "/account") 11 - ; (Permissions, "Permissions", "/account/permissions") ] 8 + [ ("Account", "/account") 9 + ; ("Permissions", "/account/permissions") ] 12 10 13 11 let[@react.component] make ~current_user ~logged_in_users ~active_page () = 14 12 let selected_class = "text-mana-100 font-medium" in 15 13 let unselected_class = "text-mist-100 hover:text-mana-100" in 16 - let permissions_class = 17 - match active_page with 18 - | Account -> 19 - "text-mist-100 hover:text-mana-100" 20 - | Permissions -> 21 - "text-mana-100 font-medium" 22 - in 23 14 <aside className="flex flex-col gap-y-2 min-w-48 max-w-3xs"> 24 15 <AccountSwitcher 25 16 current_user logged_in_users add_account_url="/account/login" 26 17 /> 27 18 <nav className="flex flex-col gap-y-1 mt-2"> 28 19 ( List.map 29 - (fun (key, label, href) -> 20 + (fun (label, href) -> 30 21 let className = 31 - if key = active_page then selected_class else unselected_class 22 + if href = active_page then selected_class else unselected_class 32 23 in 33 - <a href className key=label>(string label)</a> ) 24 + <a href className key=href>(string label)</a> ) 34 25 pages 35 26 |> Array.of_list |> array ) 36 27 </nav>
+3 -3
frontend/src/components/Input.mlx
··· 24 24 placeholder:font-medium focus-visible:outline-none" 25 25 /> 26 26 in 27 - <div> 27 + <div className="text-mist-100 focus-within:text-mana-100"> 28 28 ( match label with 29 29 | Some label -> 30 30 <div 31 31 className=( "flex justify-between text-sm" 32 32 ^ if sr_only then " sr-only" else "" )> 33 - <label htmlFor=id className="text-mist-100 mb-1"> 33 + <label htmlFor=id className="mb-1.5"> 34 34 (string label) 35 35 ( if required && showIndicator then 36 36 <span className="text-phoenix-100">(string req_marker)</span> ··· 45 45 else 46 46 <div 47 47 className=( "flex items-center rounded-lg py-1.5 px-3 outline-1 \ 48 - outline-mana-40 disabled:outline-mana-40/20 \ 48 + outline-mana-40/50 disabled:outline-mana-40/20 \ 49 49 disabled:bg-mana-40/20 focus-within:outline-2 \ 50 50 focus-within:outline-mana-100" ^ className )> 51 51 input
+231 -231
frontend/src/templates/AccountPage.mlx
··· 65 65 let deleteTokenInput, setDeleteTokenInput = useState (fun () -> "") in 66 66 <div className="w-auto h-auto px-4 sm:px-0 flex flex-col md:flex-row gap-12"> 67 67 <AccountSidebar 68 - current_user logged_in_users active_page=AccountSidebar.Account 68 + current_user logged_in_users active_page="/account" 69 69 /> 70 70 <main className="flex-1 w-full max-w-md"> 71 71 <h1 className="text-2xl font-serif text-mana-200 mb-1"> ··· 185 185 () 186 186 in 187 187 <Aria.DialogTrigger defaultOpen=email_change_pending> 188 - <Input 189 - name="email" 190 - type_="email" 191 - label="Email" 192 - placeholder=email 193 - showIndicator=false 194 - disabled=true 195 - trailing=( 196 - <Aria.Pressable> 197 - <button 198 - type_="button" 199 - className="p-1 hover:text-mana-100 cursor-pointer" 200 - ariaLabel="Change email" 201 - onClick=(fun _ -> setEmailModalOpen (fun _ -> true))> 202 - <PencilLineIcon className="w-4 h-4" /> 203 - </button> 204 - </Aria.Pressable> 205 - ) 206 - /> 207 - <Aria.ModalOverlay 208 - className="fixed inset-0 z-50 bg-feather-100/80 \ 209 - flex items-center justify-center" 210 - isDismissable=(not emailPending) 211 - isOpen=emailModalOpen 212 - onOpenChange=(fun o -> setEmailModalOpen (fun _ -> o)) 213 - > 214 - <Aria.Modal 215 - className="bg-feather-100 border border-mist-40 rounded-xl \ 216 - p-6 w-full max-w-sm shadow-xl"> 217 - <Aria.Dialog className="outline-none"> 218 - <Aria.Heading 219 - slot="title" 220 - className="text-lg font-serif text-mana-200 mb-2"> 221 - (string "change email") 222 - </Aria.Heading> 223 - ( if emailPending then 224 - <form 225 - className="flex flex-col gap-y-3" 226 - onSubmit=(fun e -> 227 - Event.Form.preventDefault e ; 228 - submitEmailForm "confirm_email_change" 229 - [|("token", emailTokenInput)|] )> 230 - <p className="text-mist-100"> 231 - (string 232 - ( "Enter the verification code sent to " 233 - ^ Option.value emailPendingAddress 234 - ~default:"your new email" 235 - ^ "." ) ) 236 - </p> 237 - <Input 238 - name="token" 239 - label="Verification code" 240 - placeholder="eml-..." 241 - required=true 242 - showIndicator=false 243 - value=emailTokenInput 244 - onChange=(fun e -> 245 - setEmailTokenInput (fun _ -> 246 - (Event.Form.target e)##value ) ) 247 - /> 248 - ( match emailErrorState with 249 - | Some err -> 250 - <span 251 - className="inline-flex items-center \ 252 - text-phoenix-100 text-sm"> 253 - <CircleAlertIcon className="w-4 h-4 mr-2" /> 254 - (string err) 255 - </span> 256 - | None -> 257 - null ) 258 - <div className="flex flex-row gap-x-3 mt-2"> 259 - <Button 260 - type_="submit" 261 - disabled=emailLoading> 262 - (string (if emailLoading then "verifying..." else "verify")) 263 - </Button> 264 - <Button 265 - kind=`Secondary 266 - type_="button" 267 - disabled=emailLoading 268 - onClick=(fun _ -> 269 - submitEmailForm "cancel_email_change" [||])> 270 - (string "cancel") 271 - </Button> 272 - </div> 273 - </form> 274 - else 275 - <form 276 - className="flex flex-col gap-y-3" 277 - onSubmit=(fun e -> 278 - Event.Form.preventDefault e ; 279 - submitEmailForm "request_email_change" 280 - [|("new_email", newEmailInput)|] )> 281 - <Input 282 - name="new_email" 283 - label="New email address" 284 - type_="email" 285 - required=true 286 - showIndicator=false 287 - value=newEmailInput 288 - onChange=(fun e -> 289 - setNewEmailInput (fun _ -> 290 - (Event.Form.target e)##value ) ) 291 - /> 292 - ( match emailErrorState with 293 - | Some err -> 294 - <span 295 - className="inline-flex items-center \ 296 - text-phoenix-100 text-sm"> 297 - <CircleAlertIcon className="w-4 h-4 mr-2" /> 298 - (string err) 299 - </span> 300 - | None -> 301 - null ) 302 - <div className="flex flex-row gap-x-3 mt-2"> 303 - <Button 304 - type_="submit" 305 - disabled=emailLoading> 306 - (string (if emailLoading then "sending..." else "send code")) 307 - </Button> 308 - <Button kind=`Tertiary 309 - className="text-mist-100 hover:text-mana-100" 310 - onClick=(fun _ -> setEmailModalOpen (fun _ -> false))> 311 - (string "cancel") 312 - </Button> 313 - </div> 314 - </form> ) 315 - </Aria.Dialog> 316 - </Aria.Modal> 317 - </Aria.ModalOverlay> 188 + <Input 189 + name="email" 190 + type_="email" 191 + label="Email" 192 + placeholder=email 193 + showIndicator=false 194 + disabled=true 195 + trailing=( 196 + <Aria.Pressable> 197 + <button 198 + type_="button" 199 + className="p-1 hover:text-mana-100 cursor-pointer" 200 + ariaLabel="Change email" 201 + onClick=(fun _ -> setEmailModalOpen (fun _ -> true))> 202 + <PencilLineIcon className="w-4 h-4" /> 203 + </button> 204 + </Aria.Pressable> 205 + ) 206 + /> 207 + <Aria.ModalOverlay 208 + className="fixed inset-0 z-50 bg-mist-80/80 \ 209 + flex items-center justify-center" 210 + isDismissable=(not emailPending) 211 + isOpen=emailModalOpen 212 + onOpenChange=(fun o -> setEmailModalOpen (fun _ -> o)) 213 + > 214 + <Aria.Modal 215 + className="bg-feather-100 border border-mist-60 rounded-xl \ 216 + px-6 pb-6 pt-5 w-full max-w-sm mx-4 shadow-xl"> 217 + <Aria.Dialog className="outline-none"> 218 + <Aria.Heading 219 + slot="title" 220 + className="text-lg font-serif text-mana-200 mb-2"> 221 + (string "change email") 222 + </Aria.Heading> 223 + ( if emailPending then 224 + <form 225 + className="flex flex-col gap-y-3" 226 + onSubmit=(fun e -> 227 + Event.Form.preventDefault e ; 228 + submitEmailForm "confirm_email_change" 229 + [|("token", emailTokenInput)|] )> 230 + <p className="text-mist-100"> 231 + (string 232 + ( "Enter the verification code sent to " 233 + ^ Option.value emailPendingAddress 234 + ~default:"your new email" 235 + ^ "." ) ) 236 + </p> 237 + <Input 238 + name="token" 239 + label="Verification code" 240 + placeholder="eml-..." 241 + required=true 242 + showIndicator=false 243 + value=emailTokenInput 244 + onChange=(fun e -> 245 + setEmailTokenInput (fun _ -> 246 + (Event.Form.target e)##value ) ) 247 + /> 248 + ( match emailErrorState with 249 + | Some err -> 250 + <span 251 + className="inline-flex items-center \ 252 + text-phoenix-100 text-sm"> 253 + <CircleAlertIcon className="w-4 h-4 mr-2" /> 254 + (string err) 255 + </span> 256 + | None -> 257 + null ) 258 + <div className="flex flex-row gap-x-3 mt-2"> 259 + <Button 260 + type_="submit" 261 + disabled=emailLoading> 262 + (string (if emailLoading then "verifying..." else "verify")) 263 + </Button> 264 + <Button 265 + kind=`Secondary 266 + type_="button" 267 + disabled=emailLoading 268 + onClick=(fun _ -> 269 + submitEmailForm "cancel_email_change" [||])> 270 + (string "cancel") 271 + </Button> 272 + </div> 273 + </form> 274 + else 275 + <form 276 + className="flex flex-col gap-y-3" 277 + onSubmit=(fun e -> 278 + Event.Form.preventDefault e ; 279 + submitEmailForm "request_email_change" 280 + [|("new_email", newEmailInput)|] )> 281 + <Input 282 + name="new_email" 283 + label="New email address" 284 + type_="email" 285 + required=true 286 + showIndicator=false 287 + value=newEmailInput 288 + onChange=(fun e -> 289 + setNewEmailInput (fun _ -> 290 + (Event.Form.target e)##value ) ) 291 + /> 292 + ( match emailErrorState with 293 + | Some err -> 294 + <span 295 + className="inline-flex items-center \ 296 + text-phoenix-100 text-sm"> 297 + <CircleAlertIcon className="w-4 h-4 mr-2" /> 298 + (string err) 299 + </span> 300 + | None -> 301 + null ) 302 + <div className="flex flex-row gap-x-3 mt-2"> 303 + <Button 304 + type_="submit" 305 + disabled=emailLoading> 306 + (string (if emailLoading then "sending..." else "send code")) 307 + </Button> 308 + <Button kind=`Tertiary 309 + className="text-mist-100 hover:text-mana-100" 310 + onClick=(fun _ -> setEmailModalOpen (fun _ -> false))> 311 + (string "cancel") 312 + </Button> 313 + </div> 314 + </form> ) 315 + </Aria.Dialog> 316 + </Aria.Modal> 317 + </Aria.ModalOverlay> 318 318 </Aria.DialogTrigger> )] 319 319 </ClientOnly> 320 320 <Input ··· 327 327 name="password" 328 328 type_="password" 329 329 label="Password" 330 - placeholder="********" 330 + placeholder="⸱⸱⸱⸱⸱⸱⸱⸱" 331 331 autoComplete="current-password" 332 332 showIndicator=false 333 333 /> ··· 361 361 <h2 className="text-xl font-serif text-mana-200 mb-1"> 362 362 (string "download repository") 363 363 </h2> 364 - <p className="text-mist-100 mb-3"> 364 + <p className="text-mist-100 mb-4"> 365 365 (string 366 366 "Export your data to back up or transfer to another PDS." ) 367 367 </p> ··· 377 377 <h2 className="text-xl font-serif text-mana-200 mb-1"> 378 378 (string "danger zone") 379 379 </h2> 380 - <p className="text-mist-100 mb-1.5"> 380 + <p className="text-mist-100 mb-1"> 381 381 (string 382 382 "Deactivating your account will temporarily render your \ 383 383 data inaccessible until you reactivate it." ) 384 384 </p> 385 - <p className="text-mist-100 mb-3"> 385 + <p className="text-mist-100 mb-4"> 386 386 (string 387 387 "Deleting your account will permanently remove all your \ 388 388 data." ) ··· 453 453 () 454 454 in 455 455 <Aria.DialogTrigger defaultOpen=delete_pending> 456 - <Aria.Pressable> 457 - <Button kind=`Danger className="flex-1" onClick=(fun _ -> setDeleteModalOpen (fun _ -> true))> 458 - (string "delete account") 459 - </Button> 460 - </Aria.Pressable> 461 - <Aria.ModalOverlay 462 - className="fixed inset-0 z-50 bg-feather-100/80 \ 463 - flex items-center justify-center" 464 - isDismissable=(not deletePendingState) 465 - isOpen=deleteModalOpen onOpenChange=(fun o -> setDeleteModalOpen (fun _ -> o))> 466 - <Aria.Modal 467 - className="bg-feather-100 border border-mist-40 rounded-xl \ 468 - p-6 w-full max-w-sm shadow-xl"> 469 - <Aria.Dialog className="outline-none"> 470 - <Aria.Heading 471 - slot="title" 472 - className="text-lg font-serif text-mana-200 mb-2"> 473 - (string "delete account") 474 - </Aria.Heading> 475 - ( if deletePendingState then 476 - <form 477 - className="flex flex-col gap-y-3" 478 - onSubmit=(fun e -> 479 - Event.Form.preventDefault e ; 480 - submitDeleteForm "confirm_delete" 481 - [|("token", deleteTokenInput)|] )> 482 - <p className="text-mist-100 text-sm"> 483 - (string 484 - "Enter the confirmation code sent to your email." ) 485 - </p> 486 - <Input 487 - name="token" 488 - label="Confirmation code" 489 - placeholder="del-..." 490 - required=true 491 - showIndicator=false 492 - value=deleteTokenInput 493 - onChange=(fun e -> 494 - setDeleteTokenInput (fun _ -> 495 - (Event.Form.target e)##value ) ) 496 - /> 497 - ( match deleteErrorState with 498 - | Some err -> 499 - <span 500 - className="inline-flex items-center \ 501 - text-phoenix-100 text-sm"> 502 - <CircleAlertIcon className="w-4 h-4 mr-2" /> 503 - (string err) 504 - </span> 505 - | None -> 506 - null ) 507 - <div className="flex flex-row gap-x-3 mt-2"> 508 - <Button 509 - kind=`Danger 510 - type_="submit" 511 - disabled=deleteLoading> 512 - (string (if deleteLoading then "deleting..." else "confirm")) 513 - </Button> 514 - <Button 515 - kind=`Secondary 516 - type_="button" 517 - disabled=deleteLoading 518 - onClick=(fun _ -> 519 - submitDeleteForm "cancel_delete" [||])> 520 - (string "cancel") 521 - </Button> 522 - </div> 523 - </form> 524 - else 525 - <form 526 - className="flex flex-col gap-y-3" 527 - onSubmit=(fun e -> 528 - Event.Form.preventDefault e ; 529 - submitDeleteForm "request_delete" [||] )> 530 - <p className="text-mist-100"> 531 - (string 532 - "This action is irreversible. A confirmation \ 533 - code will be sent to your email." ) 534 - </p> 535 - <div className="flex flex-row gap-x-3 mt-2"> 536 - <Button 537 - kind=`Danger 538 - type_="submit" 539 - disabled=deleteLoading> 540 - (string (if deleteLoading then "sending..." else "send code")) 541 - </Button> 542 - <Button kind=`Tertiary 543 - onClick=(fun _ -> setDeleteModalOpen (fun _ -> false)) 544 - className="text-mist-100 hover:text-mana-100"> 545 - (string "cancel") 546 - </Button> 547 - </div> 548 - </form> ) 549 - </Aria.Dialog> 550 - </Aria.Modal> 551 - </Aria.ModalOverlay> 456 + <Aria.Pressable> 457 + <Button kind=`Danger className="flex-1" onClick=(fun _ -> setDeleteModalOpen (fun _ -> true))> 458 + (string "delete account") 459 + </Button> 460 + </Aria.Pressable> 461 + <Aria.ModalOverlay 462 + className="fixed inset-0 z-50 bg-mist-80/80 \ 463 + flex items-center justify-center" 464 + isDismissable=(not deletePendingState) 465 + isOpen=deleteModalOpen onOpenChange=(fun o -> setDeleteModalOpen (fun _ -> o))> 466 + <Aria.Modal 467 + className="bg-feather-100 border border-mist-60 rounded-xl \ 468 + px-6 pb-6 pt-5 w-full max-w-sm mx-4 shadow-xl"> 469 + <Aria.Dialog className="outline-none"> 470 + <Aria.Heading 471 + slot="title" 472 + className="text-lg font-serif text-mana-200 mb-2"> 473 + (string "delete account") 474 + </Aria.Heading> 475 + ( if deletePendingState then 476 + <form 477 + className="flex flex-col gap-y-3" 478 + onSubmit=(fun e -> 479 + Event.Form.preventDefault e ; 480 + submitDeleteForm "confirm_delete" 481 + [|("token", deleteTokenInput)|] )> 482 + <p className="text-mist-100 text-sm"> 483 + (string 484 + "Enter the confirmation code sent to your email." ) 485 + </p> 486 + <Input 487 + name="token" 488 + label="Confirmation code" 489 + placeholder="del-..." 490 + required=true 491 + showIndicator=false 492 + value=deleteTokenInput 493 + onChange=(fun e -> 494 + setDeleteTokenInput (fun _ -> 495 + (Event.Form.target e)##value ) ) 496 + /> 497 + ( match deleteErrorState with 498 + | Some err -> 499 + <span 500 + className="inline-flex items-center \ 501 + text-phoenix-100 text-sm"> 502 + <CircleAlertIcon className="w-4 h-4 mr-2" /> 503 + (string err) 504 + </span> 505 + | None -> 506 + null ) 507 + <div className="flex flex-row gap-x-3 mt-2"> 508 + <Button 509 + kind=`Danger 510 + type_="submit" 511 + disabled=deleteLoading> 512 + (string (if deleteLoading then "deleting..." else "confirm")) 513 + </Button> 514 + <Button 515 + kind=`Secondary 516 + type_="button" 517 + disabled=deleteLoading 518 + onClick=(fun _ -> 519 + submitDeleteForm "cancel_delete" [||])> 520 + (string "cancel") 521 + </Button> 522 + </div> 523 + </form> 524 + else 525 + <form 526 + className="flex flex-col gap-y-3" 527 + onSubmit=(fun e -> 528 + Event.Form.preventDefault e ; 529 + submitDeleteForm "request_delete" [||] )> 530 + <p className="text-mist-100"> 531 + (string 532 + "This action is irreversible. A confirmation \ 533 + code will be sent to your email." ) 534 + </p> 535 + <div className="flex flex-row gap-x-3 mt-2"> 536 + <Button 537 + kind=`Danger 538 + type_="submit" 539 + disabled=deleteLoading> 540 + (string (if deleteLoading then "sending..." else "send code")) 541 + </Button> 542 + <Button kind=`Tertiary 543 + onClick=(fun _ -> setDeleteModalOpen (fun _ -> false)) 544 + className="text-mist-100 hover:text-mana-100"> 545 + (string "cancel") 546 + </Button> 547 + </div> 548 + </form> ) 549 + </Aria.Dialog> 550 + </Aria.Modal> 551 + </Aria.ModalOverlay> 552 552 </Aria.DialogTrigger> )] 553 553 </ClientOnly> 554 554 </div>
+1 -1
frontend/src/templates/AccountPermissionsPage.mlx
··· 76 76 props ) () = 77 77 <div className="w-auto h-auto px-4 sm:px-0 flex flex-col md:flex-row gap-12"> 78 78 <AccountSidebar 79 - current_user logged_in_users active_page=AccountSidebar.Permissions 79 + current_user logged_in_users active_page="/account/permissions" 80 80 /> 81 81 <main className="flex-1 w-full max-w-md"> 82 82 <section>