- {e.title}
+ {e.title}
|
@@ -177,7 +180,7 @@ function FormTable() {
{e.status === "active" ? t("Live") : t("Draft")}
|
-
+ |
{(createDesigns || viewDesigns) && (
{
- handleConfirm(FormSettingsRef.current);
+ const handleConfirmFunction = async () => {
+ const { formDetails, validateField } = FormSettingsRef.current;
+ const fieldsToValidate = ["title", "path"];
+
+ // Reset validation error state at the beginning
+ let validationError = false;
+
+ for (const field of fieldsToValidate) {
+ const fieldValue = formDetails?.[field];
+ if (!fieldValue || !(await validateField(field, fieldValue))) {
+ validationError = true;
+ break; // Stop further validation if any field fails
+ }
+ }
+ if (!validationError) {
+ handleConfirm(FormSettingsRef.current);
+ }
};
return (
{
- const dispatch = useDispatch();
- const { t } = useTranslation();
- const dmn = useSelector((state) => state.process?.dmnProcessList);
- const [isLoading, setIsLoading] = useState(true);
- const searchText = useSelector((state) => state.process?.dmnSearchText);
- const [activePage, setActivePage] = useState(1);
- const [limit, setLimit] = useState(5);
- const tenantKey = useSelector((state) => state.tenants?.tenantId);
- const totalCount = useSelector((state) => state.process.totalDmnCount);
- const [currentDmnSort, setCurrentDmnSort] = useState({
- activeKey: "name",
- name: { sortOrder: "asc" },
- processKey: { sortOrder: "asc" },
- modified: { sortOrder: "asc" },
- status: { sortOrder: "asc" },
- });
- const [importDecisionTable, setImportDecisionTable] = useState(false);
- const closeDmnImport = () => {
- setImportDecisionTable(false);
- };
- const [searchDmnLoading, setSearchDmnLoading] = useState(false);
- const redirectUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : "/";
- const [search, setSearch] = useState(searchText || "");
- const [showBuildModal, setShowBuildModal] = useState(false);
- const handleBuildClick = () => {
- dispatch(push(`${redirectUrl}decision-table/create`));
- };
- const handleImportClick = () => {
- setShowBuildModal(false);
- setImportDecisionTable(true);
- };
- const contents = [
- {
- id: 1,
- heading: "Build",
- body: "Create the DMN from scratch",
- onClick: handleBuildClick
- },
- {
- id: 2,
- heading: "Import",
- body: "Upload DMN from a file",
- onClick: handleImportClick
- }
- ];
-
-
- useEffect(() => {
- if (!search?.trim()) {
- dispatch(setDmnSearchText(""));
- }
- }, [search]);
-
-
- useEffect(() => {
- setIsLoading(true);
- dispatch(
- fetchAllProcesses(
- {
- pageNo: activePage,
- tenant_key: tenantKey,
- processType: "DMN",
- limit: limit,
- searchKey: search,
- sortBy: currentDmnSort.activeKey,
- sortOrder: currentDmnSort[currentDmnSort.activeKey].sortOrder,
- },
- () => {
- setIsLoading(false);
- setSearchDmnLoading(false);
- }
- )
- );
- }, [dispatch, activePage, limit, searchText, currentDmnSort]);
-
-
- const handleSort = (key) => {
- setCurrentDmnSort((prevSort) => {
- const newSortOrder = prevSort[key].sortOrder === "asc" ? "desc" : "asc";
- return {
- ...prevSort,
- activeKey: key,
- [key]: { sortOrder: newSortOrder },
- };
- });
- };
-
- const pageOptions = [
- { text: "5", value: 5 },
- { text: "10", value: 10 },
- { text: "25", value: 25 },
- { text: "50", value: 50 },
- { text: "100", value: 100 },
- { text: "All", value: totalCount },
- ];
-
- const handleClearSearch = () => {
- setSearch("");
- setActivePage(1);
- dispatch(setDmnSearchText(""));
- };
- const handleSearch = () => {
- setSearchDmnLoading(true);
- setActivePage(1);
- dispatch(setDmnSearchText(search));
- };
- const onLimitChange = (newLimit) => {
- setLimit(newLimit);
- handlePageChange(1);
- };
- const handlePageChange = (page) => setActivePage(page);
- const gotoEdit = (data) => {
- if (MULTITENANCY_ENABLED) {
- dispatch(setIsPublicDiagram(!!data.tenantId));
- }
- dispatch(push(`${redirectUrl}decision-table/edit/${data.processKey}`));
- };
-
- const handleCreateDMN = () => {
- setShowBuildModal(true);
- };
- const handleBuildModal = () => {
- setShowBuildModal(false);
- };
-
-
- return (
- <>
-
-
-
-
-
- handleCreateDMN()}
- />
-
-
-
-
-
-
-
-
-
- |
-
-
- |
-
-
- |
-
-
- |
- |
-
-
- {dmn.length ?
-
- {dmn.map((dmnItem) => (
-
- ))}
-
- : !isLoading ? (
-
- ) : null}
-
-
-
-
-
-
- {importDecisionTable && (
-
- )}
- >);
-});
-
-DecisionTable.propTypes = {};
-
-export default DecisionTable;
diff --git a/forms-flow-web/src/components/Modeler/ProcessTable.js b/forms-flow-web/src/components/Modeler/ProcessTable.js
new file mode 100644
index 0000000000..aec12e7238
--- /dev/null
+++ b/forms-flow-web/src/components/Modeler/ProcessTable.js
@@ -0,0 +1,322 @@
+import React, { useEffect, useState } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import {
+ CustomButton,
+ CustomSearch,
+ ReusableProcessTableRow,
+ TableFooter,
+ NoDataFound,
+ BuildModal,
+} from "@formsflow/components";
+import LoadingOverlay from "react-loading-overlay-ts";
+import { useTranslation } from "react-i18next";
+import { useParams } from "react-router-dom";
+import SortableHeader from "../CustomComponents/SortableHeader";
+import { fetchAllProcesses } from "../../apiManager/services/processServices";
+import { MULTITENANCY_ENABLED } from "../../constants/constants";
+import { push } from "connected-react-router";
+import ImportProcess from "../Modals/ImportProcess";
+import {
+ setBpmnSearchText,
+ setDmnSearchText,
+ setIsPublicDiagram,
+} from "../../actions/processActions";
+
+const ProcessTable = React.memo(() => {
+ const { viewType } = useParams();
+ const isBPMN = viewType === "subflow";
+ const dispatch = useDispatch();
+ const { t } = useTranslation();
+ const ProcessContents = isBPMN
+ ? {
+ processType: "BPMN",
+ extension: ".bpmn",
+ }
+ : {
+ processType: "DMN",
+ extension: ".dmn",
+ };
+
+ // States and selectors
+ const processList = useSelector((state) =>
+ isBPMN ? state.process.processList : state.process.dmnProcessList
+ );
+ const searchText = useSelector((state) =>
+ isBPMN ? state.process.bpmnSearchText : state.process.dmnSearchText
+ );
+ const totalCount = useSelector((state) =>
+ isBPMN ? state.process.totalBpmnCount : state.process.totalDmnCount
+ );
+ const tenantKey = useSelector((state) => state.tenants?.tenantId);
+
+ const initialSortConfig = {
+ activeKey: "name",
+ name: { sortOrder: "asc" },
+ processKey: { sortOrder: "asc" },
+ modified: { sortOrder: "asc" },
+ status: { sortOrder: "asc" },
+ };
+
+ const [bpmnState, setBpmnState] = useState({
+ activePage: 1,
+ limit: 5,
+ sortConfig: initialSortConfig,
+ });
+
+ const [dmnState, setDmnState] = useState({
+ activePage: 1,
+ limit: 5,
+ sortConfig: initialSortConfig,
+ });
+ const [searchDMN, setSearchDMN] = useState(searchText || "");
+ const [searchBPMN, setSearchBPMN] = useState(searchText || "");
+ const search = isBPMN ? searchBPMN : searchDMN;
+
+ const [showBuildModal, setShowBuildModal] = useState(false);
+ const [importProcess, setImportProcess] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
+ const [searchLoading, setSearchLoading] = useState(false);
+
+ const currentState = isBPMN ? bpmnState : dmnState;
+ const setCurrentState = isBPMN ? setBpmnState : setDmnState;
+
+ const redirectUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : "/";
+
+ //fetching bpmn or dmn
+ useEffect(() => {
+ setIsLoading(true);
+ dispatch(
+ fetchAllProcesses(
+ {
+ pageNo: currentState.activePage,
+ tenant_key: tenantKey,
+ processType: ProcessContents.processType,
+ limit: currentState.limit,
+ searchKey: search,
+ sortBy: currentState.sortConfig.activeKey,
+ sortOrder: currentState.sortConfig[currentState.sortConfig.activeKey].sortOrder,
+ },
+ () => {
+ setIsLoading(false);
+ setSearchLoading(false);
+ }
+ )
+ );
+ }, [dispatch, currentState, tenantKey,searchText, isBPMN]);
+
+ //Update api call when search field is empty
+ useEffect(() => {
+ if (!search.trim()) {
+ dispatch(isBPMN ? setBpmnSearchText("") : setDmnSearchText(""));
+ }
+ }, [search, dispatch, isBPMN]);
+
+ const handleSort = (key) => {
+ setCurrentState((prevState) => ({
+ ...prevState,
+ sortConfig: {
+ ...prevState.sortConfig,
+ activeKey: key,
+ [key]: {
+ sortOrder: prevState.sortConfig[key]?.sortOrder === "asc" ? "desc" : "asc",
+ },
+ },
+ }));
+ };
+
+ const handleSearch = () => {
+ setSearchLoading(true);
+ if (isBPMN) {
+ dispatch(setBpmnSearchText(searchBPMN));
+ } else {
+ dispatch(setDmnSearchText(searchDMN));
+ }
+ handlePageChange(1);
+ };
+
+ const handleClearSearch = () => {
+ if (isBPMN) {
+ setSearchBPMN("");
+ dispatch(setBpmnSearchText(""));
+ } else {
+ setSearchDMN("");
+ dispatch(setDmnSearchText(""));
+ }
+ handlePageChange(1);
+ };
+
+ const handlePageChange = (page) => {
+ setCurrentState((prevState) => ({
+ ...prevState,
+ activePage: page,
+ }));
+ };
+
+ const onLimitChange = (newLimit) => {
+ setCurrentState((prevState) => ({
+ ...prevState,
+ limit: newLimit,
+ activePage: 1,
+ }));
+ };
+
+ const gotoEdit = (data) => {
+ if (MULTITENANCY_ENABLED) {
+ dispatch(setIsPublicDiagram(!!data.tenantId));
+ }
+ dispatch(
+ push(
+ `${redirectUrl}${viewType}/edit/${data.processKey}`
+ )
+ );
+ };
+
+ const handleCreateProcess = () => {
+ setShowBuildModal(true);
+ };
+
+ const handleBuildModal = () => {
+ setShowBuildModal(false);
+ };
+
+ const showImportModal = () => {
+ setShowBuildModal(false);
+ setImportProcess(true);
+ };
+
+ // contents for import of BPMN or DMN
+ const modalContents = [
+ {
+ id: 1,
+ heading: "Build",
+ body: `Create the ${ProcessContents.processType} from scratch`,
+ onClick: () => dispatch(push(`${redirectUrl}${viewType}/create`)),
+ },
+ {
+ id: 2,
+ heading: "Import",
+ body: `Upload ${ProcessContents.processType} from a file`,
+ onClick: showImportModal,
+ },
+ ];
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+ |
+
+
+ {processList.length ? (
+
+ {processList.map((processItem) => (
+
+ ))}
+
+
+ ) : !isLoading && }
+
+
+
+
+
+ {importProcess && (
+ setImportProcess(false)}
+ fileType={ProcessContents.extension}
+ />
+ )}
+ >
+ );
+});
+
+export default ProcessTable;
diff --git a/forms-flow-web/src/components/Modeler/SubFlowTable.js b/forms-flow-web/src/components/Modeler/SubFlowTable.js
deleted file mode 100644
index c966f1ffb6..0000000000
--- a/forms-flow-web/src/components/Modeler/SubFlowTable.js
+++ /dev/null
@@ -1,246 +0,0 @@
-import React, { useEffect, useState } from "react";
-import {
- CustomButton,
- CustomSearch,
- TableFooter,
- ReusableProcessTableRow,
- NoDataFound,
- BuildModal,
-} from "@formsflow/components";
-import { useSelector, useDispatch } from "react-redux";
-import { useTranslation } from "react-i18next";
-import { fetchAllProcesses } from "../../apiManager/services/processServices";
-import LoadingOverlay from "react-loading-overlay-ts";
-import {
- setBpmnSearchText,
- setIsPublicDiagram,
-} from "../../actions/processActions";
-import { push } from "connected-react-router";
-import { MULTITENANCY_ENABLED } from "../../constants/constants";
-import SortableHeader from "../CustomComponents/SortableHeader";
-import ImportProcess from "../Modals/ImportProcess";
-
-const SubFlow = React.memo(() => {
- const dispatch = useDispatch();
- const { t } = useTranslation();
- const searchText = useSelector((state) => state.process.bpmnSearchText);
- const tenantKey = useSelector((state) => state.tenants?.tenantId);
- const processList = useSelector((state) => state.process.processList);
- const totalCount = useSelector((state) => state.process.totalBpmnCount);
- const [importSubflow, setImportSubflow] = useState(false);
-
- // Local states
- const [activePage, setActivePage] = useState(1);
- const [isLoading, setIsLoading] = useState(true);
- const [limit, setLimit] = useState(5);
- const [search, setSearch] = useState(searchText || "");
- const [searchBpmnLoading, setSearchBpmnLoading] = useState(false);
- const [currentBpmnSort, setCurrentBpmnSort] = useState({
- activeKey: "name",
- name: { sortOrder: "asc" },
- processKey: { sortOrder: "asc" },
- modified: { sortOrder: "asc" },
- status: { sortOrder: "asc" },
- });
- const [showBuildModal, setShowBuildModal] = useState(false);
- const redirectUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : "/";
-
- const ShowImportModal = () => {
- setShowBuildModal(false);
- setImportSubflow(true);
- };
-
- // Modal contents
- const modalContents = [
- {
- id: 1,
- heading: "Build",
- body: "Create the BPMN from scratch",
- onClick: () => dispatch(push(`${redirectUrl}subflow/create`)),
- },
- {
- id: 2,
- heading: "Import",
- body: "Upload BPMN from a file",
- onClick: ShowImportModal,
- },
- ];
-
- useEffect(() => {
- if (!search.trim()) dispatch(setBpmnSearchText(""));
- }, [search, dispatch]);
-
- useEffect(() => {
- setIsLoading(true);
- dispatch(
- fetchAllProcesses(
- {
- pageNo: activePage,
- tenant_key: tenantKey,
- processType: "BPMN",
- limit,
- searchKey: search,
- sortBy: currentBpmnSort.activeKey,
- sortOrder: currentBpmnSort[currentBpmnSort.activeKey].sortOrder,
- },
- () => {
- setIsLoading(false);
- setSearchBpmnLoading(false);
- }
- )
- );
- }, [dispatch, activePage, limit, searchText, tenantKey, currentBpmnSort]);
-
- const handleSort = (key) => {
- setCurrentBpmnSort((prevConfig) => ({
- ...prevConfig,
- activeKey: key,
- [key]: { sortOrder: prevConfig[key].sortOrder === "asc" ? "desc" : "asc" },
- }));
- };
-
- const pageOptions = [
- { text: "5", value: 5 },
- { text: "25", value: 25 },
- { text: "50", value: 50 },
- { text: "100", value: 100 },
- { text: "All", value: totalCount },
- ];
-
- const handlePageChange = (page) => setActivePage(page);
- const onLimitChange = (newLimit) => {
- setLimit(newLimit);
- setActivePage(1);
- };
- const handleClearSearch = () => {
- setSearch("");
- setActivePage(1);
- dispatch(setBpmnSearchText(""));
- };
-
- const handleSearch = () => {
- setSearchBpmnLoading(true);
- setActivePage(1);
- dispatch(setBpmnSearchText(search));
- };
-
- const gotoEdit = (data) => {
- if (MULTITENANCY_ENABLED) dispatch(setIsPublicDiagram(!!data.tenantId));
- dispatch(push(`${redirectUrl}subflow/edit/${data.processKey}`));
- };
-
- const handleCreateBPMN = () => {
- setShowBuildModal(true);
- };
- const handleBuildModal = () => {
- setShowBuildModal(false);
- };
-
- return (
- <>
-
-
-
-
-
-
-
-
-
- |
-
-
- |
-
-
- |
-
-
- |
- |
-
-
- {processList.length ? (
-
- {processList.map((processItem) => (
-
- ))}
-
-
- ) : !isLoading &&
- }
-
-
-
-
-
- {importSubflow && (
- setImportSubflow(false)} fileType=".bpmn" />
- )}
- >
- );
-});
-
-export default SubFlow;
diff --git a/forms-flow-web/src/components/Modeler/index.js b/forms-flow-web/src/components/Modeler/index.js
index a9c866af5b..f81ff723c0 100644
--- a/forms-flow-web/src/components/Modeler/index.js
+++ b/forms-flow-web/src/components/Modeler/index.js
@@ -2,8 +2,7 @@ import React from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import { useSelector } from "react-redux";
import ProcessCreateEdit from "./ProcessCreateEdit";
-import SubFlowList from './SubFlowTable';
-import DecisionTable from './DecisionTable';
+import ProcessTable from './ProcessTable';
import { BASE_ROUTE } from "../../constants/constants";
import Loading from "../../containers/Loading";
import AccessDenied from "../AccessDenied";
@@ -38,8 +37,7 @@ const Processes = () => {
return (
-
-
+
{
}
};
-export { generateUniqueId, replaceUrl, addTenantkey, removeTenantKey, textTruncate, renderPage,
- filterSelectOptionByLabel, isFormComponentsChanged,addTenantkeyAsSuffix};
+/* ----------------- convert data from and into multiselect ----------------- */
+const convertMultiSelectOptionToValue = (selectedValues = [], key = null) =>
+ selectedValues.map(i=> i[key]);
+
+const convertSelectedValueToMultiSelectOption = (values = [], key = null) =>
+ values.map((value)=>({[key]:value, id:_.uniqueId(value)}));
+/* ----------------------------------- --- ---------------------------------- */
+export { generateUniqueId,
+ replaceUrl,
+ addTenantkey,
+ removeTenantKey,
+ textTruncate,
+ renderPage,
+ filterSelectOptionByLabel,
+ isFormComponentsChanged,
+ addTenantkeyAsSuffix,
+ convertMultiSelectOptionToValue,
+ convertSelectedValueToMultiSelectOption
+};
|