Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 44 additions & 23 deletions dsf-bpe/dsf-bpe-server/src/main/resources/bpe/static/dsf.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,51 +37,72 @@ body {
background-color: var(--color-background);
}

table#header {
margin-bottom: 0.4em;
#header {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: auto auto;
margin-bottom: 1em;
}

table#header img {
height: 7em;
padding-bottom: 0.38em;
display: block;
#logo {
grid-row: 1 / span 2;
margin-bottom: 0.41em;
}

td#heading {
vertical-align: bottom;
#icons {
grid-column: 2;
grid-row: 1;
display: flex;
column-gap: 0.25em;
justify-self: right;
}

td#heading h1 {
#heading {
grid-column: 2;
grid-row: 2;
font-size: 2em;
font-family: monospace;
color: var(--color-prime);
align-self: end;
margin: 0 0 0 1em;
word-break: break-word;
}

td#heading h1 a {
white-space: nowrap;
@media ( max-width: 64rem) {
#header {
grid-template-columns: 1fr;
grid-template-rows: auto auto auto;
height: auto;
}
#icons {
grid-column: 1;
grid-row: 1;
margin: 0 0 1em 0;
}
#logo {
grid-column: 1;
grid-row: 2;
margin: 0;
height: 14vw;
}
#heading {
grid-column: 1;
grid-row: 3;
margin: 1em 0 0 0;
}
}

td#heading h1 a:link,
td#heading h1 a:visited,
td#heading h1 a:active {
#heading a:link,
#heading a:visited,
#heading a:active {
color: var(--color-prime);
text-decoration: none;
}

td#heading h1 a:hover {
#heading a:hover {
text-decoration: underline;
}

#icons {
position: absolute;
top: 2em;
right: 2em;
display: flex;
column-gap: 0.25em;
}

#hello-user {
margin-right: 0.5em;
color: #aaa;
Expand Down
28 changes: 13 additions & 15 deletions dsf-bpe/dsf-bpe-server/src/main/resources/bpe/template/main.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:attr="theme=${theme}">
<html xmlns:th="http://www.thymeleaf.org" th:attr="theme=${theme}" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#326F95">
<base th:href="(${basePath} + '/')" href="/">
<link rel="icon" type="image/svg+xml" href="static/favicon.svg">
<link rel="icon" type="image/png" href="static/favicon_32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="static/favicon_96x96.png" sizes="96x96">
<meta name="theme-color" content="#326F95">
<script src="static/main.js"></script>
<script src="static/bpmn-viewer-prod.js" th:if="${bpmnViewer}" th:src="${bpmnProd ? 'static/bpmn-viewer-prod.js' : 'static/bpmn-viewer-dev.js'}"></script>
<script src="static/bpmn.js" th:if="${bpmnViewer}"></script>
Expand All @@ -15,20 +17,16 @@
<title th:text="${title}">DSF</title>
</head>
<body>
<div id="icons">
<span id="hello-user" th:if="${username}">Hello, [[${username}]]</span><a href="logout" th:if="${openid}"><svg class="icon" id="logout-icon" viewBox="0 0 24 24"><title>Logout</title><path d="M5 21q-.825 0-1.413-.587Q3 19.825 3 19V5q0-.825.587-1.413Q4.175 3 5 3h7v2H5v14h7v2Zm11-4-1.375-1.45 2.55-2.55H9v-2h8.175l-2.55-2.55L16 7l5 5Z" /></svg></a>
<svg class="icon" id="light-mode" height="24" viewBox="0 -960 960 960" width="24"><title>Enable Light Mode</title><path d="M479.765-340Q538-340 579-380.765q41-40.764 41-99Q620-538 579.235-579q-40.764-41-99-41Q422-620 381-579.235q-41 40.764-41 99Q340-422 380.765-381q40.764 41 99 41Zm.235 60q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM70-450q-12.75 0-21.375-8.675Q40-467.351 40-480.175 40-493 48.625-501.5T70-510h100q12.75 0 21.375 8.675 8.625 8.676 8.625 21.5 0 12.825-8.625 21.325T170-450H70Zm720 0q-12.75 0-21.375-8.675-8.625-8.676-8.625-21.5 0-12.825 8.625-21.325T790-510h100q12.75 0 21.375 8.675 8.625 8.676 8.625 21.5 0 12.825-8.625 21.325T890-450H790ZM479.825-760Q467-760 458.5-768.625T450-790v-100q0-12.75 8.675-21.375 8.676-8.625 21.5-8.625 12.825 0 21.325 8.625T510-890v100q0 12.75-8.675 21.375-8.676 8.625-21.5 8.625Zm0 720Q467-40 458.5-48.625T450-70v-100q0-12.75 8.675-21.375 8.676-8.625 21.5-8.625 12.825 0 21.325 8.625T510-170v100q0 12.75-8.675 21.375Q492.649-40 479.825-40ZM240-678l-57-56q-9-9-8.629-21.603.37-12.604 8.526-21.5 8.896-8.897 21.5-8.897Q217-786 226-777l56 57q8 9 8 21t-8 20.5q-8 8.5-20.5 8.5t-21.5-8Zm494 495-56-57q-8-9-8-21.375T678.5-282q8.5-9 20.5-9t21 9l57 56q9 9 8.629 21.603-.37 12.604-8.526 21.5-8.896 8.897-21.5 8.897Q743-174 734-183Zm-56-495q-9-9-9-21t9-21l56-57q9-9 21.603-8.629 12.604.37 21.5 8.526 8.897 8.896 8.897 21.5Q786-743 777-734l-57 56q-8 8-20.364 8-12.363 0-21.636-8ZM182.897-182.897q-8.897-8.896-8.897-21.5Q174-217 183-226l57-56q8.8-9 20.9-9 12.1 0 20.709 9Q291-273 291-261t-9 21l-56 57q-9 9-21.603 8.629-12.604-.37-21.5-8.526ZM480-480Z" /></svg>
<svg class="icon" id="dark-mode" height="24" viewBox="0 -960 960 960" width="24"><title>Enable Dark Mode</title><path d="M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q8 0 17 .5t23 1.5q-36 32-56 79t-20 99q0 90 63 153t153 63q52 0 99-18.5t79-51.5q1 12 1.5 19.5t.5 14.5q0 150-105 255T480-120Zm0-60q109 0 190-67.5T771-406q-25 11-53.667 16.5Q688.667-384 660-384q-114.689 0-195.345-80.655Q384-545.311 384-660q0-24 5-51.5t18-62.5q-98 27-162.5 109.5T180-480q0 125 87.5 212.5T480-180Zm-4-297Z" /></svg>
<a href="" download="" id="download-link" title="" th:if="${download}" th:href="${download.href}" th:title="${download.title}" th:attr="download = ${download.filename}"><svg class="icon" id="download" viewBox="0 0 24 24"><path d="M18,15v3H6v-3H4v3c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-3H18z M17,11l-1.41-1.41L13,12.17V4h-2v8.17L8.41,9.59L7,11l5,5 L17,11z" /></svg></a>
<div id="header">
<div id="icons">
<span id="hello-user" th:if="${username}">Hello, [[${username}]]</span><a href="logout" th:if="${openid}"><svg class="icon" id="logout-icon" viewBox="0 0 24 24"><title>Logout</title><path d="M5 21q-.825 0-1.413-.587Q3 19.825 3 19V5q0-.825.587-1.413Q4.175 3 5 3h7v2H5v14h7v2Zm11-4-1.375-1.45 2.55-2.55H9v-2h8.175l-2.55-2.55L16 7l5 5Z" /></svg></a>
<svg class="icon" id="light-mode" height="24" viewBox="0 -960 960 960" width="24"><title>Enable Light Mode</title><path d="M479.765-340Q538-340 579-380.765q41-40.764 41-99Q620-538 579.235-579q-40.764-41-99-41Q422-620 381-579.235q-41 40.764-41 99Q340-422 380.765-381q40.764 41 99 41Zm.235 60q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM70-450q-12.75 0-21.375-8.675Q40-467.351 40-480.175 40-493 48.625-501.5T70-510h100q12.75 0 21.375 8.675 8.625 8.676 8.625 21.5 0 12.825-8.625 21.325T170-450H70Zm720 0q-12.75 0-21.375-8.675-8.625-8.676-8.625-21.5 0-12.825 8.625-21.325T790-510h100q12.75 0 21.375 8.675 8.625 8.676 8.625 21.5 0 12.825-8.625 21.325T890-450H790ZM479.825-760Q467-760 458.5-768.625T450-790v-100q0-12.75 8.675-21.375 8.676-8.625 21.5-8.625 12.825 0 21.325 8.625T510-890v100q0 12.75-8.675 21.375-8.676 8.625-21.5 8.625Zm0 720Q467-40 458.5-48.625T450-70v-100q0-12.75 8.675-21.375 8.676-8.625 21.5-8.625 12.825 0 21.325 8.625T510-170v100q0 12.75-8.675 21.375Q492.649-40 479.825-40ZM240-678l-57-56q-9-9-8.629-21.603.37-12.604 8.526-21.5 8.896-8.897 21.5-8.897Q217-786 226-777l56 57q8 9 8 21t-8 20.5q-8 8.5-20.5 8.5t-21.5-8Zm494 495-56-57q-8-9-8-21.375T678.5-282q8.5-9 20.5-9t21 9l57 56q9 9 8.629 21.603-.37 12.604-8.526 21.5-8.896 8.897-21.5 8.897Q743-174 734-183Zm-56-495q-9-9-9-21t9-21l56-57q9-9 21.603-8.629 12.604.37 21.5 8.526 8.897 8.896 8.897 21.5Q786-743 777-734l-57 56q-8 8-20.364 8-12.363 0-21.636-8ZM182.897-182.897q-8.897-8.896-8.897-21.5Q174-217 183-226l57-56q8.8-9 20.9-9 12.1 0 20.709 9Q291-273 291-261t-9 21l-56 57q-9 9-21.603 8.629-12.604-.37-21.5-8.526ZM480-480Z" /></svg>
<svg class="icon" id="dark-mode" height="24" viewBox="0 -960 960 960" width="24"><title>Enable Dark Mode</title><path d="M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q8 0 17 .5t23 1.5q-36 32-56 79t-20 99q0 90 63 153t153 63q52 0 99-18.5t79-51.5q1 12 1.5 19.5t.5 14.5q0 150-105 255T480-120Zm0-60q109 0 190-67.5T771-406q-25 11-53.667 16.5Q688.667-384 660-384q-114.689 0-195.345-80.655Q384-545.311 384-660q0-24 5-51.5t18-62.5q-98 27-162.5 109.5T180-480q0 125 87.5 212.5T480-180Zm-4-297Z" /></svg>
<a href="" download="" id="download-link" title="" th:if="${download}" th:href="${download.href}" th:title="${download.title}" th:attr="download = ${download.filename}"><svg class="icon" id="download" viewBox="0 0 24 24"><path d="M18,15v3H6v-3H4v3c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-3H18z M17,11l-1.41-1.41L13,12.17V4h-2v8.17L8.41,9.59L7,11l5,5 L17,11z" /></svg></a>
</div>
<img id="logo" src="static/logo.svg" title="Logo">
<h1 id="heading" th:utext="${heading}"></h1>
</div>
<table id="header">
<tr>
<td><image src="static/logo.svg"></td>
<td id="heading">
<h1 th:utext="${heading}"></h1>
</td>
</tr>
</table>
<div id="html" th:insert="${htmlFragment} ? ~{(${htmlFragment})::content} : _" th:if="${htmlFragment}"></div>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ Optional<CacheEntry> get(String fileName)
private static final String FILENAME_PATTERN_STRING = "^[0-9a-zA-Z_-]+\\.[0-9a-zA-Z]+$";
private static final Pattern FILENAME_PATTERN = Pattern.compile(FILENAME_PATTERN_STRING);

private static final Map<String, String> MIME_TYPE_BY_SUFFIX = Map.of("css", "text/css", "js", "text/javascript",
"html", "text/html", "pdf", "application/pdf", "png", "image/png", "svg", "image/svg+xml", "jpg",
"image/jpeg");
private static final Map<String, String> MIME_TYPE_BY_SUFFIX = Map.of("css", "text/css; charset=utf-8", "js",
"text/javascript; charset=utf-8", "html", "text/html; charset=utf-8", "pdf", "application/pdf", "png",
"image/png", "svg", "image/svg+xml; charset=utf-8", "jpg", "image/jpeg");

private final AbstractCache cache;
private final CacheControl cacheControl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import ca.uhn.fhir.model.api.annotation.ResourceDef;

abstract class AbstractResource<R extends Resource> extends AbstractThymeleafContext<R>
abstract class AbstractResource<R extends Resource> extends AbstractResourceThymeleafContext<R>
{
private record ResourceData(String type, String id, String version, String lastUpdated, String profiles,
Boolean active, String status)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package dev.dsf.fhir.adapter;

import java.util.Objects;
import java.util.function.BiConsumer;

import org.hl7.fhir.r4.model.Resource;

abstract class AbstractResourceThymeleafContext<R extends Resource> extends AbstractThymeleafContext
{
private final Class<R> resourceType;
private final String htmlFragment;

protected AbstractResourceThymeleafContext(Class<R> resourceType, String htmlFragment)
{
this.resourceType = Objects.requireNonNull(resourceType, "resourceType");
this.htmlFragment = Objects.requireNonNull(htmlFragment, "htmlFragment");
}

@Override
public Class<R> getResourceType()
{
return resourceType;
}

@Override
public String getHtmlFragment()
{
return htmlFragment;
}

@Override
public final void setVariables(BiConsumer<String, Object> variables, Resource resource)
{
if (resourceType.isInstance(resource))
doSetVariables(variables, resourceType.cast(resource));
else
throw new IllegalStateException("Unsupported resource of type " + resource.getClass().getName()
+ ", expected " + resourceType.getName());
}

protected abstract void doSetVariables(BiConsumer<String, Object> variables, R resource);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import jakarta.ws.rs.core.MultivaluedMap;

abstract class AbstractSearchSet<MR extends Resource> extends AbstractThymeleafContext<Bundle>
abstract class AbstractSearchSet<MR extends Resource> extends AbstractResourceThymeleafContext<Bundle>
{
protected static final String INSTANTIATES_CANONICAL_PATTERN_STRING = "(?<processUrl>http[s]{0,1}://(?<domain>(?:(?:[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])\\.)+(?:[a-zA-Z0-9]{1,63}))"
+ "/bpe/Process/(?<processName>[a-zA-Z0-9-]+))\\|(?<processVersion>\\d+\\.\\d+)$";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;

Expand All @@ -27,44 +26,22 @@
import org.hl7.fhir.r4.model.UriType;
import org.hl7.fhir.r4.model.UrlType;

abstract class AbstractThymeleafContext<R extends Resource> implements ThymeleafContext
public abstract class AbstractThymeleafContext implements ThymeleafContext
{
private static final DateTimeFormatter DATE_DISPLAY_FORMAT = DateTimeFormatter.ofPattern("dd.MM.yyyy");
private static final DateTimeFormatter DATE_TIME_DISPLAY_FORMAT = DateTimeFormatter
.ofPattern("dd.MM.yyyy HH:mm:ss");

private final Class<R> resourceType;
private final String htmlFragment;

protected AbstractThymeleafContext(Class<R> resourceType, String htmlFragment)
{
this.resourceType = Objects.requireNonNull(resourceType, "resourceType");
this.htmlFragment = Objects.requireNonNull(htmlFragment, "htmlFragment");
}

@Override
public Class<R> getResourceType()
{
return resourceType;
}

@Override
public String getHtmlFragment()
protected final String format(Date date, DateTimeFormatter formatter)
{
return htmlFragment;
}
Objects.requireNonNull(formatter, "formatter");

@Override
public final void setVariables(BiConsumer<String, Object> variables, Resource resource)
{
if (resourceType.isInstance(resource))
doSetVariables(variables, resourceType.cast(resource));
if (date == null)
return null;
else
throw new IllegalStateException("Unsupported resource of type " + resource.getClass().getName()
+ ", expected " + resourceType.getName());
return formatter.format(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()));
}

protected abstract void doSetVariables(BiConsumer<String, Object> variables, R resource);

protected final String formatDate(Date date)
{
Expand All @@ -76,16 +53,6 @@ protected final String formatDateTime(Date date)
return format(date, DATE_TIME_DISPLAY_FORMAT);
}

protected final String format(Date date, DateTimeFormatter formatter)
{
Objects.requireNonNull(formatter, "formatter");

if (date == null)
return null;
else
return formatter.format(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()));
}

protected final String formatLastUpdated(Resource resource)
{
return formatLastUpdated(resource, DATE_TIME_DISPLAY_FORMAT);
Expand Down
Loading