update lisensi prosess
tests / ci (push) Has been cancelled

This commit is contained in:
Wian Drs
2026-08-25 13:43:55 +07:00
parent 1e80be180e
commit 60946ddf37
58 changed files with 2903 additions and 165 deletions
+137 -36
View File
@@ -8,14 +8,20 @@ import { Label } from '@/components/ui/label';
type Item = { id: number; name: string; slug?: string };
type Model = Item & { device_vendor_id: number; device_type_id: number };
type Props = {
device: (Record<string, unknown> & { connection_ports?: Record<string, number> }) | null;
device:
| (Record<string, unknown> & {
connection_ports?: Record<string, number>;
})
| null;
vendors: Item[];
types: Item[];
models: Model[];
};
export default function DeviceForm({ device, vendors, types, models }: Props) {
const editing = !!device;
const initialVendor = vendors.find((vendor) => vendor.id === Number(device?.device_vendor_id));
const initialVendor = vendors.find(
(vendor) => vendor.id === Number(device?.device_vendor_id),
);
const [vendorSlug, setVendorSlug] = useState(initialVendor?.slug ?? '');
const fields = [
['name', 'Nama Perangkat'],
@@ -25,12 +31,20 @@ export default function DeviceForm({ device, vendors, types, models }: Props) {
const protocolProfiles: Record<string, Array<[string, string, number]>> = {
mikrotik: [['routeros_api', 'Port RouterOS API', 8728]],
zte: [['ssh', 'Port SSH', 22]],
hsgq: [['ssh', 'Port SSH', 22], ['telnet', 'Port Telnet', 23]],
hisfocus: [['telnet', 'Port Telnet', 23], ['web_http', 'Port WebGUI HTTP', 80]],
hsgq: [
['ssh', 'Port SSH', 22],
['telnet', 'Port Telnet', 23],
],
hisfocus: [
['telnet', 'Port Telnet', 23],
['web_http', 'Port WebGUI HTTP', 80],
],
};
const flexibleProtocols: Array<[string, string, number]> = [
['ssh', 'Port SSH', 22], ['telnet', 'Port Telnet', 23],
['web_http', 'Port WebGUI HTTP', 80], ['snmp', 'Port SNMP', 161],
['ssh', 'Port SSH', 22],
['telnet', 'Port Telnet', 23],
['web_http', 'Port WebGUI HTTP', 80],
['snmp', 'Port SNMP', 161],
['vendor_api', 'Port Vendor API', 0],
];
const protocols = protocolProfiles[vendorSlug] ?? flexibleProtocols;
@@ -84,7 +98,11 @@ export default function DeviceForm({ device, vendors, types, models }: Props) {
)}
required
onChange={(event) => {
const selected = vendors.find((vendor) => vendor.id === Number(event.target.value));
const selected = vendors.find(
(vendor) =>
vendor.id ===
Number(event.target.value),
);
setVendorSlug(selected?.slug ?? '');
}}
className="h-10 rounded-md border bg-background px-3"
@@ -139,24 +157,57 @@ export default function DeviceForm({ device, vendors, types, models }: Props) {
</select>
</div>
<div className="rounded-lg border p-4 md:col-span-2">
<h3 className="font-medium">Koneksi Management</h3>
<p className="mb-4 text-sm text-muted-foreground">Kosongkan port jika protokol tersebut tidak tersedia pada perangkat.</p>
<InputError message={errors.connection_ports} />
<h3 className="font-medium">
Koneksi Management
</h3>
<p className="mb-4 text-sm text-muted-foreground">
Kosongkan port jika protokol tersebut
tidak tersedia pada perangkat.
</p>
<InputError
message={errors.connection_ports}
/>
<div className="grid gap-4 md:grid-cols-2">
{protocols.map(([protocol, label, defaultPort]) => (
<div key={`${vendorSlug}-${protocol}`} className="grid gap-2">
<Label>{label}</Label>
<Input
name={`connection_ports[${protocol}]`}
type="number"
min={1}
max={65535}
placeholder={defaultPort ? String(defaultPort) : 'Port custom'}
defaultValue={device?.connection_ports?.[protocol] ?? ''}
/>
<InputError message={errors[`connection_ports.${protocol}`]} />
</div>
))}
{protocols.map(
([
protocol,
label,
defaultPort,
]) => (
<div
key={`${vendorSlug}-${protocol}`}
className="grid gap-2"
>
<Label>{label}</Label>
<Input
name={`connection_ports[${protocol}]`}
type="number"
min={1}
max={65535}
placeholder={
defaultPort
? String(
defaultPort,
)
: 'Port custom'
}
defaultValue={
device
?.connection_ports?.[
protocol
] ?? ''
}
/>
<InputError
message={
errors[
`connection_ports.${protocol}`
]
}
/>
</div>
),
)}
</div>
</div>
<div className="grid gap-2 md:col-span-2">
@@ -173,26 +224,76 @@ export default function DeviceForm({ device, vendors, types, models }: Props) {
<>
<div className="grid gap-2">
<Label>Username Awal</Label>
<Input name="initial_username" required autoComplete="off" />
<InputError message={errors.initial_username} />
<Input
name="initial_username"
required
autoComplete="off"
/>
<InputError
message={
errors.initial_username
}
/>
</div>
<div className="grid gap-2">
<Label>Password Awal</Label>
<Input name="initial_password" type="password" autoComplete="new-password" />
<p className="text-xs text-muted-foreground">Boleh kosong untuk perangkat MikroTik yang masih memakai password kosong.</p>
<InputError message={errors.initial_password} />
<Input
name="initial_password"
type="password"
autoComplete="new-password"
/>
<p className="text-xs text-muted-foreground">
Boleh kosong untuk perangkat
MikroTik yang masih memakai
password kosong.
</p>
<InputError
message={
errors.initial_password
}
/>
</div>
<div className="grid gap-2 md:col-span-2">
<Label>Enable Password (opsional)</Label>
<Input name="initial_enable_password" type="password" autoComplete="new-password" />
<p className="text-xs text-muted-foreground">Khusus perangkat CLI seperti ZTE C300/C320. Default pabrik tertentu adalah zxr10; isi sesuai kondisi perangkat.</p>
<InputError message={errors.initial_enable_password} />
<Label>
Enable Password (opsional)
</Label>
<Input
name="initial_enable_password"
type="password"
autoComplete="new-password"
/>
<p className="text-xs text-muted-foreground">
Khusus perangkat CLI seperti ZTE
C300/C320. Default pabrik
tertentu adalah zxr10; isi
sesuai kondisi perangkat.
</p>
<InputError
message={
errors.initial_enable_password
}
/>
</div>
<label className="flex items-start gap-3 rounded-lg border p-4 md:col-span-2">
<input type="checkbox" name="remove_legacy_users_on_activation" value="1" className="mt-1" />
<input
type="checkbox"
name="remove_legacy_users_on_activation"
value="1"
className="mt-1"
/>
<span>
<span className="block font-medium">Hapus user lama setelah koneksi pertama</span>
<span className="block text-sm text-muted-foreground">Dijalankan hanya setelah Base User RADIQ berhasil dibuat dan diuji login. User grup full tetap dipertahankan untuk mencegah perangkat terkunci.</span>
<span className="block font-medium">
Hapus user lama setelah
koneksi pertama
</span>
<span className="block text-sm text-muted-foreground">
Dijalankan hanya setelah
Base User RADIQ berhasil
dibuat dan diuji login. User
grup full tetap
dipertahankan untuk mencegah
perangkat terkunci.
</span>
</span>
</label>
</>