Skip to content

Commit 59ebbd3

Browse files
authored
Change Frontend Version Info (#3527)
* Change Frontend Version Info * Fix * Update ScriptItem.tsx
1 parent e6208a4 commit 59ebbd3

File tree

1 file changed

+165
-50
lines changed

1 file changed

+165
-50
lines changed

frontend/src/app/scripts/_components/ScriptItem.tsx

Lines changed: 165 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,29 @@
1-
21
import { Separator } from "@/components/ui/separator";
3-
import { extractDate } from "@/lib/time";
4-
import { Script, AppVersion } from "@/lib/types";
52
import { fetchVersions } from "@/lib/data";
3+
import { extractDate } from "@/lib/time";
4+
import { AppVersion, Script } from "@/lib/types";
65

76
import { X } from "lucide-react";
87
import Image from "next/image";
98

9+
import { basePath } from "@/config/siteConfig";
10+
import { useEffect, useState } from "react";
1011
import { getDisplayValueFromType } from "./ScriptInfoBlocks";
1112
import Alerts from "./ScriptItems/Alerts";
1213
import Buttons from "./ScriptItems/Buttons";
1314
import DefaultPassword from "./ScriptItems/DefaultPassword";
14-
import DefaultSettings from "./ScriptItems/DefaultSettings";
1515
import Description from "./ScriptItems/Description";
1616
import InstallCommand from "./ScriptItems/InstallCommand";
1717
import InterFaces from "./ScriptItems/InterFaces";
1818
import Tooltips from "./ScriptItems/Tooltips";
19-
import { basePath } from "@/config/siteConfig";
20-
import { useEffect, useState } from "react";
2119

22-
23-
function ScriptItem({
24-
item,
25-
setSelectedScript,
26-
}: {
27-
item: Script;
28-
setSelectedScript: (script: string | null) => void;
29-
}) {
20+
function ScriptItem({ item, setSelectedScript }: { item: Script; setSelectedScript: (script: string | null) => void }) {
3021
const closeScript = () => {
3122
window.history.pushState({}, document.title, window.location.pathname);
3223
setSelectedScript(null);
3324
};
3425
const [versions, setVersions] = useState<AppVersion[]>([]);
3526

36-
3727
useEffect(() => {
3828
fetchVersions()
3929
.then((fetchedVersions) => {
@@ -68,10 +58,7 @@ function ScriptItem({
6858
className="h-32 w-32 rounded-lg bg-accent/60 object-contain p-3 shadow-md"
6959
src={item.logo || `/${basePath}/logo.png`}
7060
width={400}
71-
onError={(e) =>
72-
((e.currentTarget as HTMLImageElement).src =
73-
`/${basePath}/logo.png`)
74-
}
61+
onError={(e) => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
7562
height={400}
7663
alt={item.name}
7764
unoptimized
@@ -89,35 +76,165 @@ function ScriptItem({
8976
Default OS: {os} {version}
9077
</p>
9178
</div>
92-
<div className="flex gap-5">
93-
<DefaultSettings item={item} />
94-
</div>
95-
<div>{versions.length === 0 ? (<p>Loading versions...</p>) :
96-
(<>
97-
<p className="text-l text-foreground">Version:</p>
98-
<p className="text-l text-muted-foreground">{versions.find((v) =>
99-
v.name === item.slug.replace(/[^a-z0-9]/g, '') ||
100-
v.name.includes(item.slug.replace(/[^a-z0-9]/g, '')) ||
101-
v.name.replace(/[^a-z0-9]/g, '') === item.slug.replace(/[^a-z0-9]/g, '')
102-
103-
)?.version || "No Version information found"
104-
}</p>
105-
<p className="text-l text-foreground">Latest Version changes(Pulled from newreleases.io):</p>
106-
<p className="text-l text-muted-foreground">
107-
{(() => {
108-
const matchedVersion = versions.find((v) =>
109-
v.name === item.slug.replace(/[^a-z0-9]/g, '') ||
110-
v.name.includes(item.slug.replace(/[^a-z0-9]/g, '')) ||
111-
v.name.replace(/[^a-z0-9]/g, '') === item.slug.replace(/[^a-z0-9]/g, '')
112-
);
113-
return matchedVersion?.date ?
114-
extractDate(matchedVersion.date as unknown as string) :
115-
"No date information found"
116-
})()}
117-
</p>
118-
</>)
119-
}
79+
<div className="flex min-w-[600px] flex-wrap gap-6 text-sm text-muted-foreground">
80+
{(() => {
81+
const getDisplayValueFromRAM = (ram: number) =>
82+
ram >= 1024 ? `${Math.floor(ram / 1024)}GB` : `${ram}MB`;
83+
84+
const IconText = ({ icon, label }: { icon: React.ReactNode; label: string }) => (
85+
<span className="flex items-center gap-1">
86+
{icon}
87+
{label}
88+
</span>
89+
);
90+
91+
const CPUIcon = (
92+
<svg
93+
xmlns="http://www.w3.org/2000/svg"
94+
className="w-4 h-4"
95+
fill="none"
96+
viewBox="0 0 24 24"
97+
stroke="currentColor"
98+
strokeWidth={2}
99+
>
100+
<rect x="9" y="9" width="6" height="6" />
101+
<path d="M3 9h2m14 0h2M3 15h2m14 0h2M9 3v2m6-2v2M9 19v2m6-2v2" />
102+
</svg>
103+
);
104+
105+
const RAMIcon = (
106+
<svg
107+
xmlns="http://www.w3.org/2000/svg"
108+
className="w-4 h-4"
109+
fill="none"
110+
viewBox="0 0 24 24"
111+
stroke="currentColor"
112+
strokeWidth={2}
113+
>
114+
<rect x="4" y="6" width="16" height="12" rx="2" ry="2" />
115+
<path d="M8 6v12M16 6v12" />
116+
</svg>
117+
);
118+
119+
const HDDIcon = (
120+
<svg
121+
xmlns="http://www.w3.org/2000/svg"
122+
className="w-4 h-4"
123+
fill="none"
124+
viewBox="0 0 24 24"
125+
stroke="currentColor"
126+
strokeWidth={2}
127+
>
128+
<path d="M4 4h16v16H4z" />
129+
<circle cx="8" cy="16" r="1" />
130+
<circle cx="16" cy="16" r="1" />
131+
</svg>
132+
);
133+
134+
const ResourceDisplay = ({
135+
title,
136+
cpu,
137+
ram,
138+
hdd,
139+
}: {
140+
title: string;
141+
cpu: number | null;
142+
ram: number | null;
143+
hdd: number | null;
144+
}) => {
145+
const getDisplayValueFromRAM = (ram: number) =>
146+
ram >= 1024 ? `${Math.floor(ram / 1024)}GB` : `${ram}MB`;
147+
148+
const IconText = ({ icon, label }: { icon: React.ReactNode; label: string }) => (
149+
<span className="flex items-center gap-1 whitespace-nowrap">
150+
{icon}
151+
{label}
152+
</span>
153+
);
154+
155+
const hasCPU = typeof cpu === "number" && cpu > 0;
156+
const hasRAM = typeof ram === "number" && ram > 0;
157+
const hasHDD = typeof hdd === "number" && hdd > 0;
158+
159+
if (!hasCPU && !hasRAM && !hasHDD) return null;
160+
161+
return (
162+
<div className="flex flex-wrap items-center gap-1">
163+
<span className="font-semibold text-foreground">{title}:</span>
164+
{hasCPU && (
165+
<>
166+
<IconText icon={CPUIcon} label={`CPU: ${cpu} vCPU`} />
167+
<span>|</span>
168+
</>
169+
)}
170+
{hasRAM && (
171+
<>
172+
<IconText icon={RAMIcon} label={`RAM: ${getDisplayValueFromRAM(ram!)}`} />
173+
<span>|</span>
174+
</>
175+
)}
176+
{hasHDD && <IconText icon={HDDIcon} label={`HDD: ${hdd} GB`} />}
177+
</div>
178+
);
179+
};
180+
181+
const defaultSettings = item.install_methods.find((method) => method.type === "default");
182+
const alpineSettings = item.install_methods.find((method) => method.type === "alpine");
183+
return (
184+
<>
185+
{defaultSettings?.resources && (
186+
<ResourceDisplay
187+
title="Default"
188+
cpu={defaultSettings.resources.cpu}
189+
ram={defaultSettings.resources.ram}
190+
hdd={defaultSettings.resources.hdd}
191+
/>
192+
)}
193+
194+
{alpineSettings?.resources && (
195+
<ResourceDisplay
196+
title="Alpine"
197+
cpu={alpineSettings.resources.cpu}
198+
ram={alpineSettings.resources.ram}
199+
hdd={alpineSettings.resources.hdd}
200+
/>
201+
)}
202+
</>
203+
);
204+
})()}
120205
</div>
206+
207+
{(() => {
208+
if (versions.length === 0) {
209+
return <p>Loading versions...</p>;
210+
}
211+
212+
const cleanSlug = item.slug.replace(/[^a-z0-9]/gi, "").toLowerCase();
213+
214+
const matched = versions.find((v) => {
215+
const cleanName = v.name.replace(/[^a-z0-9]/gi, "").toLowerCase();
216+
return cleanName === cleanSlug || cleanName.includes(cleanSlug);
217+
});
218+
219+
if (!matched) return null;
220+
221+
return (
222+
<div className="flex items-center gap-2 text-sm text-muted-foreground mt-2">
223+
<span className="text-foreground">
224+
Version: {matched.version} (
225+
{extractDate(
226+
matched.date instanceof Date ? matched.date.toISOString() : matched.date || "",
227+
)}
228+
</span>
229+
<span
230+
title="Crawled version from newreleases.io"
231+
className="cursor-help rounded-full border border-green-500 px-2 py-0.5 text-xs font-semibold text-green-500"
232+
>
233+
Info
234+
</span>
235+
</div>
236+
);
237+
})()}
121238
</div>
122239
</div>
123240
</div>
@@ -134,9 +251,7 @@ function ScriptItem({
134251
</div>
135252
<div className="mt-4 rounded-lg border bg-accent/50">
136253
<div className="flex gap-3 px-4 py-2">
137-
<h2 className="text-lg font-semibold">
138-
How to {item.type == "misc" ? "use" : "install"}
139-
</h2>
254+
<h2 className="text-lg font-semibold">How to {item.type == "misc" ? "use" : "install"}</h2>
140255
<Tooltips item={item} />
141256
</div>
142257
<Separator className="w-full"></Separator>

0 commit comments

Comments
 (0)