History

Add `delete` option for project actions (#223)

Adds a delete button to the action edit dialog with a confirmation alert. Fixes pingdotgg/t3code#208.

Mubin Ansari committed 8 months ago

Commit 1c43bad1 parent 18b65902 files · +79 −1Browse files

Showing the changes to apps/web/src/components/ProjectScriptsControl.tsx (1 of 2 files). Show all

Unified · Split

apps/web/src/components/ProjectScriptsControl.tsx+45−1
@@ -14,7 +14,7 @@ import { · 13 unmodified lines
14 SettingsIcon,14 SettingsIcon,
15 WrenchIcon,15 WrenchIcon,
16} from "lucide-react";16} from "lucide-react";
17import React, { type FormEvent, type KeyboardEvent, useMemo, useState } from "react";17import React, { type FormEvent, type KeyboardEvent, useCallback, useMemo, useState } from "react";
18 18
19import {19import {
20 keybindingValueForCommand,20 keybindingValueForCommand,
@@ -27,6 +27,15 @@ import { · 6 unmodified lines
27} from "~/projectScripts";27} from "~/projectScripts";
28import { shortcutLabelForCommand } from "~/keybindings";28import { shortcutLabelForCommand } from "~/keybindings";
29import { isMacPlatform } from "~/lib/utils";29import { isMacPlatform } from "~/lib/utils";
30import {
31 AlertDialog,
32 AlertDialogClose,
33 AlertDialogDescription,
34 AlertDialogFooter,
35 AlertDialogHeader,
36 AlertDialogPopup,
37 AlertDialogTitle,
38} from "./ui/alert-dialog";
30import { Button } from "./ui/button";39import { Button } from "./ui/button";
31import {40import {
32 Dialog,41 Dialog,
@@ -84,6 +93,7 @@ interface ProjectScriptsControlProps { · 51 unmodified lines
84 onRunScript: (script: ProjectScript) => void;93 onRunScript: (script: ProjectScript) => void;
85 onAddScript: (input: NewProjectScriptInput) => Promise<void> | void;94 onAddScript: (input: NewProjectScriptInput) => Promise<void> | void;
86 onUpdateScript: (scriptId: string, input: NewProjectScriptInput) => Promise<void> | void;95 onUpdateScript: (scriptId: string, input: NewProjectScriptInput) => Promise<void> | void;
96 onDeleteScript: (scriptId: string) => Promise<void> | void;
87}97}
88 98
89function normalizeShortcutKeyToken(key: string): string | null {99function normalizeShortcutKeyToken(key: string): string | null {
@@ -144,6 +154,7 @@ export default function ProjectScriptsControl({ · 54 unmodified lines
144 onRunScript,154 onRunScript,
145 onAddScript,155 onAddScript,
146 onUpdateScript,156 onUpdateScript,
157 onDeleteScript,
147}: ProjectScriptsControlProps) {158}: ProjectScriptsControlProps) {
148 const addScriptFormId = React.useId();159 const addScriptFormId = React.useId();
149 const [editingScriptId, setEditingScriptId] = useState<string | null>(null);160 const [editingScriptId, setEditingScriptId] = useState<string | null>(null);
@@ -155,6 +166,7 @@ export default function ProjectScriptsControl({ · 5 unmodified lines
155 const [runOnWorktreeCreate, setRunOnWorktreeCreate] = useState(false);166 const [runOnWorktreeCreate, setRunOnWorktreeCreate] = useState(false);
156 const [keybinding, setKeybinding] = useState("");167 const [keybinding, setKeybinding] = useState("");
157 const [validationError, setValidationError] = useState<string | null>(null);168 const [validationError, setValidationError] = useState<string | null>(null);
169 const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
158 170
159 const primaryScript = useMemo(() => {171 const primaryScript = useMemo(() => {
160 if (preferredScriptId) {172 if (preferredScriptId) {
@@ -247,6 +259,13 @@ export default function ProjectScriptsControl({ · 86 unmodified lines
247 setDialogOpen(true);259 setDialogOpen(true);
248 };260 };
249 261
262 const confirmDeleteScript = useCallback(() => {
263 if (!editingScriptId) return;
264 setDeleteConfirmOpen(false);
265 setDialogOpen(false);
266 void onDeleteScript(editingScriptId);
267 }, [editingScriptId, onDeleteScript]);
268
250 return (269 return (
251 <>270 <>
252 {primaryScript ? (271 {primaryScript ? (
@@ -440,6 +459,16 @@ export default function ProjectScriptsControl({ · 187 unmodified lines
440 </form>459 </form>
441 </DialogPanel>460 </DialogPanel>
442 <DialogFooter>461 <DialogFooter>
462 {isEditing && (
463 <Button
464 type="button"
465 variant="destructive-outline"
466 className="mr-auto"
467 onClick={() => setDeleteConfirmOpen(true)}
468 >
469 Delete
470 </Button>
471 )}
443 <Button472 <Button
444 type="button"473 type="button"
445 variant="outline"474 variant="outline"
@@ -455,6 +484,21 @@ export default function ProjectScriptsControl({ · 9 unmodified lines
455 </DialogFooter>484 </DialogFooter>
456 </DialogPopup>485 </DialogPopup>
457 </Dialog>486 </Dialog>
487
488 <AlertDialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}>
489 <AlertDialogPopup>
490 <AlertDialogHeader>
491 <AlertDialogTitle>Delete action "{name}"?</AlertDialogTitle>
492 <AlertDialogDescription>This action cannot be undone.</AlertDialogDescription>
493 </AlertDialogHeader>
494 <AlertDialogFooter>
495 <AlertDialogClose render={<Button variant="outline" />}>Cancel</AlertDialogClose>
496 <Button variant="destructive" onClick={confirmDeleteScript}>
497 Delete action
498 </Button>
499 </AlertDialogFooter>
500 </AlertDialogPopup>
501 </AlertDialog>
458 </>502 </>
459 );503 );
460}504}