Implementing Geoportal_Exporter
This commit is contained in:
parent
57dec57f72
commit
99cfe3976a
|
@ -7,7 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||
## [v2.10.0-SNAPSHOT]
|
||||
|
||||
- GeoPortal-Resolver enhancement: implemented share link towards Geoportal Data-Entry facility [#27135]
|
||||
- Added Geoportal Exporter as PDF [#26026]
|
||||
- Added Geoportal Exporter as PDF [#27274]
|
||||
|
||||
## [v2.9.0]
|
||||
|
||||
|
|
|
@ -19,14 +19,19 @@ import javax.ws.rs.core.MultivaluedMap;
|
|||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
import org.gcube.common.authorization.library.provider.AccessTokenProvider;
|
||||
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
||||
import org.gcube.common.authorization.utils.manager.SecretManager;
|
||||
import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
|
||||
import org.gcube.common.authorization.utils.secret.GCubeSecret;
|
||||
import org.gcube.common.authorization.utils.secret.JWTSecret;
|
||||
import org.gcube.common.authorization.utils.secret.Secret;
|
||||
import org.gcube.common.scope.api.ScopeProvider;
|
||||
import org.gcube.datatransfer.resolver.ConstantsResolver;
|
||||
import org.gcube.datatransfer.resolver.UriResolverServices;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* The Class RequestHandler.
|
||||
*
|
||||
|
@ -44,7 +49,8 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class);
|
||||
|
||||
@Context ServletContext context;
|
||||
@Context
|
||||
ServletContext context;
|
||||
|
||||
@Context
|
||||
HttpServletRequest webRequest;
|
||||
|
@ -55,12 +61,23 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse
|
|||
@Context
|
||||
ResourceContext resourceContext;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.ws.rs.container.ContainerRequestFilter#filter(javax.ws.rs.container.ContainerRequestContext)
|
||||
/**
|
||||
* Filter.
|
||||
*
|
||||
* @param reqContext the req context
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* javax.ws.rs.container.ContainerRequestFilter#filter(javax.ws.rs.container.
|
||||
* ContainerRequestContext)
|
||||
*/
|
||||
@Override
|
||||
public void filter(ContainerRequestContext reqContext) throws IOException {
|
||||
log.info(RequestHandler.class.getSimpleName() + " Request called");
|
||||
setSecretManager(reqContext);
|
||||
|
||||
if (SecurityTokenProvider.instance.get() == null)
|
||||
SecurityTokenProvider.instance.set(context.getInitParameter(ROOT_APP_TOKEN));
|
||||
|
@ -77,15 +94,13 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse
|
|||
log.debug("The path is: {}", path);
|
||||
|
||||
// HOW TO READ THE QUERY STRING
|
||||
/*MultivaluedMap<String, String> queryParameters = reqContext.getUriInfo().getQueryParameters();
|
||||
String queryString = "";
|
||||
try {
|
||||
queryString = Util.toQueryString(queryParameters);
|
||||
}catch (Exception e) {
|
||||
//silent
|
||||
log.warn("Error on reading the query string, trying to continue...");
|
||||
}
|
||||
log.debug("The query string is: {}", queryString);
|
||||
/*
|
||||
* MultivaluedMap<String, String> queryParameters =
|
||||
* reqContext.getUriInfo().getQueryParameters(); String queryString = ""; try {
|
||||
* queryString = Util.toQueryString(queryParameters); }catch (Exception e) {
|
||||
* //silent
|
||||
* log.warn("Error on reading the query string, trying to continue..."); }
|
||||
* log.debug("The query string is: {}", queryString);
|
||||
*/
|
||||
|
||||
if (path == null || path.isEmpty()) {
|
||||
|
@ -118,15 +133,18 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse
|
|||
|
||||
// Try to manage as Catalogue Request ctlg, ctlg-p, etc.
|
||||
if (!resourceToRedirectFound) {
|
||||
log.info("Trying to manage as hard-coded case among cases: {}", Arrays.asList(ConstantsResolver.resourcesHardCoded).toString());
|
||||
log.info("Trying to manage as hard-coded case among cases: {}",
|
||||
Arrays.asList(ConstantsResolver.resourcesHardCoded).toString());
|
||||
String[] hardCode = ConstantsResolver.resourcesHardCoded;
|
||||
|
||||
for (String resource : hardCode) {
|
||||
log.trace("Is requested resource '{}' starting with hard-coded resource '{}'?",requestedResourceName,resource);
|
||||
log.trace("Is requested resource '{}' starting with hard-coded resource '{}'?",
|
||||
requestedResourceName, resource);
|
||||
if (requestedResourceName.startsWith(resource)) {
|
||||
log.trace("Yes it starts!");
|
||||
candidateResource = resource;
|
||||
log.info("The candidate resource to manage the request is the hard-coded resource: {}",candidateResource);
|
||||
log.info("The candidate resource to manage the request is the hard-coded resource: {}",
|
||||
candidateResource);
|
||||
resourceToRedirectFound = true;
|
||||
break;
|
||||
}
|
||||
|
@ -135,7 +153,9 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse
|
|||
}
|
||||
|
||||
} else
|
||||
log.warn("It was not possible to get the resource name from the splitted path {}. No action performed", path);
|
||||
log.warn(
|
||||
"It was not possible to get the resource name from the splitted path {}. No action performed",
|
||||
path);
|
||||
} else {
|
||||
log.warn("It was not possible to split the path {}. No action performed", path);
|
||||
}
|
||||
|
@ -144,12 +164,14 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse
|
|||
}
|
||||
|
||||
if (resourceToRedirectFound) {
|
||||
log.debug("The input request '{}' can be managed by the service '{}'. No redirect performed", path, candidateResource);
|
||||
log.debug("The input request '{}' can be managed by the service '{}'. No redirect performed", path,
|
||||
candidateResource);
|
||||
} else {
|
||||
log.info("No resource/service found to manage the input request '{}'", path);
|
||||
String newPath = String.format("/%s/%s", ConstantsResolver.defaultServiceToRedirect, path);
|
||||
// log.debug("The path to redirect is '{}'", newPath);
|
||||
//URI newRequestURI = reqContext.getUriInfo().getBaseUriBuilder().path(newPath).build();
|
||||
// URI newRequestURI =
|
||||
// reqContext.getUriInfo().getBaseUriBuilder().path(newPath).build();
|
||||
UriBuilder uriBuilder = reqContext.getUriInfo().getBaseUriBuilder();
|
||||
// ADDING THE INPUT QUERY STRING
|
||||
MultivaluedMap<String, String> queryParameters = reqContext.getUriInfo().getQueryParameters();
|
||||
|
@ -165,8 +187,19 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.ws.rs.container.ContainerResponseFilter#filter(javax.ws.rs.container.ContainerRequestContext, javax.ws.rs.container.ContainerResponseContext)
|
||||
/**
|
||||
* Filter.
|
||||
*
|
||||
* @param requestContext the request context
|
||||
* @param responseContext the response context
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* javax.ws.rs.container.ContainerResponseFilter#filter(javax.ws.rs.container.
|
||||
* ContainerRequestContext, javax.ws.rs.container.ContainerResponseContext)
|
||||
*/
|
||||
@Override
|
||||
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
|
||||
|
@ -174,8 +207,49 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse
|
|||
log.info(RequestHandler.class.getSimpleName() + " Response called");
|
||||
SecurityTokenProvider.instance.reset();
|
||||
ScopeProvider.instance.reset();
|
||||
log.info("Token and Scope Provider reset called");
|
||||
log.debug("Token and Scope Provider reset called");
|
||||
resetScretManager(requestContext, responseContext);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset scret manager.
|
||||
*
|
||||
* @param requestContext the request context
|
||||
* @param responseContext the response context
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
private void resetScretManager(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
|
||||
throws IOException {
|
||||
log.debug("SecreteManager instance remove");
|
||||
SecretManagerProvider.instance.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the secret manager.
|
||||
*
|
||||
* @param requestContext the new secret manager
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
private void setSecretManager(ContainerRequestContext requestContext) throws IOException {
|
||||
log.debug("setSecretManager called");
|
||||
|
||||
SecretManagerProvider.instance.remove();
|
||||
SecretManager secretManager = new SecretManager();
|
||||
|
||||
String token = AccessTokenProvider.instance.get();
|
||||
if (token != null) {
|
||||
Secret secret = new JWTSecret(token);
|
||||
secretManager.addSecret(secret);
|
||||
}
|
||||
|
||||
token = SecurityTokenProvider.instance.get();
|
||||
if (token != null) {
|
||||
Secret secret = new GCubeSecret(token);
|
||||
secretManager.addSecret(secret);
|
||||
}
|
||||
|
||||
SecretManagerProvider.instance.set(secretManager);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package org.gcube.datatransfer.resolver.services;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
|
@ -9,17 +12,23 @@ import javax.ws.rs.WebApplicationException;
|
|||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
|
||||
import org.gcube.application.geoportalcommon.GeoportalCommon;
|
||||
import org.gcube.application.geoportalcommon.shared.GeoportalItemReferences;
|
||||
import org.gcube.application.geoportalcommon.shared.GeoportalItemReferences.SHARE_LINK_TO;
|
||||
import org.gcube.application.geoportaldatamapper.exporter.Geoportal_PDF_Exporter;
|
||||
import org.gcube.application.geoportaldatamapper.shared.ExporterProjectSource;
|
||||
import org.gcube.application.geoportaldatamapper.shared.FileReference;
|
||||
import org.gcube.common.authorization.utils.manager.SecretManager;
|
||||
import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
|
||||
import org.gcube.common.authorization.utils.user.User;
|
||||
import org.gcube.datatransfer.resolver.ConstantsResolver;
|
||||
import org.gcube.datatransfer.resolver.geoportal.TargetAppGeoportalCodes;
|
||||
import org.gcube.datatransfer.resolver.services.GeoportalResolver.RESOLVE_AS;
|
||||
import org.gcube.datatransfer.resolver.services.error.ExceptionManager;
|
||||
import org.gcube.datatransfer.resolver.services.exceptions.BadRequestException;
|
||||
import org.gcube.datatransfer.resolver.util.SingleFileStreamingOutput;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -59,11 +68,13 @@ public class GeoportalExporter {
|
|||
*/
|
||||
@GET
|
||||
@Path("/export/{type}/{usecase_id}/{project_id}")
|
||||
@Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN })
|
||||
@Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN, MediaType.APPLICATION_OCTET_STREAM })
|
||||
public Response export(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type,
|
||||
@PathParam(PATH_USECASE_ID) String ucdID, @PathParam(PATH_PROJECT_ID) String projectID)
|
||||
throws WebApplicationException {
|
||||
|
||||
String userAgentName = req.getHeader("User-Agent");
|
||||
|
||||
LOG.info(this.getClass().getSimpleName() + " export - GET starts...");
|
||||
LOG.debug("params are: exportType: {}, ucdID: {}, projectID: {}", export_type, ucdID, projectID);
|
||||
|
||||
|
@ -71,7 +82,7 @@ public class GeoportalExporter {
|
|||
checkPathParameterNotNull(req, PATH_USECASE_ID, ucdID);
|
||||
checkPathParameterNotNull(req, PATH_PROJECT_ID, projectID);
|
||||
|
||||
ACCEPTED_EXPORT_TYPE exportType = toKnowExportType(req, export_type);
|
||||
checkExportType(req, export_type);
|
||||
|
||||
try {
|
||||
|
||||
|
@ -87,43 +98,56 @@ public class GeoportalExporter {
|
|||
Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter();
|
||||
boolean checked = pdfExporter.checkConfig();
|
||||
|
||||
if (!checked)
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
|
||||
ExporterProjectSource exporterSource = new ExporterProjectSource();
|
||||
RESOLVE_AS resolveAs = RESOLVE_AS.PUBLIC;
|
||||
// #NB SET USERNAME = null to export with PUBLIC ACCESS
|
||||
if (!cm.getUser().isApplication()) {
|
||||
// here the token is of an user
|
||||
resolveAs = RESOLVE_AS.PRIVATE;
|
||||
exporterSource.setAccountname(user.getUsername());
|
||||
}
|
||||
|
||||
exporterSource.setScope(context);
|
||||
exporterSource.setProjectID(projectID);
|
||||
exporterSource.setProfileID(ucdID);
|
||||
|
||||
String vreName = context.substring(context.lastIndexOf("/") + 1, context.length());
|
||||
LOG.info("Requesting gis link to vre {}", vreName);
|
||||
Response theReponseWithLink = new GeoportalResolver().genericResolveLink(req,
|
||||
TargetAppGeoportalCodes.GEO_DV, vreName, ucdID, projectID, resolveAs.name());
|
||||
String theGisLink = theReponseWithLink.getEntity().toString();
|
||||
LOG.info("Gis link returned {}", theGisLink);
|
||||
exporterSource.setGisLink(theGisLink);
|
||||
// ExporterProjectSource exporterSource = new ExporterProjectSource();
|
||||
// RESOLVE_AS resolveAs = RESOLVE_AS.PUBLIC;
|
||||
// // #NB SET USERNAME = null to export with PUBLIC ACCESS
|
||||
// if (!cm.getUser().isApplication()) {
|
||||
// // here the token is of an user
|
||||
// resolveAs = RESOLVE_AS.PRIVATE;
|
||||
// exporterSource.setAccountname(user.getUsername());
|
||||
// }
|
||||
//
|
||||
// exporterSource.setScope(context);
|
||||
// exporterSource.setProjectID(projectID);
|
||||
// exporterSource.setProfileID(ucdID);
|
||||
//
|
||||
// String vreName = context.substring(context.lastIndexOf("/") + 1, context.length());
|
||||
// LOG.info("Requesting gis link to vre {}", vreName);
|
||||
// Response theReponseWithLink = new GeoportalResolver().genericResolveLink(req,
|
||||
// TargetAppGeoportalCodes.GEO_DV, vreName, ucdID, projectID, resolveAs.name());
|
||||
// String theGisLink = theReponseWithLink.getEntity().toString();
|
||||
// LOG.info("Gis link returned {}", theGisLink);
|
||||
// exporterSource.setGisLink(theGisLink);
|
||||
|
||||
if (checked) {
|
||||
String pdfURL = null;
|
||||
if (userAgentName != null) {
|
||||
LOG.info("Serving request as User-Agent {}", userAgentName);
|
||||
String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true);
|
||||
return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html")
|
||||
.build();
|
||||
} else {
|
||||
return Response.status(Status.NOT_FOUND).entity(GeoportalExporter.class.getSimpleName() + " Config KO")
|
||||
LOG.info("Serving request as client...");
|
||||
FileReference pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user);
|
||||
|
||||
InputStream input = new URL(pdfURL).openStream();
|
||||
StreamingOutput so = new SingleFileStreamingOutput(input);
|
||||
|
||||
ResponseBuilder response = Response.ok(so)
|
||||
.header(ConstantsResolver.CONTENT_DISPOSITION,
|
||||
"inline; filename=\"" + pdfRef.getFileName() + "\"")
|
||||
.header("Content-Type", pdfRef.getContentType());
|
||||
return response.build();
|
||||
}
|
||||
} else {
|
||||
return Response.status(Status.NOT_FOUND)
|
||||
.entity(GeoportalExporter.class.getSimpleName() + " Config not found in the context " + context)
|
||||
.type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error on performing healthcheck", e);
|
||||
throw ExceptionManager.internalErrorException(req,
|
||||
"Error when performing " + GeoportalExporter.class.getSimpleName() + " healthcheck",
|
||||
LOG.error("Error on performing export", e);
|
||||
throw ExceptionManager.internalErrorException(req, "Sorry, error occurred when exporting the project",
|
||||
this.getClass(), helpURI);
|
||||
}
|
||||
|
||||
|
@ -140,7 +164,7 @@ public class GeoportalExporter {
|
|||
|
||||
checkPathParameterNotNull(req, EXPORT_TYPE, export_type);
|
||||
|
||||
ACCEPTED_EXPORT_TYPE exportType = toKnowExportType(req, export_type);
|
||||
checkExportType(req, export_type);
|
||||
|
||||
try {
|
||||
|
||||
|
@ -183,8 +207,7 @@ public class GeoportalExporter {
|
|||
}
|
||||
}
|
||||
|
||||
public ACCEPTED_EXPORT_TYPE toKnowExportType(HttpServletRequest req, String export_type)
|
||||
throws BadRequestException {
|
||||
public ACCEPTED_EXPORT_TYPE checkExportType(HttpServletRequest req, String export_type) throws BadRequestException {
|
||||
ACCEPTED_EXPORT_TYPE exportType;
|
||||
try {
|
||||
exportType = ACCEPTED_EXPORT_TYPE.valueOf(export_type);
|
||||
|
@ -199,6 +222,67 @@ public class GeoportalExporter {
|
|||
return exportType;
|
||||
}
|
||||
|
||||
public FileReference exportAsPDF(HttpServletRequest req, String profileID, String projectID, String profileTitle,
|
||||
String context, User user) throws WebApplicationException {
|
||||
LOG.info("exportAsPDF for profileID: " + profileID + ", projectID: " + projectID + "called");
|
||||
LOG.info("exportAsPDF context is {}, user is {}", context, user);
|
||||
|
||||
FileReference pdfRef = null;
|
||||
try {
|
||||
|
||||
Geoportal_PDF_Exporter gpdfe = new Geoportal_PDF_Exporter();
|
||||
ExporterProjectSource exportSource = new ExporterProjectSource();
|
||||
exportSource.setProfileID(profileID);
|
||||
exportSource.setProfileTitle(profileTitle);
|
||||
exportSource.setProjectID(projectID);
|
||||
exportSource.setScope(context);
|
||||
|
||||
GeoportalItemReferences geoportalItemReferences = new GeoportalItemReferences(projectID, profileID,
|
||||
SHARE_LINK_TO.DATA_VIEWER);
|
||||
GeoportalItemReferences gir = getPublicLinksFor(geoportalItemReferences, context);
|
||||
|
||||
if (user.isApplication()) {
|
||||
exportSource.setGisLink(gir.getOpenLink().getShortURL());
|
||||
exportSource.setAccountname(null);
|
||||
} else {
|
||||
exportSource.setGisLink(gir.getRestrictedLink().getShortURL());
|
||||
exportSource.setAccountname(user.getUsername());
|
||||
}
|
||||
|
||||
pdfRef = gpdfe.createPDFFile(exportSource);
|
||||
|
||||
} catch (Exception e1) {
|
||||
LOG.error("Error occurred when exporting the project", e1);
|
||||
throw ExceptionManager.internalErrorException(req, "Sorry, an error occurred when exporting the project",
|
||||
this.getClass(), helpURI);
|
||||
}
|
||||
return pdfRef;
|
||||
}
|
||||
|
||||
public GeoportalItemReferences getPublicLinksFor(GeoportalItemReferences item, String context) throws Exception {
|
||||
LOG.info("getPublicLinksFor called for: " + item);
|
||||
|
||||
try {
|
||||
|
||||
if (item == null)
|
||||
throw new Exception("Bad request, the item is null");
|
||||
|
||||
if (item.getProjectID() == null)
|
||||
throw new Exception("Bad request, the projectID is null");
|
||||
|
||||
if (item.getProfileID() == null)
|
||||
throw new Exception("Bad request, the profileID is null");
|
||||
|
||||
GeoportalCommon gc = new GeoportalCommon();
|
||||
return gc.getPublicLinksFor(context, item, true);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error on getPublicLinksFor for: " + item, e);
|
||||
throw new Exception("Share link not available for this item. Try later or contact the support. Error: "
|
||||
+ e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the HTML message.
|
||||
*
|
||||
|
@ -210,29 +294,13 @@ public class GeoportalExporter {
|
|||
protected String entityHTMLMessage(String action, String message, boolean waiting) {
|
||||
|
||||
String html = "<html>" + "<head>" + "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">"
|
||||
+ "<style>"
|
||||
+ "html, body {\n"
|
||||
+ " margin: 10px;\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " height: 100%;\n"
|
||||
+ " display: table\n"
|
||||
+ "}\n"
|
||||
+ "#content {\n"
|
||||
+ " position: absolute;\n"
|
||||
+ " left: 50%;\n"
|
||||
+ " top: 50%;\n"
|
||||
+ " -webkit-transform: translate(-50%, -50%);\n"
|
||||
+ " transform: translate(-50%, -50%);\n"
|
||||
+ " text-align: center;\n"
|
||||
+ "}"
|
||||
+ "#message {\n"
|
||||
+ " color:gray;"
|
||||
+ " font-size: 24px;"
|
||||
+ "}"
|
||||
+ "</style>"
|
||||
+ "<style>" + "html, body {\n" + " margin: 10px;\n" + " width: 100%;\n" + " height: 100%;\n"
|
||||
+ " display: table\n" + "}\n" + "#content {\n" + " position: absolute;\n" + " left: 50%;\n"
|
||||
+ " top: 50%;\n" + " -webkit-transform: translate(-50%, -50%);\n"
|
||||
+ " transform: translate(-50%, -50%);\n" + " text-align: center;\n" + "}" + "#message {\n"
|
||||
+ " color:gray;" + " font-size: 24px;" + "}" + "</style>"
|
||||
+ "<title>D4Science Geoportal - Action</title>" + "</head>" + "<body>";
|
||||
|
||||
|
||||
html += "<img alt=\"D4Science Logo\" src=\"https://services.d4science.org/image/layout_set_logo?img_id=32727\"><br />";
|
||||
|
||||
html += "<div id=\"content\">";
|
||||
|
|
Loading…
Reference in New Issue