mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-18 20:29:44 -05:00
2ed3bd6a88
Add multi-select with Shift/Ctrl toggles and marquee selection on the invoice and quote PDF template editors, plus a shared transformer, group nudge with snap-aware arrow keys, multi copy/paste/duplicate, align-to-page or align-to-selection, horizontal/vertical distribute, and Ctrl/Cmd+G group / Ctrl/Cmd+Shift+G ungroup. Expose horizontal (left/center/right/justify) and vertical (top/middle/bottom) text controls in the properties panel; export verticalAlign, group_id, locked, and hidden in template JSON where set. Skip hidden elements in ReportLab rendering; draw justified text on canvas via Paragraph; honor verticalAlign when a text box height is present. Introduce app/static/js/pdf_editor helpers (loaded with dynamic import from the templates), pdf_editor.css, a layers panel with visibility and lock toggles, smart-guide snapping, and optional ruler chrome. Document behaviour and manual QA in docs/PDF_LAYOUT_EDITOR.md; add tests/test_pdf_template_schema.py for optional template fields. Closes #619.
52 lines
1.4 KiB
Python
52 lines
1.4 KiB
Python
"""Tests for optional PDF template JSON fields (issue #619 extensions)."""
|
|
|
|
from app.utils.pdf_template_schema import validate_template_json
|
|
|
|
|
|
def _minimal_template(**element):
|
|
return {
|
|
"page": {"size": "A4", "margin": {"top": 20, "right": 20, "bottom": 20, "left": 20}},
|
|
"elements": [
|
|
{
|
|
"type": "text",
|
|
"x": 10,
|
|
"y": 10,
|
|
"text": "Hello",
|
|
"width": 100,
|
|
"style": {"font": "Helvetica", "size": 10, "color": "#000", "align": "left"},
|
|
**element,
|
|
}
|
|
],
|
|
}
|
|
|
|
|
|
def test_validate_accepts_text_style_vertical_align():
|
|
t = _minimal_template()
|
|
t["elements"][0]["style"]["verticalAlign"] = "middle"
|
|
ok, err = validate_template_json(t)
|
|
assert ok, err
|
|
|
|
|
|
def test_validate_accepts_optional_metadata_on_text():
|
|
t = _minimal_template(
|
|
group_id="g-1",
|
|
locked=True,
|
|
hidden=False,
|
|
)
|
|
ok, err = validate_template_json(t)
|
|
assert ok, err
|
|
|
|
|
|
def test_validate_accepts_justify_align():
|
|
t = _minimal_template()
|
|
t["elements"][0]["style"]["align"] = "justify"
|
|
ok, err = validate_template_json(t)
|
|
assert ok, err
|
|
|
|
|
|
def test_validate_rejects_bad_page_size():
|
|
t = _minimal_template()
|
|
t["page"]["size"] = "BadSize"
|
|
ok, err = validate_template_json(t)
|
|
assert not ok
|