mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 20:50:44 +00:00
CE-1772 - update fileDownload adornment type to be able to specify a process name or custom code-ref, to run along with downloading a field's file.
This commit is contained in:
@ -529,10 +529,16 @@ public class QValueFormatter
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// if field type is blob, update its value //
|
||||
/////////////////////////////////////////////
|
||||
if(QFieldType.BLOB.equals(field.getType()))
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if field type is blob OR if there's a supplemental process or code-ref that needs to run - //
|
||||
// then update its value to be a callback-url that'll give access to the bytes to download //
|
||||
// implied here is that a String value (w/o supplemental code/proc) has its value stay as a //
|
||||
// URL, which is where the file is directly downloaded from. And in the case of a String //
|
||||
// with code-to-run, then the code should run, followed by a redirect to the value URL. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(QFieldType.BLOB.equals(field.getType())
|
||||
|| adornmentValues.containsKey(AdornmentType.FileDownloadValues.SUPPLEMENTAL_CODE_REFERENCE)
|
||||
|| adornmentValues.containsKey(AdornmentType.FileDownloadValues.SUPPLEMENTAL_PROCESS_NAME))
|
||||
{
|
||||
record.setValue(field.getName(), "/data/" + table.getName() + "/" + primaryKey + "/" + field.getName() + "/" + fileName);
|
||||
}
|
||||
|
@ -68,6 +68,9 @@ public enum AdornmentType
|
||||
String DEFAULT_EXTENSION = "defaultExtension";
|
||||
String DEFAULT_MIME_TYPE = "defaultMimeType";
|
||||
|
||||
String SUPPLEMENTAL_PROCESS_NAME = "supplementalProcessName";
|
||||
String SUPPLEMENTAL_CODE_REFERENCE = "supplementalCodeReference";
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// use these two together, as in: //
|
||||
// FILE_NAME_FORMAT = "Order %s Packing Slip.pdf" //
|
||||
|
@ -44,6 +44,7 @@ import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncJobManager;
|
||||
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||
import com.kingsrook.qqq.backend.core.actions.dashboard.RenderWidgetAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.metadata.MetaDataAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.metadata.ProcessMetaDataAction;
|
||||
@ -51,6 +52,8 @@ import com.kingsrook.qqq.backend.core.actions.metadata.TableMetaDataAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionCheckResult;
|
||||
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionsHelper;
|
||||
import com.kingsrook.qqq.backend.core.actions.permissions.TablePermissionSubType;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.QProcessCallbackFactory;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.ExportAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
||||
@ -77,6 +80,7 @@ import com.kingsrook.qqq.backend.core.model.actions.metadata.ProcessMetaDataInpu
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.ProcessMetaDataOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
|
||||
@ -106,6 +110,7 @@ import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
@ -130,6 +135,7 @@ import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder;
|
||||
import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeConsumer;
|
||||
import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeFunction;
|
||||
import com.kingsrook.qqq.middleware.javalin.misc.DownloadFileSupplementalAction;
|
||||
import io.javalin.Javalin;
|
||||
import io.javalin.apibuilder.EndpointGroup;
|
||||
import io.javalin.http.Context;
|
||||
@ -1089,12 +1095,13 @@ public class QJavalinImplementation
|
||||
throw (new QNotFoundException("Could not find " + table.getLabel() + " with " + table.getFields().get(table.getPrimaryKeyField()).getLabel() + " of " + primaryKey));
|
||||
}
|
||||
|
||||
String mimeType = null;
|
||||
Optional<FieldAdornment> fileDownloadAdornment = fieldMetaData.getAdornments().stream().filter(a -> a.getType().equals(AdornmentType.FILE_DOWNLOAD)).findFirst();
|
||||
String mimeType = null;
|
||||
Optional<FieldAdornment> fileDownloadAdornment = fieldMetaData.getAdornments().stream().filter(a -> a.getType().equals(AdornmentType.FILE_DOWNLOAD)).findFirst();
|
||||
Map<String, Serializable> adornmentValues = null;
|
||||
if(fileDownloadAdornment.isPresent())
|
||||
{
|
||||
Map<String, Serializable> values = fileDownloadAdornment.get().getValues();
|
||||
mimeType = ValueUtils.getValueAsString(values.get(AdornmentType.FileDownloadValues.DEFAULT_MIME_TYPE));
|
||||
adornmentValues = fileDownloadAdornment.get().getValues();
|
||||
mimeType = ValueUtils.getValueAsString(adornmentValues.get(AdornmentType.FileDownloadValues.DEFAULT_MIME_TYPE));
|
||||
}
|
||||
|
||||
if(mimeType != null)
|
||||
@ -1107,7 +1114,56 @@ public class QJavalinImplementation
|
||||
context.header("Content-Disposition", "attachment; filename=" + filename);
|
||||
}
|
||||
|
||||
context.result(getOutput.getRecord().getValueByteArray(fieldName));
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if the adornment has a supplemental process name in it, or a supplemental code reference //
|
||||
// then execute that custom code - e.g., to log that the file was downloaded. //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(fileDownloadAdornment.isPresent())
|
||||
{
|
||||
String processName = ValueUtils.getValueAsString(adornmentValues.get(AdornmentType.FileDownloadValues.SUPPLEMENTAL_PROCESS_NAME));
|
||||
if(StringUtils.hasContent(processName))
|
||||
{
|
||||
RunProcessInput input = new RunProcessInput();
|
||||
input.setProcessName(processName);
|
||||
input.setCallback(QProcessCallbackFactory.forRecord(getOutput.getRecord()));
|
||||
input.setFrontendStepBehavior(RunProcessInput.FrontendStepBehavior.SKIP);
|
||||
input.addValue("tableName", tableName);
|
||||
input.addValue("primaryKey", primaryKey);
|
||||
input.addValue("fieldName", fieldName);
|
||||
input.addValue("filename", filename);
|
||||
new RunProcessAction().execute(input);
|
||||
}
|
||||
else if(adornmentValues.containsKey(AdornmentType.FileDownloadValues.SUPPLEMENTAL_CODE_REFERENCE))
|
||||
{
|
||||
QCodeReference codeReference = (QCodeReference) adornmentValues.get(AdornmentType.FileDownloadValues.SUPPLEMENTAL_CODE_REFERENCE);
|
||||
|
||||
DownloadFileSupplementalAction action = QCodeLoader.getAdHoc(DownloadFileSupplementalAction.class, codeReference);
|
||||
|
||||
DownloadFileSupplementalAction.DownloadFileSupplementalActionInput input = new DownloadFileSupplementalAction.DownloadFileSupplementalActionInput()
|
||||
.withTableName(tableName)
|
||||
.withFieldName(fieldName)
|
||||
.withPrimaryKey(primaryKey)
|
||||
.withFileName(filename);
|
||||
|
||||
DownloadFileSupplementalAction.DownloadFileSupplementalActionOutput output = new DownloadFileSupplementalAction.DownloadFileSupplementalActionOutput();
|
||||
action.run(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// if the field is a BLOB - send the bytes to the user //
|
||||
/////////////////////////////////////////////////////////
|
||||
if(QFieldType.BLOB.equals(fieldMetaData.getType()))
|
||||
{
|
||||
context.result(getOutput.getRecord().getValueByteArray(fieldName));
|
||||
}
|
||||
else
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// else - assume a string is a URL - and issue a redirect to it //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
context.redirect(getOutput.getRecord().getValueString(fieldName));
|
||||
}
|
||||
|
||||
QJavalinAccessLogger.logEndSuccess();
|
||||
}
|
||||
|
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.middleware.javalin.misc;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** custom code that can run when user downloads a file. Set as a code-reference
|
||||
** on a field adornment.
|
||||
*******************************************************************************/
|
||||
public interface DownloadFileSupplementalAction
|
||||
{
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
void run(DownloadFileSupplementalActionInput input, DownloadFileSupplementalActionOutput output) throws QException;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
class DownloadFileSupplementalActionInput
|
||||
{
|
||||
private String tableName;
|
||||
private String primaryKey;
|
||||
private String fieldName;
|
||||
private String fileName;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for tableName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getTableName()
|
||||
{
|
||||
return tableName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for tableName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setTableName(String tableName)
|
||||
{
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for tableName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public DownloadFileSupplementalActionInput withTableName(String tableName)
|
||||
{
|
||||
this.tableName = tableName;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for primaryKey
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getPrimaryKey()
|
||||
{
|
||||
return primaryKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for primaryKey
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setPrimaryKey(String primaryKey)
|
||||
{
|
||||
this.primaryKey = primaryKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for primaryKey
|
||||
**
|
||||
*******************************************************************************/
|
||||
public DownloadFileSupplementalActionInput withPrimaryKey(String primaryKey)
|
||||
{
|
||||
this.primaryKey = primaryKey;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for fieldName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getFieldName()
|
||||
{
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for fieldName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setFieldName(String fieldName)
|
||||
{
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for fieldName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public DownloadFileSupplementalActionInput withFieldName(String fieldName)
|
||||
{
|
||||
this.fieldName = fieldName;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for fileName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getFileName()
|
||||
{
|
||||
return fileName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for fileName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setFileName(String fileName)
|
||||
{
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for fileName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public DownloadFileSupplementalActionInput withFileName(String fileName)
|
||||
{
|
||||
this.fileName = fileName;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
class DownloadFileSupplementalActionOutput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -29,8 +29,11 @@ import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QCollectingLogger;
|
||||
@ -39,12 +42,19 @@ import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReferenceLambda;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.implementations.mock.MockBackendModule;
|
||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.SleepUtils;
|
||||
import com.kingsrook.qqq.middleware.javalin.misc.DownloadFileSupplementalAction;
|
||||
import kong.unirest.HttpResponse;
|
||||
import kong.unirest.Unirest;
|
||||
import org.apache.logging.log4j.Level;
|
||||
@ -282,6 +292,69 @@ class QJavalinImplementationTest extends QJavalinTestBase
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** test downloading from a URL field
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_dataDownloadRecordFieldUrl()
|
||||
{
|
||||
try
|
||||
{
|
||||
TestDownloadFileSupplementalAction.callCount = 0;
|
||||
|
||||
Unirest.config().followRedirects(false);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// first request - has no custom code - should just give us back a redirect to the value in the field //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HttpResponse<String> response = Unirest.get(BASE_URL + "/data/person/1/licenseScanPdfUrl/License-1.pdf").asString();
|
||||
assertEquals(302, response.getStatus());
|
||||
assertThat(response.getHeaders().get("location").get(0)).contains("https://");
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// set a code-reference on the download adornment //
|
||||
////////////////////////////////////////////////////
|
||||
Optional<FieldAdornment> fileDownloadAdornment = QJavalinImplementation.getQInstance().getTable(TestUtils.TABLE_NAME_PERSON)
|
||||
.getField("licenseScanPdfUrl")
|
||||
.getAdornment(AdornmentType.FILE_DOWNLOAD);
|
||||
fileDownloadAdornment.get().withValue(AdornmentType.FileDownloadValues.SUPPLEMENTAL_CODE_REFERENCE, new QCodeReference(TestDownloadFileSupplementalAction.class));
|
||||
|
||||
/////////////////////////////////////////
|
||||
// request again - assert the code ran //
|
||||
/////////////////////////////////////////
|
||||
assertEquals(0, TestDownloadFileSupplementalAction.callCount);
|
||||
response = Unirest.get(BASE_URL + "/data/person/1/licenseScanPdfUrl/License-1.pdf").asString();
|
||||
assertEquals(302, response.getStatus());
|
||||
assertThat(response.getHeaders().get("location").get(0)).contains("https://");
|
||||
assertEquals(1, TestDownloadFileSupplementalAction.callCount);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// set adornment to run process (note, leaving the code-ref - this demonstrates that process "trumps" if both exist) //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
AtomicInteger processRunCount = new AtomicInteger(0);
|
||||
QJavalinImplementation.getQInstance().addProcess(new QProcessMetaData().withName("testDownloadProcess").withStep(
|
||||
new QBackendStepMetaData().withName("execute").withCode(new QCodeReferenceLambda<BackendStep>((input, output) -> processRunCount.incrementAndGet()))
|
||||
));
|
||||
fileDownloadAdornment.get().withValue(AdornmentType.FileDownloadValues.SUPPLEMENTAL_PROCESS_NAME, "testDownloadProcess");
|
||||
|
||||
/////////////////////////////////////////
|
||||
// request again - assert the code ran //
|
||||
/////////////////////////////////////////
|
||||
response = Unirest.get(BASE_URL + "/data/person/1/licenseScanPdfUrl/License-1.pdf").asString();
|
||||
assertEquals(302, response.getStatus());
|
||||
assertThat(response.getHeaders().get("location").get(0)).contains("https://");
|
||||
assertEquals(1, TestDownloadFileSupplementalAction.callCount);
|
||||
assertEquals(1, processRunCount.get());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Unirest.config().reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** test a table get (single record) for an id that isn't found
|
||||
**
|
||||
@ -1395,4 +1468,19 @@ class QJavalinImplementationTest extends QJavalinTestBase
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static class TestDownloadFileSupplementalAction implements DownloadFileSupplementalAction
|
||||
{
|
||||
static int callCount = 0;
|
||||
|
||||
@Override
|
||||
public void run(DownloadFileSupplementalActionInput input, DownloadFileSupplementalActionOutput output) throws QException
|
||||
{
|
||||
callCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.javalin;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@ -316,6 +317,8 @@ public class TestUtils
|
||||
.withField(new QFieldMetaData("testScriptId", QFieldType.INTEGER).withBackendName("test_script_id"))
|
||||
.withField(new QFieldMetaData("photo", QFieldType.BLOB).withBackendName("photo"))
|
||||
.withField(new QFieldMetaData("photoFileName", QFieldType.STRING).withBackendName("photo_file_name"))
|
||||
.withField(new QFieldMetaData("licenseScanPdfUrl", QFieldType.STRING).withBackendName("license_scan_pdf_url"))
|
||||
|
||||
.withAssociation(new Association().withName("pets").withJoinName("personJoinPet").withAssociatedTableName(TABLE_NAME_PET))
|
||||
.withAssociatedScript(new AssociatedScript()
|
||||
.withFieldName("testScriptId")
|
||||
@ -331,6 +334,11 @@ public class TestUtils
|
||||
.withValue(AdornmentType.FileDownloadValues.DEFAULT_MIME_TYPE, "image")
|
||||
.withValue(AdornmentType.FileDownloadValues.FILE_NAME_FIELD, "photoFileName"));
|
||||
|
||||
qTableMetaData.getField("licenseScanPdfUrl")
|
||||
.withFieldAdornment(new FieldAdornment(AdornmentType.FILE_DOWNLOAD)
|
||||
.withValue(AdornmentType.FileDownloadValues.FILE_NAME_FORMAT, "License-%s.pdf")
|
||||
.withValue(AdornmentType.FileDownloadValues.FILE_NAME_FORMAT_FIELDS, new ArrayList<>(List.of("id"))));
|
||||
|
||||
return (qTableMetaData);
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,11 @@ CREATE TABLE person
|
||||
partner_person_id INT,
|
||||
test_script_id INT,
|
||||
photo BLOB,
|
||||
photo_file_name VARCHAR(50)
|
||||
photo_file_name VARCHAR(50),
|
||||
license_scan_pdf_url VARCHAR(250)
|
||||
);
|
||||
|
||||
INSERT INTO person (id, first_name, last_name, birth_date, email, partner_person_id, photo, photo_file_name) VALUES (1, 'Darin', 'Kelkhoff', '1980-05-31', 'darin.kelkhoff@gmail.com', 6, '12345', 'darin-photo.png');
|
||||
INSERT INTO person (id, first_name, last_name, birth_date, email, partner_person_id, photo, photo_file_name, license_scan_pdf_url) VALUES (1, 'Darin', 'Kelkhoff', '1980-05-31', 'darin.kelkhoff@gmail.com', 6, '12345', 'darin-photo.png', 'https://somedomain/somepath.pdf');
|
||||
INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (2, 'James', 'Maes', '1980-05-15', 'jmaes@mmltholdings.com');
|
||||
INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (3, 'Tim', 'Chamberlain', '1976-05-28', 'tchamberlain@mmltholdings.com');
|
||||
INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (4, 'Tyler', 'Samples', '1990-01-01', 'tsamples@mmltholdings.com');
|
||||
|
Reference in New Issue
Block a user