Skip to content

Commit 026a911

Browse files
move resource niceid update to general page
1 parent 3047cf3 commit 026a911

File tree

3 files changed

+41
-154
lines changed

3 files changed

+41
-154
lines changed

src/app/[orgId]/settings/resources/[niceId]/general/page.tsx

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ export default function GeneralForm() {
6868
const router = useRouter();
6969
const t = useTranslations();
7070
const [editDomainOpen, setEditDomainOpen] = useState(false);
71-
const {licenseStatus } = useLicenseStatusContext();
71+
const { licenseStatus } = useLicenseStatusContext();
7272
const subscriptionStatus = useSubscriptionStatusContext();
73-
const {user} = useUserContext();
73+
const { user } = useUserContext();
7474

7575
const { env } = useEnvContext();
7676

@@ -102,6 +102,7 @@ export default function GeneralForm() {
102102
enabled: z.boolean(),
103103
subdomain: z.string().optional(),
104104
name: z.string().min(1).max(255),
105+
niceId: z.string().min(1).max(255).optional(),
105106
domainId: z.string().optional(),
106107
proxyPort: z.number().int().min(1).max(65535).optional(),
107108
// enableProxy: z.boolean().optional()
@@ -130,6 +131,7 @@ export default function GeneralForm() {
130131
defaultValues: {
131132
enabled: resource.enabled,
132133
name: resource.name,
134+
niceId: resource.niceId,
133135
subdomain: resource.subdomain ? resource.subdomain : undefined,
134136
domainId: resource.domainId || undefined,
135137
proxyPort: resource.proxyPort || undefined,
@@ -192,6 +194,7 @@ export default function GeneralForm() {
192194
{
193195
enabled: data.enabled,
194196
name: data.name,
197+
niceId: data.niceId,
195198
subdomain: data.subdomain ? toASCII(data.subdomain) : undefined,
196199
domainId: data.domainId,
197200
proxyPort: data.proxyPort,
@@ -212,16 +215,12 @@ export default function GeneralForm() {
212215
});
213216

214217
if (res && res.status === 200) {
215-
toast({
216-
title: t("resourceUpdated"),
217-
description: t("resourceUpdatedDescription")
218-
});
219-
220-
const resource = res.data.data;
218+
const updated = res.data.data;
221219

222220
updateResource({
223221
enabled: data.enabled,
224222
name: data.name,
223+
niceId: data.niceId,
225224
subdomain: data.subdomain,
226225
fullDomain: resource.fullDomain,
227226
proxyPort: data.proxyPort,
@@ -230,8 +229,20 @@ export default function GeneralForm() {
230229
// })
231230
});
232231

233-
router.refresh();
232+
toast({
233+
title: t("resourceUpdated"),
234+
description: t("resourceUpdatedDescription")
235+
});
236+
237+
if (data.niceId && data.niceId !== resource?.niceId) {
238+
router.replace(`/${updated.orgId}/settings/resources/${data.niceId}/general`);
239+
} else {
240+
router.refresh();
241+
}
242+
243+
setSaveLoading(false);
234244
}
245+
235246
setSaveLoading(false);
236247
}
237248

@@ -304,6 +315,24 @@ export default function GeneralForm() {
304315
)}
305316
/>
306317

318+
<FormField
319+
control={form.control}
320+
name="niceId"
321+
render={({ field }) => (
322+
<FormItem>
323+
<FormLabel>{t("niceId") || "Nice ID"}</FormLabel>
324+
<FormControl>
325+
<Input
326+
{...field}
327+
placeholder="Enter Nice ID"
328+
className="flex-1"
329+
/>
330+
</FormControl>
331+
<FormMessage />
332+
</FormItem>
333+
)}
334+
/>
335+
307336
{!resource.http && (
308337
<>
309338
<FormField

src/app/[orgId]/settings/sites/[niceId]/general/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import { Tag, TagInput } from "@app/components/tags/tag-input";
3737

3838
const GeneralFormSchema = z.object({
3939
name: z.string().nonempty("Name is required"),
40-
niceId: z.string().optional(),
40+
niceId: z.string().min(1).max(255).optional(),
4141
dockerSocketEnabled: z.boolean().optional(),
4242
remoteSubnets: z
4343
.array(

src/components/ResourceInfoBox.tsx

Lines changed: 2 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

33
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
4-
import { Check, InfoIcon, Pencil, ShieldCheck, ShieldOff, X } from "lucide-react";
4+
import { ShieldCheck, ShieldOff } from "lucide-react";
55
import { useResourceContext } from "@app/hooks/useResourceContext";
66
import CopyToClipboard from "@app/components/CopyToClipboard";
77
import {
@@ -14,167 +14,25 @@ import { useTranslations } from "next-intl";
1414
import CertificateStatus from "@app/components/private/CertificateStatus";
1515
import { toUnicode } from "punycode";
1616
import { useEnvContext } from "@app/hooks/useEnvContext";
17-
import { Button } from "./ui/button";
18-
import { Input } from "./ui/input";
19-
import { createApiClient, formatAxiosError } from "@app/lib/api";
20-
import { useState } from "react";
21-
import { useToast } from "@app/hooks/useToast";
22-
import { UpdateResourceResponse } from "@server/routers/resource";
23-
import { AxiosResponse } from "axios";
24-
import { useRouter, usePathname } from "next/navigation";
2517

2618
type ResourceInfoBoxType = {};
2719

2820
export default function ResourceInfoBox({ }: ResourceInfoBoxType) {
2921
const { resource, authInfo, updateResource } = useResourceContext();
3022
const { env } = useEnvContext();
31-
const api = createApiClient(useEnvContext());
32-
const router = useRouter();
33-
const pathname = usePathname();
34-
35-
const [isEditing, setIsEditing] = useState(false);
36-
const [niceId, setNiceId] = useState(resource.niceId);
37-
const [tempNiceId, setTempNiceId] = useState(resource.niceId);
38-
const [isLoading, setIsLoading] = useState(false);
39-
const { toast } = useToast();
4023

4124
const t = useTranslations();
4225

4326
const fullUrl = `${resource.ssl ? "https" : "http"}://${toUnicode(resource.fullDomain || "")}`;
4427

4528

46-
const handleEdit = () => {
47-
setTempNiceId(niceId);
48-
setIsEditing(true);
49-
};
50-
51-
const handleCancel = () => {
52-
setTempNiceId(niceId);
53-
setIsEditing(false);
54-
};
55-
56-
const handleSave = async () => {
57-
if (tempNiceId.trim() === "") {
58-
toast({
59-
variant: "destructive",
60-
title: t("error"),
61-
description: t("niceIdCannotBeEmpty")
62-
});
63-
return;
64-
}
65-
66-
if (tempNiceId === niceId) {
67-
setIsEditing(false);
68-
return;
69-
}
70-
71-
setIsLoading(true);
72-
73-
try {
74-
const res = await api
75-
.post<AxiosResponse<UpdateResourceResponse>>(
76-
`resource/${resource?.resourceId}`,
77-
{
78-
niceId: tempNiceId.trim()
79-
}
80-
);
81-
82-
setNiceId(tempNiceId.trim());
83-
setIsEditing(false);
84-
85-
updateResource({
86-
niceId: tempNiceId.trim()
87-
});
88-
89-
// update the URL to reflect the new niceId
90-
const newPath = pathname.replace(`/resources/${niceId}`, `/resources/${tempNiceId.trim()}`);
91-
router.replace(newPath);
92-
93-
toast({
94-
title: t("niceIdUpdated"),
95-
description: t("niceIdUpdatedSuccessfully")
96-
});
97-
} catch (e: any) {
98-
toast({
99-
variant: "destructive",
100-
title: t("niceIdUpdateError"),
101-
description: formatAxiosError(
102-
e,
103-
t("niceIdUpdateErrorDescription")
104-
)
105-
});
106-
} finally {
107-
setIsLoading(false);
108-
}
109-
};
110-
111-
112-
const handleKeyDown = (e: React.KeyboardEvent) => {
113-
if (e.key === "Enter") {
114-
handleSave();
115-
} else if (e.key === "Escape") {
116-
handleCancel();
117-
}
118-
};
119-
12029
return (
12130
<Alert>
12231
<AlertDescription>
12332
{/* 4 cols because of the certs */}
12433
<InfoSections
125-
cols={resource.http && env.flags.usePangolinDns ? 5 : 4}
34+
cols={resource.http && env.flags.usePangolinDns ? 4 : 3}
12635
>
127-
<InfoSection>
128-
<InfoSectionTitle>
129-
{t("niceId")}
130-
</InfoSectionTitle>
131-
<InfoSectionContent>
132-
<div className="flex items-center gap-2">
133-
{isEditing ? (
134-
<>
135-
<Input
136-
value={tempNiceId}
137-
onChange={(e) => setTempNiceId(e.target.value)}
138-
onKeyDown={handleKeyDown}
139-
disabled={isLoading}
140-
className="flex-1"
141-
autoFocus
142-
/>
143-
<Button
144-
size="icon"
145-
variant="ghost"
146-
onClick={handleSave}
147-
disabled={isLoading}
148-
className="h-8 w-8"
149-
>
150-
<Check className="h-4 w-4" />
151-
</Button>
152-
<Button
153-
size="icon"
154-
variant="ghost"
155-
onClick={handleCancel}
156-
disabled={isLoading}
157-
className="h-8 w-8"
158-
>
159-
<X className="h-4 w-4" />
160-
</Button>
161-
</>
162-
) : (
163-
<>
164-
<span>{niceId}</span>
165-
<Button
166-
size="icon"
167-
variant="ghost"
168-
onClick={handleEdit}
169-
className="h-8 w-8"
170-
>
171-
<Pencil className="h-4 w-4" />
172-
</Button>
173-
</>
174-
)}
175-
</div>
176-
</InfoSectionContent>
177-
</InfoSection>
17836
{resource.http ? (
17937
<>
18038
<InfoSection>

0 commit comments

Comments
 (0)