refactor: path selector design
This commit is contained in:
parent
7f9c020127
commit
a6a28f7352
4 changed files with 12 additions and 28 deletions
|
|
@ -8,12 +8,7 @@ type Props = {
|
|||
label?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* A reusable path selector component that shows the selected path
|
||||
* with a "Change" button, and expands to a DirectoryBrowser when clicked.
|
||||
* Matches the pattern used in the volume creation form.
|
||||
*/
|
||||
export const PathSelector = ({ value, onChange, label = "Selected path:" }: Props) => {
|
||||
export const PathSelector = ({ value, onChange }: Props) => {
|
||||
const [showBrowser, setShowBrowser] = useState(false);
|
||||
|
||||
if (showBrowser) {
|
||||
|
|
@ -26,25 +21,18 @@ export const PathSelector = ({ value, onChange, label = "Selected path:" }: Prop
|
|||
}}
|
||||
selectedPath={value}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setShowBrowser(false)}
|
||||
>
|
||||
<Button type="button" variant="ghost" size="sm" onClick={() => setShowBrowser(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
console.log("Rendering PathSelector with value:", value);
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex-1 border rounded-md p-3 bg-muted/50">
|
||||
<div className="text-xs font-medium text-muted-foreground mb-1">{label}</div>
|
||||
<div className="text-sm font-mono break-all">{value}</div>
|
||||
</div>
|
||||
<Button type="button" variant="outline" size="sm" onClick={() => setShowBrowser(true)}>
|
||||
<div className="flex-1 text-sm font-mono bg-muted px-3 py-2 rounded-md border">{value}</div>
|
||||
<Button type="button" variant="outline" onClick={() => setShowBrowser(true)} size="sm">
|
||||
Change
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -142,7 +142,6 @@ export const SnapshotFileBrowser = (props: Props) => {
|
|||
path: { name: repositoryName },
|
||||
body: {
|
||||
snapshotId: snapshot.short_id,
|
||||
target: targetPath || undefined,
|
||||
include: includePaths,
|
||||
delete: deleteExtraFiles,
|
||||
excludeXattr: excludeXattrArray && excludeXattrArray.length > 0 ? excludeXattrArray : undefined,
|
||||
|
|
@ -282,11 +281,7 @@ export const SnapshotFileBrowser = (props: Props) => {
|
|||
</div>
|
||||
{restoreLocation === "custom" && (
|
||||
<div className="space-y-2">
|
||||
<Input
|
||||
placeholder="/path/to/restore"
|
||||
value={customTargetPath}
|
||||
onChange={(e) => setCustomTargetPath(e.target.value)}
|
||||
/>
|
||||
<PathSelector value={customTargetPath || "/"} onChange={setCustomTargetPath} />
|
||||
<p className="text-xs text-muted-foreground">Files will be restored directly to this path</p>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export const RestoreSnapshotDialog = ({ name, snapshotId }: Props) => {
|
|||
path: { name },
|
||||
body: {
|
||||
snapshotId,
|
||||
target: values.target || undefined,
|
||||
targetPath: values.targetPath || undefined,
|
||||
include: include && include.length > 0 ? include : undefined,
|
||||
exclude: exclude && exclude.length > 0 ? exclude : undefined,
|
||||
excludeXattr: excludeXattr && excludeXattr.length > 0 ? excludeXattr : undefined,
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@ import {
|
|||
} from "~/client/components/ui/form";
|
||||
import { Input } from "~/client/components/ui/input";
|
||||
import { Button } from "~/client/components/ui/button";
|
||||
import { PathSelector } from "~/client/components/path-selector";
|
||||
|
||||
const restoreSnapshotFormSchema = type({
|
||||
path: "string?",
|
||||
target: "string?",
|
||||
targetPath: "string?",
|
||||
include: "string?",
|
||||
exclude: "string?",
|
||||
excludeXattr: "string?",
|
||||
|
|
@ -38,7 +39,7 @@ export const RestoreSnapshotForm = ({ formId, onSubmit, className }: Props) => {
|
|||
resolver: arktypeResolver(restoreSnapshotFormSchema),
|
||||
defaultValues: {
|
||||
path: "",
|
||||
target: "",
|
||||
targetPath: "",
|
||||
include: "",
|
||||
exclude: "",
|
||||
excludeXattr: "",
|
||||
|
|
@ -72,12 +73,12 @@ export const RestoreSnapshotForm = ({ formId, onSubmit, className }: Props) => {
|
|||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="target"
|
||||
name="targetPath"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Target Directory (Optional)</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="/" {...field} />
|
||||
<PathSelector {...field} value={field.value ?? "/"} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Restore to a custom location instead of the original path (defaults to /)
|
||||
|
|
|
|||
Loading…
Reference in a new issue