From 9b365ce8b5a94b762b2279e78f1e7fecc9bf341b Mon Sep 17 00:00:00 2001 From: Damon McCullough Date: Mon, 2 Dec 2024 12:02:28 -0500 Subject: [PATCH] compose and style data dictionary HTML --- .../package/generate_metadata_assets.py | 23 +++--- dcpy/lifecycle/package/resources/DCP_Logo.svg | 9 --- .../package/resources/data_dictionary.css | 22 ------ .../resources/data_dictionary_template.jinja | 69 ------------------ dcpy/lifecycle/package/resources/dcp_logo.png | Bin 0 -> 6859 bytes .../document_templates/attributes.jinja | 21 ++++++ .../document_templates/columns.jinja | 28 +++++++ .../document_templates/data_dictionary.jinja | 17 +++++ .../resources/document_templates/document.css | 12 +++ .../document_templates/paged_media.css | 12 +++ .../package/test_generate_data_dictionary.py | 1 + products/template/build_scripts/export.py | 2 +- pyproject.toml | 2 +- 13 files changed, 105 insertions(+), 113 deletions(-) delete mode 100644 dcpy/lifecycle/package/resources/DCP_Logo.svg delete mode 100644 dcpy/lifecycle/package/resources/data_dictionary.css delete mode 100644 dcpy/lifecycle/package/resources/data_dictionary_template.jinja create mode 100644 dcpy/lifecycle/package/resources/dcp_logo.png create mode 100644 dcpy/lifecycle/package/resources/document_templates/attributes.jinja create mode 100644 dcpy/lifecycle/package/resources/document_templates/columns.jinja create mode 100644 dcpy/lifecycle/package/resources/document_templates/data_dictionary.jinja create mode 100644 dcpy/lifecycle/package/resources/document_templates/document.css create mode 100644 dcpy/lifecycle/package/resources/document_templates/paged_media.css diff --git a/dcpy/lifecycle/package/generate_metadata_assets.py b/dcpy/lifecycle/package/generate_metadata_assets.py index b76dd5966..0093b6dd0 100644 --- a/dcpy/lifecycle/package/generate_metadata_assets.py +++ b/dcpy/lifecycle/package/generate_metadata_assets.py @@ -1,5 +1,5 @@ from pathlib import Path -from jinja2 import Template, Environment, FileSystemLoader +from jinja2 import Environment, FileSystemLoader import css_inline from bs4 import BeautifulSoup import subprocess @@ -9,9 +9,12 @@ from . import RESOURCES_PATH DEFAULT_DATA_DICTIONARY_TEMPLATE_PATH = ( - RESOURCES_PATH / "data_dictionary_template.jinja" + RESOURCES_PATH / "document_templates" / "data_dictionary.jinja" ) -DEFAULT_DATA_DICTIONARY_STYLESHEET_PATH = RESOURCES_PATH / "data_dictionary.css" +DEFAULT_DATA_DICTIONARY_STYLESHEET_PATH = ( + RESOURCES_PATH / "document_templates" / "document.css" +) +DEFAULT_PDF_STYLESHEET_PATH = RESOURCES_PATH / "document_templates" / "paged_media.css" def _format_html(html: str) -> str: @@ -48,10 +51,9 @@ def _style_html_document(html: str, stylesheet_path: Path) -> str: def generate_pdf_from_html( html_path: Path, output_path: Path, - stylesheet_path: Path, + stylesheet_path: Path = DEFAULT_PDF_STYLESHEET_PATH, ) -> Path: logger.info(f"Saving DCP PDF to {output_path}") - # TODO style HTML before converting to PDF subprocess.run( [ "weasyprint", @@ -69,17 +71,16 @@ def generate_html_from_yaml( metadata_path: Path, output_path: Path, html_template_path: Path, + stylesheet_path: Path, ) -> Path: - metadata = Metadata.from_path(metadata_path, template_vars={"var1": "value1"}) + metadata = Metadata.from_path(metadata_path) - # TODO use _render_html_template and _compose_html_document - with open(html_template_path, "r") as f: - template_text = f.read() - rendered_template = Template(template_text).render({"metadata": metadata}) + html = _render_html_template(html_template_path, {"metadata": metadata}) + styled_html = _style_html_document(html, stylesheet_path) output_path.parent.mkdir(parents=True, exist_ok=True) logger.info(f"Saving DCP HTML to {output_path}") with open(output_path, "w") as f: - f.write(rendered_template) + f.write(styled_html) return output_path diff --git a/dcpy/lifecycle/package/resources/DCP_Logo.svg b/dcpy/lifecycle/package/resources/DCP_Logo.svg deleted file mode 100644 index bab3856f5..000000000 --- a/dcpy/lifecycle/package/resources/DCP_Logo.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/dcpy/lifecycle/package/resources/data_dictionary.css b/dcpy/lifecycle/package/resources/data_dictionary.css deleted file mode 100644 index e3500423e..000000000 --- a/dcpy/lifecycle/package/resources/data_dictionary.css +++ /dev/null @@ -1,22 +0,0 @@ -html { - color: #393939; - font-family: Fira Sans; - font-size: 11pt; - font-weight: 300; - line-height: 1.5; -} -h1 { - string-set: top-right-text content(); -} -@page { - @top-left { - content: url("DCP_Logo.svg"); - } - @top-right { - content: string(top-right-text); - } - @bottom-right-corner { - content: counter(page); - text-align: center; - } -} diff --git a/dcpy/lifecycle/package/resources/data_dictionary_template.jinja b/dcpy/lifecycle/package/resources/data_dictionary_template.jinja deleted file mode 100644 index 29b752949..000000000 --- a/dcpy/lifecycle/package/resources/data_dictionary_template.jinja +++ /dev/null @@ -1,69 +0,0 @@ - - - - - {{ metadata.attributes.display_name }} - - - -

Data Dictionary

-

Description

-

{{ metadata.attributes.description }}

- -

Tags

- - -

Each row is a

-

{{ metadata.attributes.each_row_is_a }}

- -

Columns

- - - - - diff --git a/dcpy/lifecycle/package/resources/dcp_logo.png b/dcpy/lifecycle/package/resources/dcp_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4c2b3334fa39fe64f54b3d915f087ecab32947be GIT binary patch literal 6859 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 literal 0 HcmV?d00001 diff --git a/dcpy/lifecycle/package/resources/document_templates/attributes.jinja b/dcpy/lifecycle/package/resources/document_templates/attributes.jinja new file mode 100644 index 000000000..5cac709dd --- /dev/null +++ b/dcpy/lifecycle/package/resources/document_templates/attributes.jinja @@ -0,0 +1,21 @@ +
+ +

Attributes

+ +
+ +

+ Description: {{ metadata.attributes.description }} +

+ +

+ Each row is a: {{ metadata.attributes.each_row_is_a }} +

+ +

+ Tags: {{ metadata.attributes.tags|join(', ') }} +

+ +
+ +
\ No newline at end of file diff --git a/dcpy/lifecycle/package/resources/document_templates/columns.jinja b/dcpy/lifecycle/package/resources/document_templates/columns.jinja new file mode 100644 index 000000000..e2854c410 --- /dev/null +++ b/dcpy/lifecycle/package/resources/document_templates/columns.jinja @@ -0,0 +1,28 @@ +
+ +

Columns

+ + {% for column in metadata.columns %} +
+ +

{{ column.name }}

+ +

+ Description: {{ column.description }} +

+

+ Type: + {% if column.custom.readme_data_type %} + {{ column.custom.readme_data_type }} + {% else %} + {{ column.data_type }} + {% endif %} +

+

+ Source: {{ column.data_source }} +

+ +
+ {% endfor %} + +
\ No newline at end of file diff --git a/dcpy/lifecycle/package/resources/document_templates/data_dictionary.jinja b/dcpy/lifecycle/package/resources/document_templates/data_dictionary.jinja new file mode 100644 index 000000000..2f88225ad --- /dev/null +++ b/dcpy/lifecycle/package/resources/document_templates/data_dictionary.jinja @@ -0,0 +1,17 @@ + + + + + + {{ metadata.attributes.display_name }} Data Dictionary + + + +

{{ metadata.attributes.display_name }} - Data Dictionary

+ + {% include 'attributes.jinja' %} + + {% include 'columns.jinja' %} + + + \ No newline at end of file diff --git a/dcpy/lifecycle/package/resources/document_templates/document.css b/dcpy/lifecycle/package/resources/document_templates/document.css new file mode 100644 index 000000000..ac42af58f --- /dev/null +++ b/dcpy/lifecycle/package/resources/document_templates/document.css @@ -0,0 +1,12 @@ +html { + color: #393939; + font-family: Fira Sans; + font-size: 10pt; +} + +.field-name { + font-weight: bold; +} +.column-field { + text-indent: 1cm; +} diff --git a/dcpy/lifecycle/package/resources/document_templates/paged_media.css b/dcpy/lifecycle/package/resources/document_templates/paged_media.css new file mode 100644 index 000000000..31c69d363 --- /dev/null +++ b/dcpy/lifecycle/package/resources/document_templates/paged_media.css @@ -0,0 +1,12 @@ +@page { + @top-left { + content: url("../dcp_logo.png"); + } + @top-right { + content: string(top-right-text); + } + @bottom-right-corner { + content: counter(page); + text-align: center; + } +} diff --git a/dcpy/test/lifecycle/package/test_generate_data_dictionary.py b/dcpy/test/lifecycle/package/test_generate_data_dictionary.py index c2962878b..ea9fd66fa 100644 --- a/dcpy/test/lifecycle/package/test_generate_data_dictionary.py +++ b/dcpy/test/lifecycle/package/test_generate_data_dictionary.py @@ -77,6 +77,7 @@ def test_generate_pdf_from_yaml(self): metadata_path=self.yaml_path, output_path=self.html_path, html_template_path=generate_metadata_assets.DEFAULT_DATA_DICTIONARY_TEMPLATE_PATH, + stylesheet_path=generate_metadata_assets.DEFAULT_DATA_DICTIONARY_STYLESHEET_PATH, ) pdf_path = generate_metadata_assets.generate_pdf_from_html( html_path=html_path, diff --git a/products/template/build_scripts/export.py b/products/template/build_scripts/export.py index 93fcc354f..d41a88319 100644 --- a/products/template/build_scripts/export.py +++ b/products/template/build_scripts/export.py @@ -31,11 +31,11 @@ def generate_metadata(): dataset_metadata_yml, PRODUCT_PATH / "data_dictionary.html", generate_metadata_assets.DEFAULT_DATA_DICTIONARY_TEMPLATE_PATH, + generate_metadata_assets.DEFAULT_DATA_DICTIONARY_STYLESHEET_PATH, ) generate_metadata_assets.generate_pdf_from_html( html_path, PRODUCT_PATH / "data_dictionary.pdf", - generate_metadata_assets.DEFAULT_DATA_DICTIONARY_STYLESHEET_PATH, ) oti_xlsx.write_oti_xlsx( dataset=md.Metadata.from_path(dataset_metadata_yml).dataset, diff --git a/pyproject.toml b/pyproject.toml index 2d12a8039..ae65e3780 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -150,5 +150,5 @@ library = "dcpy.library.cli:run" [tool.setuptools.package-data] dcpy = [ "library/templates/*.yml", - "lifecycle/package/resources/*", + "lifecycle/package/resources/**", ]