mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Brand the export header band and freeze the header row 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
000ebf82be
commit
8f24187d03
2 changed files with 47 additions and 0 deletions
27
infrastructure/xlsx/branding.py
Normal file
27
infrastructure/xlsx/branding.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
"""Monday.com-style branding for the Scenario Export workbook (ADR-0065).
|
||||
|
||||
A programmatic openpyxl styling pass (no template): a bold indigo header band
|
||||
with white text, a frozen header row, subtle alternating row bands, and roomy
|
||||
column widths. The palette lives here as the single home for brand colour — the
|
||||
"no brand-colour constants anywhere" gap the review flagged.
|
||||
|
||||
TODO(brand): swap the placeholder Monday-style hex for the real Domna brand
|
||||
palette once design supplies it.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from openpyxl.worksheet.worksheet import Worksheet
|
||||
|
||||
# openpyxl colours are 8-char ARGB. Placeholder Monday-style palette.
|
||||
HEADER_FILL: str = "FF6C6CFF" # indigo header band
|
||||
HEADER_FONT: str = "FFFFFFFF" # white header text
|
||||
ROW_BAND_FILL: str = "FFF1F1FF" # subtle alternating-row tint
|
||||
|
||||
_COLUMN_WIDTH: int = 18
|
||||
|
||||
|
||||
def style_sheet(worksheet: Worksheet) -> None:
|
||||
"""Paint the Monday-style branding onto a populated worksheet: header band +
|
||||
font, frozen header row, banded rows, and column widths."""
|
||||
raise NotImplementedError
|
||||
|
|
@ -8,6 +8,7 @@ from io import BytesIO
|
|||
from openpyxl import load_workbook
|
||||
|
||||
from domain.scenario_export.scenario_sheet import ExportSheet
|
||||
from infrastructure.xlsx.branding import HEADER_FILL
|
||||
from infrastructure.xlsx.scenario_export_workbook import render_workbook
|
||||
|
||||
|
||||
|
|
@ -48,3 +49,22 @@ def test_sanitises_and_deduplicates_scenario_sheet_names() -> None:
|
|||
assert len(set(names)) == 3
|
||||
assert all(len(name) <= 31 for name in names)
|
||||
assert not any(ch in name for name in names for ch in r":/\?*[]")
|
||||
|
||||
|
||||
def test_brands_the_header_row_and_freezes_it() -> None:
|
||||
# arrange
|
||||
sheet = ExportSheet(
|
||||
columns=("property_id", "loft_insulation"),
|
||||
rows=({"property_id": 1, "loft_insulation": 1200.0},),
|
||||
)
|
||||
|
||||
# act
|
||||
data = render_workbook([("Fabric first", sheet)])
|
||||
|
||||
# assert — the header is a bold, brand-filled band and the header row is
|
||||
# frozen so it stays visible while scrolling.
|
||||
worksheet = load_workbook(BytesIO(data))["Fabric first"]
|
||||
header_cell = worksheet["A1"]
|
||||
assert header_cell.font.bold is True
|
||||
assert header_cell.fill.fgColor.rgb == HEADER_FILL
|
||||
assert worksheet.freeze_panes == "A2"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue