Skip to content

Commit

Permalink
Merge pull request #14 from oarepo/miroslavsimek/be-263-generate-init…
Browse files Browse the repository at this point in the history
…ial-layout-macros

Generating initial detail page
  • Loading branch information
mirekys authored May 13, 2024
2 parents 5e7bfd2 + 3623598 commit 1b6cf65
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 2 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies = [
"wheel",
"click",
"aenum",
"pydash",

# config loading/writing
"PyYAML",
Expand Down
15 changes: 15 additions & 0 deletions src/nrp_devtools/commands/ui/create.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
from pathlib import Path

import caseconverter
Expand All @@ -6,6 +7,9 @@
from nrp_devtools.commands.utils import capitalize_name, run_cookiecutter
from nrp_devtools.config import OARepoConfig

from .create_detail import create_detail_page
from nrp_devtools.config.model_config import ModelConfig


def create_page_ui(config: OARepoConfig, *, ui_name: str):
ui_config = config.get_ui(ui_name)
Expand Down Expand Up @@ -50,6 +54,9 @@ def create_model_ui(config: OARepoConfig, *, ui_name: str):
capitalized_name = caseconverter.camelcase(ui_config.name)
capitalized_name = capitalized_name[0].upper() + capitalized_name[1:]

model_name = ui_config.model
prefix = model_name.capitalize()

run_cookiecutter(
config.ui_dir,
template=Path(__file__).parent.parent.parent / "templates" / "ui_model",
Expand All @@ -61,9 +68,17 @@ def create_model_ui(config: OARepoConfig, *, ui_name: str):
"resource_config": capitalized_name + "ResourceConfig",
"ui_serializer_class": ui_config.ui_serializer_class,
"api_service": ui_config.api_service,
"root_component": prefix + "DetailRoot",
},
)

model_config: ModelConfig = config.get_model(model_name)

ui_file = config.repository_dir / model_config.model_package / 'models' / 'ui.json'
ui_components_dir = config.ui_dir / ui_config.name / 'templates' / 'semantic-ui' / 'components'
ui_components_dir.mkdir(parents=True, exist_ok=True)
create_detail_page(ui_file, ui_components_dir, prefix)


def register_model_ui(config: OARepoConfig, *, ui_name: str):
ui_config = config.get_ui(ui_name)
Expand Down
137 changes: 137 additions & 0 deletions src/nrp_devtools/commands/ui/create_detail.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import json
from pathlib import Path
import pydash


def create_detail_page(ui_file, target_dir: Path, prefix):
prefix = prefix.capitalize()
ui_data = json.loads(Path(ui_file).read_text())
if 'metadata' in ui_data['children']:
in_metadata = True
root = ui_data['children']['metadata']
else:
in_metadata = False
root = ui_data
generate_jinjax_root_component(root, in_metadata, target_dir, prefix)

def generate_jinjax_root_component(root, in_metadata, target_dir: Path, prefix):
output = [
"{# def d #}",
]
if in_metadata:
output.append("{% set md=d.metadata %}")
else:
output.append("{% set md=d %}")
output.append("")

add_depth(root)
primitive, complex = pydash.partition(root['children'].items(), lambda x: x[1]['depth'] == 0)
output.append("<table class='ui compact definition table'>")
for key, value in primitive:
if not is_array(value):
output.append(" <ITableField d={md.%s} />" % key)
else:
output.append(" <ITableField d={md.%s} >" % key)
output.append(" <ITableArrayValue d={md.%s} />" % key)
output.append(" </ITableField>")

# complex values will be rendered as an ISection component
for key, value in complex:

component_name, generate = jinja_component_name(prefix, value)
if not component_name:
continue
if generate:
generate_jinjax_component(value if not is_array(value) else value['child'],
target_dir, component_name, prefix)

if not is_array(value):
output.append(" <ITableSection d={md.%s} >" % key)
output.append(" <%s d={md.%s} />" % (component_name, key))
output.append(" </ITableSection>")
else:
output.append(" {%% for item in array(md.%s) %%}" % key)
output.append(" <ITableSection d={item} >")
output.append(" <%s d={item} />" % component_name)
output.append(" </ITableSection>")
output.append(" {% endfor %}")

output.append("</table>")
(target_dir / f'{prefix}DetailRoot.jinja').write_text('\n'.join(output))


def generate_jinjax_component(data, target_dir: Path, name, prefix):
output = [
"{# def d, level=0 #}",
""
]

primitive, complex = pydash.partition(data['children'].items(), lambda x: x[1]['depth'] == 0)

for key, value in primitive:
if not is_array(value):
output.append("<ITableField d={md.%s} level={level}/>" % key)
else:
output.append("<ITableField d={md.%s} level={level}" % key)
output.append(" <ITableArrayValue d={md.%s} />" % key)
output.append("</ITableField>")

# complex values will be rendered as indented components
for key, value in complex:
component_name, generate = jinja_component_name(prefix, value)
if not component_name:
continue
if generate:
generate_jinjax_component(value if not is_array(value) else value['child'],
target_dir, component_name, prefix)
output.append("<%s d={md.%s} level={level+1}/>" % (component_name, key))

(target_dir / f'{name}.jinja').write_text('\n'.join(output))


def is_array(data):
return 'child' in data


def jinja_component_name(prefix, data):
detail = data['detail']

if detail is False:
return None, False

if detail == 'taxonomy_item':
return 'ITaxonomyItem', False

if detail == 'vocabulary_item':
return 'IVocabularyItem', False

if detail == "array":
data = data['child']
return jinja_component_name(prefix, data)

return prefix + ''.join([x.capitalize() for x in detail.split('_')]), True


def add_depth(data):
data['depth'] = 0
if 'children' in data:
for key, value in data['children'].items():
add_depth(value)
data['depth'] = max(data['depth'], value['depth'] + 1)
if 'child' in data:
add_depth(data['child'])
data['depth'] = max(data['depth'], data['child']['depth'])


if __name__ == '__main__':
import click
@click.command()
@click.argument('ui_file')
@click.argument('output_dir')
@click.argument('prefix')
def main(ui_file, output_dir, prefix):
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
create_detail_page(ui_file, output_dir, prefix)

main()
3 changes: 2 additions & 1 deletion src/nrp_devtools/templates/ui_model/cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"resource": "",
"resource_config": "",
"ui_serializer_class": "",
"api_service": ""
"api_service": "",
"root_component": ""
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{%- endblock %}

{% block record_main_content %}
Add your main content here
<{% endraw %}{{root_component}}{% raw %} d={d}>
{% endblock %}

{% block record_sidebar %}
Expand Down

0 comments on commit 1b6cf65

Please sign in to comment.