Let a person edit the asset fields the pages already display
Eight fields across three asset types were shown on the detail page and accepted by the API, but had no input on the form. A wrong value therefore needed database access to correct, which is not a thing anybody should need for a device category or a maintenance date. The shape is the same in each case: a column was added, the detail card was written, the API allowlist was updated, and the form was missed. Nothing was broken - the values arrive by import or collector - so nothing complained. PCs gain azureobjectid and azuredevicecategory. azuredeviceid was already there, which is what made the omission easy to miss: the page showed two ids and the form offered one. The two are not interchangeable and the pairing is counterintuitive - the DEVICE id opens Intune, the OBJECT id opens Entra - so each input says where it goes. Machines gain the three maintenance fields. These matter beyond the immediate fix: they are the columns a measuring instrument's calibration dates map onto when metrology moves to machines, and until now there was no way to enter a calibration date on a machine at all. Printers gain iscolor, isduplex and isnetwork as a capability group. isnetwork defaults to true in the form to match the API's create default; a new printer claiming otherwise would be wrong for nearly all of them. Checked before making any of these editable that nothing writes them automatically - a hand edit silently reverted by the next collector poll would be worse than no input at all. The printers collector reports queues and supplies, not capabilities, and nothing writes machine maintenance dates, which is exactly why they are all empty. The two genuinely collector-owned computer fields, lastreporteddate and lastboottime, are deliberately still not editable. Scope: product
This commit is contained in:
@@ -230,7 +230,36 @@
|
|||||||
v-model="form.azuredeviceid"
|
v-model="form.azuredeviceid"
|
||||||
type="text"
|
type="text"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
placeholder="Entra/Azure deviceId GUID (set by Azure imports)"
|
placeholder="Entra deviceId GUID (set by the Azure import)"
|
||||||
|
/>
|
||||||
|
<small class="muted">Opens the device in Intune from the PC page.</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- The OBJECT id, not the device id. Entra gives a device both and
|
||||||
|
they address different places: deviceId opens Intune, objectId
|
||||||
|
opens the Entra device record. The import populates both, so a
|
||||||
|
page showing only one left the other uneditable when it was
|
||||||
|
wrong. -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="azureobjectid">Azure Object ID</label>
|
||||||
|
<input
|
||||||
|
id="azureobjectid"
|
||||||
|
v-model="form.azureobjectid"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Entra objectId GUID (set by the Azure import)"
|
||||||
|
/>
|
||||||
|
<small class="muted">Opens the device in Entra from the PC page.</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="azuredevicecategory">Azure Device Category</label>
|
||||||
|
<input
|
||||||
|
id="azuredevicecategory"
|
||||||
|
v-model="form.azuredevicecategory"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Entra device category or group label"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -395,6 +424,8 @@ const form = ref({
|
|||||||
osid: '',
|
osid: '',
|
||||||
loggedinuser: '',
|
loggedinuser: '',
|
||||||
azuredeviceid: '',
|
azuredeviceid: '',
|
||||||
|
azureobjectid: '',
|
||||||
|
azuredevicecategory: '',
|
||||||
accessmethods: [],
|
accessmethods: [],
|
||||||
notes: '',
|
notes: '',
|
||||||
mapx: null,
|
mapx: null,
|
||||||
@@ -529,6 +560,8 @@ onMounted(async () => {
|
|||||||
osid: ext.osid || '',
|
osid: ext.osid || '',
|
||||||
loggedinuser: ext.loggedinuser || '',
|
loggedinuser: ext.loggedinuser || '',
|
||||||
azuredeviceid: ext.azuredeviceid || '',
|
azuredeviceid: ext.azuredeviceid || '',
|
||||||
|
azureobjectid: ext.azureobjectid || '',
|
||||||
|
azuredevicecategory: ext.azuredevicecategory || '',
|
||||||
accessmethods: (pc.accessmethods || []).map(a => ({
|
accessmethods: (pc.accessmethods || []).map(a => ({
|
||||||
protocolid: a.protocolid,
|
protocolid: a.protocolid,
|
||||||
portoverride: a.portoverride ?? null
|
portoverride: a.portoverride ?? null
|
||||||
@@ -605,6 +638,8 @@ async function savePC() {
|
|||||||
osid: form.value.osid || null,
|
osid: form.value.osid || null,
|
||||||
loggedinuser: form.value.loggedinuser || null,
|
loggedinuser: form.value.loggedinuser || null,
|
||||||
azuredeviceid: form.value.azuredeviceid || null,
|
azuredeviceid: form.value.azuredeviceid || null,
|
||||||
|
azureobjectid: form.value.azureobjectid || null,
|
||||||
|
azuredevicecategory: form.value.azuredevicecategory || null,
|
||||||
accessmethods: form.value.accessmethods,
|
accessmethods: form.value.accessmethods,
|
||||||
notes: form.value.notes || null,
|
notes: form.value.notes || null,
|
||||||
ipaddress: form.value.ipaddress || null,
|
ipaddress: form.value.ipaddress || null,
|
||||||
|
|||||||
@@ -336,6 +336,44 @@
|
|||||||
|
|
||||||
<!-- Notes Section -->
|
<!-- Notes Section -->
|
||||||
<h3 class="form-section-title">Notes</h3>
|
<h3 class="form-section-title">Notes</h3>
|
||||||
|
<!-- Maintenance. Shown on the detail page since it was added but never
|
||||||
|
editable, so a wrong date needed database access to correct. These
|
||||||
|
are the columns a measuring instrument's calibration dates map onto
|
||||||
|
when metrology moves to machines, which is the other reason they
|
||||||
|
have to be enterable. -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="lastmaintenancedate">Last Maintenance</label>
|
||||||
|
<input
|
||||||
|
id="lastmaintenancedate"
|
||||||
|
v-model="form.lastmaintenancedate"
|
||||||
|
type="date"
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="nextmaintenancedate">Next Maintenance</label>
|
||||||
|
<input
|
||||||
|
id="nextmaintenancedate"
|
||||||
|
v-model="form.nextmaintenancedate"
|
||||||
|
type="date"
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
|
<small class="muted">Set directly; it is not derived from the interval.</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="maintenanceintervaldays">Maintenance Interval (days)</label>
|
||||||
|
<input
|
||||||
|
id="maintenanceintervaldays"
|
||||||
|
v-model.number="form.maintenanceintervaldays"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="e.g. 180"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<textarea
|
<textarea
|
||||||
id="notes"
|
id="notes"
|
||||||
@@ -420,6 +458,9 @@ const form = ref({
|
|||||||
businessunitid: '',
|
businessunitid: '',
|
||||||
requiresmanualconfig: false,
|
requiresmanualconfig: false,
|
||||||
islocationonly: false,
|
islocationonly: false,
|
||||||
|
lastmaintenancedate: '',
|
||||||
|
nextmaintenancedate: '',
|
||||||
|
maintenanceintervaldays: null,
|
||||||
notes: '',
|
notes: '',
|
||||||
mapx: null,
|
mapx: null,
|
||||||
mapy: null,
|
mapy: null,
|
||||||
@@ -613,6 +654,9 @@ onMounted(async () => {
|
|||||||
businessunitid: data.businessunitid || '',
|
businessunitid: data.businessunitid || '',
|
||||||
requiresmanualconfig: data.machine?.requiresmanualconfig || false,
|
requiresmanualconfig: data.machine?.requiresmanualconfig || false,
|
||||||
islocationonly: data.machine?.islocationonly || false,
|
islocationonly: data.machine?.islocationonly || false,
|
||||||
|
lastmaintenancedate: (data.machine?.lastmaintenancedate || '').slice(0, 10),
|
||||||
|
nextmaintenancedate: (data.machine?.nextmaintenancedate || '').slice(0, 10),
|
||||||
|
maintenanceintervaldays: data.machine?.maintenanceintervaldays ?? null,
|
||||||
notes: data.notes || '',
|
notes: data.notes || '',
|
||||||
mapx: data.mapx ?? null,
|
mapx: data.mapx ?? null,
|
||||||
mapy: data.mapy ?? null,
|
mapy: data.mapy ?? null,
|
||||||
@@ -714,6 +758,9 @@ async function saveMachine() {
|
|||||||
businessunitid: form.value.businessunitid || null,
|
businessunitid: form.value.businessunitid || null,
|
||||||
requiresmanualconfig: form.value.requiresmanualconfig,
|
requiresmanualconfig: form.value.requiresmanualconfig,
|
||||||
islocationonly: form.value.islocationonly,
|
islocationonly: form.value.islocationonly,
|
||||||
|
lastmaintenancedate: form.value.lastmaintenancedate || null,
|
||||||
|
nextmaintenancedate: form.value.nextmaintenancedate || null,
|
||||||
|
maintenanceintervaldays: form.value.maintenanceintervaldays || null,
|
||||||
notes: form.value.notes || null,
|
notes: form.value.notes || null,
|
||||||
mapx: form.value.mapx,
|
mapx: form.value.mapx,
|
||||||
mapy: form.value.mapy
|
mapy: form.value.mapy
|
||||||
|
|||||||
@@ -223,6 +223,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Capabilities. On the detail page since they were added but never
|
||||||
|
editable, so a wrong one needed database access to correct.
|
||||||
|
Nothing writes these automatically - the collector reports queues
|
||||||
|
and supplies, not capabilities - so a person is the only source. -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Capabilities</label>
|
||||||
|
<div class="capability-list">
|
||||||
|
<label class="capability-item">
|
||||||
|
<input type="checkbox" v-model="form.iscolor" />
|
||||||
|
<span>Colour</span>
|
||||||
|
</label>
|
||||||
|
<label class="capability-item">
|
||||||
|
<input type="checkbox" v-model="form.isduplex" />
|
||||||
|
<span>Duplex</span>
|
||||||
|
</label>
|
||||||
|
<label class="capability-item">
|
||||||
|
<input type="checkbox" v-model="form.isnetwork" />
|
||||||
|
<span>Network</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="installpath">Driver Install Path</label>
|
<label for="installpath">Driver Install Path</label>
|
||||||
<input
|
<input
|
||||||
@@ -361,7 +383,12 @@ const form = ref({
|
|||||||
ipaddress: '',
|
ipaddress: '',
|
||||||
csfname: '',
|
csfname: '',
|
||||||
installpath: '',
|
installpath: '',
|
||||||
pin: ''
|
pin: '',
|
||||||
|
iscolor: false,
|
||||||
|
isduplex: false,
|
||||||
|
// true to match the create default in the API; most printers here are
|
||||||
|
// networked and a new record that claimed otherwise would be wrong.
|
||||||
|
isnetwork: true
|
||||||
})
|
})
|
||||||
|
|
||||||
const printerTypes = ref([])
|
const printerTypes = ref([])
|
||||||
@@ -559,6 +586,9 @@ onMounted(async () => {
|
|||||||
modelnumberid: ext.modelnumberid || '',
|
modelnumberid: ext.modelnumberid || '',
|
||||||
locationid: printer.locationid || '',
|
locationid: printer.locationid || '',
|
||||||
notes: printer.notes || '',
|
notes: printer.notes || '',
|
||||||
|
iscolor: !!printer.printer?.iscolor,
|
||||||
|
isduplex: !!printer.printer?.isduplex,
|
||||||
|
isnetwork: printer.printer?.isnetwork !== false,
|
||||||
mapx: printer.mapx ?? null,
|
mapx: printer.mapx ?? null,
|
||||||
mapy: printer.mapy ?? null,
|
mapy: printer.mapy ?? null,
|
||||||
levelid: printer.levelid ?? null,
|
levelid: printer.levelid ?? null,
|
||||||
@@ -652,6 +682,9 @@ async function savePrinter() {
|
|||||||
installpath: form.value.installpath || null,
|
installpath: form.value.installpath || null,
|
||||||
pin: form.value.pin || null,
|
pin: form.value.pin || null,
|
||||||
ipaddress: form.value.ipaddress || null,
|
ipaddress: form.value.ipaddress || null,
|
||||||
|
iscolor: !!form.value.iscolor,
|
||||||
|
isduplex: !!form.value.isduplex,
|
||||||
|
isnetwork: !!form.value.isnetwork,
|
||||||
mapx: form.value.mapx,
|
mapx: form.value.mapx,
|
||||||
mapy: form.value.mapy
|
mapy: form.value.mapy
|
||||||
}
|
}
|
||||||
@@ -688,6 +721,9 @@ async function savePrinter() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.capability-list { display: flex; flex-wrap: wrap; gap: 1rem; }
|
||||||
|
.capability-item { display: inline-flex; align-items: center; gap: 0.4rem; font-weight: normal; }
|
||||||
|
|
||||||
.map-location-control {
|
.map-location-control {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user