asset panels: add a tabs render mode, align the keyvalue grid
A panel with many fields was unusable. The detail page is a two-column
multicol (.content-column is display:contents, so the left/right wrappers are
dissolved and cards flow into one balanced flow), and a card cannot be split
across a column break. One 30-row panel therefore became a single unbreakable
block that dragged its column far past the other.
The tabs mode renders sections one at a time, so such a panel stays the height
of its largest section. Payload is {sections: [{label, fields}]}; sections that
end up with no fields are dropped rather than left as empty tabs. The active
tab is marked by an underline AND weight, not colour alone.
keyvalue rows now sit in two aligned columns instead of space-between: a ragged
right edge is hard to scan, and one long value (a UNC path) otherwise pushed
its label away from every other row.
Four specs cover the new mode, including that it drives panel visibility.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import {
|
||||
toApiPath, subst, rows, mapTitle, mapBadge, mapMeta, manageLink,
|
||||
keyvalueFields, tableColumns, badges, panelVisible,
|
||||
keyvalueFields, tableColumns, badges, panelVisible, tabSections,
|
||||
} from './pluginAssetPanels'
|
||||
|
||||
const warrantyPanel = {
|
||||
@@ -98,3 +98,35 @@ describe('keyvalue + table + badge', () => {
|
||||
expect(badges({ render: 'badge', _data: { badges: [{ label: 'B', color: '#222' }] } })).toEqual([{ label: 'B', color: '#222' }])
|
||||
})
|
||||
})
|
||||
|
||||
describe('tabSections', () => {
|
||||
const panel = {
|
||||
render: 'tabs',
|
||||
_data: {
|
||||
sections: [
|
||||
{ label: 'General', fields: [{ label: 'Cnc', value: 'OKUMA' }] },
|
||||
{ label: 'eFocas', fields: [{ label: 'IpAddr', value: '192.168.1.1', mono: true }] },
|
||||
// A section whose fields all dropped out must not leave an empty tab.
|
||||
{ label: 'NTSHR', fields: [] },
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
it('returns one entry per non-empty section', () => {
|
||||
expect(tabSections(panel).map((s) => s.label)).toEqual(['General', 'eFocas'])
|
||||
})
|
||||
|
||||
it('formats field values and carries mono through', () => {
|
||||
const efocas = tabSections(panel)[1]
|
||||
expect(efocas.fields[0]).toEqual({ label: 'IpAddr', value: '192.168.1.1', mono: true })
|
||||
})
|
||||
|
||||
it('is empty for a payload with no sections', () => {
|
||||
expect(tabSections({ render: 'tabs', _data: null })).toEqual([])
|
||||
})
|
||||
|
||||
it('drives panel visibility', () => {
|
||||
expect(panelVisible(panel)).toBe(true)
|
||||
expect(panelVisible({ render: 'tabs', _data: { sections: [] } })).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user