diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/SavedReportsMetaDataProvider.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/SavedReportsMetaDataProvider.java index 47d3df3a..dd706df9 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/SavedReportsMetaDataProvider.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/SavedReportsMetaDataProvider.java @@ -52,6 +52,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.Tier; import com.kingsrook.qqq.backend.core.processes.implementations.savedreports.RenderSavedReportMetaDataProducer; +import com.kingsrook.qqq.backend.core.processes.implementations.savedreports.RunScheduledReportMetaDataProducer; /******************************************************************************* @@ -63,6 +64,8 @@ public class SavedReportsMetaDataProvider public static final String SAVED_REPORT_JOIN_SCHEDULED_REPORT = "scheduledReportJoinSavedReport"; + public static final String SCHEDULED_REPORT_VALUES_WIDGET = "scheduledReportValuesWidget"; + public static final String RENDER_REPORT_PROCESS_VALUES_WIDGET = "renderReportProcessValuesWidget"; /******************************************************************************* @@ -85,6 +88,7 @@ public class SavedReportsMetaDataProvider .filter(f -> RenderSavedReportMetaDataProducer.FIELD_NAME_STORAGE_TABLE_NAME.equals(f.getName())) .findFirst() .ifPresent(f -> f.setDefaultValue(REPORT_STORAGE_TABLE_NAME)); + instance.addWidget(defineRenderReportProcessValuesWidget()); instance.addWidget(defineReportSetupWidget()); instance.addWidget(definePivotTableSetupWidget()); @@ -98,6 +102,10 @@ public class SavedReportsMetaDataProvider instance.addWidget(defineScheduledReportJoinSavedReportWidget(join)); QProcessMetaData scheduledReportSyncToScheduledJobProcess = new ScheduledReportSyncToScheduledJobProcess().produce(instance); instance.addProcess(scheduledReportSyncToScheduledJobProcess); + instance.addWidget(defineScheduledReportValuesWidget()); + + QProcessMetaData runScheduledReportProcess = new RunScheduledReportMetaDataProducer().produce(instance); + instance.addProcess(runScheduledReportProcess); if(instance.getPossibleValueSource(TimeZonePossibleValueSourceMetaDataProvider.NAME) == null) { @@ -107,6 +115,36 @@ public class SavedReportsMetaDataProvider + /******************************************************************************* + ** + *******************************************************************************/ + private QWidgetMetaDataInterface defineScheduledReportValuesWidget() + { + return new QWidgetMetaData() + .withName(SCHEDULED_REPORT_VALUES_WIDGET) + .withType(WidgetType.DYNAMIC_FORM.getType()) + .withIsCard(true) + .withLabel("Variable Values") + .withCodeReference(new QCodeReference(ReportValuesDynamicFormWidgetRenderer.class)); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private QWidgetMetaDataInterface defineRenderReportProcessValuesWidget() + { + return new QWidgetMetaData() + .withName(RENDER_REPORT_PROCESS_VALUES_WIDGET) + .withType(WidgetType.DYNAMIC_FORM.getType()) + .withIsCard(false) + .withDefaultValue("isEditable", true) + .withCodeReference(new QCodeReference(ReportValuesDynamicFormWidgetRenderer.class)); + } + + + /******************************************************************************* ** *******************************************************************************/ @@ -277,7 +315,8 @@ public class SavedReportsMetaDataProvider .withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "savedReportId"))) .withSection(new QFieldSection("settings", new QIcon().withName("settings"), Tier.T2, List.of("cronExpression", "cronTimeZoneId", "isActive", "format"))) .withSection(new QFieldSection("recipient", new QIcon().withName("email"), Tier.T2, List.of("toAddresses", "subject"))) - .withSection(new QFieldSection("variableValues", new QIcon().withName("data_object"), Tier.T2, List.of("inputValues"))) + .withSection(new QFieldSection("variableValues", new QIcon().withName("data_object"), Tier.T2).withWidgetName(SCHEDULED_REPORT_VALUES_WIDGET)) + .withSection(new QFieldSection("hidden", new QIcon().withName("visibility_off"), Tier.T2, List.of("inputValues")).withIsHidden(true)) .withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate"))); if(backendDetailEnricher != null) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/ScheduledReportSyncToScheduledJobProcess.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/ScheduledReportSyncToScheduledJobProcess.java index f4f6a5ee..68f0cbd3 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/ScheduledReportSyncToScheduledJobProcess.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/ScheduledReportSyncToScheduledJobProcess.java @@ -41,7 +41,7 @@ import com.kingsrook.qqq.backend.core.model.scheduledjobs.ScheduledJob; import com.kingsrook.qqq.backend.core.model.scheduledjobs.ScheduledJobParameter; import com.kingsrook.qqq.backend.core.model.scheduledjobs.ScheduledJobType; import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend.StreamedETLWithFrontendProcess; -import com.kingsrook.qqq.backend.core.processes.implementations.savedreports.RenderSavedReportMetaDataProducer; +import com.kingsrook.qqq.backend.core.processes.implementations.savedreports.RunScheduledReportMetaDataProducer; import com.kingsrook.qqq.backend.core.processes.implementations.tablesync.AbstractTableSyncTransformStep; import com.kingsrook.qqq.backend.core.processes.implementations.tablesync.TableSyncProcess; import com.kingsrook.qqq.backend.core.utils.ValueUtils; @@ -121,7 +121,7 @@ public class ScheduledReportSyncToScheduledJobProcess extends AbstractTableSyncT scheduledJob.setForeignKeyValue(String.valueOf(scheduledReport.getId())); scheduledJob.setJobParameters(List.of( new ScheduledJobParameter().withKey("processName").withValue(getProcessNameScheduledJobParameter()), - new ScheduledJobParameter().withKey("scheduledReportId").withValue(ValueUtils.getValueAsString(scheduledReport.getId())) + new ScheduledJobParameter().withKey("recordId").withValue(ValueUtils.getValueAsString(scheduledReport.getId())) )); } else @@ -160,7 +160,7 @@ public class ScheduledReportSyncToScheduledJobProcess extends AbstractTableSyncT *******************************************************************************/ private static String getProcessNameScheduledJobParameter() { - return RenderSavedReportMetaDataProducer.NAME; + return RunScheduledReportMetaDataProducer.NAME; } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportExecuteStep.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportExecuteStep.java index d75e74c1..73006358 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportExecuteStep.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportExecuteStep.java @@ -100,6 +100,7 @@ public class RenderSavedReportExecuteStep implements BackendStep String storageTableName = runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_STORAGE_TABLE_NAME); ReportFormat reportFormat = ReportFormat.fromString(runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_REPORT_FORMAT)); String sendToEmailAddress = runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_EMAIL_ADDRESS); + String emailSubject = runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_EMAIL_SUBJECT); SavedReport savedReport = new SavedReport(runBackendStepInput.getRecords().get(0)); String downloadFileBaseName = getDownloadFileBaseName(runBackendStepInput, savedReport); String storageReference = LocalDate.now() + "/" + LocalTime.now().toString().replaceAll(":", "").replaceFirst("\\..*", "") + "/" + UUID.randomUUID() + "/" + downloadFileBaseName + "." + reportFormat.getExtension(); @@ -108,7 +109,7 @@ public class RenderSavedReportExecuteStep implements BackendStep // if sending an email (or emails), validate the addresses before doing anything so user gets error and can fix // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// List toEmailAddressList = new ArrayList<>(); - if(sendToEmailAddress != null) + if(StringUtils.hasContent(sendToEmailAddress)) { toEmailAddressList = validateEmailAddresses(sendToEmailAddress); } @@ -146,6 +147,10 @@ public class RenderSavedReportExecuteStep implements BackendStep .withReportFormat(reportFormat) .withReportOutputStream(outputStream)); + ////////////////////////// + // todo variable-values // + ////////////////////////// + Map values = runBackendStepInput.getValues(); reportInput.setInputValues(values); @@ -192,7 +197,7 @@ public class RenderSavedReportExecuteStep implements BackendStep .withParty(new Party().withAddress(fromEmailAddress).withRole(EmailPartyRole.FROM)) .withParty(new Party().withAddress(replyToEmailAddress).withRole(EmailPartyRole.REPLY_TO)) ) - .withSubject(downloadFileBaseName) + .withSubject(StringUtils.hasContent(emailSubject) ? emailSubject : downloadFileBaseName) .withContent(new Content().withContentRole(EmailContentRole.TEXT).withBody("To download your report, open this URL in your browser: " + downloadURL)) .withContent(new Content().withContentRole(EmailContentRole.HTML).withBody("Link: " + downloadFileName + "")) ); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportMetaDataProducer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportMetaDataProducer.java index 6490fb65..8141e5b5 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportMetaDataProducer.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportMetaDataProducer.java @@ -38,6 +38,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMet import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData; import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport; +import com.kingsrook.qqq.backend.core.model.savedreports.SavedReportsMetaDataProvider; /******************************************************************************* @@ -53,6 +54,7 @@ public class RenderSavedReportMetaDataProducer implements MetaDataProducerInterf public static final String FIELD_NAME_STORAGE_TABLE_NAME = "storageTableName"; public static final String FIELD_NAME_REPORT_FORMAT = "reportFormat"; public static final String FIELD_NAME_EMAIL_ADDRESS = "reportDestinationEmailAddress"; + public static final String FIELD_NAME_EMAIL_SUBJECT = "emailSubject"; @@ -67,6 +69,7 @@ public class RenderSavedReportMetaDataProducer implements MetaDataProducerInterf .withLabel("Render Report") .withTableName(SavedReport.TABLE_NAME) .withIcon(new QIcon().withName("print")) + .addStep(new QBackendStepMetaData() .withName("pre") .withInputData(new QFunctionInputMetaData() @@ -76,18 +79,24 @@ public class RenderSavedReportMetaDataProducer implements MetaDataProducerInterf .withField(new QFieldMetaData(FIELD_NAME_STORAGE_TABLE_NAME, QFieldType.STRING)) .withRecordListMetaData(new QRecordListMetaData().withTableName(SavedReport.TABLE_NAME))) .withCode(new QCodeReference(RenderSavedReportPreStep.class))) + .addStep(new QFrontendStepMetaData() .withName("input") .withComponent(new QFrontendComponentMetaData().withType(QComponentType.EDIT_FORM)) .withFormField(new QFieldMetaData(FIELD_NAME_REPORT_FORMAT, QFieldType.STRING) .withPossibleValueSourceName(ReportFormatPossibleValueEnum.NAME) .withIsRequired(true)) - .withFormField(new QFieldMetaData(FIELD_NAME_EMAIL_ADDRESS, QFieldType.STRING).withLabel("Send To Email Address"))) + .withFormField(new QFieldMetaData(FIELD_NAME_EMAIL_ADDRESS, QFieldType.STRING).withLabel("Send To Email Address")) + .withFormField(new QFieldMetaData(FIELD_NAME_EMAIL_SUBJECT, QFieldType.STRING).withLabel("Email Subject")) + .withComponent(new QFrontendComponentMetaData().withType(QComponentType.WIDGET) + .withValue("widgetName", SavedReportsMetaDataProvider.RENDER_REPORT_PROCESS_VALUES_WIDGET))) + .addStep(new QBackendStepMetaData() .withName("execute") .withInputData(new QFunctionInputMetaData().withRecordListMetaData(new QRecordListMetaData() .withTableName(SavedReport.TABLE_NAME))) .withCode(new QCodeReference(RenderSavedReportExecuteStep.class))) + .addStep(new QFrontendStepMetaData() .withName("output") .withComponent(new QFrontendComponentMetaData().withType(QComponentType.DOWNLOAD_FORM))); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportPreStep.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportPreStep.java index f74298fb..6520812c 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportPreStep.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportPreStep.java @@ -63,17 +63,20 @@ public class RenderSavedReportPreStep implements BackendStep List records = runBackendStepInput.getRecords(); if(!CollectionUtils.nullSafeHasContents(records)) { - throw (new QUserFacingException("No report was selected or found to be rendered.")); + throw (new QUserFacingException("No report was selected or found.")); } if(records.size() > 1) { - throw (new QUserFacingException("You may only render 1 report at a time.")); + throw (new QUserFacingException("You may only run 1 report at a time.")); } + /////////////////////////////////////////////////////////////////////////////////////// + // put the savedReportId in values - this'll get passed into the widget, so it knows // + // what report we're working with, and thus what inputs to prompt for // + /////////////////////////////////////////////////////////////////////////////////////// SavedReport savedReport = new SavedReport(records.get(0)); - - // todo - check for inputs - set up the input screen... + runBackendStepOutput.addValue("savedReportId", savedReport.getId()); } }