dashboarddefaults: pick a kiosk from a dropdown (auto-fill FQDN) + Location wording
Adds GET /api/computers/display-kiosks - the displays that reported in (Kiosk type), each with its derived FQDN (F<serial>.<domain>). The Dashboard Defaults form gets a kiosk dropdown that fills the FQDN so admins pick a display instead of typing an IP; IP stays an optional manual field. Table shows FQDN or IP. 'Business Unit' label -> 'Location' on this page + the settings nav.
This commit is contained in:
@@ -19,16 +19,16 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>IP Address</th>
|
||||
<th>Kiosk (FQDN / IP)</th>
|
||||
<th>Display</th>
|
||||
<th>Business Unit</th>
|
||||
<th>Location</th>
|
||||
<th>Description</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="d in items" :key="d.dashboarddefaultid">
|
||||
<td class="mono">{{ d.ipaddress }}</td>
|
||||
<td class="mono">{{ d.fqdn || d.ipaddress }}</td>
|
||||
<td>{{ roleLabel(d.displayrole) }}</td>
|
||||
<td>{{ d.businessunit || '-' }}</td>
|
||||
<td class="cell-truncate" :title="d.description">{{ d.description || '-' }}</td>
|
||||
@@ -57,9 +57,19 @@
|
||||
<form @submit.prevent="save">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="ipaddress">IP Address *</label>
|
||||
<label for="kiosk">Kiosk</label>
|
||||
<select id="kiosk" v-model="form.fqdn" class="form-control">
|
||||
<option value="">Select a kiosk (or enter an IP below)...</option>
|
||||
<option v-for="k in kiosks" :key="k.computerid" :value="k.fqdn" :disabled="!k.fqdn">
|
||||
{{ k.hostname }}{{ k.fqdn ? ' - ' + k.fqdn : ' (no serial reported yet)' }}
|
||||
</option>
|
||||
</select>
|
||||
<small class="form-hint">Pick a reporting display to fill its FQDN, or enter an IP manually below.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ipaddress">IP Address (optional)</label>
|
||||
<input id="ipaddress" v-model="form.ipaddress" type="text" class="form-control"
|
||||
placeholder="e.g., 10.20.30.40" required />
|
||||
placeholder="e.g., 10.20.30.40" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="displayrole">Display *</label>
|
||||
@@ -68,10 +78,10 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" v-if="form.displayrole === 'dashboard'">
|
||||
<label for="businessunitid">Business Unit *</label>
|
||||
<label for="businessunitid">Location *</label>
|
||||
<select id="businessunitid" v-model="form.businessunitid" class="form-control"
|
||||
:required="form.displayrole === 'dashboard'">
|
||||
<option value="">Select business unit...</option>
|
||||
<option value="">Select location...</option>
|
||||
<option v-for="bu in businessUnits" :key="bu.businessunitid" :value="bu.businessunitid">
|
||||
{{ bu.businessunit }}
|
||||
</option>
|
||||
@@ -112,7 +122,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { dashboardDefaultsApi, businessUnitsApi } from '../../api'
|
||||
import { dashboardDefaultsApi, businessUnitsApi, computersApi } from '../../api'
|
||||
import { useToast } from '../../composables/toast'
|
||||
import { apiError } from '../../utils/apiError'
|
||||
const toast = useToast()
|
||||
@@ -128,6 +138,7 @@ function roleLabel(value) {
|
||||
|
||||
const items = ref([])
|
||||
const businessUnits = ref([])
|
||||
const kiosks = ref([])
|
||||
const loading = ref(true)
|
||||
|
||||
const showModal = ref(false)
|
||||
@@ -138,7 +149,7 @@ const error = ref('')
|
||||
const showDeleteModal = ref(false)
|
||||
const toDelete = ref(null)
|
||||
|
||||
const form = ref({ ipaddress: '', displayrole: 'dashboard', businessunitid: '', description: '' })
|
||||
const form = ref({ fqdn: '', ipaddress: '', displayrole: 'dashboard', businessunitid: '', description: '' })
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
@@ -147,6 +158,12 @@ onMounted(async () => {
|
||||
} catch (err) {
|
||||
console.error('Error loading business units:', err)
|
||||
}
|
||||
try {
|
||||
const kioskResp = await computersApi.displayKiosks()
|
||||
kiosks.value = kioskResp.data.data || []
|
||||
} catch (err) {
|
||||
console.error('Error loading display kiosks:', err)
|
||||
}
|
||||
await loadData()
|
||||
})
|
||||
|
||||
@@ -165,11 +182,12 @@ async function loadData() {
|
||||
function openModal(item = null) {
|
||||
editing.value = item
|
||||
form.value = item ? {
|
||||
fqdn: item.fqdn || '',
|
||||
ipaddress: item.ipaddress || '',
|
||||
displayrole: item.displayrole || 'dashboard',
|
||||
businessunitid: item.businessunitid || '',
|
||||
description: item.description || ''
|
||||
} : { ipaddress: '', displayrole: 'dashboard', businessunitid: '', description: '' }
|
||||
} : { fqdn: '', ipaddress: '', displayrole: 'dashboard', businessunitid: '', description: '' }
|
||||
error.value = ''
|
||||
showModal.value = true
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ export const settingsGroups = [
|
||||
{
|
||||
title: 'Displays & Kiosks',
|
||||
cards: [
|
||||
{ to: '/settings/dashboarddefaults', icon: MonitorSmartphone, title: 'Dashboard Defaults', description: 'Map kiosk IPs to a default business unit' },
|
||||
{ to: '/settings/dashboarddefaults', icon: MonitorSmartphone, title: 'Dashboard Defaults', description: 'Map kiosk IPs to a default location' },
|
||||
{ to: '/settings/notificationtypes', icon: Bell, title: 'Notification Types', description: 'Manage notification types, display styles, colors, and auto-expiry' },
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user