mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-08-28 21:01:30 +00:00
FIX - allow configurable radio channel jobs (#46)
Mark locked-channel job maps mutable in the configurator schema and initialize new structured list rows from their schema template so required frequency ranges remain valid.
This commit is contained in:
@@ -380,10 +380,10 @@ function toggleOptionalString(event: Event): void {
|
||||
function addListRow(): void {
|
||||
const rows = Array.isArray(props.modelValue) ? [...props.modelValue] : []
|
||||
const index = rows.length
|
||||
const value = rows.length
|
||||
? blankLike(rows[0])
|
||||
: listTemplate.value
|
||||
? blankFromConfiguratorStructure(listTemplate.value)
|
||||
const value = listTemplate.value
|
||||
? blankFromConfiguratorStructure(listTemplate.value)
|
||||
: rows.length
|
||||
? blankLike(rows[0])
|
||||
: blankValue(newArrayKind.value)
|
||||
rows.push(value)
|
||||
emit('update:modelValue', rows)
|
||||
|
||||
@@ -440,6 +440,9 @@ describe('standalone admin panel contracts', () => {
|
||||
expect(source).toContain("selectConfiguratorScope('media')")
|
||||
expect(source).not.toContain('class="admin-panel-config-meta"')
|
||||
expect(configuratorValueEditor).toContain('function addListRow()')
|
||||
expect(configuratorValueEditor).toMatch(
|
||||
/const value = listTemplate\.value\s+\? blankFromConfiguratorStructure\(listTemplate\.value\)\s+: rows\.length\s+\? blankLike\(rows\[0\]\)/,
|
||||
)
|
||||
expect(configuratorValueEditor).toContain('function addTableField()')
|
||||
expect(configuratorValueEditor).toContain(
|
||||
'const canExtendTable = computed(',
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import type { AdminConfiguratorStructure } from '@/types/admin'
|
||||
import { createMutableTableEntry } from '@/utils/adminConfiguratorDefaults'
|
||||
import {
|
||||
blankFromConfiguratorStructure,
|
||||
createMutableTableEntry,
|
||||
} from '@/utils/adminConfiguratorDefaults'
|
||||
|
||||
describe('admin configurator defaults', () => {
|
||||
it('creates a usable company draft from its key and the server defaults', () => {
|
||||
@@ -111,4 +114,33 @@ describe('admin configurator defaults', () => {
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
it('preserves required nested list fields in schema-derived rows', () => {
|
||||
const structure: AdminConfiguratorStructure = {
|
||||
fields: {
|
||||
jobs: {
|
||||
fields: {
|
||||
police: { kind: 'value', valueType: 'boolean' },
|
||||
},
|
||||
kind: 'table',
|
||||
mutableKeys: true,
|
||||
template: { kind: 'value', valueType: 'boolean' },
|
||||
},
|
||||
range: {
|
||||
items: [
|
||||
{ kind: 'value', valueType: 'number' },
|
||||
{ kind: 'value', valueType: 'number' },
|
||||
],
|
||||
kind: 'list',
|
||||
template: { kind: 'value', valueType: 'number' },
|
||||
},
|
||||
},
|
||||
kind: 'table',
|
||||
}
|
||||
|
||||
expect(blankFromConfiguratorStructure(structure)).toEqual({
|
||||
jobs: { police: false },
|
||||
range: [0, 0],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -540,6 +540,25 @@ function buildStructure(value, scope, path) {
|
||||
if (scope === 'config' && path === 'Phone.Keybind') {
|
||||
return { kind: 'optionalString' }
|
||||
}
|
||||
if (
|
||||
scope === 'config' &&
|
||||
/^Radio\.LockedChannels\.\d+\.jobs$/.test(path) &&
|
||||
value !== null &&
|
||||
typeof value === 'object' &&
|
||||
!Array.isArray(value)
|
||||
) {
|
||||
return {
|
||||
fields: Object.fromEntries(
|
||||
Object.entries(value).map(([key, child]) => [
|
||||
key,
|
||||
buildStructure(child, scope, `${path}.${key}`),
|
||||
]),
|
||||
),
|
||||
kind: 'table',
|
||||
mutableKeys: true,
|
||||
template: { kind: 'value', valueType: 'boolean' },
|
||||
}
|
||||
}
|
||||
if (
|
||||
scope === 'config' &&
|
||||
path === 'Companies.Definitions' &&
|
||||
|
||||
@@ -193,6 +193,29 @@ describe('admin configurator fixture', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('allows custom jobs in locked radio channel entries', () => {
|
||||
const radio = loadConfiguratorSections()
|
||||
.flatMap((section) => section.fields)
|
||||
.find((field) => field.path === 'Radio')
|
||||
const lockedChannels = radio?.structure?.fields?.LockedChannels
|
||||
const jobs = lockedChannels?.items?.[0]?.fields?.jobs
|
||||
|
||||
expect(jobs).toMatchObject({
|
||||
fields: {
|
||||
ambulance: { kind: 'value', valueType: 'boolean' },
|
||||
police: { kind: 'value', valueType: 'boolean' },
|
||||
},
|
||||
kind: 'table',
|
||||
mutableKeys: true,
|
||||
template: { kind: 'value', valueType: 'boolean' },
|
||||
})
|
||||
expect(lockedChannels?.template?.fields?.jobs).toMatchObject({
|
||||
kind: 'table',
|
||||
mutableKeys: true,
|
||||
template: { kind: 'value', valueType: 'boolean' },
|
||||
})
|
||||
})
|
||||
|
||||
it('publishes fixed schemas for every empty configurable collection', () => {
|
||||
const fields = loadConfiguratorSections().flatMap(
|
||||
(section) => section.fields,
|
||||
|
||||
@@ -637,6 +637,21 @@ local function build_structure(value, scope, path)
|
||||
if scope == "config" and path == "Phone.Keybind" then
|
||||
return { kind = "optionalString" }
|
||||
end
|
||||
if scope == "config"
|
||||
and path:match("^Radio%.LockedChannels%.%d+%.jobs$")
|
||||
and value_type == "table"
|
||||
then
|
||||
local fields = {}
|
||||
for key, child in pairs(value) do
|
||||
fields[key] = build_structure(child, scope, path .. "." .. tostring(key))
|
||||
end
|
||||
return {
|
||||
fields = fields,
|
||||
kind = "table",
|
||||
mutableKeys = true,
|
||||
template = { kind = "value", valueType = "boolean" },
|
||||
}
|
||||
end
|
||||
if scope == "config" and path == "Companies.Definitions" and value_type == "table" then
|
||||
local keys = {}
|
||||
for key in pairs(value) do
|
||||
|
||||
Reference in New Issue
Block a user