Merge remote-tracking branch 'origin/master' into ja_20231203_hapi_7_0
This commit is contained in:
12
.github/workflows/chart-test.yaml
vendored
12
.github/workflows/chart-test.yaml
vendored
@@ -10,7 +10,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
container: quay.io/helmpack/chart-testing:v3.8.0@sha256:f058c660a28d99a9394ae081d98921efe068079531f247c86b8054e3c9d407aa
|
container: quay.io/helmpack/chart-testing:v3.10.1@sha256:7d8a7f99fc5840142249cc33ed6d9752fc66b92f9e1bf792d987ee85227d84da
|
||||||
steps:
|
steps:
|
||||||
- name: Install helm-docs
|
- name: Install helm-docs
|
||||||
working-directory: /tmp
|
working-directory: /tmp
|
||||||
@@ -27,7 +27,7 @@ jobs:
|
|||||||
git config --global --add safe.directory /__w/hapi-fhir-jpaserver-starter/hapi-fhir-jpaserver-starter
|
git config --global --add safe.directory /__w/hapi-fhir-jpaserver-starter/hapi-fhir-jpaserver-starter
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
@@ -41,17 +41,17 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
k8s-version: [1.25.9, 1.26.4, 1.27.2]
|
k8s-version: [1.25.11, 1.26.6, 1.27.3, 1.28.0, 1.29.0]
|
||||||
needs:
|
needs:
|
||||||
- lint
|
- lint
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up chart-testing
|
- name: Set up chart-testing
|
||||||
uses: helm/chart-testing-action@e8788873172cb653a90ca2e819d79d65a66d4e76 # v2.4.0
|
uses: helm/chart-testing-action@e6669bcd63d7cb57cb4380c33043eebe5d111992 # v2.6.1
|
||||||
|
|
||||||
- name: Run chart-testing (list-changed)
|
- name: Run chart-testing (list-changed)
|
||||||
id: list-changed
|
id: list-changed
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Create k8s Kind Cluster
|
- name: Create k8s Kind Cluster
|
||||||
uses: helm/kind-action@fa81e57adff234b2908110485695db0f181f3c67 # v1.7.0
|
uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0
|
||||||
if: ${{ steps.list-changed.outputs.changed == 'true' }}
|
if: ${{ steps.list-changed.outputs.changed == 'true' }}
|
||||||
with:
|
with:
|
||||||
cluster_name: kind-cluster-k8s-${{ matrix.k8s-version }}
|
cluster_name: kind-cluster-k8s-${{ matrix.k8s-version }}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- name: postgresql
|
- name: postgresql
|
||||||
repository: oci://registry-1.docker.io/bitnamicharts
|
repository: oci://registry-1.docker.io/bitnamicharts
|
||||||
version: 12.5.6
|
version: 13.2.27
|
||||||
digest: sha256:4d21dbc02bbdb55b957b0093e37376853727de82396abfadfaf1d738bd51b8e6
|
digest: sha256:6374f6f32d32adbe6763c48e2d817d85ec20a1784b2aea1fb0312c658f8e58e9
|
||||||
generated: "2023-06-03T20:58:45.922102213+02:00"
|
generated: "2024-01-10T17:56:36.521957926+01:00"
|
||||||
|
|||||||
@@ -7,21 +7,25 @@ sources:
|
|||||||
- https://github.com/hapifhir/hapi-fhir-jpaserver-starter
|
- https://github.com/hapifhir/hapi-fhir-jpaserver-starter
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: postgresql
|
- name: postgresql
|
||||||
version: 12.5.6
|
version: 13.2.27
|
||||||
repository: oci://registry-1.docker.io/bitnamicharts
|
repository: oci://registry-1.docker.io/bitnamicharts
|
||||||
condition: postgresql.enabled
|
condition: postgresql.enabled
|
||||||
appVersion: 6.8.3
|
appVersion: 6.10.1
|
||||||
version: 0.14.0
|
version: 0.15.0
|
||||||
annotations:
|
annotations:
|
||||||
artifacthub.io/license: Apache-2.0
|
artifacthub.io/license: Apache-2.0
|
||||||
|
artifacthub.io/containsSecurityUpdates: "false"
|
||||||
|
artifacthub.io/operator: "false"
|
||||||
|
artifacthub.io/prerelease: "false"
|
||||||
|
artifacthub.io/recommendations: |
|
||||||
|
- url: https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack
|
||||||
|
- url: https://artifacthub.io/packages/helm/bitnami/postgresql
|
||||||
artifacthub.io/changes: |
|
artifacthub.io/changes: |
|
||||||
# When using the list of objects option the valid supported kinds are
|
# When using the list of objects option the valid supported kinds are
|
||||||
# added, changed, deprecated, removed, fixed, and security.
|
# added, changed, deprecated, removed, fixed, and security.
|
||||||
- kind: added
|
- kind: changed
|
||||||
description: updated starter image to 6.8.3
|
description: updated starter image to 6.10.1
|
||||||
- kind: fixed
|
- kind: changed
|
||||||
description: incorrect handling of existing secret database config
|
description: updated curlimages/curl to 8.5.0
|
||||||
- kind: added
|
- kind: changed
|
||||||
description: support for using a non-admin user for the postgres database
|
description: "updated postgresql sub-chart to 13.2.27. ⚠️: this updates the used PostgreSQL image from v15 to v16."
|
||||||
- kind: added
|
|
||||||
description: ability to create a dedicated ServiceAccount
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# HAPI FHIR JPA Server Starter Helm Chart
|
# HAPI FHIR JPA Server Starter Helm Chart
|
||||||
|
|
||||||
  
|
  
|
||||||
|
|
||||||
This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment.
|
This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment.
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver
|
|||||||
|
|
||||||
| Repository | Name | Version |
|
| Repository | Name | Version |
|
||||||
|------------|------|---------|
|
|------------|------|---------|
|
||||||
| oci://registry-1.docker.io/bitnamicharts | postgresql | 12.5.6 |
|
| oci://registry-1.docker.io/bitnamicharts | postgresql | 13.2.27 |
|
||||||
|
|
||||||
## Values
|
## Values
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver
|
|||||||
| image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use |
|
| image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use |
|
||||||
| image.registry | string | `"docker.io"` | registry where the HAPI FHIR server image is hosted |
|
| image.registry | string | `"docker.io"` | registry where the HAPI FHIR server image is hosted |
|
||||||
| image.repository | string | `"hapiproject/hapi"` | the path inside the repository |
|
| image.repository | string | `"hapiproject/hapi"` | the path inside the repository |
|
||||||
| image.tag | string | `"v6.8.3@sha256:6195f1116ebabfb0a608addde043b3e524c456c4d4f35b3d25025afd7dcd2e27"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. |
|
| image.tag | string | `"v6.10.1@sha256:4eac1b3481180b028616d1fab7e657e368538063d75f7ed3be2032e34c657dd4"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. |
|
||||||
| imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image |
|
| imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image |
|
||||||
| ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. |
|
| ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. |
|
||||||
| ingress.enabled | bool | `false` | whether to create an Ingress to expose the FHIR server HTTP endpoint |
|
| ingress.enabled | bool | `false` | whether to create an Ingress to expose the FHIR server HTTP endpoint |
|
||||||
@@ -57,10 +57,6 @@ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver
|
|||||||
| postgresql.auth.database | string | `"fhir"` | name for a custom database to create |
|
| postgresql.auth.database | string | `"fhir"` | name for a custom database to create |
|
||||||
| postgresql.auth.existingSecret | string | `""` | Name of existing secret to use for PostgreSQL credentials `auth.postgresPassword`, `auth.password`, and `auth.replicationPassword` will be ignored and picked up from this secret The secret must contain the keys `postgres-password` (which is the password for "postgres" admin user), `password` (which is the password for the custom user to create when `auth.username` is set), and `replication-password` (which is the password for replication user). The secret might also contains the key `ldap-password` if LDAP is enabled. `ldap.bind_password` will be ignored and picked from this secret in this case. The value is evaluated as a template. |
|
| postgresql.auth.existingSecret | string | `""` | Name of existing secret to use for PostgreSQL credentials `auth.postgresPassword`, `auth.password`, and `auth.replicationPassword` will be ignored and picked up from this secret The secret must contain the keys `postgres-password` (which is the password for "postgres" admin user), `password` (which is the password for the custom user to create when `auth.username` is set), and `replication-password` (which is the password for replication user). The secret might also contains the key `ldap-password` if LDAP is enabled. `ldap.bind_password` will be ignored and picked from this secret in this case. The value is evaluated as a template. |
|
||||||
| postgresql.enabled | bool | `true` | enable an included PostgreSQL DB. see <https://github.com/bitnami/charts/tree/master/bitnami/postgresql> for details if set to `false`, the values under `externalDatabase` are used |
|
| postgresql.enabled | bool | `true` | enable an included PostgreSQL DB. see <https://github.com/bitnami/charts/tree/master/bitnami/postgresql> for details if set to `false`, the values under `externalDatabase` are used |
|
||||||
| postgresql.primary.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | |
|
|
||||||
| postgresql.primary.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | |
|
|
||||||
| postgresql.primary.containerSecurityContext.runAsNonRoot | bool | `true` | |
|
|
||||||
| postgresql.primary.containerSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | |
|
|
||||||
| replicaCount | int | `1` | number of replicas to deploy |
|
| replicaCount | int | `1` | number of replicas to deploy |
|
||||||
| resources | object | `{}` | configure the FHIR server's resource requests and limits |
|
| resources | object | `{}` | configure the FHIR server's resource requests and limits |
|
||||||
| securityContext.allowPrivilegeEscalation | bool | `false` | |
|
| securityContext.allowPrivilegeEscalation | bool | `false` | |
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ spec:
|
|||||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||||
initContainers:
|
initContainers:
|
||||||
- name: wait-for-db-to-be-ready
|
- name: wait-for-db-to-be-ready
|
||||||
image: docker.io/bitnami/postgresql:15.3.0-debian-11-r7@sha256:cc301eef743685f4f69d1d719853988e8a9650c90fd9521f4742ce400b3fdf6a
|
image: docker.io/bitnami/postgresql:16.1.0-debian-11-r18@sha256:06f1f2297f6241a02bd8e8c025b31625254ca66784ac75a4a62e945fa611d045
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
{{- with .Values.restrictedContainerSecurityContext }}
|
{{- with .Values.restrictedContainerSecurityContext }}
|
||||||
securityContext:
|
securityContext:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ image:
|
|||||||
# -- the path inside the repository
|
# -- the path inside the repository
|
||||||
repository: hapiproject/hapi
|
repository: hapiproject/hapi
|
||||||
# -- the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image.
|
# -- the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image.
|
||||||
tag: "v6.8.3@sha256:6195f1116ebabfb0a608addde043b3e524c456c4d4f35b3d25025afd7dcd2e27"
|
tag: "v6.10.1@sha256:4eac1b3481180b028616d1fab7e657e368538063d75f7ed3be2032e34c657dd4"
|
||||||
# -- image pullPolicy to use
|
# -- image pullPolicy to use
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
@@ -121,15 +121,6 @@ postgresql:
|
|||||||
# picked from this secret in this case.
|
# picked from this secret in this case.
|
||||||
# The value is evaluated as a template.
|
# The value is evaluated as a template.
|
||||||
existingSecret: ""
|
existingSecret: ""
|
||||||
primary:
|
|
||||||
containerSecurityContext:
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
capabilities:
|
|
||||||
drop:
|
|
||||||
- ALL
|
|
||||||
runAsNonRoot: true
|
|
||||||
seccompProfile:
|
|
||||||
type: RuntimeDefault
|
|
||||||
|
|
||||||
# -- readiness probe
|
# -- readiness probe
|
||||||
# @ignored
|
# @ignored
|
||||||
@@ -240,7 +231,7 @@ curl:
|
|||||||
image:
|
image:
|
||||||
registry: docker.io
|
registry: docker.io
|
||||||
repository: curlimages/curl
|
repository: curlimages/curl
|
||||||
tag: 8.4.0@sha256:4a3396ae573c44932d06ba33f8696db4429c419da87cbdc82965ee96a37dd0af
|
tag: 8.6.0@sha256:c3b8bee303c6c6beed656cfc921218c529d65aa61114eb9e27c62047a1271b9b
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
# -- configure the test pods resource requests and limits
|
# -- configure the test pods resource requests and limits
|
||||||
|
|||||||
3
configs/app/index.html
Normal file
3
configs/app/index.html
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<p>
|
||||||
|
Greetings from the custom web app page!
|
||||||
|
</p>
|
||||||
14
custom/about.html
Normal file
14
custom/about.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<p>
|
||||||
|
<b>This is a custom about page! It means you have configured 'custom_content_path: ./custom' in the application.yaml</b>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This server provides a complete implementation of the FHIR Specification
|
||||||
|
using a 100% open source software stack.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This server is built
|
||||||
|
from a number of modules of the
|
||||||
|
<a href="https://github.com/hapifhir/hapi-fhir/">HAPI FHIR</a>
|
||||||
|
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
|
||||||
|
implementation of the FHIR specification.
|
||||||
|
</p>
|
||||||
BIN
custom/logo.jpg
Normal file
BIN
custom/logo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
14
custom/welcome.html
Normal file
14
custom/welcome.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<p>
|
||||||
|
<b>This is a custom welcome page! It means you have configured 'custom_content_path: ./custom' in the application.yaml</b>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This server provides a complete implementation of the FHIR Specification
|
||||||
|
using a 100% open source software stack.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This server is built
|
||||||
|
from a number of modules of the
|
||||||
|
<a href="https://github.com/hapifhir/hapi-fhir/">HAPI FHIR</a>
|
||||||
|
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
|
||||||
|
implementation of the FHIR specification.
|
||||||
|
</p>
|
||||||
@@ -79,9 +79,8 @@ public class AppProperties {
|
|||||||
private Boolean install_transitive_ig_dependencies = true;
|
private Boolean install_transitive_ig_dependencies = true;
|
||||||
private Map<String, PackageInstallationSpec> implementationGuides = null;
|
private Map<String, PackageInstallationSpec> implementationGuides = null;
|
||||||
|
|
||||||
private String staticLocation = null;
|
private String custom_content_path = null;
|
||||||
|
private String app_content_path = null;
|
||||||
private String staticLocationPrefix = "/static";
|
|
||||||
|
|
||||||
private Boolean lastn_enabled = false;
|
private Boolean lastn_enabled = false;
|
||||||
private boolean store_resource_in_lucene_index_enabled = false;
|
private boolean store_resource_in_lucene_index_enabled = false;
|
||||||
@@ -97,13 +96,6 @@ public class AppProperties {
|
|||||||
|
|
||||||
private final List<String> custom_interceptor_classes = new ArrayList<>();
|
private final List<String> custom_interceptor_classes = new ArrayList<>();
|
||||||
|
|
||||||
public String getStaticLocationPrefix() {
|
|
||||||
return staticLocationPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStaticLocationPrefix(String staticLocationPrefix) {
|
|
||||||
this.staticLocationPrefix = staticLocationPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public List<String> getCustomInterceptorClasses() {
|
public List<String> getCustomInterceptorClasses() {
|
||||||
@@ -111,14 +103,6 @@ public class AppProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getStaticLocation() {
|
|
||||||
return staticLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStaticLocation(String staticLocation) {
|
|
||||||
this.staticLocation = staticLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Boolean getOpenapi_enabled() {
|
public Boolean getOpenapi_enabled() {
|
||||||
return openapi_enabled;
|
return openapi_enabled;
|
||||||
@@ -600,6 +584,7 @@ public Cors getCors() {
|
|||||||
return logical_urls;
|
return logical_urls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Boolean getIg_runtime_upload_enabled() {
|
public Boolean getIg_runtime_upload_enabled() {
|
||||||
return ig_runtime_upload_enabled;
|
return ig_runtime_upload_enabled;
|
||||||
}
|
}
|
||||||
@@ -608,6 +593,22 @@ public Cors getCors() {
|
|||||||
this.ig_runtime_upload_enabled = ig_runtime_upload_enabled;
|
this.ig_runtime_upload_enabled = ig_runtime_upload_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCustom_content_path() {
|
||||||
|
return custom_content_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustom_content_path(String custom_content_path) {
|
||||||
|
this.custom_content_path = custom_content_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApp_content_path() {
|
||||||
|
return app_content_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApp_content_path(String app_content_path) {
|
||||||
|
this.app_content_path = app_content_path;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Cors {
|
public static class Cors {
|
||||||
private Boolean allow_Credentials = true;
|
private Boolean allow_Credentials = true;
|
||||||
private List<String> allowed_origin = List.of("*");
|
private List<String> allowed_origin = List.of("*");
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
package ca.uhn.fhir.jpa.starter;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.core.Ordered;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ConditionalOnProperty(prefix = "hapi.fhir", name = "staticLocation")
|
|
||||||
public class ExtraStaticFilesConfigurer implements WebMvcConfigurer {
|
|
||||||
|
|
||||||
private String staticLocation;
|
|
||||||
private String rootContextPath;
|
|
||||||
|
|
||||||
public ExtraStaticFilesConfigurer(AppProperties appProperties) {
|
|
||||||
|
|
||||||
rootContextPath = appProperties.getStaticLocationPrefix();
|
|
||||||
if (rootContextPath.endsWith("/"))
|
|
||||||
rootContextPath = rootContextPath.substring(0, rootContextPath.lastIndexOf('/'));
|
|
||||||
|
|
||||||
staticLocation = appProperties.getStaticLocation();
|
|
||||||
if (staticLocation.endsWith("/")) staticLocation = staticLocation.substring(0, staticLocation.lastIndexOf('/'));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addResourceHandlers(ResourceHandlerRegistry theRegistry) {
|
|
||||||
theRegistry.addResourceHandler(rootContextPath + "/**").addResourceLocations(staticLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addViewControllers(ViewControllerRegistry registry) {
|
|
||||||
String path = URI.create(staticLocation).getPath();
|
|
||||||
String lastSegment = path.substring(path.lastIndexOf('/') + 1);
|
|
||||||
|
|
||||||
registry.addViewController(rootContextPath)
|
|
||||||
.setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
|
|
||||||
|
|
||||||
registry.addViewController(rootContextPath + "/*")
|
|
||||||
.setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
|
|
||||||
|
|
||||||
registry.addViewController(rootContextPath + "/" + lastSegment + "/")
|
|
||||||
.setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
|
|
||||||
|
|
||||||
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ import ca.uhn.fhir.jpa.starter.AppProperties;
|
|||||||
import ca.uhn.fhir.to.FhirTesterMvcConfig;
|
import ca.uhn.fhir.to.FhirTesterMvcConfig;
|
||||||
import ca.uhn.fhir.to.TesterConfig;
|
import ca.uhn.fhir.to.TesterConfig;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ import org.springframework.context.annotation.Import;
|
|||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(FhirTesterMvcConfig.class)
|
@Import(FhirTesterMvcConfig.class)
|
||||||
// @Conditional(FhirTesterConfigCondition.class)
|
@Conditional(FhirTesterConfigCondition.class)
|
||||||
public class FhirTesterConfig {
|
public class FhirTesterConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import ca.uhn.fhir.jpa.starter.annotations.OnImplementationGuidesPresent;
|
|||||||
import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory;
|
import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory;
|
||||||
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
|
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
|
||||||
import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper;
|
import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper;
|
||||||
|
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
|
||||||
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
|
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
|
||||||
import ca.uhn.fhir.jpa.util.ResourceCountCache;
|
import ca.uhn.fhir.jpa.util.ResourceCountCache;
|
||||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
|
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
|
||||||
@@ -272,8 +273,7 @@ public class StarterJpaConfig {
|
|||||||
IPackageInstallerSvc packageInstallerSvc,
|
IPackageInstallerSvc packageInstallerSvc,
|
||||||
ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc,
|
ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc,
|
||||||
ApplicationContext appContext,
|
ApplicationContext appContext,
|
||||||
Optional<IpsOperationProvider> theIpsOperationProvider,
|
Optional<IpsOperationProvider> theIpsOperationProvider, Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
|
||||||
Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
|
|
||||||
RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext());
|
RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext());
|
||||||
|
|
||||||
List<String> supportedResourceTypes = appProperties.getSupported_resource_types();
|
List<String> supportedResourceTypes = appProperties.getSupported_resource_types();
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class RepositoryValidationInterceptorFactoryDstu3 implements IRepositoryV
|
|||||||
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
||||||
|
|
||||||
IBundleProvider results = structureDefinitionResourceProvider.search(
|
IBundleProvider results = structureDefinitionResourceProvider.search(
|
||||||
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
new SearchParameterMap().setLoadSynchronous(true).add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
||||||
Map<String, List<StructureDefinition>> structureDefinitions = results.getResources(0, results.size()).stream()
|
Map<String, List<StructureDefinition>> structureDefinitions = results.getResources(0, results.size()).stream()
|
||||||
.map(StructureDefinition.class::cast)
|
.map(StructureDefinition.class::cast)
|
||||||
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class RepositoryValidationInterceptorFactoryR4 implements IRepositoryVali
|
|||||||
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
||||||
|
|
||||||
IBundleProvider results = structureDefinitionResourceProvider.search(
|
IBundleProvider results = structureDefinitionResourceProvider.search(
|
||||||
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
new SearchParameterMap().setLoadSynchronous(true).add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
||||||
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
|
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
|
||||||
.map(StructureDefinition.class::cast)
|
.map(StructureDefinition.class::cast)
|
||||||
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class RepositoryValidationInterceptorFactoryR4B implements IRepositoryVal
|
|||||||
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
||||||
|
|
||||||
IBundleProvider results = structureDefinitionResourceProvider.search(
|
IBundleProvider results = structureDefinitionResourceProvider.search(
|
||||||
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
new SearchParameterMap().setLoadSynchronous(true).add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
||||||
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
|
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
|
||||||
.map(StructureDefinition.class::cast)
|
.map(StructureDefinition.class::cast)
|
||||||
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class RepositoryValidationInterceptorFactoryR5 implements IRepositoryVali
|
|||||||
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
||||||
|
|
||||||
IBundleProvider results = structureDefinitionResourceProvider.search(
|
IBundleProvider results = structureDefinitionResourceProvider.search(
|
||||||
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
new SearchParameterMap().setLoadSynchronous(true).add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
||||||
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
|
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
|
||||||
.map(StructureDefinition.class::cast)
|
.map(StructureDefinition.class::cast)
|
||||||
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
||||||
|
|||||||
@@ -9,16 +9,10 @@ import java.io.IOException;
|
|||||||
public interface IImplementationGuideOperationProvider {
|
public interface IImplementationGuideOperationProvider {
|
||||||
static PackageInstallationSpec toPackageInstallationSpec(byte[] npmPackageAsByteArray) throws IOException {
|
static PackageInstallationSpec toPackageInstallationSpec(byte[] npmPackageAsByteArray) throws IOException {
|
||||||
NpmPackage npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(npmPackageAsByteArray));
|
NpmPackage npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(npmPackageAsByteArray));
|
||||||
return new PackageInstallationSpec()
|
return new PackageInstallationSpec().setName(npmPackage.name()).setPackageContents(npmPackageAsByteArray).setVersion(npmPackage.version()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL).setFetchDependencies(false);
|
||||||
.setName(npmPackage.name())
|
|
||||||
.setPackageContents(npmPackageAsByteArray)
|
|
||||||
.setVersion(npmPackage.version())
|
|
||||||
.setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL)
|
|
||||||
.setFetchDependencies(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following declaration is the one that counts but cannot be used across different versions as stating
|
// The following declaration is the one that counts but cannot be used across different versions as stating Base64BinaryType would bind to a separate version
|
||||||
// Base64BinaryType would bind to a separate version
|
|
||||||
// @Operation(name = "$install", typeName = "ImplementationGuide")
|
|
||||||
// Parameters install(@OperationParam(name = "npmContent",min = 1, max = 1) Base64BinaryType implementationGuide);
|
// Parameters install(@OperationParam(name = "npmContent",min = 1, max = 1) Base64BinaryType implementationGuide);
|
||||||
|
// Parameters uninstall(@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) ;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.ig;
|
package ca.uhn.fhir.jpa.starter.ig;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
|
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
|
||||||
|
import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
|
||||||
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
|
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
@@ -22,15 +23,21 @@ public class ImplementationGuideR4OperationProvider implements IImplementationGu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = "$install", typeName = "ImplementationGuide")
|
@Operation(name = "$install", typeName = "ImplementationGuide")
|
||||||
public Parameters install(
|
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
||||||
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
packageInstallerSvc.install(
|
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
||||||
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return new Parameters();
|
return new Parameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(name = "$uninstall", typeName = "ImplementationGuide")
|
||||||
|
public Parameters uninstall(@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) {
|
||||||
|
|
||||||
|
packageInstallerSvc.uninstall(new PackageInstallationSpec().setName(name).setVersion(version));
|
||||||
|
return new Parameters();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.ig;
|
package ca.uhn.fhir.jpa.starter.ig;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
|
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
|
||||||
|
import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
|
||||||
import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition;
|
import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition;
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
@@ -13,7 +14,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
@Conditional({OnR5Condition.class, IgConfigCondition.class})
|
@Conditional({OnR5Condition.class, IgConfigCondition.class})
|
||||||
@Service
|
@Service
|
||||||
public class ImplementationGuideR5OperationProvider {
|
public class ImplementationGuideR5OperationProvider implements IImplementationGuideOperationProvider {
|
||||||
|
|
||||||
IPackageInstallerSvc packageInstallerSvc;
|
IPackageInstallerSvc packageInstallerSvc;
|
||||||
|
|
||||||
@@ -22,15 +23,21 @@ public class ImplementationGuideR5OperationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = "$install", typeName = "ImplementationGuide")
|
@Operation(name = "$install", typeName = "ImplementationGuide")
|
||||||
public Parameters install(
|
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
||||||
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
packageInstallerSvc.install(
|
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
||||||
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return new Parameters();
|
return new Parameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Operation(name = "$uninstall", typeName = "ImplementationGuide")
|
||||||
|
public org.hl7.fhir.r4.model.Parameters uninstall(@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) {
|
||||||
|
|
||||||
|
packageInstallerSvc.uninstall(new PackageInstallationSpec().setName(name).setVersion(version));
|
||||||
|
return new org.hl7.fhir.r4.model.Parameters();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package ca.uhn.fhir.jpa.starter.web;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.starter.AppProperties;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.io.FileUrlResource;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnProperty(prefix = "hapi.fhir", name = "custom_content_path")
|
||||||
|
public class CustomContentFilesConfigurer implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
public static final String CUSTOM_CONTENT = "/content";
|
||||||
|
private String customContentPath;
|
||||||
|
|
||||||
|
|
||||||
|
public CustomContentFilesConfigurer(AppProperties appProperties) {
|
||||||
|
customContentPath = appProperties.getCustom_content_path();
|
||||||
|
if (customContentPath.endsWith("/"))
|
||||||
|
customContentPath = customContentPath.substring(0, customContentPath.lastIndexOf('/'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResourceHandlers(@NotNull ResourceHandlerRegistry theRegistry) {
|
||||||
|
if (!theRegistry.hasMappingForPattern(CUSTOM_CONTENT + "/**")) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
theRegistry.addResourceHandler(CUSTOM_CONTENT + "/**").addResourceLocations(new FileUrlResource(customContentPath));
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package ca.uhn.fhir.jpa.starter.web;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.starter.AppProperties;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.io.FileUrlResource;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnProperty(prefix = "hapi.fhir", name = "app_content_path")
|
||||||
|
public class WebAppFilesConfigurer implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
public static final String WEB_CONTENT = "web";
|
||||||
|
private String appContentPath;
|
||||||
|
|
||||||
|
|
||||||
|
public WebAppFilesConfigurer(AppProperties appProperties) {
|
||||||
|
appContentPath = appProperties.getApp_content_path();
|
||||||
|
if (appContentPath.endsWith("/"))
|
||||||
|
appContentPath = appContentPath.substring(0, appContentPath.lastIndexOf('/'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResourceHandlers(@NotNull ResourceHandlerRegistry theRegistry) {
|
||||||
|
if (!theRegistry.hasMappingForPattern(WEB_CONTENT + "/**")) {
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
theRegistry.addResourceHandler(WEB_CONTENT + "/**").addResourceLocations(new FileUrlResource(appContentPath));
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addViewControllers(@NotNull ViewControllerRegistry registry) {
|
||||||
|
String path = URI.create(appContentPath).getPath();
|
||||||
|
String lastSegment = path.substring(path.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
registry.addViewController(WEB_CONTENT + "/" + lastSegment).setViewName("redirect:" + lastSegment + "/index.html");
|
||||||
|
registry.addViewController(WEB_CONTENT + "/" + lastSegment + "/").setViewName("redirect:index.html");
|
||||||
|
|
||||||
|
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,8 +14,8 @@ spring:
|
|||||||
check-location: false
|
check-location: false
|
||||||
baselineOnMigrate: true
|
baselineOnMigrate: true
|
||||||
datasource:
|
datasource:
|
||||||
url: 'jdbc:h2:file:./target/database/h2'
|
#url: 'jdbc:h2:file:./target/database/h2'
|
||||||
#url: jdbc:h2:mem:test_mem
|
url: jdbc:h2:mem:test_mem
|
||||||
username: sa
|
username: sa
|
||||||
password: null
|
password: null
|
||||||
driverClassName: org.h2.Driver
|
driverClassName: org.h2.Driver
|
||||||
@@ -76,10 +76,12 @@ hapi:
|
|||||||
### forces the use of the https:// protocol for the returned server address.
|
### forces the use of the https:// protocol for the returned server address.
|
||||||
### alternatively, it may be set using the X-Forwarded-Proto header.
|
### alternatively, it may be set using the X-Forwarded-Proto header.
|
||||||
# use_apache_address_strategy_https: false
|
# use_apache_address_strategy_https: false
|
||||||
### enables the server to host content like HTML, css, etc. under the url pattern of eg. /static/**
|
### enables the server to overwrite defaults on HTML, css, etc. under the url pattern of eg. /content/custom **
|
||||||
# staticLocationPrefix: /static
|
### Folder with custom content MUST be named custom. If omitted then default content applies
|
||||||
### the deepest folder level will be used. E.g. - if you put file:/foo/bar/bazz as value then the files are resolved under /static/bazz/**
|
#custom_content_path: ./custom
|
||||||
#staticLocation: file:/foo/bar/bazz
|
### enables the server host custom content. If e.g. the value ./configs/app is supplied then the content
|
||||||
|
### will be served under /web/app
|
||||||
|
#app_content_path: ./configs/app
|
||||||
### enable to set the Server URL
|
### enable to set the Server URL
|
||||||
# server_address: http://hapi.fhir.org/baseR4
|
# server_address: http://hapi.fhir.org/baseR4
|
||||||
# defer_indexing_for_codesystems_of_size: 101
|
# defer_indexing_for_codesystems_of_size: 101
|
||||||
|
|||||||
@@ -21,21 +21,23 @@
|
|||||||
<h3 class="panel-title">About This Server</h3>
|
<h3 class="panel-title">About This Server</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<p>
|
<div id="replacementAbout">
|
||||||
This server provides a complete implementation of the FHIR Specification
|
<p>
|
||||||
using a 100% open source software stack.
|
This server provides a complete implementation of the FHIR Specification
|
||||||
</p>
|
using a 100% open source software stack.
|
||||||
<p>
|
</p>
|
||||||
This server is built
|
<p>
|
||||||
from a number of modules of the
|
This server is built
|
||||||
<a href="https://github.com/jamesagnew/hapi-fhir/">HAPI FHIR</a>
|
from a number of modules of the
|
||||||
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
|
<a href="https://github.com/hapifhir/hapi-fhir/">HAPI FHIR</a>
|
||||||
implementation of the FHIR specification.
|
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
|
||||||
</p>
|
implementation of the FHIR specification.
|
||||||
<p>
|
</p>
|
||||||
|
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
@@ -55,6 +57,41 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div th:replace="tmpl-footer :: footer"></div>
|
<div th:replace="tmpl-footer :: footer"></div>
|
||||||
</form>
|
</form>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
<script>
|
||||||
|
// Function to check if a file exists using AJAX
|
||||||
|
function fileExists(filePath, callback) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
callback(xhr.status === 200);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.open("HEAD", filePath, true);
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace content if the replacement exists
|
||||||
|
fileExists("content/custom/about.html", function(exists) {
|
||||||
|
if (exists) {
|
||||||
|
loadFile("content/custom/about.html", function(content) {
|
||||||
|
var replacementContainer = document.getElementById("replacementAbout");
|
||||||
|
replacementContainer.innerHTML = content;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Function to load file content using AJAX
|
||||||
|
function loadFile(filePath, callback) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||||
|
callback(xhr.responseText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.open("GET", filePath, true);
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -1,20 +1,41 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<div th:fragment="banner">
|
<div th:fragment="banner">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<img src="img/sample-logo.jpg" width="383" alt="Sample Logo" />
|
<img id="logo" src="img/sample-logo.jpg" width="383" alt="Sample Logo"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<img src="img/hapi_fhir_banner_right.png" align="right" />
|
<img src="img/hapi_fhir_banner_right.png" align="right"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Error banner in case anything went wrong -->
|
<script>
|
||||||
<div class="alert alert-danger alert-dismissable" th:if="${errorMsg} != null">
|
const customlogoImageUrl = "content/custom/logo.jpg"; // Custom logo
|
||||||
<strong>Warning!</strong>
|
const defaultLogoImageUrl = "img/sample-logo.jpg"; // Default logo
|
||||||
<p th:text="${errorMsg}"></p>
|
const logoImageElement = document.getElementById("logo");
|
||||||
</div>
|
|
||||||
|
// Check if the logo image is available
|
||||||
|
const logoImg = new Image();
|
||||||
|
logoImg.src = customlogoImageUrl;
|
||||||
|
|
||||||
|
logoImg.onload = function() {
|
||||||
|
// Logo image is available
|
||||||
|
logoImageElement.src = customlogoImageUrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
logoImg.onerror = function() {
|
||||||
|
// Logo image is not available, use the default logo image
|
||||||
|
logoImageElement.src = defaultLogoImageUrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<!-- Error banner in case anything went wrong -->
|
||||||
|
<div class="alert alert-danger alert-dismissable" th:if="${errorMsg} != null">
|
||||||
|
<strong>Warning!</strong>
|
||||||
|
<p th:text="${errorMsg}"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,16 +1,58 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<div th:fragment="banner" class="well">
|
|
||||||
<p>
|
<div th:fragment="banner" class="well" >
|
||||||
This server provides a complete implementation of the FHIR Specification
|
<script>
|
||||||
using a 100% open source software stack.
|
console.log('Hello')
|
||||||
</p>
|
// Function to check if a file exists using AJAX
|
||||||
<p>
|
function fileExists(filePath, callback) {
|
||||||
This server is built
|
var xhr = new XMLHttpRequest();
|
||||||
from a number of modules of the
|
xhr.onreadystatechange = function() {
|
||||||
<a href="https://github.com/jamesagnew/hapi-fhir/">HAPI FHIR</a>
|
if (xhr.readyState === 4) {
|
||||||
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
|
callback(xhr.status === 200);
|
||||||
implementation of the FHIR specification.
|
}
|
||||||
</p>
|
};
|
||||||
|
xhr.open("HEAD", filePath, true);
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace content if static/welcome.html exists
|
||||||
|
fileExists("content/custom/welcome.html", function(exists) {
|
||||||
|
if (exists) {
|
||||||
|
loadFile("content/custom/welcome.html", function(content) {
|
||||||
|
var replacementContainer = document.getElementById("replacementWelcome");
|
||||||
|
replacementContainer.innerHTML = content;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Function to load file content using AJAX
|
||||||
|
function loadFile(filePath, callback) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||||
|
callback(xhr.responseText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.open("GET", filePath, true);
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div id="replacementWelcome">
|
||||||
|
<p>
|
||||||
|
This server provides a complete implementation of the FHIR Specification
|
||||||
|
using a 100% open source software stack.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This server is built
|
||||||
|
from a number of modules of the
|
||||||
|
<a href="https://github.com/hapifhir/hapi-fhir/">HAPI FHIR</a>
|
||||||
|
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
|
||||||
|
implementation of the FHIR specification.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user