Skip to content

Commit 5d68d77

Browse files
authored
Merge pull request #57 from peterbaumert/feature/layout-yaml-renderer
feat: add YAML layout system with CSS Grid renderer
2 parents 4a8dbe7 + 7dd30c3 commit 5d68d77

27 files changed

Lines changed: 3130 additions & 50 deletions

.devcontainer/docker-entrypoint-dev.sh

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ echo "Installing netbox-device-view in editable mode..."
55
uv pip install --python /opt/netbox/venv/bin/python3 --no-cache -e /opt/code/netbox-device-view
66
echo "Plugin installed."
77

8-
echo "Installing pre-commit hooks..."
9-
uv tool install pre-commit
10-
pre-commit install --git-dir /opt/code/netbox-device-view/.git --work-tree /opt/code/netbox-device-view
11-
echo "Pre-commit hooks installed."
12-
138
# Enable hot-reload in Granian (used by launch-netbox.sh via ${GRANIAN_EXTRA_ARGS[@]})
149
export GRANIAN_EXTRA_ARGS="--reload"
1510

README.md

Lines changed: 86 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ PLUGINS_CONFIG = {
5959

6060
## How It Works
6161

62-
For each **Device Type** you create a **DeviceView** object (at *Plugins → Device Views → Add*) containing a CSS `grid-template-areas` definition. When you visit a device of that type, the plugin renders every interface and port as a clickable cell in the grid.
62+
For each **Device Type** you create a **DeviceView** object (at *Plugins → Device Views → Add*) with either a **YAML layout** or a raw **CSS layout**. When you visit a device of that type, the plugin renders every interface and port as a clickable cell in the grid.
6363

6464
### Port/Interface name → CSS grid-area name
6565

66-
The plugin derives a `stylename` for each interface and port, which must match the area names in your CSS:
66+
The plugin derives a `stylename` for each interface and port:
6767

6868
| Interface name | Stylename |
6969
|----------------|-----------|
@@ -82,54 +82,105 @@ The plugin derives a `stylename` for each interface and port, which must match t
8282
- Purely numeric stylenames are prefixed with `p`
8383
- Virtual and LAG interfaces are skipped
8484

85-
### CSS layout format
85+
---
86+
87+
## Layout formats
88+
89+
A DeviceView supports two layout formats. **YAML is preferred** — it is easier to write, validate, and maintain. Legacy CSS is still fully supported for backward compatibility.
90+
91+
### YAML layout (recommended)
92+
93+
Fill the **YAML Layout** field with a YAML document describing the device layout. The plugin compiles it to CSS at render time.
94+
95+
Example for a Cisco C9300-24T with an optional 8x 10G expansion module:
96+
97+
```yaml
98+
version: 1
99+
100+
meta:
101+
description: "Cisco Catalyst 9300-24T"
102+
103+
canvas:
104+
columns: 32
105+
rows: 2
106+
107+
views:
108+
front:
109+
rows:
110+
- blank: 14
111+
- group:
112+
spacer: 1
113+
sections:
114+
- sequence:
115+
kind: interface
116+
prefix: "gigabitethernet0-"
117+
start: 1
118+
count: 12
119+
pattern: top-odd
120+
- sequence:
121+
kind: interface
122+
prefix: "gigabitethernet0-"
123+
start: 13
124+
count: 12
125+
pattern: top-odd
126+
- spacer: 4
127+
128+
variants:
129+
C9300-NM-8X:
130+
match: module
131+
rows:
132+
- blank: 14
133+
- group:
134+
spacer: 1
135+
sections:
136+
- sequence:
137+
kind: interface
138+
prefix: "gigabitethernet0-"
139+
start: 1
140+
count: 12
141+
pattern: top-odd
142+
- sequence:
143+
kind: interface
144+
prefix: "gigabitethernet0-"
145+
start: 13
146+
count: 12
147+
pattern: top-odd
148+
- sequence:
149+
kind: interface
150+
prefix: "tengigabitethernet1-"
151+
start: 1
152+
count: 8
153+
pattern: top-odd
154+
```
155+
156+
See [`docs/yaml-layout-schema.md`](docs/yaml-layout-schema.md) for the full schema reference and [`examples/yaml/`](examples/yaml/) for ready-made YAML files.
86157

87-
The `grid_template_area` field stores raw CSS. The grid has **32 columns** and uses **20 px cells**.
158+
### CSS layout (legacy)
88159

89-
Placeholder names:
90-
- `x` — leading empty cell
91-
- `z` — trailing empty cell
92-
- `s0``s99` — interior spacer cells
160+
Fill the **Grid Template Area** field with raw CSS. The grid has **32 columns** and uses **20 px cells**.
93161

94-
Example for a Cisco C9300-24T with an optional 8x 10G module (more in the [`examples/`](examples/) folder):
162+
Placeholder names: `x` — leading blank, `z` — trailing blank, `s0`–`s99` — interior spacers.
95163

96164
```css
97165
/* C9300-24T */
98166
.deviceview.area {
99-
grid-template-areas:
100-
"x x x x x x x x x x x x x x gigabitethernet0-1 gigabitethernet0-3 gigabitethernet0-5 gigabitethernet0-7 gigabitethernet0-9 gigabitethernet0-11 s0 gigabitethernet0-13 gigabitethernet0-15 gigabitethernet0-17 gigabitethernet0-19 gigabitethernet0-21 gigabitethernet0-23 z z z z z"
101-
"x x x x x x x x x x x x x x gigabitethernet0-2 gigabitethernet0-4 gigabitethernet0-6 gigabitethernet0-8 gigabitethernet0-10 gigabitethernet0-12 s0 gigabitethernet0-14 gigabitethernet0-16 gigabitethernet0-18 gigabitethernet0-20 gigabitethernet0-22 gigabitethernet0-24 z z z z z";
102-
}
103-
104-
/* C9300-24T with C9300-NM-8X */
105-
.deviceview.moduleC9300-NM-8X.area {
106-
grid-template-areas:
107-
"x x x x x x x x x x x x x x gigabitethernet0-1 gigabitethernet0-3 gigabitethernet0-5 gigabitethernet0-7 gigabitethernet0-9 gigabitethernet0-11 s0 gigabitethernet0-13 gigabitethernet0-15 gigabitethernet0-17 gigabitethernet0-19 gigabitethernet0-21 gigabitethernet0-23 s1 tengigabitethernet1-1 tengigabitethernet1-3 tengigabitethernet1-5 tengigabitethernet1-7"
108-
"x x x x x x x x x x x x x x gigabitethernet0-2 gigabitethernet0-4 gigabitethernet0-6 gigabitethernet0-8 gigabitethernet0-10 gigabitethernet0-12 s0 gigabitethernet0-14 gigabitethernet0-16 gigabitethernet0-18 gigabitethernet0-20 gigabitethernet0-22 gigabitethernet0-24 s1 tengigabitethernet1-2 tengigabitethernet1-4 tengigabitethernet1-6 tengigabitethernet1-8";
167+
grid-template-areas:
168+
"x x x x x x x x x x x x x x gigabitethernet0-1 gigabitethernet0-3 ... z z z z z"
169+
"x x x x x x x x x x x x x x gigabitethernet0-2 gigabitethernet0-4 ... z z z z z";
109170
}
110171
```
111172

112-
### Module variants
113-
114-
If a device has an installed module, an additional CSS class matching the module model is added. Define a separate rule to override the layout when that module is present (see the example above).
173+
See [`examples/`](examples/) for ready-made CSS files.
115174

116-
### Virtual Chassis
175+
> **Precedence:** if a DeviceView has a YAML layout, it is used and the CSS field is ignored.
117176

118-
For virtual chassis devices, each member's CSS areas are scoped with a `.d{vc_position}` suffix automatically. Define per-member layouts using those suffixes:
177+
### Module variants
119178

120-
```css
121-
/* Member at vc_position 1 */
122-
.deviceview.area.d1 {
123-
grid-template-areas: "gigabitethernet0-1 gigabitethernet0-2";
124-
}
179+
When a device has an installed module, an extra CSS class matching the module model is added to the device div. In YAML, declare a `variants:` block. In CSS, add a `.deviceview.module{ModelName}.area` rule.
125180

126-
/* Member at vc_position 2 */
127-
.deviceview.area.d2 {
128-
grid-template-areas: "gigabitethernet0-1 gigabitethernet0-2";
129-
}
130-
```
181+
### Virtual Chassis
131182

132-
More ready-made layouts for Cisco C2960X, C8300, C9200, C9300, generic patch panels, and Ubiquiti switches are in the [`examples/`](examples/) folder.
183+
For virtual chassis devices, each member's CSS areas are scoped with a `.d{vc_position}` suffix automatically. YAML-rendered CSS is scoped the same way.
133184

134185
## Troubleshooting
135186

0 commit comments

Comments
 (0)