creacion de vlans listo
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<div v-if="showSettingsMenu" class="menu">
|
<div v-if="showSettingsMenu" class="menu">
|
||||||
<button @click="openRawDb">ver rawDB</button>
|
<button @click="openRawDb">ver rawDB</button>
|
||||||
|
<button @click="openVlanForm">crear VLAN</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -103,6 +104,10 @@
|
|||||||
<Modal :open="showRawDb" :fullscreen="rawDbFullscreen" title="Raw DB Viewer" @close="closeRawDb">
|
<Modal :open="showRawDb" :fullscreen="rawDbFullscreen" title="Raw DB Viewer" @close="closeRawDb">
|
||||||
<RawDbViewer @toggle-fullscreen="rawDbFullscreen = !rawDbFullscreen" />
|
<RawDbViewer @toggle-fullscreen="rawDbFullscreen = !rawDbFullscreen" />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<Modal :open="showVlan" title="Crear VLAN" @close="closeVlan">
|
||||||
|
<VlanForm @success="onVlanCreated" @cancel="closeVlan" />
|
||||||
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -112,6 +117,7 @@ import UserCard from './components/UserCard.js';
|
|||||||
import Modal from './components/Modal.vue';
|
import Modal from './components/Modal.vue';
|
||||||
import UserForm from './components/UserForm.vue';
|
import UserForm from './components/UserForm.vue';
|
||||||
import RawDbViewer from './components/RawDbViewer.vue';
|
import RawDbViewer from './components/RawDbViewer.vue';
|
||||||
|
import VlanForm from './components/VlanForm.vue';
|
||||||
|
|
||||||
const users = ref([]);
|
const users = ref([]);
|
||||||
const requests = ref([]);
|
const requests = ref([]);
|
||||||
@@ -245,6 +251,10 @@ const showRawDb = ref(false);
|
|||||||
const rawDbFullscreen = ref(false);
|
const rawDbFullscreen = ref(false);
|
||||||
function openRawDb() { showSettingsMenu.value = false; showRawDb.value = true; }
|
function openRawDb() { showSettingsMenu.value = false; showRawDb.value = true; }
|
||||||
function closeRawDb() { showRawDb.value = false; }
|
function closeRawDb() { showRawDb.value = false; }
|
||||||
|
const showVlan = ref(false);
|
||||||
|
function openVlanForm() { showSettingsMenu.value = false; showVlan.value = true; }
|
||||||
|
function closeVlan() { showVlan.value = false; }
|
||||||
|
function onVlanCreated() { showVlan.value = false; }
|
||||||
function openSettings() { showSettingsMenu.value = !showSettingsMenu.value; }
|
function openSettings() { showSettingsMenu.value = !showSettingsMenu.value; }
|
||||||
function openEditUser(u) {
|
function openEditUser(u) {
|
||||||
userFormMode.value = 'edit';
|
userFormMode.value = 'edit';
|
||||||
|
|||||||
51
frontend/src/components/VlanForm.vue
Normal file
51
frontend/src/components/VlanForm.vue
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<form @submit.prevent="submit" class="column" style="gap:10px;">
|
||||||
|
<div class="row">
|
||||||
|
<label class="toggle" style="flex:0 0 140px;">
|
||||||
|
<div class="muted" style="font-size:12px;">VLAN ID</div>
|
||||||
|
<input v-model.number="state.id" type="number" min="1" placeholder="e.g. 5" style="width:100%; background:transparent; border:none; outline:none; color:inherit;" required />
|
||||||
|
</label>
|
||||||
|
<label class="toggle" style="flex:1;">
|
||||||
|
<div class="muted" style="font-size:12px;">Nombre</div>
|
||||||
|
<input v-model="state.nombre" placeholder="Nombre descriptivo" style="width:100%; background:transparent; border:none; outline:none; color:inherit;" required />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<label class="toggle" style="width:100%;">
|
||||||
|
<div class="muted" style="font-size:12px;">Descripción</div>
|
||||||
|
<textarea v-model="state.descripcion" rows="3" placeholder="Opcional" style="width:100%; background:transparent; border:none; outline:none; color:inherit; resize: vertical;"></textarea>
|
||||||
|
</label>
|
||||||
|
<div v-if="error" class="muted" style="color:#ff6b6b;">{{ error }}</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="icon-btn" @click="$emit('cancel')">Cancelar</button>
|
||||||
|
<button type="submit" class="icon-btn">Crear</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['success', 'cancel']);
|
||||||
|
const state = reactive({ id: '', nombre: '', descripcion: '' });
|
||||||
|
const error = ref('');
|
||||||
|
|
||||||
|
async function submit() {
|
||||||
|
error.value = '';
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/vlans', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ id: state.id, nombre: state.nombre, descripcion: state.descripcion })
|
||||||
|
});
|
||||||
|
const data = await res.json().catch(() => ({}));
|
||||||
|
if (!res.ok || data.ok === false) {
|
||||||
|
error.value = data.error || 'Error al crear VLAN';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('success', { ...state });
|
||||||
|
} catch (e) {
|
||||||
|
error.value = String(e?.message || e) || 'Error';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -126,4 +126,29 @@ router.get('/db/table/:name', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// VLANs
|
||||||
|
router.post('/vlans', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id, nombre, descripcion } = req.body || {};
|
||||||
|
const vid = Number(id);
|
||||||
|
if (!Number.isInteger(vid) || vid <= 0) {
|
||||||
|
return res.status(400).json({ ok: false, error: 'invalid_vlan_id' });
|
||||||
|
}
|
||||||
|
if (!nombre || String(nombre).trim() === '') {
|
||||||
|
return res.status(400).json({ ok: false, error: 'nombre_required' });
|
||||||
|
}
|
||||||
|
await pool.query(
|
||||||
|
'INSERT INTO vlans (id, nombre, descripcion) VALUES ($1, $2, $3)',
|
||||||
|
[vid, String(nombre), descripcion != null ? String(descripcion) : null]
|
||||||
|
);
|
||||||
|
res.json({ ok: true });
|
||||||
|
} catch (e) {
|
||||||
|
if (e && e.code === '23505') {
|
||||||
|
return res.status(409).json({ ok: false, error: 'vlan_exists' });
|
||||||
|
}
|
||||||
|
console.error('POST /api/vlans error:', e?.message || e);
|
||||||
|
res.status(500).json({ ok: false, error: 'db_error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
Reference in New Issue
Block a user