mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Merged dev into feature/meta-data-loaders
This commit is contained in:
@ -95,8 +95,6 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
||||
@ -1200,15 +1198,18 @@ public class QJavalinImplementation
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
if(backend != null && backend.getUsesVariants())
|
||||
{
|
||||
queryInput.setTableName(backend.getVariantOptionsTableName());
|
||||
queryInput.setFilter(new QQueryFilter(new QFilterCriteria(backend.getVariantOptionsTableTypeField(), QCriteriaOperator.EQUALS, backend.getVariantOptionsTableTypeValue())));
|
||||
QTableMetaData variantsTable = QContext.getQInstance().getTable(backend.getBackendVariantsConfig().getOptionsTableName());
|
||||
|
||||
queryInput.setTableName(variantsTable.getName());
|
||||
queryInput.setFilter(backend.getBackendVariantsConfig().getOptionsFilter());
|
||||
queryInput.setShouldGenerateDisplayValues(true);
|
||||
QueryOutput output = new QueryAction().execute(queryInput);
|
||||
for(QRecord qRecord : output.getRecords())
|
||||
{
|
||||
variants.add(new QFrontendVariant()
|
||||
.withId(qRecord.getValue(backend.getVariantOptionsTableIdField()))
|
||||
.withType(backend.getVariantOptionsTableTypeValue())
|
||||
.withName(qRecord.getValueString(backend.getVariantOptionsTableNameField())));
|
||||
.withId(qRecord.getValue(variantsTable.getPrimaryKeyField()))
|
||||
.withType(backend.getBackendVariantsConfig().getVariantTypeKey())
|
||||
.withName(qRecord.getRecordLabel()));
|
||||
}
|
||||
|
||||
QJavalinAccessLogger.logStartSilent("variants");
|
||||
|
@ -26,6 +26,7 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
@ -50,24 +51,22 @@ import com.kingsrook.qqq.backend.core.actions.processes.CancelProcessAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.QProcessCallback;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.StorageAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QBadRequestException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QPermissionDeniedException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessState;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.QUploadedFile;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
@ -79,9 +78,6 @@ import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMeta
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.state.StateType;
|
||||
import com.kingsrook.qqq.backend.core.state.TempFileStateProvider;
|
||||
import com.kingsrook.qqq.backend.core.state.UUIDAndTypeStateKey;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.ExceptionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||
@ -93,6 +89,7 @@ import io.javalin.apibuilder.EndpointGroup;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.UploadedFile;
|
||||
import org.apache.commons.lang.NotImplementedException;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||
import static io.javalin.apibuilder.ApiBuilder.get;
|
||||
@ -325,7 +322,7 @@ public class QJavalinProcessHandler
|
||||
*******************************************************************************/
|
||||
public static void processInit(Context context)
|
||||
{
|
||||
doProcessInitOrStep(context, null, null, RunProcessInput.FrontendStepBehavior.BREAK);
|
||||
doProcessInitOrStep(context, null, null, null, RunProcessInput.FrontendStepBehavior.BREAK);
|
||||
}
|
||||
|
||||
|
||||
@ -339,7 +336,7 @@ public class QJavalinProcessHandler
|
||||
*******************************************************************************/
|
||||
public static void processRun(Context context)
|
||||
{
|
||||
doProcessInitOrStep(context, null, null, RunProcessInput.FrontendStepBehavior.SKIP);
|
||||
doProcessInitOrStep(context, null, null, null, RunProcessInput.FrontendStepBehavior.SKIP);
|
||||
}
|
||||
|
||||
|
||||
@ -347,7 +344,7 @@ public class QJavalinProcessHandler
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static void doProcessInitOrStep(Context context, String processUUID, String startAfterStep, RunProcessInput.FrontendStepBehavior frontendStepBehavior)
|
||||
private static void doProcessInitOrStep(Context context, String processUUID, String startAfterStep, String startAtStep, RunProcessInput.FrontendStepBehavior frontendStepBehavior)
|
||||
{
|
||||
Map<String, Object> resultForCaller = new HashMap<>();
|
||||
Exception returningException = null;
|
||||
@ -362,8 +359,22 @@ public class QJavalinProcessHandler
|
||||
}
|
||||
resultForCaller.put("processUUID", processUUID);
|
||||
|
||||
LOG.info(startAfterStep == null ? "Initiating process [" + processName + "] [" + processUUID + "]"
|
||||
: "Resuming process [" + processName + "] [" + processUUID + "] after step [" + startAfterStep + "]");
|
||||
if(startAfterStep == null && startAtStep == null)
|
||||
{
|
||||
LOG.info("Initiating process [" + processName + "] [" + processUUID + "]");
|
||||
}
|
||||
else if(startAfterStep != null)
|
||||
{
|
||||
LOG.info("Resuming process [" + processName + "] [" + processUUID + "] after step [" + startAfterStep + "]");
|
||||
}
|
||||
else if(startAtStep != null)
|
||||
{
|
||||
LOG.info("Resuming process [" + processName + "] [" + processUUID + "] at step [" + startAtStep + "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.warn("A logical impossibility was reached, regarding the nullity of startAfterStep and startAtStep, at least given how this code was originally written.");
|
||||
}
|
||||
|
||||
RunProcessInput runProcessInput = new RunProcessInput();
|
||||
QJavalinImplementation.setupSession(context, runProcessInput);
|
||||
@ -372,11 +383,13 @@ public class QJavalinProcessHandler
|
||||
runProcessInput.setFrontendStepBehavior(frontendStepBehavior);
|
||||
runProcessInput.setProcessUUID(processUUID);
|
||||
runProcessInput.setStartAfterStep(startAfterStep);
|
||||
runProcessInput.setStartAtStep(startAtStep);
|
||||
populateRunProcessRequestWithValuesFromContext(context, runProcessInput);
|
||||
|
||||
String reportName = ValueUtils.getValueAsString(runProcessInput.getValue("reportName"));
|
||||
QJavalinAccessLogger.logStart(startAfterStep == null ? "processInit" : "processStep", logPair("processName", processName), logPair("processUUID", processUUID),
|
||||
StringUtils.hasContent(startAfterStep) ? logPair("startAfterStep", startAfterStep) : null,
|
||||
StringUtils.hasContent(startAtStep) ? logPair("startAtStep", startAfterStep) : null,
|
||||
StringUtils.hasContent(reportName) ? logPair("reportName", reportName) : null);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -485,6 +498,7 @@ public class QJavalinProcessHandler
|
||||
}
|
||||
resultForCaller.put("values", runProcessOutput.getValues());
|
||||
runProcessOutput.getProcessState().getNextStepName().ifPresent(nextStep -> resultForCaller.put("nextStep", nextStep));
|
||||
runProcessOutput.getProcessState().getBackStepName().ifPresent(backStep -> resultForCaller.put("backStep", backStep));
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// todo - delete after all frontends look for processMetaDataAdjustment instead of updatedFrontendStepList //
|
||||
@ -531,7 +545,7 @@ public class QJavalinProcessHandler
|
||||
** todo - make query params have a "field-" type of prefix??
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static void populateRunProcessRequestWithValuesFromContext(Context context, RunProcessInput runProcessInput) throws IOException
|
||||
private static void populateRunProcessRequestWithValuesFromContext(Context context, RunProcessInput runProcessInput) throws IOException, QException
|
||||
{
|
||||
//////////////////////////
|
||||
// process query string //
|
||||
@ -562,20 +576,42 @@ public class QJavalinProcessHandler
|
||||
////////////////////////////
|
||||
// process uploaded files //
|
||||
////////////////////////////
|
||||
for(UploadedFile uploadedFile : context.uploadedFiles())
|
||||
for(Map.Entry<String, List<UploadedFile>> entry : context.uploadedFileMap().entrySet())
|
||||
{
|
||||
try(InputStream content = uploadedFile.content())
|
||||
String name = entry.getKey();
|
||||
List<UploadedFile> uploadedFiles = entry.getValue();
|
||||
ArrayList<StorageInput> storageInputs = new ArrayList<>();
|
||||
runProcessInput.addValue(name, storageInputs);
|
||||
|
||||
String storageTableName = QJavalinImplementation.javalinMetaData.getUploadedFileArchiveTableName();
|
||||
if(!StringUtils.hasContent(storageTableName))
|
||||
{
|
||||
QUploadedFile qUploadedFile = new QUploadedFile();
|
||||
qUploadedFile.setBytes(content.readAllBytes());
|
||||
qUploadedFile.setFilename(uploadedFile.filename());
|
||||
throw (new QException("UploadFileArchiveTableName was not specified in javalinMetaData. Cannot accept file uploads."));
|
||||
}
|
||||
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.UPLOADED_FILE);
|
||||
TempFileStateProvider.getInstance().put(key, qUploadedFile);
|
||||
LOG.info("Stored uploaded file in TempFileStateProvider under key: " + key);
|
||||
runProcessInput.addValue(QUploadedFile.DEFAULT_UPLOADED_FILE_FIELD_NAME, key);
|
||||
for(UploadedFile uploadedFile : uploadedFiles)
|
||||
{
|
||||
String reference = QValueFormatter.formatDate(LocalDate.now())
|
||||
+ File.separator + runProcessInput.getProcessName()
|
||||
+ File.separator + UUID.randomUUID()
|
||||
+ File.separator + uploadedFile.filename();
|
||||
|
||||
archiveUploadedFile(runProcessInput, qUploadedFile);
|
||||
StorageInput storageInput = new StorageInput(storageTableName).withReference(reference);
|
||||
storageInputs.add(storageInput);
|
||||
|
||||
try
|
||||
(
|
||||
InputStream content = uploadedFile.content();
|
||||
OutputStream outputStream = new StorageAction().createOutputStream(storageInput);
|
||||
)
|
||||
{
|
||||
content.transferTo(outputStream);
|
||||
LOG.info("Streamed uploaded file", logPair("storageTable", storageTableName), logPair("reference", reference), logPair("processName", runProcessInput.getProcessName()), logPair("uploadFileName", uploadedFile.filename()));
|
||||
}
|
||||
catch(QException e)
|
||||
{
|
||||
throw (new QException("Error creating output stream in table [" + storageTableName + "] for storage action", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -606,27 +642,6 @@ public class QJavalinProcessHandler
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static void archiveUploadedFile(RunProcessInput runProcessInput, QUploadedFile qUploadedFile)
|
||||
{
|
||||
String fileName = QValueFormatter.formatDate(LocalDate.now())
|
||||
+ File.separator + runProcessInput.getProcessName()
|
||||
+ File.separator + qUploadedFile.getFilename();
|
||||
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(QJavalinImplementation.javalinMetaData.getUploadedFileArchiveTableName());
|
||||
insertInput.setRecords(List.of(new QRecord()
|
||||
.withValue("fileName", fileName)
|
||||
.withValue("contents", qUploadedFile.getBytes())
|
||||
));
|
||||
|
||||
new InsertAction().executeAsync(insertInput);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -684,8 +699,19 @@ public class QJavalinProcessHandler
|
||||
public static void processStep(Context context)
|
||||
{
|
||||
String processUUID = context.pathParam("processUUID");
|
||||
String lastStep = context.pathParam("step");
|
||||
doProcessInitOrStep(context, processUUID, lastStep, RunProcessInput.FrontendStepBehavior.BREAK);
|
||||
|
||||
String startAfterStep = null;
|
||||
String startAtStep = null;
|
||||
if(BooleanUtils.isTrue(ValueUtils.getValueAsBoolean(context.queryParam("isStepBack"))))
|
||||
{
|
||||
startAtStep = context.pathParam("step");
|
||||
}
|
||||
else
|
||||
{
|
||||
startAfterStep = context.pathParam("step");
|
||||
}
|
||||
|
||||
doProcessInitOrStep(context, processUUID, startAfterStep, startAtStep, RunProcessInput.FrontendStepBehavior.BREAK);
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,7 +77,8 @@ public class QApplicationJavalinServer
|
||||
private boolean serveLegacyUnversionedMiddlewareAPI = true;
|
||||
private List<AbstractMiddlewareVersion> middlewareVersionList = List.of(new MiddlewareVersionV1());
|
||||
private List<QJavalinRouteProviderInterface> additionalRouteProviders = null;
|
||||
private Consumer<Javalin> javalinConfigurationCustomizer = null;
|
||||
private Consumer<Javalin> javalinConfigurationCustomizer = null;
|
||||
private QJavalinMetaData javalinMetaData = null;
|
||||
|
||||
private long lastQInstanceHotSwapMillis;
|
||||
private long millisBetweenHotSwaps = 2500;
|
||||
@ -115,6 +116,11 @@ public class QApplicationJavalinServer
|
||||
{
|
||||
if(serveFrontendMaterialDashboard)
|
||||
{
|
||||
if(getClass().getResource("/material-dashboard/index.html") == null)
|
||||
{
|
||||
LOG.warn("/material-dashboard/index.html resource was not found. This might happen if you're using a local (e.g., within-IDE) snapshot version... Try updating pom.xml to reference a released version of qfmd?");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// If you have any assets to add to the web server (e.g., logos, icons) place them at //
|
||||
// src/main/resources/material-dashboard-overlay //
|
||||
@ -149,7 +155,7 @@ public class QApplicationJavalinServer
|
||||
{
|
||||
try
|
||||
{
|
||||
QJavalinImplementation qJavalinImplementation = new QJavalinImplementation(qInstance);
|
||||
QJavalinImplementation qJavalinImplementation = new QJavalinImplementation(qInstance, javalinMetaData);
|
||||
config.router.apiBuilder(qJavalinImplementation.getRoutes());
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
@ -623,4 +629,35 @@ public class QApplicationJavalinServer
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for javalinMetaData
|
||||
*******************************************************************************/
|
||||
public QJavalinMetaData getJavalinMetaData()
|
||||
{
|
||||
return (this.javalinMetaData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for javalinMetaData
|
||||
*******************************************************************************/
|
||||
public void setJavalinMetaData(QJavalinMetaData javalinMetaData)
|
||||
{
|
||||
this.javalinMetaData = javalinMetaData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for javalinMetaData
|
||||
*******************************************************************************/
|
||||
public QApplicationJavalinServer withJavalinMetaData(QJavalinMetaData javalinMetaData)
|
||||
{
|
||||
this.javalinMetaData = javalinMetaData;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ public class ProcessInitOrStepInput extends AbstractMiddlewareInput
|
||||
/////////////////////////////////////
|
||||
private String processUUID;
|
||||
private String startAfterStep;
|
||||
// todo - add (in next version?) startAtStep (for back)
|
||||
|
||||
private RunProcessInput.FrontendStepBehavior frontendStepBehavior = RunProcessInput.FrontendStepBehavior.BREAK;
|
||||
|
||||
|
@ -58,6 +58,8 @@ public interface ProcessInitOrStepOrStatusOutputInterface extends AbstractMiddle
|
||||
*******************************************************************************/
|
||||
void setNextStep(String nextStep);
|
||||
|
||||
// todo - add (in next version?) backStep
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for values
|
||||
*******************************************************************************/
|
||||
|
@ -38,6 +38,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QRuntimeException;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIDescription;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIEnumSubSet;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIExclude;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIHasAdditionalProperties;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIIncludeProperties;
|
||||
@ -123,7 +124,25 @@ public class SchemaBuilder
|
||||
if(c.isEnum())
|
||||
{
|
||||
schema.withType(Type.STRING);
|
||||
schema.withEnumValues(Arrays.stream(c.getEnumConstants()).map(e -> String.valueOf(e)).collect(Collectors.toList()));
|
||||
|
||||
if(element.isAnnotationPresent(OpenAPIEnumSubSet.class))
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenAPIEnumSubSet enumSubSetAnnotation = element.getAnnotation(OpenAPIEnumSubSet.class);
|
||||
Class<? extends OpenAPIEnumSubSet.EnumSubSet<?>> enumSubSetClass = enumSubSetAnnotation.value();
|
||||
OpenAPIEnumSubSet.EnumSubSet<?> enumSubSetContainer = enumSubSetClass.getConstructor().newInstance();
|
||||
schema.withEnumValues(enumSubSetContainer.getSubSet().stream().map(e -> String.valueOf(e)).collect(Collectors.toList()));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new QRuntimeException("Error processing OpenAPIEnumSubSet on element: " + element, e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
schema.withEnumValues(Arrays.stream(c.getEnumConstants()).map(e -> String.valueOf(e)).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
else if(c.equals(String.class))
|
||||
{
|
||||
|
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.specs.v1.responses.components;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.ToSchema;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIDescription;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIEnumSubSet;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIExclude;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class FieldAdornment implements ToSchema
|
||||
{
|
||||
@OpenAPIExclude()
|
||||
private com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment wrapped;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public FieldAdornment(com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment wrapped)
|
||||
{
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public FieldAdornment()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static class FieldAdornmentSubSet implements OpenAPIEnumSubSet.EnumSubSet<AdornmentType>
|
||||
{
|
||||
private static EnumSet<AdornmentType> subSet = null;
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@Override
|
||||
public EnumSet<AdornmentType> getSubSet()
|
||||
{
|
||||
if(subSet == null)
|
||||
{
|
||||
EnumSet<AdornmentType> subSet = EnumSet.allOf(AdornmentType.class);
|
||||
subSet.remove(AdornmentType.FILE_UPLOAD); // todo - remove for next version!
|
||||
subSet.remove(AdornmentType.TOOLTIP); // todo - remove for next version!
|
||||
FieldAdornmentSubSet.subSet = subSet;
|
||||
}
|
||||
|
||||
return (subSet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@OpenAPIDescription("Type of this adornment")
|
||||
@OpenAPIEnumSubSet(FieldAdornmentSubSet.class)
|
||||
public AdornmentType getType()
|
||||
{
|
||||
return (this.wrapped == null || this.wrapped.getType() == null ? null : this.wrapped.getType());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@OpenAPIDescription("Values associated with this adornment. Keys and the meanings of their values will differ by type.")
|
||||
public Map<String, Serializable> getValues()
|
||||
{
|
||||
return (this.wrapped.getValues());
|
||||
}
|
||||
|
||||
}
|
@ -23,7 +23,6 @@ package com.kingsrook.qqq.middleware.javalin.specs.v1.responses.components;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.ToSchema;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIDescription;
|
||||
@ -61,6 +60,7 @@ public class FieldMetaData implements ToSchema
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -82,6 +82,7 @@ public class FieldMetaData implements ToSchema
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -92,6 +93,7 @@ public class FieldMetaData implements ToSchema
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -102,6 +104,7 @@ public class FieldMetaData implements ToSchema
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -112,6 +115,7 @@ public class FieldMetaData implements ToSchema
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -122,6 +126,7 @@ public class FieldMetaData implements ToSchema
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -143,6 +148,7 @@ public class FieldMetaData implements ToSchema
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -153,6 +159,7 @@ public class FieldMetaData implements ToSchema
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -166,6 +173,8 @@ public class FieldMetaData implements ToSchema
|
||||
|
||||
// todo - inline PVS
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@ -177,14 +186,17 @@ public class FieldMetaData implements ToSchema
|
||||
|
||||
// todo behaviors?
|
||||
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@OpenAPIDescription("Special UI dressings to add to the field.")
|
||||
@OpenAPIListItems(value = FieldAdornment.class) // todo!
|
||||
@OpenAPIListItems(value = FieldAdornment.class, useRef = true)
|
||||
public List<FieldAdornment> getAdornments()
|
||||
{
|
||||
return (this.wrapped.getAdornments());
|
||||
return (this.wrapped.getAdornments() == null ? null : this.wrapped.getAdornments().stream().map(a -> new FieldAdornment(a)).toList());
|
||||
}
|
||||
|
||||
// todo help content
|
||||
|
@ -23,11 +23,13 @@ package com.kingsrook.qqq.middleware.javalin.specs.v1.responses.components;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QComponentType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendComponentMetaData;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.ToSchema;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIDescription;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIEnumSubSet;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIExclude;
|
||||
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIMapKnownEntries;
|
||||
|
||||
@ -63,10 +65,39 @@ public class FrontendComponent implements ToSchema
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static class QComponentTypeSubSet implements OpenAPIEnumSubSet.EnumSubSet<QComponentType>
|
||||
{
|
||||
private static EnumSet<QComponentType> subSet = null;
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@Override
|
||||
public EnumSet<QComponentType> getSubSet()
|
||||
{
|
||||
if(subSet == null)
|
||||
{
|
||||
EnumSet<QComponentType> subSet = EnumSet.allOf(QComponentType.class);
|
||||
subSet.remove(QComponentType.BULK_LOAD_FILE_MAPPING_FORM);
|
||||
subSet.remove(QComponentType.BULK_LOAD_VALUE_MAPPING_FORM);
|
||||
subSet.remove(QComponentType.BULK_LOAD_PROFILE_FORM);
|
||||
QComponentTypeSubSet.subSet = subSet;
|
||||
}
|
||||
|
||||
return(subSet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@OpenAPIDescription("The type of this component. e.g., what kind of UI element(s) should be presented to the user.")
|
||||
@OpenAPIEnumSubSet(QComponentTypeSubSet.class)
|
||||
public QComponentType getType()
|
||||
{
|
||||
return (this.wrapped.getType());
|
||||
|
@ -130,26 +130,31 @@ components:
|
||||
description: "Description of the error"
|
||||
type: "string"
|
||||
type: "object"
|
||||
FieldAdornment:
|
||||
properties:
|
||||
type:
|
||||
description: "Type of this adornment"
|
||||
enum:
|
||||
- "LINK"
|
||||
- "CHIP"
|
||||
- "SIZE"
|
||||
- "CODE_EDITOR"
|
||||
- "RENDER_HTML"
|
||||
- "REVEAL"
|
||||
- "FILE_DOWNLOAD"
|
||||
- "ERROR"
|
||||
type: "string"
|
||||
values:
|
||||
description: "Values associated with this adornment. Keys and the meanings\
|
||||
\ of their values will differ by type."
|
||||
type: "object"
|
||||
type: "object"
|
||||
FieldMetaData:
|
||||
properties:
|
||||
adornments:
|
||||
description: "Special UI dressings to add to the field."
|
||||
items:
|
||||
properties:
|
||||
type:
|
||||
enum:
|
||||
- "LINK"
|
||||
- "CHIP"
|
||||
- "SIZE"
|
||||
- "CODE_EDITOR"
|
||||
- "RENDER_HTML"
|
||||
- "REVEAL"
|
||||
- "FILE_DOWNLOAD"
|
||||
- "ERROR"
|
||||
type: "string"
|
||||
values:
|
||||
type: "object"
|
||||
type: "object"
|
||||
$ref: "#/components/schemas/FieldAdornment"
|
||||
type: "array"
|
||||
defaultValue:
|
||||
description: "Default value to use in this field."
|
||||
@ -973,21 +978,7 @@ components:
|
||||
adornments:
|
||||
description: "Special UI dressings to add to the field."
|
||||
items:
|
||||
properties:
|
||||
type:
|
||||
enum:
|
||||
- "LINK"
|
||||
- "CHIP"
|
||||
- "SIZE"
|
||||
- "CODE_EDITOR"
|
||||
- "RENDER_HTML"
|
||||
- "REVEAL"
|
||||
- "FILE_DOWNLOAD"
|
||||
- "ERROR"
|
||||
type: "string"
|
||||
values:
|
||||
type: "object"
|
||||
type: "object"
|
||||
$ref: "#/components/schemas/FieldAdornment"
|
||||
type: "array"
|
||||
defaultValue:
|
||||
description: "Default value to use in this field."
|
||||
@ -1483,6 +1474,8 @@ paths:
|
||||
processes:
|
||||
person.bulkInsert:
|
||||
hasPermission: true
|
||||
icon:
|
||||
name: "library_add"
|
||||
isHidden: true
|
||||
label: "Person Bulk Insert"
|
||||
name: "person.bulkInsert"
|
||||
|
@ -40,8 +40,10 @@ import com.kingsrook.qqq.backend.core.logging.QCollectingLogger;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
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.QAuthenticationType;
|
||||
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.authentication.QAuthenticationMetaData;
|
||||
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;
|
||||
@ -1382,6 +1384,7 @@ class QJavalinImplementationTest extends QJavalinTestBase
|
||||
Function<String, QInstance> makeNewInstanceWithBackendName = (backendName) ->
|
||||
{
|
||||
QInstance newInstance = new QInstance();
|
||||
newInstance.setAuthentication(new QAuthenticationMetaData().withType(QAuthenticationType.FULLY_ANONYMOUS).withName("anonymous"));
|
||||
newInstance.addBackend(new QBackendMetaData().withName(backendName).withBackendType(MockBackendModule.class));
|
||||
|
||||
if(!"invalid".equals(backendName))
|
||||
|
Reference in New Issue
Block a user