Skip to content

Commit af9349d

Browse files
committed
Conform hosts table
1 parent 4ff911d commit af9349d

File tree

8 files changed

+355
-107
lines changed

8 files changed

+355
-107
lines changed

frontend/src/locale/src/de.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,6 @@
119119
"create-hint": {
120120
"defaultMessage": "Warum erstellen Sie nicht eine?"
121121
},
122-
"create-host": {
123-
"defaultMessage": "Host erstellen"
124-
},
125122
"create-host-title": {
126123
"defaultMessage": "Es gibt keine Proxy-Hosts"
127124
},
@@ -242,6 +239,9 @@
242239
"general-settings.title": {
243240
"defaultMessage": "Allgemeine Einstellungen"
244241
},
242+
"host.create": {
243+
"defaultMessage": "Host erstellen"
244+
},
245245
"hosts.title": {
246246
"defaultMessage": "Gastgeber"
247247
},

frontend/src/locale/src/en.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,6 @@
395395
"create-hint": {
396396
"defaultMessage": "Why don't you create one?"
397397
},
398-
"create-host": {
399-
"defaultMessage": "Create Host"
400-
},
401398
"create-host-title": {
402399
"defaultMessage": "There are no Hosts"
403400
},
@@ -518,6 +515,9 @@
518515
"general-settings.title": {
519516
"defaultMessage": "General Settings"
520517
},
518+
"host.create": {
519+
"defaultMessage": "Create Host"
520+
},
521521
"hosts.title": {
522522
"defaultMessage": "Hosts"
523523
},

frontend/src/locale/src/fa.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,6 @@
119119
"create-hint": {
120120
"defaultMessage": "چرا یکی را ایجاد نمی کنید؟"
121121
},
122-
"create-host": {
123-
"defaultMessage": "هاست ایجاد کنید"
124-
},
125122
"create-nginx-template": {
126123
"defaultMessage": "قالب هاست ایجاد کنید"
127124
},
@@ -245,6 +242,9 @@
245242
"nginx-templates.title": {
246243
"defaultMessage": "قالب های میزبان"
247244
},
245+
"host.create": {
246+
"defaultMessage": "هاست ایجاد کنید"
247+
},
248248
"hosts.title": {
249249
"defaultMessage": "میزبان"
250250
},
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
import {
2+
Button,
3+
Checkbox,
4+
FormControl,
5+
FormErrorMessage,
6+
FormLabel,
7+
Input,
8+
Modal,
9+
ModalOverlay,
10+
ModalContent,
11+
ModalHeader,
12+
ModalCloseButton,
13+
ModalBody,
14+
ModalFooter,
15+
Stack,
16+
useToast,
17+
} from "@chakra-ui/react";
18+
import { CertificateAuthority } from "api/npm";
19+
import { PrettyButton } from "components";
20+
import { Formik, Form, Field } from "formik";
21+
import { useSetCertificateAuthority } from "hooks";
22+
import { intl } from "locale";
23+
import { validateNumber, validateString } from "modules/Validations";
24+
25+
interface HostCreateModalProps {
26+
isOpen: boolean;
27+
onClose: () => void;
28+
}
29+
function HostCreateModal({ isOpen, onClose }: HostCreateModalProps) {
30+
const toast = useToast();
31+
const { mutate: setCertificateAuthority } = useSetCertificateAuthority();
32+
33+
const onSubmit = async (
34+
payload: CertificateAuthority,
35+
{ setErrors, setSubmitting }: any,
36+
) => {
37+
const showErr = (msg: string) => {
38+
toast({
39+
description: intl.formatMessage({
40+
id: `error.${msg}`,
41+
}),
42+
status: "error",
43+
position: "top",
44+
duration: 3000,
45+
isClosable: true,
46+
});
47+
};
48+
49+
setCertificateAuthority(payload, {
50+
onError: (err: any) => {
51+
if (err.message === "ca-bundle-does-not-exist") {
52+
setErrors({
53+
caBundle: intl.formatMessage({
54+
id: `error.${err.message}`,
55+
}),
56+
});
57+
} else {
58+
showErr(err.message);
59+
}
60+
},
61+
onSuccess: () => onClose(),
62+
onSettled: () => setSubmitting(false),
63+
});
64+
};
65+
66+
return (
67+
<Modal isOpen={isOpen} onClose={onClose} closeOnOverlayClick={false}>
68+
<ModalOverlay />
69+
<ModalContent>
70+
<Formik
71+
initialValues={
72+
{
73+
name: "",
74+
acmeshServer: "",
75+
caBundle: "",
76+
maxDomains: 5,
77+
isWildcardSupported: false,
78+
} as CertificateAuthority
79+
}
80+
onSubmit={onSubmit}>
81+
{({ isSubmitting }) => (
82+
<Form>
83+
<ModalHeader>
84+
{intl.formatMessage({ id: "certificate-authority.create" })}
85+
</ModalHeader>
86+
<ModalCloseButton />
87+
<ModalBody>
88+
<Stack spacing={4}>
89+
<Field name="name" validate={validateString(1, 100)}>
90+
{({ field, form }: any) => (
91+
<FormControl
92+
isRequired
93+
isInvalid={form.errors.name && form.touched.name}>
94+
<FormLabel htmlFor="name">
95+
{intl.formatMessage({
96+
id: "certificate-authority.name",
97+
})}
98+
</FormLabel>
99+
<Input
100+
{...field}
101+
id="name"
102+
placeholder={intl.formatMessage({
103+
id: "certificate-authority.name",
104+
})}
105+
/>
106+
<FormErrorMessage>{form.errors.name}</FormErrorMessage>
107+
</FormControl>
108+
)}
109+
</Field>
110+
<Field name="acmeshServer" validate={validateString(2, 255)}>
111+
{({ field, form }: any) => (
112+
<FormControl
113+
isRequired
114+
isInvalid={
115+
form.errors.acmeshServer && form.touched.acmeshServer
116+
}>
117+
<FormLabel htmlFor="acmeshServer">
118+
{intl.formatMessage({
119+
id: "certificate-authority.acmesh-server",
120+
})}
121+
</FormLabel>
122+
<Input
123+
{...field}
124+
id="acmeshServer"
125+
placeholder="https://example.com/acme/directory"
126+
/>
127+
<FormErrorMessage>
128+
{form.errors.acmeshServer}
129+
</FormErrorMessage>
130+
</FormControl>
131+
)}
132+
</Field>
133+
<Field name="caBundle" validate={validateString(2, 255)}>
134+
{({ field, form }: any) => (
135+
<FormControl
136+
isRequired
137+
isInvalid={
138+
form.errors.caBundle && form.touched.caBundle
139+
}>
140+
<FormLabel htmlFor="caBundle">
141+
{intl.formatMessage({
142+
id: "certificate-authority.ca-bundle",
143+
})}
144+
</FormLabel>
145+
<Input
146+
{...field}
147+
id="caBundle"
148+
placeholder="/path/to/certs/custom-ca-bundle.crt"
149+
/>
150+
<FormErrorMessage>
151+
{form.errors.caBundle}
152+
</FormErrorMessage>
153+
</FormControl>
154+
)}
155+
</Field>
156+
<Field
157+
name="maxDomains"
158+
validate={validateNumber(1)}
159+
type="number">
160+
{({ field, form }: any) => (
161+
<FormControl
162+
isRequired
163+
isInvalid={
164+
form.errors.maxDomains && form.touched.maxDomains
165+
}>
166+
<FormLabel htmlFor="maxDomains">
167+
{intl.formatMessage({
168+
id: "certificate-authority.max-domains",
169+
})}
170+
</FormLabel>
171+
<Input {...field} id="maxDomains" type="number" />
172+
<FormErrorMessage>
173+
{form.errors.maxDomains}
174+
</FormErrorMessage>
175+
</FormControl>
176+
)}
177+
</Field>
178+
<Field name="isWildcardSupported" type="checkbox">
179+
{({ field, form }: any) => (
180+
<FormControl
181+
isInvalid={
182+
form.errors.isWildcardSupported &&
183+
form.touched.isWildcardSupported
184+
}>
185+
<Checkbox
186+
{...field}
187+
isChecked={field.checked}
188+
size="md"
189+
colorScheme="green">
190+
{intl.formatMessage({
191+
id: "certificate-authority.has-wildcard-support",
192+
})}
193+
</Checkbox>
194+
<FormErrorMessage>
195+
{form.errors.isWildcardSupported}
196+
</FormErrorMessage>
197+
</FormControl>
198+
)}
199+
</Field>
200+
</Stack>
201+
</ModalBody>
202+
<ModalFooter>
203+
<PrettyButton mr={3} isLoading={isSubmitting}>
204+
{intl.formatMessage({ id: "form.save" })}
205+
</PrettyButton>
206+
<Button onClick={onClose} isLoading={isSubmitting}>
207+
{intl.formatMessage({ id: "form.cancel" })}
208+
</Button>
209+
</ModalFooter>
210+
</Form>
211+
)}
212+
</Formik>
213+
</ModalContent>
214+
</Modal>
215+
);
216+
}
217+
218+
export { HostCreateModal };

frontend/src/modals/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export * from "./CertificateEditModal";
66
export * from "./ChangePasswordModal";
77
export * from "./DNSProviderCreateModal";
88
// export * from "./DNSProviderEditModal.tsx.disabled";
9+
export * from "./HostCreateModal";
910
export * from "./ProfileModal";
1011
export * from "./SetPasswordModal";
1112
export * from "./UpstreamCreateModal";

frontend/src/pages/Hosts/HostsTable.tsx renamed to frontend/src/pages/Hosts/Table.tsx

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,33 +18,22 @@ import { intl } from "locale";
1818
import { FiEdit } from "react-icons/fi";
1919
import { useSortBy, useFilters, useTable, usePagination } from "react-table";
2020

21-
const rowActions = [
22-
{
23-
title: intl.formatMessage({ id: "action.edit" }),
24-
onClick: (e: any, data: any) => {
25-
alert(JSON.stringify(data, null, 2));
26-
},
27-
icon: <FiEdit />,
28-
show: (data: any) => !data.isSystem,
29-
},
30-
];
31-
32-
export interface HostsTableProps {
21+
export interface TableProps {
3322
data: any;
3423
pagination: TablePagination;
3524
sortBy: TableSortBy[];
3625
filters: TableFilter[];
3726
onTableEvent: any;
3827
}
39-
function HostsTable({
28+
function Table({
4029
data,
4130
pagination,
4231
onTableEvent,
4332
sortBy,
4433
filters,
45-
}: HostsTableProps) {
34+
}: TableProps) {
4635
const [columns, tableData] = useMemo(() => {
47-
const columns: any[] = [
36+
const columns: any = [
4837
{
4938
accessor: "user.gravatarUrl",
5039
Cell: GravatarFormatter(),
@@ -82,7 +71,15 @@ function HostsTable({
8271
{
8372
id: "actions",
8473
accessor: "id",
85-
Cell: ActionsFormatter(rowActions),
74+
Cell: ActionsFormatter([
75+
{
76+
title: intl.formatMessage({ id: "action.edit" }),
77+
onClick: (e: any, data: any) => {
78+
alert(JSON.stringify(data, null, 2));
79+
},
80+
icon: <FiEdit />,
81+
},
82+
]),
8683
className: "w-80",
8784
},
8885
];
@@ -162,4 +159,4 @@ function HostsTable({
162159
return <TableLayout pagination={pagination} {...tableInstance} />;
163160
}
164161

165-
export { HostsTable };
162+
export default Table;

0 commit comments

Comments
 (0)