mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2025-09-13 07:10:51 +02:00
Optimize website json-editor page and components (#265)
* Update mariadb.json * Update vaultwarden.json * Update vaultwarden.json * Update keycloak.json * Update json/keycloak.json Co-authored-by: Håvard Gjøby Thom <34199185+havardthom@users.noreply.github.com> * Update mariadb.json Co-authored-by: Håvard Gjøby Thom <34199185+havardthom@users.noreply.github.com> * Add canonical link to layout for improved SEO and page indexing * Fix image source fallback for script logos to use a consistent relative path * Fix image source for script logos across components to consistently use the "/ProxmoxVE/logo.png" path * Update image source for script logos to use basePath for consistent paths across all components * Fix image source for script logos to ensure leading slash is consistent for all components' paths * Add JSON generator component with validation and UI elements for managing scripts, categories, and installation methods * Add calendar and label components; enhance JSON generator with date selection and script path updates for installation methods * Enhance Alerts component with dynamic colored notes using AlertColors from config for better visibility and consistency * Remove MultiSelect component * Update JSON generator: streamline install methods, enhance note type selection, and refine button behavior for better UX * Refactor AlertColors: unify warning and danger styles for consistency and improved visual hierarchy in alerts * Enhance JSONGenerator: improve SelectItem layout with color indicators for better visual representation of alert types * Refactor JSON schema definitions in JSONGenerator: separate InstallMethod and Note schemas for better structure and readability * Fix JSONGenerator: streamline SelectItem markup and enhance JSON display layout for improved readability and user experience * Refactor JSON schema handling: move schema definitions to separate file * Enhance error handling in JSONGenerator: display Zod validation errors on user input for better feedback and debugging * Export InstallMethodSchema and integrate into JSONGenerator for better validation of install method data input * Add Categories and Note components to JSONGenerator for better organization and modularity in the JSON editing interface * Remove unused imports * Add JSON Editor route to sitemap for improved SEO and navigation * Refactor JSON Editor components to improve performance with memoization and streamline state updates with useCallback --------- Co-authored-by: CanbiZ <47820557+MickLesk@users.noreply.github.com> Co-authored-by: Håvard Gjøby Thom <34199185+havardthom@users.noreply.github.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import { PlusCircle, Trash2 } from "lucide-react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { z } from "zod";
|
||||
import { InstallMethodSchema, ScriptSchema } from "../_schemas/schemas";
|
||||
import { memo, useCallback } from "react";
|
||||
|
||||
type Script = z.infer<typeof ScriptSchema>;
|
||||
|
||||
@@ -20,13 +21,13 @@ type InstallMethodProps = {
|
||||
setZodErrors: (zodErrors: z.ZodError | null) => void;
|
||||
};
|
||||
|
||||
export default function InstallMethod({
|
||||
function InstallMethod({
|
||||
script,
|
||||
setScript,
|
||||
setIsValid,
|
||||
setZodErrors,
|
||||
}: InstallMethodProps) {
|
||||
const addInstallMethod = () => {
|
||||
const addInstallMethod = useCallback(() => {
|
||||
setScript((prev) => {
|
||||
const method = InstallMethodSchema.parse({
|
||||
type: "default",
|
||||
@@ -44,9 +45,9 @@ export default function InstallMethod({
|
||||
install_methods: [...prev.install_methods, method],
|
||||
};
|
||||
});
|
||||
};
|
||||
}, [setScript]);
|
||||
|
||||
const updateInstallMethod = (
|
||||
const updateInstallMethod = useCallback((
|
||||
index: number,
|
||||
key: keyof Script["install_methods"][number],
|
||||
value: Script["install_methods"][number][keyof Script["install_methods"][number]],
|
||||
@@ -82,14 +83,35 @@ export default function InstallMethod({
|
||||
}
|
||||
return updated;
|
||||
});
|
||||
};
|
||||
}, [setScript, setIsValid, setZodErrors]);
|
||||
|
||||
const removeInstallMethod = (index: number) => {
|
||||
const removeInstallMethod = useCallback((index: number) => {
|
||||
setScript((prev) => ({
|
||||
...prev,
|
||||
install_methods: prev.install_methods.filter((_, i) => i !== index),
|
||||
}));
|
||||
};
|
||||
}, [setScript]);
|
||||
|
||||
const ResourceInput = memo(({
|
||||
placeholder,
|
||||
value,
|
||||
onChange,
|
||||
type = "text"
|
||||
}: {
|
||||
placeholder: string;
|
||||
value: string | number | null;
|
||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
type?: string;
|
||||
}) => (
|
||||
<Input
|
||||
placeholder={placeholder}
|
||||
type={type}
|
||||
value={value || ""}
|
||||
onChange={onChange}
|
||||
/>
|
||||
));
|
||||
|
||||
ResourceInput.displayName = 'ResourceInput';
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -109,33 +131,33 @@ export default function InstallMethod({
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
<ResourceInput
|
||||
placeholder="CPU in Cores"
|
||||
type="number"
|
||||
value={method.resources.cpu || ""}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
value={method.resources.cpu}
|
||||
onChange={(e) =>
|
||||
updateInstallMethod(index, "resources", {
|
||||
...method.resources,
|
||||
cpu: e.target.value ? Number(e.target.value) : null,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
<ResourceInput
|
||||
placeholder="RAM in MB"
|
||||
type="number"
|
||||
value={method.resources.ram || ""}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
value={method.resources.ram}
|
||||
onChange={(e) =>
|
||||
updateInstallMethod(index, "resources", {
|
||||
...method.resources,
|
||||
ram: e.target.value ? Number(e.target.value) : null,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
placeholder="HDD in GB"
|
||||
<ResourceInput
|
||||
placeholder="HDD in GB"
|
||||
type="number"
|
||||
value={method.resources.hdd || ""}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
value={method.resources.hdd}
|
||||
onChange={(e) =>
|
||||
updateInstallMethod(index, "resources", {
|
||||
...method.resources,
|
||||
hdd: e.target.value ? Number(e.target.value) : null,
|
||||
@@ -144,21 +166,21 @@ export default function InstallMethod({
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
<ResourceInput
|
||||
placeholder="OS"
|
||||
value={method.resources.os || ""}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
value={method.resources.os}
|
||||
onChange={(e) =>
|
||||
updateInstallMethod(index, "resources", {
|
||||
...method.resources,
|
||||
os: e.target.value || null,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
<ResourceInput
|
||||
placeholder="Version"
|
||||
type="number"
|
||||
value={method.resources.version || ""}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
value={method.resources.version}
|
||||
onChange={(e) =>
|
||||
updateInstallMethod(index, "resources", {
|
||||
...method.resources,
|
||||
version: e.target.value ? Number(e.target.value) : null,
|
||||
@@ -168,7 +190,7 @@ export default function InstallMethod({
|
||||
</div>
|
||||
<Button
|
||||
variant="destructive"
|
||||
size={"sm"}
|
||||
size="sm"
|
||||
type="button"
|
||||
onClick={() => removeInstallMethod(index)}
|
||||
>
|
||||
@@ -178,7 +200,7 @@ export default function InstallMethod({
|
||||
))}
|
||||
<Button
|
||||
type="button"
|
||||
size={"sm"}
|
||||
size="sm"
|
||||
disabled={script.install_methods.length >= 2}
|
||||
onClick={addInstallMethod}
|
||||
>
|
||||
@@ -187,3 +209,5 @@ export default function InstallMethod({
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(InstallMethod);
|
||||
|
||||
Reference in New Issue
Block a user