atmosphere explorer
0
fork

Configure Feed

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

confirmation dialog during record creation

Juliet 1a617e01 f3ae3fda

+119 -48
+90
src/components/create/confirm-submit.tsx
··· 1 + import { createSignal, Show } from "solid-js"; 2 + import { Button } from "../button.jsx"; 3 + 4 + export const ConfirmSubmit = (props: { 5 + isCreate: boolean; 6 + onConfirm: (validate: boolean | undefined, recreate: boolean) => void; 7 + onClose: () => void; 8 + }) => { 9 + const [validate, setValidate] = createSignal<boolean | undefined>(undefined); 10 + const [recreate, setRecreate] = createSignal(false); 11 + 12 + const getValidateLabel = () => { 13 + return ( 14 + validate() === true ? "True" 15 + : validate() === false ? "False" 16 + : "Unset" 17 + ); 18 + }; 19 + 20 + const cycleValidate = () => { 21 + setValidate( 22 + validate() === undefined ? true 23 + : validate() === true ? false 24 + : undefined, 25 + ); 26 + }; 27 + 28 + return ( 29 + <div class="dark:bg-dark-300 dark:shadow-dark-700 absolute top-70 left-[50%] w-[24rem] -translate-x-1/2 rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 p-4 shadow-md transition-opacity duration-200 dark:border-neutral-700 starting:opacity-0"> 30 + <h2 class="mb-3 font-semibold">{props.isCreate ? "Create" : "Edit"} record</h2> 31 + <div class="flex flex-col gap-3 text-sm"> 32 + <div class="flex flex-col gap-1.5"> 33 + <div class="flex items-center gap-2"> 34 + <button 35 + type="button" 36 + class="dark:bg-dark-100 flex items-center gap-1.5 rounded-lg border-[0.5px] border-neutral-300 bg-white px-2 py-1 text-xs hover:bg-neutral-100 dark:border-neutral-600 dark:hover:bg-neutral-700" 37 + onClick={cycleValidate} 38 + > 39 + <span 40 + classList={{ 41 + iconify: true, 42 + "lucide--circle-check text-green-500 dark:text-green-400": validate() === true, 43 + "lucide--circle-x text-red-500 dark:text-red-400": validate() === false, 44 + "lucide--circle text-neutral-500 dark:text-neutral-400": validate() === undefined, 45 + }} 46 + ></span> 47 + <span>Validate: {getValidateLabel()}</span> 48 + </button> 49 + </div> 50 + <p class="text-xs text-neutral-600 dark:text-neutral-400"> 51 + Set to 'false' to skip lexicon schema validation by the PDS, 'true' to require it, or 52 + leave unset to validate only for known lexicons. 53 + </p> 54 + </div> 55 + <Show when={!props.isCreate}> 56 + <div class="flex flex-col gap-1.5"> 57 + <div class="flex items-center gap-2"> 58 + <button 59 + type="button" 60 + class="dark:bg-dark-100 flex items-center gap-1.5 rounded-lg border-[0.5px] border-neutral-300 bg-white px-2 py-1 text-xs hover:bg-neutral-100 dark:border-neutral-600 dark:hover:bg-neutral-700" 61 + onClick={() => setRecreate(!recreate())} 62 + > 63 + <span 64 + classList={{ 65 + iconify: true, 66 + "lucide--circle-check text-green-500 dark:text-green-400": recreate(), 67 + "lucide--circle text-neutral-500 dark:text-neutral-400": !recreate(), 68 + }} 69 + ></span> 70 + <span>Recreate</span> 71 + </button> 72 + </div> 73 + <p class="text-xs text-neutral-600 dark:text-neutral-400"> 74 + Delete the existing record and create a new one with the same record key. 75 + </p> 76 + </div> 77 + </Show> 78 + <div class="mt-1 flex justify-between gap-2"> 79 + <Button onClick={props.onClose}>Cancel</Button> 80 + <Button 81 + onClick={() => props.onConfirm(validate(), recreate())} 82 + class="dark:shadow-dark-700 rounded-lg bg-blue-500 px-2 py-1.5 text-xs text-white shadow-xs select-none hover:bg-blue-600 active:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-500 dark:active:bg-blue-400" 83 + > 84 + {props.isCreate ? "Create" : "Edit"} 85 + </Button> 86 + </div> 87 + </div> 88 + </div> 89 + ); 90 + };
+29 -48
src/components/create/index.tsx
··· 20 20 import { addNotification, removeNotification } from "../notification.jsx"; 21 21 import { TextInput } from "../text-input.jsx"; 22 22 import Tooltip from "../tooltip.jsx"; 23 + import { ConfirmSubmit } from "./confirm-submit"; 23 24 import { FileUpload } from "./file-upload"; 24 25 import { HandleInput } from "./handle-input"; 25 26 import { MenuItem } from "./menu-item"; ··· 37 38 const [openUpload, setOpenUpload] = createSignal(false); 38 39 const [openInsertMenu, setOpenInsertMenu] = createSignal(false); 39 40 const [openHandleDialog, setOpenHandleDialog] = createSignal(false); 40 - const [validate, setValidate] = createSignal<boolean | undefined>(undefined); 41 + const [openConfirmDialog, setOpenConfirmDialog] = createSignal(false); 41 42 const [isMaximized, setIsMaximized] = createSignal(false); 42 43 const [isMinimized, setIsMinimized] = createSignal(false); 43 44 const [collectionError, setCollectionError] = createSignal(""); ··· 96 97 }; 97 98 }; 98 99 99 - const getValidateIcon = () => { 100 - return ( 101 - validate() === true ? "lucide--circle-check" 102 - : validate() === false ? "lucide--circle-x" 103 - : "lucide--circle" 104 - ); 105 - }; 106 - 107 - const getValidateLabel = () => { 108 - return ( 109 - validate() === true ? "True" 110 - : validate() === false ? "False" 111 - : "Unset" 112 - ); 113 - }; 114 - 115 100 createEffect(() => { 116 101 if (openDialog()) { 117 - setValidate(undefined); 118 102 setCollectionError(""); 119 103 setRkeyError(""); 120 104 } 121 105 }); 122 106 123 - const createRecord = async (formData: FormData) => { 107 + const createRecord = async (validate: boolean | undefined) => { 108 + const formData = new FormData(formRef); 124 109 const repo = formData.get("repo")?.toString(); 125 110 if (!repo) return; 126 111 const rpc = new Client({ handler: new OAuthUserAgent(await getSession(repo as Did)) }); ··· 139 124 collection: collection ? collection.toString() : record.$type, 140 125 rkey: rkey?.toString().length ? rkey?.toString() : undefined, 141 126 record: record, 142 - validate: validate(), 127 + validate: validate, 143 128 }, 144 129 }); 145 130 if (!res.ok) { 146 131 setNotice(`${res.data.error}: ${res.data.message}`); 147 132 return; 148 133 } 134 + setOpenConfirmDialog(false); 149 135 setOpenDialog(false); 150 136 const id = addNotification({ 151 137 message: "Record created", ··· 155 141 navigate(`/${res.data.uri}`); 156 142 }; 157 143 158 - const editRecord = async (recreate?: boolean) => { 144 + const editRecord = async (validate: boolean | undefined, recreate: boolean) => { 159 145 const record = editorInstance.view.state.doc.toString(); 160 146 if (!record) return; 161 147 const rpc = new Client({ handler: agent()! }); ··· 165 151 const res = await rpc.post("com.atproto.repo.applyWrites", { 166 152 input: { 167 153 repo: agent()!.sub, 168 - validate: validate(), 154 + validate: validate, 169 155 writes: [ 170 156 { 171 157 collection: params.collection as `${string}.${string}.${string}`, ··· 189 175 const res = await rpc.post("com.atproto.repo.applyWrites", { 190 176 input: { 191 177 repo: agent()!.sub, 192 - validate: validate(), 178 + validate: validate, 193 179 writes: [ 194 180 { 195 181 collection: params.collection as `${string}.${string}.${string}`, ··· 205 191 return; 206 192 } 207 193 } 194 + setOpenConfirmDialog(false); 208 195 setOpenDialog(false); 209 196 const id = addNotification({ 210 197 message: "Record edited", ··· 418 405 > 419 406 <HandleInput onClose={() => setOpenHandleDialog(false)} /> 420 407 </Modal> 408 + <Modal 409 + open={openConfirmDialog()} 410 + onClose={() => setOpenConfirmDialog(false)} 411 + closeOnClick={false} 412 + > 413 + <ConfirmSubmit 414 + isCreate={props.create} 415 + onConfirm={(validate, recreate) => { 416 + if (props.create) { 417 + createRecord(validate); 418 + } else { 419 + editRecord(validate, recreate); 420 + } 421 + }} 422 + onClose={() => setOpenConfirmDialog(false)} 423 + /> 424 + </Modal> 421 425 <div class="flex items-center justify-end gap-2"> 422 - <button 423 - type="button" 424 - class="flex items-center gap-1 rounded-sm p-1.5 text-xs hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600" 425 - onClick={() => 426 - setValidate( 427 - validate() === true ? false 428 - : validate() === false ? undefined 429 - : true, 430 - ) 431 - } 432 - > 433 - <Tooltip text={getValidateLabel()}> 434 - <span class={`iconify ${getValidateIcon()}`}></span> 435 - </Tooltip> 436 - <span>Validate</span> 437 - </button> 438 - <Show when={!props.create && hasUserScope("create") && hasUserScope("delete")}> 439 - <Button onClick={() => editRecord(true)}>Recreate</Button> 440 - </Show> 441 - <Button 442 - onClick={() => 443 - props.create ? createRecord(new FormData(formRef)) : editRecord() 444 - } 445 - > 446 - {props.create ? "Create" : "Edit"} 426 + <Button onClick={() => setOpenConfirmDialog(true)}> 427 + {props.create ? "Create..." : "Edit..."} 447 428 </Button> 448 429 </div> 449 430 </div>