Skip to content

Commit

Permalink
merge: Deal with hlink:// URLs
Browse files Browse the repository at this point in the history
  • Loading branch information
Wuestengecko committed Apr 11, 2024
2 parents b384463 + 7c418f5 commit 6f4bef2
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 7 deletions.
34 changes: 33 additions & 1 deletion capella_model_explorer/backend/explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# SPDX-License-Identifier: Apache-2.0

import dataclasses
import logging
import operator
import os
import pathlib
Expand All @@ -10,6 +11,7 @@
from pathlib import Path

import capellambse
import markupsafe
import yaml
from fastapi import APIRouter, FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
Expand All @@ -20,6 +22,7 @@

PATH_TO_FRONTEND = Path("./frontend/dist")
ROUTE_PREFIX = os.getenv("ROUTE_PREFIX", "")
LOGGER = logging.getLogger(__name__)


@dataclasses.dataclass
Expand All @@ -44,13 +47,34 @@ def __post_init__(self):
allow_headers=["*"],
)
self.env = Environment()
self.env.finalize = self.__finalize
self.env.filters["make_href"] = self.__make_href
self.grouped_templates, self.templates = index_templates(
self.templates_path
)
self.app.state.templates = Jinja2Templates(directory=PATH_TO_FRONTEND)
self.configure_routes()
self.app.include_router(self.router)

def __finalize(self, markup: t.Any) -> object:
markup = markupsafe.escape(markup)
return capellambse.helpers.replace_hlinks(
markup, self.model, self.__make_href
)

def __make_href(self, obj: capellambse.model.GenericElement) -> str | None:
if isinstance(obj, capellambse.model.ElementList):
raise TypeError("Cannot make an href to a list of elements")
if not isinstance(obj, capellambse.model.GenericElement):
raise TypeError(f"Expected a model object, got {obj!r}")

for idx, template in self.templates.items():
clsname = template.get("variable", {}).get("type")
if obj.__class__.__name__ == clsname:
return f"/{idx}/{obj.uuid}"

return f"/__generic__/{obj.uuid}"

def render_instance_page(self, template_text, object=None):
try:
# render the template with the object
Expand Down Expand Up @@ -122,6 +146,9 @@ def read_template(template_name: str):
{"idx": obj.uuid, "name": obj.name} for obj in objects
]
except Exception as e:
LOGGER.exception(
"Error finding objects for template %s", template_name
)
base["objects"] = []
base["error"] = str(e)
return base
Expand Down Expand Up @@ -203,8 +230,13 @@ def find_objects(model, obj_type=None, below=None, attr=None, filters=None):
if attr:
getter = operator.attrgetter(attr)
objects = getter(model)
if objects and not isinstance(objects, list):
if hasattr(objects, "_element"):
objects = [objects]
elif not isinstance(objects, capellambse.model.ElementList):
raise ValueError(
f"Expected a list of model objects or a single model object"
f" for {attr!r} of the model, got {objects!r}"
)
elif below and obj_type:
getter = operator.attrgetter(below)
objects = model.search(obj_type, below=getter(model))
Expand Down
20 changes: 20 additions & 0 deletions templates/__generic__.html.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{#
Copyright DB InfraGO AG and contributors
SPDX-License-Identifier: Apache-2.0
#}
{% if object.name %}
<h1>{{ object.name }} <span style="font-size: 60%">({{ object.__class__.__name__ }})</span></h1>
{% else %}
<h1>Unnamed {{ object.__class__.__name__ }})</small></h1>
{% endif %}
{%- for attr in object.__dir__()|sort if not attr.startswith("_") and attr not in ("from_model", "pvmt") -%}
{%- set value = object[attr] -%}
<h2 style="opacity: 0.8; border-top: 1px solid grey; margin-top: 1rem; padding-left: 1rem; font: 1rem monospace">{{ attr }}</h2>
{%- if value.as_svg -%}
{{ value.as_svg|safe }}
{% elif value._short_html_ -%}
<p>{{ value._short_html_() }}</p>
{% else -%}
<p>{{ value }}</p>
{% endif -%}
{% endfor -%}
10 changes: 10 additions & 0 deletions templates/__generic__.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

idx: __generic__
template: __generic__.html.j2
name: Generic object display
description: Generic built-in template that shows all available information about a given object.
category: other
variable:
name: object
2 changes: 1 addition & 1 deletion templates/classes.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<td>{{ property.name }}</td>
<td>
{% if property.type.__class__ == object.__class__ %}
<a href="/classes/{{ property.type.uuid }}">{{ property.type.name }}</a>
<a href="{{ property.type | make_href }}">{{ property.type.name }}</a>
{% else %}
{{ property.type.name }}
{% endif %}
Expand Down
4 changes: 2 additions & 2 deletions templates/diagrams.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#}

<h1>{{ object.name }}</h1>
{{ object.as_svg }}
{{ object.as_svg | safe }}

<h2>Description</h2>
{% if object.description %}
Expand All @@ -18,7 +18,7 @@
<ul>
{% for node in object.nodes %}
{% if node.name %}
<li><a href="#{{ node.uuid }}">{{ node.name }}</a></li>
<li><a href="{{ node | make_href }}">{{ node.name }}</a></li>
{% endif %}
{% endfor %}
</ul>
Expand Down
2 changes: 1 addition & 1 deletion templates/system-capability.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
<ul>
{% for fnc in object.involved_functions %}
{% if fnc.owner == entity %}
<li><a href="/system_function/{{ fnc.uuid }}">{{ fnc.name }}</a></li>
<li><a href="{{ fnc | make_href }}">{{ fnc.name }}</a></li>
{% endif %}
{% endfor %}
</ul>
Expand Down
4 changes: 2 additions & 2 deletions templates/system_function.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<h2>Function owner</h2>
{% if object.owner %}
<p>An Entity that is responsible for providing this function: <b>{{object.owner.name}}</b>.</p>
<p>An Entity that is responsible for providing this function: <b><a href="{{ object.owner | make_href }}">{{object.owner.name}}</a></b>.</p>
{% else %}
<p>This function is not allocated to any entity / no entity is responsible for it.</p>
{% endif %}
Expand All @@ -23,7 +23,7 @@
<p>The function is available in the following Entity states:</p>
<ul>
{% for state in object.available_in_states %}
<li>{{ state.name }}</li>
<li><a href="{{ state | make_href }}">{{ state.name }}</a></li>
{% endfor %}
</ul>
{% else %}
Expand Down

0 comments on commit 6f4bef2

Please sign in to comment.