Feature/dynamic content (#605)
* Added dynamic content options * Added defaults * Added sane defaults * Added IG operation providers for run time installation of IG's * Refactored conditions for enabling the provider * Refactoring * Disable it by default in config as well * document package install feature * Added hosting options * Provided better custom defaults * Removed double default files --------- Co-authored-by: Jose Costa Teixeira <jose.a.teixeira@gmail.com>
This commit is contained in:
committed by
GitHub
parent
f6671f97c5
commit
9e21d8062e
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 Map<String, PackageInstallationSpec> implementationGuides = null;
|
||||
|
||||
private String staticLocation = null;
|
||||
|
||||
private String staticLocationPrefix = "/static";
|
||||
private String custom_content_path = null;
|
||||
private String app_content_path = null;
|
||||
|
||||
private Boolean lastn_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<>();
|
||||
|
||||
public String getStaticLocationPrefix() {
|
||||
return staticLocationPrefix;
|
||||
}
|
||||
|
||||
public void setStaticLocationPrefix(String staticLocationPrefix) {
|
||||
this.staticLocationPrefix = staticLocationPrefix;
|
||||
}
|
||||
|
||||
|
||||
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() {
|
||||
return openapi_enabled;
|
||||
@@ -600,6 +584,7 @@ public Cors getCors() {
|
||||
return logical_urls;
|
||||
}
|
||||
|
||||
|
||||
public Boolean getIg_runtime_upload_enabled() {
|
||||
return ig_runtime_upload_enabled;
|
||||
}
|
||||
@@ -608,6 +593,22 @@ public Cors getCors() {
|
||||
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 {
|
||||
private Boolean allow_Credentials = true;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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.ig.IImplementationGuideOperationProvider;
|
||||
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.util.ResourceCountCache;
|
||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
|
||||
@@ -272,8 +273,7 @@ public class StarterJpaConfig {
|
||||
IPackageInstallerSvc packageInstallerSvc,
|
||||
ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc,
|
||||
ApplicationContext appContext,
|
||||
Optional<IpsOperationProvider> theIpsOperationProvider,
|
||||
Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
|
||||
Optional<IpsOperationProvider> theIpsOperationProvider, Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
|
||||
RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext());
|
||||
|
||||
List<String> supportedResourceTypes = appProperties.getSupported_resource_types();
|
||||
|
||||
@@ -9,20 +9,10 @@ import java.io.IOException;
|
||||
public interface IImplementationGuideOperationProvider {
|
||||
static PackageInstallationSpec toPackageInstallationSpec(byte[] npmPackageAsByteArray) throws IOException {
|
||||
NpmPackage npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(npmPackageAsByteArray));
|
||||
return new PackageInstallationSpec()
|
||||
.setName(npmPackage.name())
|
||||
.setPackageContents(npmPackageAsByteArray)
|
||||
.setVersion(npmPackage.version())
|
||||
.setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL)
|
||||
.setFetchDependencies(false);
|
||||
return new PackageInstallationSpec().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
|
||||
// Base64BinaryType would bind to a separate version
|
||||
// @Operation(name = "$install", typeName = "ImplementationGuide")
|
||||
|
||||
// The following declaration is the one that counts but cannot be used across different versions as stating Base64BinaryType would bind to a separate version
|
||||
// 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) ;
|
||||
|
||||
}
|
||||
|
||||
@@ -23,12 +23,10 @@ public class ImplementationGuideR4OperationProvider implements IImplementationGu
|
||||
}
|
||||
|
||||
@Operation(name = "$install", typeName = "ImplementationGuide")
|
||||
public Parameters install(
|
||||
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
||||
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
||||
try {
|
||||
|
||||
packageInstallerSvc.install(
|
||||
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
||||
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -36,10 +34,10 @@ public class ImplementationGuideR4OperationProvider implements IImplementationGu
|
||||
}
|
||||
|
||||
@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) {
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,21 +23,19 @@ public class ImplementationGuideR5OperationProvider implements IImplementationGu
|
||||
}
|
||||
|
||||
@Operation(name = "$install", typeName = "ImplementationGuide")
|
||||
public Parameters install(
|
||||
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
||||
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
||||
try {
|
||||
|
||||
packageInstallerSvc.install(
|
||||
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
||||
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
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) {
|
||||
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
|
||||
baselineOnMigrate: true
|
||||
datasource:
|
||||
url: 'jdbc:h2:file:./target/database/h2'
|
||||
#url: jdbc:h2:mem:test_mem
|
||||
#url: 'jdbc:h2:file:./target/database/h2'
|
||||
url: jdbc:h2:mem:test_mem
|
||||
username: sa
|
||||
password: null
|
||||
driverClassName: org.h2.Driver
|
||||
@@ -76,10 +76,12 @@ hapi:
|
||||
### forces the use of the https:// protocol for the returned server address.
|
||||
### alternatively, it may be set using the X-Forwarded-Proto header.
|
||||
# use_apache_address_strategy_https: false
|
||||
### enables the server to host content like HTML, css, etc. under the url pattern of eg. /static/**
|
||||
# staticLocationPrefix: /static
|
||||
### 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/**
|
||||
#staticLocation: file:/foo/bar/bazz
|
||||
### enables the server to overwrite defaults on HTML, css, etc. under the url pattern of eg. /content/custom **
|
||||
### Folder with custom content MUST be named custom. If omitted then default content applies
|
||||
#custom_content_path: ./custom
|
||||
### 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
|
||||
# server_address: http://hapi.fhir.org/baseR4
|
||||
# defer_indexing_for_codesystems_of_size: 101
|
||||
|
||||
@@ -21,21 +21,23 @@
|
||||
<h3 class="panel-title">About This Server</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<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/jamesagnew/hapi-fhir/">HAPI FHIR</a>
|
||||
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
|
||||
implementation of the FHIR specification.
|
||||
</p>
|
||||
<p>
|
||||
<div id="replacementAbout">
|
||||
<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>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
@@ -55,6 +57,41 @@
|
||||
</div>
|
||||
|
||||
<div th:replace="tmpl-footer :: footer"></div>
|
||||
</form>
|
||||
</form>
|
||||
</body>
|
||||
</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>
|
||||
<html lang="en">
|
||||
<div th:fragment="banner">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<img src="img/sample-logo.jpg" width="383" alt="Sample Logo" />
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<img src="img/hapi_fhir_banner_right.png" align="right" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<img id="logo" src="img/sample-logo.jpg" width="383" alt="Sample Logo"/>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<img src="img/hapi_fhir_banner_right.png" align="right"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 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>
|
||||
<script>
|
||||
const customlogoImageUrl = "content/custom/logo.jpg"; // Custom logo
|
||||
const defaultLogoImageUrl = "img/sample-logo.jpg"; // Default logo
|
||||
const logoImageElement = document.getElementById("logo");
|
||||
|
||||
// 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>
|
||||
</html>
|
||||
|
||||
@@ -1,16 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<div th:fragment="banner" class="well">
|
||||
<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/jamesagnew/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 th:fragment="banner" class="well" >
|
||||
<script>
|
||||
console.log('Hello')
|
||||
// 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 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>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user