diff --git a/src/App.tsx b/src/App.tsx
index b0177f8..13e32f8 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -49,6 +49,7 @@ import EntityEdit from "qqq/pages/entity-edit";
import EntityList from "qqq/pages/entity-list";
import EntityView from "qqq/pages/entity-view";
import ProcessRun from "qqq/pages/process-run";
+import ReportRun from "qqq/pages/process-run/ReportRun";
import QClient from "qqq/utils/QClient";
import QProcessUtils from "qqq/utils/QProcessUtils";
@@ -270,6 +271,17 @@ export default function App()
component: ,
});
});
+
+ const reportsForTable = QProcessUtils.getReportsForTable(metaData, table.name, true);
+ reportsForTable.forEach((report) =>
+ {
+ routeList.push({
+ name: report.label,
+ key: report.name,
+ route: `${path}/${report.name}`,
+ component: ,
+ });
+ });
}
else if (app.type === QAppNodeType.PROCESS)
{
@@ -281,6 +293,16 @@ export default function App()
component: ,
});
}
+ else if (app.type === QAppNodeType.REPORT)
+ {
+ const report = metaData.reports.get(app.name);
+ routeList.push({
+ name: `${app.label}`,
+ key: app.name,
+ route: path,
+ component: ,
+ });
+ }
}
try
diff --git a/src/qqq/components/ProcessLinkCard/index.tsx b/src/qqq/components/ProcessLinkCard/index.tsx
index 3aa3cdc..2588ac0 100644
--- a/src/qqq/components/ProcessLinkCard/index.tsx
+++ b/src/qqq/components/ProcessLinkCard/index.tsx
@@ -29,6 +29,7 @@ import MDTypography from "qqq/components/Temporary/MDTypography";
interface Props
{
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark";
+ isReport?: boolean;
title: string;
percentage?: {
color: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "dark" | "white";
@@ -41,7 +42,7 @@ interface Props
}
function ProcessLinkCard({
- color, title, percentage, icon,
+ color, isReport, title, percentage, icon,
}: Props): JSX.Element
{
return (
@@ -81,10 +82,11 @@ function ProcessLinkCard({
>
{percentage.amount}
- Click here to run the process called
- {" "}
- {title}
- .
+ {
+ isReport
+ ? `Click here to run the process called ${title}.`
+ : `Click here to access the ${title} report.`
+ }
{percentage.label}
@@ -94,6 +96,7 @@ function ProcessLinkCard({
ProcessLinkCard.defaultProps = {
color: "info",
+ isReport: false,
percentage: {
color: "success",
text: "",
diff --git a/src/qqq/pages/app-home/index.tsx b/src/qqq/pages/app-home/index.tsx
index d375ed3..827274d 100644
--- a/src/qqq/pages/app-home/index.tsx
+++ b/src/qqq/pages/app-home/index.tsx
@@ -22,6 +22,7 @@ import {QAppMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QApp
import {QAppNodeType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QAppNodeType";
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
+import {QReportMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QReportMetaData";
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
import {Icon} from "@mui/material";
import Card from "@mui/material/Card";
@@ -53,6 +54,7 @@ function AppHome({app}: Props): JSX.Element
const [qInstance, setQInstance] = useState(null as QInstance);
const [tables, setTables] = useState([] as QTableMetaData[]);
const [processes, setProcesses] = useState([] as QProcessMetaData[]);
+ const [reports, setReports] = useState([] as QReportMetaData[]);
const [childApps, setChildApps] = useState([] as QAppMetaData[]);
const [tableCounts, setTableCounts] = useState(new Map());
const [updatedTableCounts, setUpdatedTableCounts] = useState(new Date());
@@ -78,6 +80,7 @@ function AppHome({app}: Props): JSX.Element
const newTables: QTableMetaData[] = [];
const newProcesses: QProcessMetaData[] = [];
+ const newReports: QReportMetaData[] = [];
const newChildApps: QAppMetaData[] = [];
app.children.forEach((child) =>
@@ -91,6 +94,9 @@ function AppHome({app}: Props): JSX.Element
case QAppNodeType.PROCESS:
newProcesses.push(qInstance.processes.get(child.name));
break;
+ case QAppNodeType.REPORT:
+ newReports.push(qInstance.reports.get(child.name));
+ break;
case QAppNodeType.APP:
newChildApps.push(qInstance.apps.get(child.name));
break;
@@ -101,6 +107,7 @@ function AppHome({app}: Props): JSX.Element
setTables(newTables);
setProcesses(newProcesses);
+ setReports(newReports);
setChildApps(newChildApps);
const tableCounts = new Map();
@@ -231,7 +238,6 @@ function AppHome({app}: Props): JSX.Element
{
app.sections ? (
-
{app.sections.map((section) => (
@@ -268,7 +274,42 @@ function AppHome({app}: Props): JSX.Element
) : null
}
{
- section.processes && section.tables ? (
+ section.processes && section.reports ? (
+
+ ) : null
+ }
+ {
+ section.reports ? (
+
+ Reports
+
+ ) : null
+ }
+ {
+ section.reports ? (
+
+ {
+ section.reports.map((reportName) =>
+ {
+ let report = app.childMap.get(reportName);
+ return (
+
+
+
+
+
+ );
+ })
+ }
+
+ ) : null
+ }
+ {
+ section.reports && section.tables ? (
) : null
}
diff --git a/src/qqq/pages/process-run/ReportRun.tsx b/src/qqq/pages/process-run/ReportRun.tsx
new file mode 100644
index 0000000..b048fa9
--- /dev/null
+++ b/src/qqq/pages/process-run/ReportRun.tsx
@@ -0,0 +1,71 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2022. 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 .
+ */
+
+import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
+import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
+import {QReportMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QReportMetaData";
+import React, {useEffect, useState} from "react";
+import ProcessRun from "qqq/pages/process-run/index";
+import QClient from "qqq/utils/QClient";
+
+interface Props
+{
+ report?: QReportMetaData;
+}
+
+function ReportRun({report}: Props): JSX.Element
+{
+ // const reportNameParam = useParams().reportName;
+ // const processName = process === null ? processNameParam : process.name;
+ const [metaData, setMetaData] = useState(null as QInstance);
+
+ useEffect(() =>
+ {
+ if(!metaData)
+ {
+ (async () =>
+ {
+ const metaData = await QClient.getInstance().loadMetaData();
+ setMetaData(metaData);
+ })();
+ }
+ });
+
+ if(metaData)
+ {
+ console.log(`Report Process name is ${report.processName}`)
+ const process = metaData.processes.get(report.processName)
+ console.log(`Process is ${process.name}`)
+ const defaultProcessValues = {reportName: report.name}
+ return ();
+ }
+ else
+ {
+ // todo - loading?
+ return ();
+ }
+}
+
+ReportRun.defaultProps = {
+ process: null,
+};
+
+export default ReportRun;
diff --git a/src/qqq/pages/process-run/index.tsx b/src/qqq/pages/process-run/index.tsx
index e248e2a..8a3db4d 100644
--- a/src/qqq/pages/process-run/index.tsx
+++ b/src/qqq/pages/process-run/index.tsx
@@ -35,6 +35,7 @@ import {Button, Icon, CircularProgress, TablePagination} from "@mui/material";
import Box from "@mui/material/Box";
import Card from "@mui/material/Card";
import Grid from "@mui/material/Grid";
+import Link from "@mui/material/Link";
import Step from "@mui/material/Step";
import StepLabel from "@mui/material/StepLabel";
import Stepper from "@mui/material/Stepper";
@@ -42,7 +43,7 @@ import Typography from "@mui/material/Typography";
import {DataGridPro, GridColDef} from "@mui/x-data-grid-pro";
import FormData from "form-data";
import {Form, Formik} from "formik";
-import React, {Fragment, useEffect, useState} from "react";
+import React, {useEffect, useState} from "react";
import {useLocation, useParams, useNavigate} from "react-router-dom";
import * as Yup from "yup";
import BaseLayout from "qqq/components/BaseLayout";
@@ -61,13 +62,14 @@ import QProcessSummaryResults from "./components/QProcessSummaryResults";
interface Props
{
process?: QProcessMetaData;
+ defaultProcessValues?: any;
}
const INITIAL_RETRY_MILLIS = 1_500;
const RETRY_MAX_MILLIS = 12_000;
const BACKOFF_AMOUNT = 1.5;
-function ProcessRun({process}: Props): JSX.Element
+function ProcessRun({process, defaultProcessValues}: Props): JSX.Element
{
const processNameParam = useParams().processName;
const processName = process === null ? processNameParam : process.name;
@@ -339,6 +341,29 @@ function ProcessRun({process}: Props): JSX.Element
)
}
+ {
+ component.type === QComponentType.DOWNLOAD_FORM && (
+
+
+
+
+ Download
+
+
+
+
+
+ download_for_offline
+
+ {processValues.downloadFileName}
+
+
+
+
+
+
+ )
+ }
{
component.type === QComponentType.VALIDATION_REVIEW_SCREEN && (
+ {
+ let rs: QFieldMetaData[] = [];
+
+ if(activeStep && activeStep.formFields)
+ {
+ for(let i = 0; i
+ fullFieldList.forEach((field) =>
{
initialValues[field.name] = processValues[field.name];
});
@@ -492,7 +540,7 @@ function ProcessRun({process}: Props): JSX.Element
if (doesStepHaveComponent(activeStep, QComponentType.BULK_EDIT_FORM))
{
const newDisabledBulkEditFields: any = {};
- activeStep.formFields.forEach((field) =>
+ fullFieldList.forEach((field) =>
{
newDisabledBulkEditFields[field.name] = true;
dynamicFormFields[field.name].isRequired = false;
@@ -562,11 +610,12 @@ function ProcessRun({process}: Props): JSX.Element
/////////////////////////////////////////////////////
useEffect(() =>
{
- if (activeStep && activeStep.formFields)
+ if (activeStep && (activeStep.formFields || processValues.inputFieldList))
{
+ let fullFieldList = getFullFieldList(activeStep, processValues);
const newDynamicFormFields: any = {};
const newFormValidations: any = {};
- activeStep.formFields.forEach((field) =>
+ fullFieldList.forEach((field) =>
{
const fieldName = field.name;
const isDisabled = disabledBulkEditFields[fieldName];
@@ -738,22 +787,21 @@ function ProcessRun({process}: Props): JSX.Element
(async () =>
{
const urlSearchParams = new URLSearchParams(location.search);
- let queryStringForInit = null;
+ let queryStringPairsForInit = [];
if (urlSearchParams.get("recordIds"))
{
- queryStringForInit = `recordsParam=recordIds&recordIds=${urlSearchParams.get(
- "recordIds",
- )}`;
+ queryStringPairsForInit.push("recordsParam=recordIds");
+ queryStringPairsForInit.push(`recordIds=${urlSearchParams.get("recordIds")}`);
}
else if (urlSearchParams.get("filterJSON"))
{
- queryStringForInit = `recordsParam=filterJSON&filterJSON=${urlSearchParams.get(
- "filterJSON",
- )}`;
+ queryStringPairsForInit.push("recordsParam=filterJSON");
+ queryStringPairsForInit.push(`filterJSON=${urlSearchParams.get("filterJSON")}`);
}
// todo once saved filters exist
//else if(urlSearchParams.get("filterId")) {
- // queryStringForInit = `recordsParam=filterId&filterId=${urlSearchParams.get("filterId")}`
+ // queryStringPairsForInit.push("recordsParam=filterId");
+ // queryStringPairsForInit.push(`filterId=${urlSearchParams.get("filterId")}`);
// }
try
@@ -792,9 +840,17 @@ function ProcessRun({process}: Props): JSX.Element
return;
}
+ if(defaultProcessValues)
+ {
+ for(let key in defaultProcessValues)
+ {
+ queryStringPairsForInit.push(`${key}=${encodeURIComponent(defaultProcessValues[key])}`);
+ }
+ }
+
try
{
- const processResponse = await QClient.getInstance().processInit(processName, queryStringForInit);
+ const processResponse = await QClient.getInstance().processInit(processName, queryStringPairsForInit.join("&"));
setProcessUUID(processResponse.processUUID);
setLastProcessResponse(processResponse);
}
@@ -830,7 +886,8 @@ function ProcessRun({process}: Props): JSX.Element
if (doesStepHaveComponent(activeStep, QComponentType.BULK_EDIT_FORM))
{
const bulkEditEnabledFields: string[] = [];
- activeStep.formFields.forEach((field) =>
+ let fullFieldList = getFullFieldList(activeStep, processValues);
+ fullFieldList.forEach((field) =>
{
if (!disabledBulkEditFields[field.name])
{
@@ -904,7 +961,7 @@ function ProcessRun({process}: Props): JSX.Element
-
+
+ {
+ const process = metaData.reports.get(key);
+ if (process.tableName === tableName)
+ {
+ matchingReports.push(process);
+ }
+ });
+ return matchingReports;
+ }
+
}
export default QProcessUtils;
diff --git a/src/setupProxy.js b/src/setupProxy.js
index a129a43..d6d896c 100644
--- a/src/setupProxy.js
+++ b/src/setupProxy.js
@@ -36,4 +36,12 @@ module.exports = function (app)
changeOrigin: true,
}),
);
+
+ app.use(
+ "/download/*",
+ createProxyMiddleware({
+ target: "http://localhost:8000",
+ changeOrigin: true,
+ }),
+ );
};