fix: resolve cancel and close buttons not working on server modals
This commit is contained in:
parent
36acc3ea65
commit
5f4acb755e
2 changed files with 131 additions and 151 deletions
|
|
@ -2,17 +2,19 @@ import {
|
||||||
IconDeviceFloppy,
|
IconDeviceFloppy,
|
||||||
IconX,
|
IconX,
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
|
import EasyModal, { useModal } from "ez-modal-react";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
|
import Modal from "react-bootstrap/Modal";
|
||||||
import type { WgInterface } from "src/api/backend/wireguard";
|
import type { WgInterface } from "src/api/backend/wireguard";
|
||||||
|
import { Button } from "src/components";
|
||||||
|
|
||||||
interface WireGuardLinkedServersModalProps {
|
interface WireGuardLinkedServersModalProps {
|
||||||
wgInterface: WgInterface;
|
wgInterface: WgInterface;
|
||||||
allInterfaces: WgInterface[];
|
allInterfaces: WgInterface[];
|
||||||
onHide?: () => void;
|
|
||||||
resolve?: (data: { linked_servers: number[] }) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function WireGuardLinkedServersModal({ wgInterface, allInterfaces, onHide, resolve }: WireGuardLinkedServersModalProps) {
|
const WireGuardLinkedServersModal = EasyModal.create(({ wgInterface, allInterfaces }: WireGuardLinkedServersModalProps) => {
|
||||||
|
const modal = useModal<any>();
|
||||||
// A map or set to manage checked status easily
|
// A map or set to manage checked status easily
|
||||||
const [selected, setSelected] = useState<Set<number>>(new Set());
|
const [selected, setSelected] = useState<Set<number>>(new Set());
|
||||||
|
|
||||||
|
|
@ -33,77 +35,64 @@ function WireGuardLinkedServersModal({ wgInterface, allInterfaces, onHide, resol
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSave = () => {
|
const onSave = () => {
|
||||||
if (resolve) {
|
modal.resolve({ linked_servers: Array.from(selected) });
|
||||||
resolve({ linked_servers: Array.from(selected) });
|
modal.hide();
|
||||||
}
|
};
|
||||||
if (onHide) {
|
|
||||||
onHide();
|
const handleClose = () => {
|
||||||
}
|
modal.resolve(null);
|
||||||
|
modal.hide();
|
||||||
};
|
};
|
||||||
|
|
||||||
const availableServers = allInterfaces.filter(i => i.id !== wgInterface.id);
|
const availableServers = allInterfaces.filter(i => i.id !== wgInterface.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="modal modal-blur fade show d-block" tabIndex={-1}>
|
<Modal show={modal.visible} onHide={handleClose} backdrop="static">
|
||||||
<div className="modal-dialog modal-dialog-centered" role="document">
|
<Modal.Header closeButton>
|
||||||
<div className="modal-content">
|
<Modal.Title>
|
||||||
<div className="modal-header">
|
Linked Servers for {wgInterface.name}
|
||||||
<h5 className="modal-title">
|
</Modal.Title>
|
||||||
Linked Servers for {wgInterface.name}
|
</Modal.Header>
|
||||||
</h5>
|
<Modal.Body>
|
||||||
<button
|
<p className="text-muted mb-3">
|
||||||
type="button"
|
Select the WireGuard servers that clients from <strong>{wgInterface.name}</strong> will be allowed to communicate with.
|
||||||
className="btn-close"
|
</p>
|
||||||
onClick={onHide}
|
|
||||||
aria-label="Close"
|
|
||||||
></button>
|
|
||||||
</div>
|
|
||||||
<div className="modal-body">
|
|
||||||
<p className="text-muted mb-3">
|
|
||||||
Select the WireGuard servers that clients from <strong>{wgInterface.name}</strong> will be allowed to communicate with.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{availableServers.length === 0 ? (
|
{availableServers.length === 0 ? (
|
||||||
<div className="alert alert-info border-0 mb-0">
|
<div className="alert alert-info border-0 mb-0">
|
||||||
There are no other servers available to link to.
|
There are no other servers available to link to.
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="list-group list-group-flush mb-3">
|
|
||||||
{availableServers.map(server => (
|
|
||||||
<label key={server.id} className="list-group-item d-flex align-items-center cursor-pointer px-0">
|
|
||||||
<input
|
|
||||||
className="form-check-input mt-0 me-3"
|
|
||||||
type="checkbox"
|
|
||||||
checked={selected.has(server.id)}
|
|
||||||
onChange={() => toggleServer(server.id)}
|
|
||||||
/>
|
|
||||||
<div className="flex-grow-1">
|
|
||||||
<div><strong>{server.name}</strong></div>
|
|
||||||
<div className="text-muted small border border-light border-1 bg-light rounded mt-1 p-1 d-inline-block">
|
|
||||||
Subnet: {server.ipv4Cidr}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-footer">
|
) : (
|
||||||
<button
|
<div className="list-group list-group-flush mb-3">
|
||||||
type="button"
|
{availableServers.map(server => (
|
||||||
className="btn btn-link link-secondary me-auto"
|
<label key={server.id} className="list-group-item d-flex align-items-center cursor-pointer px-0">
|
||||||
onClick={onHide}
|
<input
|
||||||
>
|
className="form-check-input mt-0 me-3"
|
||||||
<IconX size={16} className="me-1" /> Cancel
|
type="checkbox"
|
||||||
</button>
|
checked={selected.has(server.id)}
|
||||||
<button type="button" className="btn btn-primary" onClick={onSave} disabled={availableServers.length === 0 && selected.size === 0}>
|
onChange={() => toggleServer(server.id)}
|
||||||
<IconDeviceFloppy size={16} className="me-1" /> Save Links
|
/>
|
||||||
</button>
|
<div className="flex-grow-1">
|
||||||
|
<div><strong>{server.name}</strong></div>
|
||||||
|
<div className="text-muted small border border-light border-1 bg-light rounded mt-1 p-1 d-inline-block">
|
||||||
|
Subnet: {server.ipv4Cidr}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</Modal.Body>
|
||||||
</div>
|
<Modal.Footer>
|
||||||
|
<Button type="button" data-bs-dismiss="modal" onClick={handleClose}>
|
||||||
|
<IconX size={16} className="me-1" /> Cancel
|
||||||
|
</Button>
|
||||||
|
<Button type="button" className="ms-auto btn-primary" onClick={onSave} disabled={availableServers.length === 0 && selected.size === 0}>
|
||||||
|
<IconDeviceFloppy size={16} className="me-1" /> Save Links
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
export default WireGuardLinkedServersModal;
|
export default WireGuardLinkedServersModal;
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,21 @@ import {
|
||||||
IconDeviceFloppy,
|
IconDeviceFloppy,
|
||||||
IconX,
|
IconX,
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
|
import EasyModal, { useModal } from "ez-modal-react";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import Modal from "react-bootstrap/Modal";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { Button } from "src/components";
|
||||||
|
|
||||||
interface WireGuardServerModalProps {
|
interface WireGuardServerModalProps {
|
||||||
wgInterface?: any;
|
wgInterface?: any;
|
||||||
onHide?: () => void;
|
|
||||||
resolve?: (data: any) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const WG_DEFAULT_MTU = 1420;
|
const WG_DEFAULT_MTU = 1420;
|
||||||
const WG_DEFAULT_DNS = "1.1.1.1, 8.8.8.8";
|
const WG_DEFAULT_DNS = "1.1.1.1, 8.8.8.8";
|
||||||
|
|
||||||
function WireGuardServerModal({ wgInterface, onHide, resolve }: WireGuardServerModalProps) {
|
const WireGuardServerModal = EasyModal.create(({ wgInterface }: WireGuardServerModalProps) => {
|
||||||
|
const modal = useModal<any>();
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
|
|
@ -44,95 +46,84 @@ function WireGuardServerModal({ wgInterface, onHide, resolve }: WireGuardServerM
|
||||||
...data,
|
...data,
|
||||||
mtu: Number(data.mtu) || WG_DEFAULT_MTU,
|
mtu: Number(data.mtu) || WG_DEFAULT_MTU,
|
||||||
};
|
};
|
||||||
if (resolve) {
|
modal.resolve(submitData);
|
||||||
resolve(submitData);
|
modal.hide();
|
||||||
}
|
};
|
||||||
if (onHide) {
|
|
||||||
onHide();
|
const handleClose = () => {
|
||||||
}
|
modal.resolve(null);
|
||||||
|
modal.hide();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="modal modal-blur fade show d-block" tabIndex={-1}>
|
<Modal show={modal.visible} onHide={handleClose} backdrop="static">
|
||||||
<div className="modal-dialog modal-dialog-centered" role="document">
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<form className="modal-content" onSubmit={handleSubmit(onSubmit)}>
|
<Modal.Header closeButton>
|
||||||
<div className="modal-header">
|
<Modal.Title>
|
||||||
<h5 className="modal-title">
|
{wgInterface ? `Edit Server: ${wgInterface.name}` : "New WireGuard Server"}
|
||||||
{wgInterface ? `Edit Server: ${wgInterface.name}` : "New WireGuard Server"}
|
</Modal.Title>
|
||||||
</h5>
|
</Modal.Header>
|
||||||
<button
|
<Modal.Body>
|
||||||
type="button"
|
<div className="mb-3">
|
||||||
className="btn-close"
|
<label className="form-label required">Host / Endpoint IP</label>
|
||||||
onClick={onHide}
|
<input
|
||||||
aria-label="Close"
|
type="text"
|
||||||
></button>
|
className={`form-control ${errors.host ? "is-invalid" : ""}`}
|
||||||
|
placeholder="e.g., 203.0.113.1"
|
||||||
|
{...register("host", { required: "Host IP is required" })}
|
||||||
|
/>
|
||||||
|
{errors.host && (
|
||||||
|
<div className="invalid-feedback">{errors.host.message as string}</div>
|
||||||
|
)}
|
||||||
|
<small className="form-hint">
|
||||||
|
The public IP or hostname domain that clients will use to connect.
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
|
||||||
<div className="mb-3">
|
|
||||||
<label className="form-label required">Host / Endpoint IP</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className={`form-control ${errors.host ? "is-invalid" : ""}`}
|
|
||||||
placeholder="e.g., 203.0.113.1"
|
|
||||||
{...register("host", { required: "Host IP is required" })}
|
|
||||||
/>
|
|
||||||
{errors.host && (
|
|
||||||
<div className="invalid-feedback">{errors.host.message as string}</div>
|
|
||||||
)}
|
|
||||||
<small className="form-hint">
|
|
||||||
The public IP or hostname domain that clients will use to connect.
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="form-label">Client DNS Servers</label>
|
<label className="form-label">Client DNS Servers</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
placeholder={WG_DEFAULT_DNS}
|
placeholder={WG_DEFAULT_DNS}
|
||||||
{...register("dns")}
|
{...register("dns")}
|
||||||
/>
|
/>
|
||||||
<small className="form-hint">Comma separated list. Assigned to clients.</small>
|
<small className="form-hint">Comma separated list. Assigned to clients.</small>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-3">
|
|
||||||
<label className="form-label">MTU</label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
placeholder={WG_DEFAULT_MTU.toString()}
|
|
||||||
{...register("mtu")}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-3">
|
|
||||||
<label className="form-label">Client Isolation</label>
|
|
||||||
<label className="form-check form-switch">
|
|
||||||
<input
|
|
||||||
className="form-check-input"
|
|
||||||
type="checkbox"
|
|
||||||
{...register("isolate_clients")}
|
|
||||||
/>
|
|
||||||
<span className="form-check-label">Prevent clients on this server from communicating with each other</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-footer">
|
|
||||||
<button
|
<div className="mb-3">
|
||||||
type="button"
|
<label className="form-label">MTU</label>
|
||||||
className="btn btn-link link-secondary me-auto"
|
<input
|
||||||
onClick={onHide}
|
type="number"
|
||||||
>
|
className="form-control"
|
||||||
<IconX size={16} className="me-1" /> Cancel
|
placeholder={WG_DEFAULT_MTU.toString()}
|
||||||
</button>
|
{...register("mtu")}
|
||||||
<button type="submit" className="btn btn-primary">
|
/>
|
||||||
<IconDeviceFloppy size={16} className="me-1" /> Save
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
</div>
|
<div className="mb-3">
|
||||||
</div>
|
<label className="form-label">Client Isolation</label>
|
||||||
|
<label className="form-check form-switch">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
{...register("isolate_clients")}
|
||||||
|
/>
|
||||||
|
<span className="form-check-label">Prevent clients on this server from communicating with each other</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<Button type="button" data-bs-dismiss="modal" onClick={handleClose}>
|
||||||
|
<IconX size={16} className="me-1" /> Cancel
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" className="ms-auto btn-primary">
|
||||||
|
<IconDeviceFloppy size={16} className="me-1" /> Save
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</form>
|
||||||
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
export default WireGuardServerModal;
|
export default WireGuardServerModal;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue