From 4ce3f6e51931ff5643925028a9d2401966785f6c Mon Sep 17 00:00:00 2001 From: Reto Wettstein Date: Tue, 12 Dec 2023 17:11:43 +0100 Subject: [PATCH 1/7] html view for activity definition search bundle --- .../adapter/SearchBundleHtmlGenerator.java | 89 +++++++++++++------ 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java index bca3631b5..ac307cc0e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java @@ -16,6 +16,7 @@ import org.glassfish.jersey.uri.UriComponent; import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.Bundle.BundleLinkComponent; @@ -52,26 +53,31 @@ public class SearchBundleHtmlGenerator extends InputHtmlGenerator implements Htm private static final String CODE_SYSTEM_BPMN_MESSAGE_MESSAGE_NAME = "message-name"; private static final String CODE_SYSTEM_BPMN_MESSAGE_BUSINESS_KEY = "business-key"; private static final String CODE_SYSTEM_ORGANIZATION_ROLE = "http://dsf.dev/fhir/CodeSystem/organization-role"; + private static final String EXTENSION_PROCESS_AUTHORIZATION = "http://dsf.dev/fhir/StructureDefinition/extension-process-authorization"; + private static final String EXTENSION_PROCESS_AUTHORIZATION_MESSAGE_NAME = "message-name"; private static final String NAMING_SYSTEM_ENDPOINT_IDENTIFIER = "http://dsf.dev/sid/endpoint-identifier"; private static final String NAMING_SYSTEM_ORGANIZATION_IDENTIFIER = "http://dsf.dev/sid/organization-identifier"; private static final String NAMING_SYSTEM_TASK_IDENTIFIER = "http://dsf.dev/sid/task-identifier"; - private final String taskRessourcePath; - private final String questionnaireResponseRessourcePath; + private final String activityDefinitionResourcePath; + private final String endpointResourcePath; private final String organizationResourcePath; private final String organizationAffiliationResourcePath; - private final String endpointResourcePath; + private final String questionnaireResponseRessourcePath; + private final String taskRessourcePath; private final int defaultPageCount; public SearchBundleHtmlGenerator(String serverBaseUrl, int defaultPageCount) { String serverBaseUrlPath = getServerBaseUrlPath(serverBaseUrl); - taskRessourcePath = serverBaseUrlPath + "/" + ResourceType.Task.name(); - questionnaireResponseRessourcePath = serverBaseUrlPath + "/" + ResourceType.QuestionnaireResponse.name(); + + activityDefinitionResourcePath = serverBaseUrlPath + "/" + ResourceType.ActivityDefinition.name(); + endpointResourcePath = serverBaseUrlPath + "/" + ResourceType.Endpoint.name(); organizationResourcePath = serverBaseUrlPath + "/" + ResourceType.Organization.name(); organizationAffiliationResourcePath = serverBaseUrlPath + "/" + ResourceType.OrganizationAffiliation.name(); - endpointResourcePath = serverBaseUrlPath + "/" + ResourceType.Endpoint.name(); + questionnaireResponseRessourcePath = serverBaseUrlPath + "/" + ResourceType.QuestionnaireResponse.name(); + taskRessourcePath = serverBaseUrlPath + "/" + ResourceType.Task.name(); this.defaultPageCount = defaultPageCount; } @@ -98,11 +104,12 @@ public Class getResourceType() public boolean isResourceSupported(URI resourceUri, Resource resource) { return resource != null && resource instanceof Bundle - && (taskRessourcePath.equals(resourceUri.getPath()) - || questionnaireResponseRessourcePath.equals(resourceUri.getPath()) + && (activityDefinitionResourcePath.equals(resourceUri.getPath()) + || endpointResourcePath.equals(resourceUri.getPath()) || organizationResourcePath.equals(resourceUri.getPath()) || organizationAffiliationResourcePath.equals(resourceUri.getPath()) - || endpointResourcePath.equals(resourceUri.getPath())); + || questionnaireResponseRessourcePath.equals(resourceUri.getPath()) + || taskRessourcePath.equals(resourceUri.getPath())); } @Override @@ -215,28 +222,30 @@ private int getCount(URI uri) private String getHeader(URI uri) { - if (taskRessourcePath.equals(uri.getPath())) - return getTaskHeader(); - else if (questionnaireResponseRessourcePath.equals(uri.getPath())) - return getQuestionnaireResponseHeader(); + if (activityDefinitionResourcePath.equals(uri.getPath())) + return getActivityDefinitionHeader(); + else if (endpointResourcePath.equals(uri.getPath())) + return getEndpointHeader(); else if (organizationResourcePath.equals(uri.getPath())) return getOrganizationHeader(); else if (organizationAffiliationResourcePath.equals(uri.getPath())) return getOrganizationAffiliationHeader(); - else if (endpointResourcePath.equals(uri.getPath())) - return getEndpointHeader(); + else if (questionnaireResponseRessourcePath.equals(uri.getPath())) + return getQuestionnaireResponseHeader(); + else if (taskRessourcePath.equals(uri.getPath())) + return getTaskHeader(); else throw new IllegalArgumentException("Unexpected resource path: " + uri.getPath()); } - private String getTaskHeader() + private String getActivityDefinitionHeader() { - return "IDStatusProcessMessage-NameRequesterBusiness-Key / IdentifierLast Updated"; + return "IDStatusTitlePublisherMessage NamesLast Updated"; } - private String getQuestionnaireResponseHeader() + private String getEndpointHeader() { - return "IDStatusQuestionnaireBusiness-KeyLast Updated"; + return "IDStatusIdentifierNameAddressManaging OrganizationLast Updated"; } private String getOrganizationHeader() @@ -249,23 +258,30 @@ private String getOrganizationAffiliationHeader() return "IDActiveParent OrganizationParticipating OrganizationRoleEndpointLast Updated"; } - private String getEndpointHeader() + private String getQuestionnaireResponseHeader() { - return "IDStatusIdentifierNameAddressManaging OrganizationLast Updated"; + return "IDStatusQuestionnaireBusiness-KeyLast Updated"; + } + + private String getTaskHeader() + { + return "IDStatusProcessMessage-NameRequesterBusiness-Key / IdentifierLast Updated"; } private String getRow(Resource resource) { - if (resource instanceof Task t) - return getTaskRow(t); - else if (resource instanceof QuestionnaireResponse qr) - return getQuestionnaireResponseRow(qr); + if (resource instanceof ActivityDefinition a) + return getActivityDefinitionRow(a); + else if (resource instanceof Endpoint e) + return getEndpointRow(e); else if (resource instanceof Organization o) return getOrganizationRow(o); else if (resource instanceof OrganizationAffiliation oa) return getOrganizationAffiliationRow(oa); - else if (resource instanceof Endpoint e) - return getEndpointRow(e); + else if (resource instanceof QuestionnaireResponse qr) + return getQuestionnaireResponseRow(qr); + else if (resource instanceof Task t) + return getTaskRow(t); else throw new IllegalArgumentException("Unexpected resource type: " + resource.getResourceType().name()); } @@ -325,6 +341,25 @@ private String toLastUpdated(Resource resource) return DATE_TIME_DISPLAY_FORMAT.format(resource.getMeta().getLastUpdated()); } + private String getActivityDefinitionRow(ActivityDefinition resource) + { + List messageNames = resource.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION).stream() + .flatMap(e -> e.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION_MESSAGE_NAME).stream()) + .filter(e -> e.getValue() instanceof StringType).map(e -> ((StringType) e.getValue()).getValue()) + .toList(); + + String combinedMessageNames = (messageNames.size() > 2) + ? String.join(", ", messageNames.subList(0, 2)) + ", ..." + : String.join(", ", messageNames); + + return "" + + createResourceLink(resource) + "" + + (resource.hasStatus() ? resource.getStatus().toCode() : "") + "" + + (resource.hasTitle() ? resource.getTitle() : "") + "" + + (resource.hasPublisher() ? resource.getPublisher() : "") + "" + combinedMessageNames + + "" + toLastUpdated(resource) + ""; + } + private String getTaskRow(Task resource) { String domain = "", processName = "", processVersion = ""; From 30a6e904f9a4d7f67da468c00cb8609c49e35626 Mon Sep 17 00:00:00 2001 From: Reto Wettstein Date: Wed, 13 Dec 2023 13:30:49 +0100 Subject: [PATCH 2/7] activity definition html view --- .../ActivityDefinitionHtmlGenerator.java | 121 +++++++++++++++--- .../adapter/OrganizationHtmlGenerator.java | 20 ++- .../fhir/adapter/ResourceHtmlGenerator.java | 20 +-- .../dsf/fhir/spring/config/AdapterConfig.java | 10 +- .../src/main/resources/static/dsf.css | 41 ++++-- .../src/main/resources/static/form.css | 11 +- 6 files changed, 157 insertions(+), 66 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java index 586b08026..93400a268 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java @@ -7,9 +7,13 @@ import java.util.Optional; import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.CanonicalType; +import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; public class ActivityDefinitionHtmlGenerator extends ResourceHtmlGenerator implements HtmlGenerator { @@ -56,47 +60,124 @@ public void writeHtml(URI resourceUri, ActivityDefinition resource, OutputStream if (!processAuthorizations.isEmpty()) { - writeSectionHeader("Process Authorization", out); - - for (Extension extension : processAuthorizations) + for (int i = 0; i < processAuthorizations.size(); i++) { - writeProcessAuthorizationRow(extension, out); + writeProcessAuthorizationRow(processAuthorizations.get(i), + "Authorization" + (processAuthorizations.size() > 1 ? " " + (i + 1) : ""), out); } } out.write("\n"); } - private void writeProcessAuthorizationRow(Extension extension, OutputStreamWriter out) throws IOException + private void writeProcessAuthorizationRow(Extension extension, String header, OutputStreamWriter out) + throws IOException { Optional taskProfile = extension.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION_TASK_PROFILE) - .stream().filter(e -> e.getValue() instanceof StringType) - .map(e -> ((StringType) e.getValue()).getValue()).findFirst(); + .stream().filter(e -> e.getValue() instanceof CanonicalType) + .map(e -> String.join(" | ", ((CanonicalType) e.getValue()).getValue().split("\\|"))).findFirst(); Optional messageName = extension.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION_MESSAGE_NAME) .stream().filter(e -> e.getValue() instanceof StringType) .map(e -> ((StringType) e.getValue()).getValue()).findFirst(); - if (taskProfile.isPresent()) + if (taskProfile.isPresent() || messageName.isPresent()) + { + writeSectionHeader(header, out); + out.write("
\n"); + + if (messageName.isPresent()) + { + writeRowWithAdditionalRowClasses("Message Name", messageName.get(), + taskProfile.isPresent() ? "flex-element-33 flex-element-margin" : "flex-element-100", out); + } + + if (taskProfile.isPresent()) + { + writeRowWithAdditionalRowClasses("Task Profile", taskProfile.get(), + messageName.isPresent() ? "flex-element-67" : "flex-element-100", out); + } + + out.write("
\n"); + } + + List requester = extension.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION_REQUESTER).stream() + .filter(e -> e.getValue() instanceof Coding).map(e -> ((Coding) e.getValue())).toList(); + writeAuthorizationFor(requester, "Requester", out); + + List recipient = extension.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT).stream() + .filter(e -> e.getValue() instanceof Coding).map(e -> ((Coding) e.getValue())).toList(); + writeAuthorizationFor(recipient, "Recipient", out); + } + + private void writeAuthorizationFor(List authorization, String header, OutputStreamWriter out) + throws IOException + { + for (int i = 0; i < authorization.size(); i++) { - writeRowWithAdditionalTextClasses("Task Profile", taskProfile.get(), messageName.isPresent() ? "66" : "", - out); + out.write("
\n"); + out.write("

" + header + (authorization.size() > 1 ? " " + (i + 1) : "") + "

\n"); + + Coding authorizationCode = authorization.get(i); + writeRowWithAdditionalRowClasses("Authorization Type", + authorizationCode.getSystem() + " | " + authorizationCode.getCode() + "", "nested-row", out); + + writeCoding("Practitioner", authorizationCode, + "http://dsf.dev/fhir/StructureDefinition/extension-process-authorization-practitioner", out); + writeIdentifier("Organization", authorizationCode, + "http://dsf.dev/fhir/StructureDefinition/extension-process-authorization-organization", out); + + List authorizationOrganizationPractitioner = authorizationCode.getExtensionsByUrl( + "http://dsf.dev/fhir/StructureDefinition/extension-process-authorization-organization-practitioner"); + for (Extension extension : authorizationOrganizationPractitioner) + { + writeIdentifier("Organization", extension, "organization", out); + writeCoding("Practitioner Role", extension, "practitioner-role", out); + } + + List authorizationParentOrganizationRole = authorizationCode.getExtensionsByUrl( + "http://dsf.dev/fhir/StructureDefinition/extension-process-authorization-parent-organization-role"); + for (Extension extension : authorizationParentOrganizationRole) + { + writeIdentifier("Parent Organization", extension, "parent-organization", out); + writeCoding("Organization Role", extension, "organization-role", out); + } + + List authorizationParentOrganizationPractitionerRole = authorizationCode.getExtensionsByUrl( + "http://dsf.dev/fhir/StructureDefinition/extension-process-authorization-parent-organization-role-practitioner"); + for (Extension extension : authorizationParentOrganizationPractitionerRole) + { + writeIdentifier("Parent Organization", extension, "parent-organization", out); + writeCoding("Organization Role", extension, "organization-role", out); + writeCoding("Practitioner Role", extension, "practitioner-role", out); + } + + out.write("
\n"); } + } + + private void writeCoding(String label, Type type, String url, OutputStreamWriter out) throws IOException + { + Optional coding = type.getExtension().stream().filter(e -> url.equals(e.getUrl())) + .filter(e -> e.getValue() instanceof Coding).map(e -> ((Coding) e.getValue())).findFirst(); - if (messageName.isPresent()) + if (coding.isPresent()) { - writeRowWithAdditionalRowClasses("Message Name", messageName.get(), taskProfile.isPresent() ? "33" : "", - out); + writeRowWithAdditionalRowClasses(label, + coding.get().getSystem() + " | " + coding.get().getCode() + "", "nested-row", out); } + } - extension.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION_REQUESTER); - extension.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT); + private void writeIdentifier(String label, Type type, String url, OutputStreamWriter out) throws IOException + { + Optional identifier = type.getExtension().stream().filter(e -> url.equals(e.getUrl())) + .filter(e -> e.getValue() instanceof Identifier).map(e -> ((Identifier) e.getValue())).findFirst(); - // TODO: - // task-profile - // message-name - // requestor role - // recipient role + if (identifier.isPresent()) + { + writeRowWithAdditionalRowClasses(label, + identifier.get().getSystem() + " | " + identifier.get().getValue() + "", "nested-row", out); + } } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/OrganizationHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/OrganizationHtmlGenerator.java index 293beef5d..5db4c6edc 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/OrganizationHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/OrganizationHtmlGenerator.java @@ -82,20 +82,18 @@ public void writeHtml(URI resourceUri, Organization resource, OutputStreamWriter List contacts = resource.getContact(); for (OrganizationContactComponent contact : contacts) { - boolean isAdmin = contact.getPurpose().getCoding().stream() - .anyMatch(c -> CODE_SYSTEM_CONTACT_TYPE.equals(c.getSystem()) - && CODE_SYSTEM_CONTACT_TYPE_VALUE_ADMIN.equals(c.getCode())); + boolean isAdmin = contact.getPurpose().getCoding().stream().anyMatch( + c -> CODE_SYSTEM_CONTACT_TYPE.equals(c.getSystem()) && CODE_SYSTEM_CONTACT_TYPE_VALUE_ADMIN.equals( + c.getCode())); if (isAdmin && (contact.hasName() || contact.hasAddress() || contact.hasTelecom())) { writeSectionHeader("Admin Contact", out); if (contact.hasName()) - writeRow("Name", - contact.getName().getNameAsSingleString() != null - ? contact.getName().getNameAsSingleString() - : "", - out); + writeRow("Name", contact.getName().getNameAsSingleString() != null ? + contact.getName().getNameAsSingleString() : + "", out); if (contact.hasAddress()) writeRowWithAddress(resource.getAddressFirstRep(), out); @@ -131,15 +129,15 @@ private void writeRowWithContacts(List contacts, OutputStreamWrite if (eMail.isPresent() || phone.isPresent()) { - out.write("
\n"); + out.write("
\n"); if (eMail.isPresent()) writeRowWithAdditionalRowClasses("eMail", eMail.get().getValue(), - phone.isPresent() ? "contact-element-50 contact-element-margin" : "contact-element-100", out); + phone.isPresent() ? "flex-element-50 flex-element-margin" : "flex-element-100", out); if (phone.isPresent()) writeRowWithAdditionalRowClasses("Phone", phone.get().getValue(), - eMail.isPresent() ? "contact-element-50" : "contact-element-100", out); + eMail.isPresent() ? "flex-element-50" : "flex-element-100", out); out.write("
\n"); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ResourceHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ResourceHtmlGenerator.java index d367f1ac2..8db5804d2 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ResourceHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ResourceHtmlGenerator.java @@ -2,26 +2,12 @@ import java.io.IOException; import java.io.OutputStreamWriter; -import java.net.MalformedURLException; -import java.net.URL; import java.util.List; import org.hl7.fhir.r4.model.Resource; public abstract class ResourceHtmlGenerator extends AbstractHtmlAdapter { - protected String getServerBaseUrlPath(String serverBaseUrl) - { - try - { - return new URL(serverBaseUrl).getPath(); - } - catch (MalformedURLException e) - { - throw new RuntimeException(e); - } - } - protected void writeMeta(Resource resource, OutputStreamWriter out) throws IOException { writeSectionHeader("Meta", out); @@ -31,13 +17,15 @@ protected void writeMeta(Resource resource, OutputStreamWriter out) throws IOExc { List profiles = resource.getMeta().getProfile().stream() .map(p -> p.getValue().replaceAll("\\|", " \\| ")).toList(); - writeRowWithListAndAdditionalRowClasses("Profiles", profiles, "profiles", out); + writeRowWithListAndAdditionalRowClasses("Profiles", profiles, + resource.getMeta().hasLastUpdated() ? "flex-element-67 flex-element-margin" : "flex-element-100", + out); } if (resource.getMeta().hasLastUpdated()) { writeRowWithAdditionalRowClasses("Last Updated", formatLastUpdated(resource, DATE_TIME_DISPLAY_FORMAT), - "last-updated", out); + resource.getMeta().hasProfile() ? "flex-element-33 flex-element-margin" : "flex-element-100", out); } out.write("
\n"); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AdapterConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AdapterConfig.java index bffd47ccb..fb1e9b8b6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AdapterConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AdapterConfig.java @@ -6,6 +6,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import dev.dsf.fhir.adapter.ActivityDefinitionHtmlGenerator; import dev.dsf.fhir.adapter.EndpointHtmlGenerator; import dev.dsf.fhir.adapter.FhirAdapter; import dev.dsf.fhir.adapter.HtmlFhirAdapter; @@ -34,9 +35,10 @@ public FhirAdapter fhirAdapter() public HtmlFhirAdapter htmlFhirAdapter() { return new HtmlFhirAdapter(propertiesConfig.getServerBaseUrl(), fhirConfig.fhirContext(), - List.of(new EndpointHtmlGenerator(), new OrganizationHtmlGenerator(), - new OrganizationAffiliationHtmlGenerator(), new QuestionnaireResponseHtmlGenerator(), - new TaskHtmlGenerator(), new SearchBundleHtmlGenerator(propertiesConfig.getServerBaseUrl(), - propertiesConfig.getDefaultPageCount()))); + List.of(new ActivityDefinitionHtmlGenerator(), new EndpointHtmlGenerator(), + new OrganizationHtmlGenerator(), new OrganizationAffiliationHtmlGenerator(), + new QuestionnaireResponseHtmlGenerator(), + new SearchBundleHtmlGenerator(propertiesConfig.getServerBaseUrl(), + propertiesConfig.getDefaultPageCount()), new TaskHtmlGenerator())); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/static/dsf.css b/dsf-fhir/dsf-fhir-server/src/main/resources/static/dsf.css index 1014f020f..a35313ec4 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/static/dsf.css +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/static/dsf.css @@ -505,15 +505,6 @@ pre.lang-html { flex-direction: row } -.profiles { - margin-right: 0.7em; - width: 67%; -} - -.last-updated { - width: 33%; -} - .row-list { padding-inline-start: 25px; margin-top: 0.15em; @@ -574,25 +565,49 @@ div.row-text { background: var(--color-row-border-draft); } -.contact { +.row[status="draft"]:first-child { + background: var(--color-row-border-draft); +} + +.flex-element { display: flex; flex-direction: row; } -.contact-element-100 { +.flex-element-100 { width: 100%; margin-right: 0em; } -.contact-element-50 { +.flex-element-67 { + width: 67%; +} + +.flex-element-50 { width: 50%; margin-right: 0em; } -.contact-element-margin { +.flex-element-33 { + width: 33%; +} + +.flex-element-margin { margin-right: 0.7em; } +.authorization { + padding-bottom: 0.25em !important; +} + +.authorization>h3 +{ + margin-top: 0; + margin-bottom: 0; + padding: 1em 1em 0.75em 0.25em; + font-size: 1em; +} + @media print { body { margin: 0; diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/static/form.css b/dsf-fhir/dsf-fhir-server/src/main/resources/static/form.css index 7597e90e3..7ebcca221 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/static/form.css +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/static/form.css @@ -19,6 +19,13 @@ fieldset#form-fieldset { background-color: var(--color-row-background); } +.row>.nested-row { + border-radius: 5px; + padding: 0 1em 1em 0.5em; + margin-bottom: 0.7em; + background-color: var(--color-row-background-deep); +} + .row-extension-0 { margin-top: 12px; padding: 0 0 12px 12px; @@ -196,7 +203,7 @@ form .row-info a:hover { label { display: block; - padding: 12px 12px 12px 0; + padding: 1em 1em 1em 0; font-weight: regular; } @@ -395,7 +402,7 @@ button.submit { .row-label { color: var(--color-input-text); - padding: 12px 0 6px 6px; + padding: 1em 0 0.25em 0.4em; font-weight: bold; font-size: small; position: relative; From 79e4d28963f5fb8e5bc72e634220e1310a45f1d4 Mon Sep 17 00:00:00 2001 From: Reto Wettstein Date: Wed, 13 Dec 2023 13:50:43 +0100 Subject: [PATCH 3/7] add url & version --- .../adapter/ActivityDefinitionHtmlGenerator.java | 7 +++++++ .../fhir/adapter/OrganizationHtmlGenerator.java | 14 ++++++++------ .../dev/dsf/fhir/spring/config/AdapterConfig.java | 3 ++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java index 93400a268..28d1f113a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java @@ -43,12 +43,19 @@ public void writeHtml(URI resourceUri, ActivityDefinition resource, OutputStream writeSectionHeader("Activity Definition", out); + if (resource.hasUrl()) + writeRow("Url" + (resource.hasVersion() ? " & Version" : ""), + resource.getUrl() + (resource.hasVersion() ? " | " + resource.getVersion() : ""), out); + if (resource.hasTitle()) writeRow("Title", resource.getTitle(), out); if (resource.hasSubtitle()) writeRow("Subtitle", resource.getSubtitle(), out); + if (resource.hasDescription()) + writeRow("Description", resource.getDescription(), out); + if (resource.hasPublisher()) writeRow("Publisher", resource.getPublisher(), out); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/OrganizationHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/OrganizationHtmlGenerator.java index 5db4c6edc..bfa5101e8 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/OrganizationHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/OrganizationHtmlGenerator.java @@ -82,18 +82,20 @@ public void writeHtml(URI resourceUri, Organization resource, OutputStreamWriter List contacts = resource.getContact(); for (OrganizationContactComponent contact : contacts) { - boolean isAdmin = contact.getPurpose().getCoding().stream().anyMatch( - c -> CODE_SYSTEM_CONTACT_TYPE.equals(c.getSystem()) && CODE_SYSTEM_CONTACT_TYPE_VALUE_ADMIN.equals( - c.getCode())); + boolean isAdmin = contact.getPurpose().getCoding().stream() + .anyMatch(c -> CODE_SYSTEM_CONTACT_TYPE.equals(c.getSystem()) + && CODE_SYSTEM_CONTACT_TYPE_VALUE_ADMIN.equals(c.getCode())); if (isAdmin && (contact.hasName() || contact.hasAddress() || contact.hasTelecom())) { writeSectionHeader("Admin Contact", out); if (contact.hasName()) - writeRow("Name", contact.getName().getNameAsSingleString() != null ? - contact.getName().getNameAsSingleString() : - "", out); + writeRow("Name", + contact.getName().getNameAsSingleString() != null + ? contact.getName().getNameAsSingleString() + : "", + out); if (contact.hasAddress()) writeRowWithAddress(resource.getAddressFirstRep(), out); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AdapterConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AdapterConfig.java index fb1e9b8b6..a8ac4e3e7 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AdapterConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/spring/config/AdapterConfig.java @@ -39,6 +39,7 @@ public HtmlFhirAdapter htmlFhirAdapter() new OrganizationHtmlGenerator(), new OrganizationAffiliationHtmlGenerator(), new QuestionnaireResponseHtmlGenerator(), new SearchBundleHtmlGenerator(propertiesConfig.getServerBaseUrl(), - propertiesConfig.getDefaultPageCount()), new TaskHtmlGenerator())); + propertiesConfig.getDefaultPageCount()), + new TaskHtmlGenerator())); } } From fc52c67f185c0484fce6415a9efb72144d36f021 Mon Sep 17 00:00:00 2001 From: Reto Wettstein Date: Wed, 13 Dec 2023 14:01:02 +0100 Subject: [PATCH 4/7] bookmark for activity definition to sort by status,url,version --- dsf-fhir/dsf-fhir-server/src/main/resources/static/bookmarks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/static/bookmarks.js b/dsf-fhir/dsf-fhir-server/src/main/resources/static/bookmarks.js index 36aa73d86..204375847 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/static/bookmarks.js +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/static/bookmarks.js @@ -130,7 +130,7 @@ function getBasePath() { function getInitialBookmarks() { return { '_misc': ['metadata'], - 'ActivityDefinition': ['ActivityDefinition'], + 'ActivityDefinition': ['ActivityDefinition', "ActivityDefinition?_sort=status,url,version"], 'CodeSystem': ['CodeSystem'], 'Endpoint': ['Endpoint'], 'NamingSystem': ['NamingSystem'], From 5a49bd24e90d415ad7d7b932f581a2220636903b Mon Sep 17 00:00:00 2001 From: Reto Wettstein Date: Wed, 13 Dec 2023 14:51:25 +0100 Subject: [PATCH 5/7] add url and version to search bundle view --- .../adapter/SearchBundleHtmlGenerator.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java index 5b569c95b..43160168f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java @@ -238,7 +238,7 @@ else if (taskRessourcePath.equals(uri.getPath())) private String getActivityDefinitionHeader() { - return "IDStatusTitlePublisherMessage NamesLast Updated"; + return "IDStatusTitleUrl & VersionMessage NamesLast Updated"; } private String getEndpointHeader() @@ -333,6 +333,19 @@ private String createResourceLink(Reference reference) private String getActivityDefinitionRow(ActivityDefinition resource) { + String domain = "", processName = "", processVersion = ""; + if (resource.getUrl() != null && !resource.getUrl().isBlank()) + { + Matcher matcher = INSTANTIATES_CANONICAL_PATTERN + .matcher(resource.getUrl() + (resource.hasVersion() ? "|" + resource.getVersion() : "")); + if (matcher.matches()) + { + domain = matcher.group("domain"); + processName = matcher.group("processName"); + processVersion = matcher.group("processVersion"); + } + } + List messageNames = resource.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION).stream() .flatMap(e -> e.getExtensionsByUrl(EXTENSION_PROCESS_AUTHORIZATION_MESSAGE_NAME).stream()) .filter(e -> e.getValue() instanceof StringType).map(e -> ((StringType) e.getValue()).getValue()) @@ -345,9 +358,9 @@ private String getActivityDefinitionRow(ActivityDefinition resource) return "" + createResourceLink(resource) + "" + (resource.hasStatus() ? resource.getStatus().toCode() : "") + "" - + (resource.hasTitle() ? resource.getTitle() : "") + "" - + (resource.hasPublisher() ? resource.getPublisher() : "") + "" + combinedMessageNames - + "" + formatLastUpdated(resource, DATE_TIME_DISPLAY_FORMAT) + ""; + + (resource.hasTitle() ? resource.getTitle() : "") + "" + domain + " | " + processName + " | " + + processVersion + "" + combinedMessageNames + "" + + formatLastUpdated(resource, DATE_TIME_DISPLAY_FORMAT) + ""; } private String getTaskRow(Task resource) From 846a20c0c00ddd31a370ad7c84689cbd3957c230 Mon Sep 17 00:00:00 2001 From: Reto Wettstein Date: Wed, 13 Dec 2023 15:00:06 +0100 Subject: [PATCH 6/7] rename url & version to process and message name to message-name --- .../dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java | 5 ++--- .../java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java index 28d1f113a..a58d603ef 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java @@ -44,8 +44,7 @@ public void writeHtml(URI resourceUri, ActivityDefinition resource, OutputStream writeSectionHeader("Activity Definition", out); if (resource.hasUrl()) - writeRow("Url" + (resource.hasVersion() ? " & Version" : ""), - resource.getUrl() + (resource.hasVersion() ? " | " + resource.getVersion() : ""), out); + writeRow("Process", resource.getUrl() + (resource.hasVersion() ? " | " + resource.getVersion() : ""), out); if (resource.hasTitle()) writeRow("Title", resource.getTitle(), out); @@ -95,7 +94,7 @@ private void writeProcessAuthorizationRow(Extension extension, String header, Ou if (messageName.isPresent()) { - writeRowWithAdditionalRowClasses("Message Name", messageName.get(), + writeRowWithAdditionalRowClasses("Message-Name", messageName.get(), taskProfile.isPresent() ? "flex-element-33 flex-element-margin" : "flex-element-100", out); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java index 43160168f..8e28bbfe0 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/SearchBundleHtmlGenerator.java @@ -238,7 +238,7 @@ else if (taskRessourcePath.equals(uri.getPath())) private String getActivityDefinitionHeader() { - return "IDStatusTitleUrl & VersionMessage NamesLast Updated"; + return "IDStatusTitleProcessMessage-NamesLast Updated"; } private String getEndpointHeader() From aadf9dd915b6539845ca215685d9cad0b7c8dfc6 Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Sat, 16 Dec 2023 19:42:12 +0100 Subject: [PATCH 7/7] html end tag name fix h4->h3 --- .../dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java index a58d603ef..153099036 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/adapter/ActivityDefinitionHtmlGenerator.java @@ -122,7 +122,7 @@ private void writeAuthorizationFor(List authorization, String header, Ou for (int i = 0; i < authorization.size(); i++) { out.write("
\n"); - out.write("

" + header + (authorization.size() > 1 ? " " + (i + 1) : "") + "

\n"); + out.write("

" + header + (authorization.size() > 1 ? " " + (i + 1) : "") + "

\n"); Coding authorizationCode = authorization.get(i); writeRowWithAdditionalRowClasses("Authorization Type",