diff --git a/designer/client/src/components/modals/ActivityCommentTextField.tsx b/designer/client/src/components/modals/ActivityCommentTextField.tsx
new file mode 100644
index 00000000000..256808dc198
--- /dev/null
+++ b/designer/client/src/components/modals/ActivityCommentTextField.tsx
@@ -0,0 +1,21 @@
+import { styled, TextField, TextFieldProps } from "@mui/material";
+import React from "react";
+
+export const ActivityCommentTextField = styled((props: TextFieldProps) => (
+
+))({
+ flexDirection: "column",
+ ".MuiFormLabel-root": {
+ margin: 0,
+ flexDirection: "column",
+ },
+});
diff --git a/designer/client/src/components/modals/ActivityHeader.tsx b/designer/client/src/components/modals/ActivityHeader.tsx
new file mode 100644
index 00000000000..4c02dcf8f43
--- /dev/null
+++ b/designer/client/src/components/modals/ActivityHeader.tsx
@@ -0,0 +1,33 @@
+import { useSelector } from "react-redux";
+import { getProcessName } from "../../reducers/selectors/graph";
+import { Box, Typography } from "@mui/material";
+import React from "react";
+import ProcessDialogWarnings from "./ProcessDialogWarnings";
+
+interface Props {
+ title: string;
+ displayWarnings?: boolean;
+}
+
+export function ActivityHeader(props: Props): JSX.Element {
+ const processName = useSelector(getProcessName);
+ return (
+
+
+ {props.title}
+
+
+ {processName}
+
+ {props.displayWarnings && }
+
+ );
+}
diff --git a/designer/client/src/components/modals/ActivityProperty.tsx b/designer/client/src/components/modals/ActivityProperty.tsx
new file mode 100644
index 00000000000..c401d025e16
--- /dev/null
+++ b/designer/client/src/components/modals/ActivityProperty.tsx
@@ -0,0 +1,49 @@
+import { ExpressionLang } from "../graph/node-modal/editors/expression/types";
+import React, { useCallback } from "react";
+import { FieldLabel } from "../graph/node-modal/FieldLabel";
+import { getValidationErrorsForField } from "../graph/node-modal/editors/Validators";
+import { ActivityNodeParameters, ActivityParameterConfig } from "../../types/activity";
+import { NodesDeploymentData } from "../../http/HttpService";
+import { NodeValidationError } from "../../types";
+import { default as EditableEditor } from "../graph/node-modal/editors/EditableEditor";
+
+interface Props {
+ nodeName: string;
+ propertyName: string;
+ propertyConfig: ActivityParameterConfig;
+ nodesData: NodesDeploymentData;
+ onChange: (
+ nodeId: string,
+ property: K,
+ newValue: ActivityNodeParameters["parameters"][K],
+ defaultValue?: ActivityNodeParameters["parameters"][K],
+ ) => void;
+ errors: NodeValidationError[];
+}
+
+export function ActivityProperty(props: Props): JSX.Element {
+ const { nodeName, propertyName, propertyConfig, errors, nodesData, onChange } = props;
+
+ const current = nodesData[nodeName][propertyName] || "";
+ const expressionObj = { expression: current, value: current, language: ExpressionLang.String };
+ const onValueChange = useCallback((newValue) => onChange(nodeName, propertyName, newValue), [onChange, nodeName, propertyName]);
+
+ return (
+ (
+
+ )}
+ readOnly={false}
+ showSwitch={false}
+ showValidation={true}
+ //ScenarioProperties do not use any variables
+ variableTypes={{}}
+ fieldErrors={getValidationErrorsForField(errors, propertyName)}
+ />
+ );
+}
diff --git a/designer/client/src/components/modals/AdvancedParametersSection.tsx b/designer/client/src/components/modals/AdvancedParametersSection.tsx
new file mode 100644
index 00000000000..74cb8897190
--- /dev/null
+++ b/designer/client/src/components/modals/AdvancedParametersSection.tsx
@@ -0,0 +1,26 @@
+import React, { PropsWithChildren } from "react";
+import Accordion from "@mui/material/Accordion";
+import AccordionSummary from "@mui/material/AccordionSummary";
+import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
+import { Typography } from "@mui/material";
+import AccordionDetails from "@mui/material/AccordionDetails";
+
+interface Props {
+ nodeId: string;
+}
+
+export function AdvancedParametersSection({ children, nodeId }: PropsWithChildren): JSX.Element {
+ return (
+
+ }
+ aria-controls={`${nodeId}-content`}
+ id={`${nodeId}-header`}
+ sx={{ flexDirection: "row-reverse", px: 0, border: 0 }}
+ >
+ {nodeId}
+
+ {children}
+
+ );
+}
diff --git a/designer/client/src/components/modals/CalculateCounts/CalculateCountsDialog.tsx b/designer/client/src/components/modals/CalculateCounts/CalculateCountsDialog.tsx
index 7391493f8c5..3a2f045e048 100644
--- a/designer/client/src/components/modals/CalculateCounts/CalculateCountsDialog.tsx
+++ b/designer/client/src/components/modals/CalculateCounts/CalculateCountsDialog.tsx
@@ -59,7 +59,7 @@ export function CountsDialog({ children, ...props }: PropsWithChildren {
await confirm();
diff --git a/designer/client/src/components/modals/CustomActionDialog.tsx b/designer/client/src/components/modals/CustomActionDialog.tsx
index 679f2a0afb6..7818d1f87d4 100644
--- a/designer/client/src/components/modals/CustomActionDialog.tsx
+++ b/designer/client/src/components/modals/CustomActionDialog.tsx
@@ -7,7 +7,7 @@ import { loadProcessState } from "../../actions/nk";
import HttpService, { CustomActionValidationRequest } from "../../http/HttpService";
import { CustomAction, NodeValidationError } from "../../types";
import { UnknownRecord } from "../../types/common";
-import { WindowContent, WindowKind } from "../../windowManager";
+import { PromptContent, WindowKind } from "../../windowManager";
import { ChangeableValue } from "../ChangeableValue";
import { editors, ExtendedEditor, SimpleEditor } from "../graph/node-modal/editors/expression/Editor";
import { ExpressionLang } from "../graph/node-modal/editors/expression/types";
@@ -18,7 +18,8 @@ import { LoadingButtonTypes } from "../../windowManager/LoadingButton";
import { nodeValue } from "../graph/node-modal/NodeDetailsContent/NodeTableStyled";
import { getValidationErrorsForField } from "../graph/node-modal/editors/Validators";
import { getFeatureSettings } from "../../reducers/selectors/settings";
-import CommentInput from "../comment/CommentInput";
+import { ActivityCommentTextField } from "./ActivityCommentTextField";
+import { ActivityHeader } from "./ActivityHeader";
interface CustomActionFormProps extends ChangeableValue {
action: CustomAction;
@@ -123,32 +124,25 @@ export function CustomActionDialog(props: WindowContentProps [
{ title: t("dialog.button.cancel", "Cancel"), action: () => props.close(), classname: LoadingButtonTypes.secondaryButton },
- { title: t("dialog.button.confirm", "Ok"), action: () => confirmAction() },
+ { title: t("dialog.button.confirm", "Apply"), action: () => confirmAction() },
],
[confirmAction, props, t],
);
return (
-
+
-
+
setComment(e.target.value)}
- value={comment}
- defaultValue={deploymentCommentSettings?.exampleComment}
- className={cx(
- css({
- minWidth: 600,
- minHeight: 80,
- }),
- )}
autoFocus
/>
-
- {validationError}
-
-
+
);
}
diff --git a/designer/client/src/components/modals/DeployProcessDialog.tsx b/designer/client/src/components/modals/DeployProcessDialog.tsx
index a9c468f2b10..2eae9482915 100644
--- a/designer/client/src/components/modals/DeployProcessDialog.tsx
+++ b/designer/client/src/components/modals/DeployProcessDialog.tsx
@@ -7,26 +7,43 @@ import { getActivityParameters, getProcessName } from "../../reducers/selectors/
import { getFeatureSettings } from "../../reducers/selectors/settings";
import { ProcessName } from "../Process/types";
import { PromptContent, WindowKind } from "../../windowManager";
-import CommentInput from "../comment/CommentInput";
-import ProcessDialogWarnings from "./ProcessDialogWarnings";
-import { FormHelperText, Typography } from "@mui/material";
import { LoadingButtonTypes } from "../../windowManager/LoadingButton";
+import { ActivityNodeParameters } from "../../types/activity";
+import { AdvancedParametersSection } from "./AdvancedParametersSection";
+import { mapValues } from "lodash";
+import { NodesDeploymentData } from "../../http/HttpService";
+import { ActivityProperty } from "./ActivityProperty";
+import { ActivityCommentTextField } from "./ActivityCommentTextField";
+import { ActivityHeader } from "./ActivityHeader";
+import { NodeTable } from "../graph/node-modal/NodeDetailsContent/NodeTable";
export type ToggleProcessActionModalData = {
- action: (processName: ProcessName, comment: string) => Promise;
+ action: (processName: ProcessName, comment: string, nodeData: NodesDeploymentData) => Promise;
+ activityName: string;
displayWarnings?: boolean;
};
+function initialNodesData(params: ActivityNodeParameters[]) {
+ return params.reduce(
+ (paramObj, { nodeId, parameters }) => ({
+ ...paramObj,
+ [nodeId]: mapValues(parameters, (value) => value.defaultValue || ""),
+ }),
+ {},
+ );
+}
+
export function DeployProcessDialog(props: WindowContentProps): JSX.Element {
// TODO: get rid of meta
const {
- meta: { action, displayWarnings },
+ meta: { action, activityName, displayWarnings },
} = props.data;
const processName = useSelector(getProcessName);
const activityParameters = useSelector(getActivityParameters);
- const activityNodeParameters = activityParameters["DEPLOY"] || [];
- console.log(activityNodeParameters);
+ const activityNodeParameters = activityParameters[activityName] || ([] as ActivityNodeParameters[]);
+ const initialValues = useMemo(() => initialNodesData(activityNodeParameters), [activityNodeParameters]);
+ const [values, setValues] = useState(initialValues);
const [comment, setComment] = useState("");
const [validationError, setValidationError] = useState("");
@@ -37,7 +54,7 @@ export function DeployProcessDialog(props: WindowContentProps {
try {
- await action(processName, comment);
+ await action(processName, comment, values);
props.close();
} catch (error) {
setValidationError(error?.response?.data);
@@ -47,32 +64,54 @@ export function DeployProcessDialog(props: WindowContentProps [
- { title: t("dialog.button.cancel", "Cancel"), action: () => props.close(), classname: LoadingButtonTypes.secondaryButton },
- { title: t("dialog.button.ok", "Ok"), action: () => confirmAction() },
+ {
+ title: t("dialog.button.cancel", "Cancel"),
+ action: () => props.close(),
+ classname: LoadingButtonTypes.secondaryButton,
+ },
+ { title: t("dialog.button.ok", "Apply"), action: () => confirmAction() },
],
[confirmAction, props, t],
);
return (
-
-
{props.data.title}
- {displayWarnings &&
}
-
+
+ setComment(e.target.value)}
- value={comment}
- defaultValue={deploymentCommentSettings?.exampleComment}
- className={cx(
- css({
- minWidth: 600,
- minHeight: 80,
- }),
- )}
autoFocus
/>
-
- {validationError}
-
+ {activityNodeParameters.map((anp: ActivityNodeParameters) => (
+
+
+ {Object.entries(anp.parameters).map(([paramName, paramConfig]) => {
+ return (
+ {
+ setValues({
+ ...values,
+ [nodeId]: {
+ ...values[nodeId],
+ [paramName]: newValue,
+ },
+ });
+ }}
+ nodesData={values}
+ />
+ );
+ })}
+
+
+ ))}
);
diff --git a/designer/client/src/components/modals/GenerateTestDataDialog.tsx b/designer/client/src/components/modals/GenerateTestDataDialog.tsx
index 03d80ea3905..a9ae5ab792e 100644
--- a/designer/client/src/components/modals/GenerateTestDataDialog.tsx
+++ b/designer/client/src/components/modals/GenerateTestDataDialog.tsx
@@ -46,7 +46,7 @@ function GenerateTestDataDialog(props: WindowContentProps): JSX.Element {
const buttons: WindowButtonProps[] = useMemo(
() => [
{ title: t("dialog.button.cancel", "Cancel"), action: () => props.close(), classname: LoadingButtonTypes.secondaryButton },
- { title: t("dialog.button.ok", "Ok"), disabled: !isValid, action: () => confirmAction() },
+ { title: t("dialog.button.ok", "Apply"), disabled: !isValid, action: () => confirmAction() },
],
[t, confirmAction, props, isValid],
);
diff --git a/designer/client/src/components/modals/SaveProcessDialog.tsx b/designer/client/src/components/modals/SaveProcessDialog.tsx
index d77f2222c57..8853392368e 100644
--- a/designer/client/src/components/modals/SaveProcessDialog.tsx
+++ b/designer/client/src/components/modals/SaveProcessDialog.tsx
@@ -5,7 +5,6 @@ import { useTranslation } from "react-i18next";
import { useDispatch } from "react-redux";
import { displayCurrentProcessVersion, displayProcessActivity, loadProcessToolbarsConfiguration } from "../../actions/nk";
import { PromptContent } from "../../windowManager";
-import { CommentInput } from "../comment/CommentInput";
import { ThunkAction } from "../../actions/reduxTypes";
import {
getScenarioGraph,
@@ -18,8 +17,9 @@ import HttpService from "../../http/HttpService";
import { ActionCreators as UndoActionCreators } from "redux-undo";
import { visualizationUrl } from "../../common/VisualizationUrl";
import { useLocation, useNavigate } from "react-router-dom";
-import { Typography } from "@mui/material";
import { LoadingButtonTypes } from "../../windowManager/LoadingButton";
+import { ActivityCommentTextField } from "./ActivityCommentTextField";
+import { ActivityHeader } from "./ActivityHeader";
export function SaveProcessDialog(props: WindowContentProps): JSX.Element {
const location = useLocation();
@@ -70,7 +70,7 @@ export function SaveProcessDialog(props: WindowContentProps): JSX.Element {
const buttons: WindowButtonProps[] = useMemo(
() => [
{ title: t("dialog.button.cancel", "Cancel"), action: () => props.close(), classname: LoadingButtonTypes.secondaryButton },
- { title: t("dialog.button.ok", "Ok"), action: () => confirmAction() },
+ { title: t("dialog.button.ok", "Apply"), action: () => confirmAction() },
],
[confirmAction, props, t],
);
@@ -78,16 +78,8 @@ export function SaveProcessDialog(props: WindowContentProps): JSX.Element {
return (
-
{props.data.title}
-
setState(e.target.value)}
- value={comment}
- className={css({
- minWidth: 600,
- minHeight: 80,
- })}
- autoFocus
- />
+
+ setState(e.target.value)} autoFocus />
);
diff --git a/designer/client/src/components/toolbars/process/buttons/SaveButton.tsx b/designer/client/src/components/toolbars/process/buttons/SaveButton.tsx
index 44e25d994ee..19812e0277a 100644
--- a/designer/client/src/components/toolbars/process/buttons/SaveButton.tsx
+++ b/designer/client/src/components/toolbars/process/buttons/SaveButton.tsx
@@ -17,8 +17,8 @@ function SaveButton(props: ToolbarButtonProps): JSX.Element {
const unsavedNewName = useSelector(getProcessUnsavedNewName);
const isRenamed = useSelector(isProcessRenamed);
const title = isRenamed
- ? t("saveProcess.renameTitle", "Save scenario as {{name}}", { name: unsavedNewName })
- : t("saveProcess.title", "Save scenario {{name}}", { name: processName });
+ ? t("saveProcess.renameTitle", "Save scenario as", { name: unsavedNewName })
+ : t("saveProcess.title", "Save scenario", { name: processName });
const { open } = useWindows();
const onClick = () =>
diff --git a/designer/client/src/components/toolbars/scenarioActions/buttons/CancelDeployButton.tsx b/designer/client/src/components/toolbars/scenarioActions/buttons/CancelDeployButton.tsx
index cc14a764dcb..1bb36088e26 100644
--- a/designer/client/src/components/toolbars/scenarioActions/buttons/CancelDeployButton.tsx
+++ b/designer/client/src/components/toolbars/scenarioActions/buttons/CancelDeployButton.tsx
@@ -23,7 +23,7 @@ export default function CancelDeployButton(props: ToolbarButtonProps) {
const { open } = useWindows();
const action = (p, c) => HttpService.cancel(p, c).finally(() => dispatch(loadProcessState(processName)));
- const message = t("panels.actions.deploy-canel.dialog", "Cancel scenario {{name}}", { name: processName });
+ const message = t("panels.actions.deploy-canel.dialog", "Cancel scenario");
return (
HttpService.deploy(p, c).finally(() => dispatch(loadProcessState(processName)));
+ const message = t("panels.actions.deploy.dialog", "Deploy scenario");
+ const action = (p, c, d) => HttpService.deploy(p, c, d).finally(() => dispatch(loadProcessState(processName)));
return (
;
+ parameters: { [key: ActivityParameterName]: ActivityParameterConfig };
}
export type ActivityName = string;
-export type ActivityParameters = Record;
+export type ActivityParameters = { [key: ActivityName]: ActivityNodeParameters[] };
diff --git a/designer/client/src/windowManager/PromptContent.tsx b/designer/client/src/windowManager/PromptContent.tsx
index 37a76f38740..785d9d6137d 100644
--- a/designer/client/src/windowManager/PromptContent.tsx
+++ b/designer/client/src/windowManager/PromptContent.tsx
@@ -16,7 +16,13 @@ export function PromptContent(props: PropsWithChildren): JS
paddingLeft: theme.custom.spacing.baseUnit * 6,
paddingRight: theme.custom.spacing.baseUnit * 6,
});
- return { ...props.classnames, content };
+ return {
+ footer: css({
+ justifyContent: "flex-end",
+ }),
+ ...props.classnames,
+ content,
+ };
}, [props.classnames, theme.custom.spacing.baseUnit]);
const components = useMemo(
diff --git a/nussknacker-dist/src/universal/conf/dev-application.conf b/nussknacker-dist/src/universal/conf/dev-application.conf
index ddf3c4c27aa..3082ff0a08c 100644
--- a/nussknacker-dist/src/universal/conf/dev-application.conf
+++ b/nussknacker-dist/src/universal/conf/dev-application.conf
@@ -359,8 +359,8 @@ commentSettings: {
}
deploymentCommentSettings: {
- validationPattern: "(.*)"
- exampleComment: "issues/1234"
+ validationPattern: "issues/\\d+"
+ exampleComment: "issues/1234 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies nec sapien id bibendum. Ut in mollis risus. Curabitur efficitur maximus interdum. Vivamus convallis eu nibh ut rhoncus. Quisque finibus maximus dui vel finibus."
}
countsSettings {