Skip to content

Commit 171aa39

Browse files
committed
Merge remote-tracking branch 'upstream/staging' into keyboard-events
# Conflicts: # designer/client/src/actions/nk/node.ts
2 parents 135688e + d5154a3 commit 171aa39

File tree

103 files changed

+1090
-463
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+1090
-463
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package pl.touk.nussknacker.engine.api
2+
3+
case class TemplateEvaluationResult(renderedParts: List[TemplateRenderedPart]) {
4+
def renderedTemplate: String = renderedParts.map(_.value).mkString("")
5+
}
6+
7+
sealed trait TemplateRenderedPart {
8+
def value: String
9+
}
10+
11+
object TemplateRenderedPart {
12+
case class RenderedLiteral(value: String) extends TemplateRenderedPart
13+
14+
case class RenderedSubExpression(value: String) extends TemplateRenderedPart
15+
}

components/sql/src/main/scala/pl/touk/nussknacker/sql/service/DatabaseQueryEnricher.scala

+6-8
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,7 @@ object DatabaseQueryEnricher {
4141

4242
final val queryParamName: ParameterName = ParameterName("Query")
4343

44-
final val queryParamDeclaration =
45-
ParameterDeclaration
46-
.mandatory[String](queryParamName)
47-
.withCreator(modify = _.copy(editor = Some(SqlParameterEditor)))
44+
final val queryParam = Parameter[String](queryParamName).copy(editor = Some(SqlParameterEditor))
4845

4946
final val resultStrategyParamName: ParameterName = ParameterName("Result strategy")
5047

@@ -132,7 +129,7 @@ class DatabaseQueryEnricher(val dbPoolConfig: DBPoolConfig, val dbMetaDataProvid
132129
): ContextTransformationDefinition = { case TransformationStep(Nil, _) =>
133130
NextParameters(parameters =
134131
resultStrategyParamDeclaration.createParameter() ::
135-
queryParamDeclaration.createParameter() ::
132+
queryParam ::
136133
cacheTTLParamDeclaration.createParameter() :: Nil
137134
)
138135
}
@@ -142,14 +139,15 @@ class DatabaseQueryEnricher(val dbPoolConfig: DBPoolConfig, val dbMetaDataProvid
142139
): ContextTransformationDefinition = {
143140
case TransformationStep(
144141
(`resultStrategyParamName`, DefinedEagerParameter(strategyName: String, _)) ::
145-
(`queryParamName`, DefinedEagerParameter(query: String, _)) ::
142+
(`queryParamName`, DefinedEagerParameter(query: TemplateEvaluationResult, _)) ::
146143
(`cacheTTLParamName`, _) :: Nil,
147144
None
148145
) =>
149-
if (query.isEmpty) {
146+
val renderedQuery = query.renderedTemplate
147+
if (renderedQuery.isEmpty) {
150148
FinalResults(context, errors = CustomNodeError("Query is missing", Some(queryParamName)) :: Nil, state = None)
151149
} else {
152-
parseQuery(context, dependencies, strategyName, query)
150+
parseQuery(context, dependencies, strategyName, renderedQuery)
153151
}
154152
}
155153

components/sql/src/test/scala/pl/touk/nussknacker/sql/service/DatabaseQueryEnricherValidationTest.scala

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package pl.touk.nussknacker.sql.service
22

3+
import pl.touk.nussknacker.engine.api.TemplateRenderedPart.RenderedLiteral
34
import pl.touk.nussknacker.engine.api.context.ProcessCompilationError.CustomNodeError
45
import pl.touk.nussknacker.engine.api.context.transformation.{DefinedEagerParameter, OutputVariableNameValue}
56
import pl.touk.nussknacker.engine.api.context.{OutputVar, ValidationContext}
67
import pl.touk.nussknacker.engine.api.typed.typing.{Typed, Unknown}
7-
import pl.touk.nussknacker.engine.api.NodeId
8+
import pl.touk.nussknacker.engine.api.{NodeId, TemplateEvaluationResult}
89
import pl.touk.nussknacker.sql.db.query.{ResultSetStrategy, SingleResultStrategy}
910
import pl.touk.nussknacker.sql.db.schema.MetaDataProviderFactory
1011
import pl.touk.nussknacker.sql.utils.BaseHsqlQueryEnricherTest
@@ -32,8 +33,10 @@ class DatabaseQueryEnricherValidationTest extends BaseHsqlQueryEnricherTest {
3233
service.TransformationStep(
3334
List(
3435
DatabaseQueryEnricher.resultStrategyParamName -> eagerValueParameter(SingleResultStrategy.name),
35-
DatabaseQueryEnricher.queryParamName -> eagerValueParameter("select from"),
36-
DatabaseQueryEnricher.cacheTTLParamName -> eagerValueParameter(Duration.ofMinutes(1)),
36+
DatabaseQueryEnricher.queryParamName -> eagerValueParameter(
37+
TemplateEvaluationResult(List(RenderedLiteral("select from")))
38+
),
39+
DatabaseQueryEnricher.cacheTTLParamName -> eagerValueParameter(Duration.ofMinutes(1)),
3740
),
3841
None
3942
)
@@ -62,8 +65,10 @@ class DatabaseQueryEnricherValidationTest extends BaseHsqlQueryEnricherTest {
6265
service.TransformationStep(
6366
List(
6467
DatabaseQueryEnricher.resultStrategyParamName -> eagerValueParameter(ResultSetStrategy.name),
65-
DatabaseQueryEnricher.queryParamName -> eagerValueParameter("select * from persons"),
66-
DatabaseQueryEnricher.cacheTTLParamName -> eagerValueParameter(Duration.ofMinutes(1)),
68+
DatabaseQueryEnricher.queryParamName -> eagerValueParameter(
69+
TemplateEvaluationResult(List(RenderedLiteral("select * from persons")))
70+
),
71+
DatabaseQueryEnricher.cacheTTLParamName -> eagerValueParameter(Duration.ofMinutes(1)),
6772
),
6873
None
6974
)

designer/client/cypress/e2e/description.cy.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ describe("Description", () => {
2222
it("should display markdown", () => {
2323
cy.get(`[title="toggle description view"]`).should("not.exist");
2424

25-
cy.contains(/^properties$/i)
26-
.should("be.enabled")
27-
.dblclick();
25+
cy.contains(/^properties$/i).click();
2826
cy.get("[data-testid=window]").should("be.visible").as("window");
2927

3028
cy.get("[data-testid=window]").contains("Description").next().find(".ace_editor").should("be.visible").click("center")

designer/client/src/actions/actionTypes.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,5 @@ export type ActionTypes =
4141
| "PROCESS_VERSIONS_LOADED"
4242
| "UPDATE_BACKEND_NOTIFICATIONS"
4343
| "MARK_BACKEND_NOTIFICATION_READ"
44-
| "ARCHIVED";
44+
| "ARCHIVED"
45+
| "EDIT_PROPERTIES";

designer/client/src/actions/nk/calculateProcessAfterChange.ts

+3-31
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,16 @@
1-
import NodeUtils from "../../components/graph/NodeUtils";
2-
import { fetchProcessDefinition } from "./processDefinitionData";
31
import { getProcessDefinitionData } from "../../reducers/selectors/settings";
42
import { mapProcessWithNewNode, replaceNodeOutputEdges } from "../../components/graph/utils/graphUtils";
5-
import { alignFragmentWithSchema } from "../../components/graph/utils/fragmentSchemaAligner";
6-
import { Edge, NodeType, ScenarioGraph, ProcessDefinitionData, ScenarioGraphWithName } from "../../types";
3+
import { Edge, NodeType, ScenarioGraphWithName } from "../../types";
74
import { ThunkAction } from "../reduxTypes";
85
import { Scenario } from "../../components/Process/types";
96

10-
function alignFragmentsNodeWithSchema(scenarioGraph: ScenarioGraph, processDefinitionData: ProcessDefinitionData): ScenarioGraph {
11-
return {
12-
...scenarioGraph,
13-
nodes: scenarioGraph.nodes.map((node) => {
14-
return node.type === "FragmentInput" ? alignFragmentWithSchema(processDefinitionData, node) : node;
15-
}),
16-
};
17-
}
18-
197
export function calculateProcessAfterChange(
208
scenario: Scenario,
219
before: NodeType,
2210
after: NodeType,
2311
outputEdges: Edge[],
2412
): ThunkAction<Promise<ScenarioGraphWithName>> {
25-
return async (dispatch, getState) => {
26-
if (NodeUtils.nodeIsProperties(after)) {
27-
const processDefinitionData = await dispatch(fetchProcessDefinition(scenario.processingType, scenario.isFragment));
28-
const processWithNewFragmentSchema = alignFragmentsNodeWithSchema(scenario.scenarioGraph, processDefinitionData);
29-
// TODO: We shouldn't keep scenario name in properties.id - it is a top-level scenario property
30-
if (after.id !== before.id) {
31-
dispatch({ type: "PROCESS_RENAME", name: after.id });
32-
}
33-
34-
const { id, ...properties } = after;
35-
36-
return {
37-
processName: after.id,
38-
scenarioGraph: { ...processWithNewFragmentSchema, properties },
39-
};
40-
}
41-
13+
return async (_, getState) => {
4214
let changedProcess = scenario.scenarioGraph;
4315
if (outputEdges) {
4416
const processDefinitionData = getProcessDefinitionData(getState());
@@ -54,7 +26,7 @@ export function calculateProcessAfterChange(
5426
}
5527

5628
return {
57-
processName: scenario.scenarioGraph.properties.id || scenario.name,
29+
processName: scenario.name,
5830
scenarioGraph: mapProcessWithNewNode(changedProcess, before, after),
5931
};
6032
};

designer/client/src/actions/nk/editNode.ts

-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ export type EditNodeAction = {
1212
validationResult: ValidationResult;
1313
scenarioGraphAfterChange: ScenarioGraph;
1414
};
15-
export type RenameProcessAction = {
16-
type: "PROCESS_RENAME";
17-
name: string;
18-
};
1915

2016
export type EditScenarioLabels = {
2117
type: "EDIT_LABELS";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { ProcessDefinitionData, PropertiesType, ScenarioGraph, ScenarioGraphWithName, ValidationResult } from "../../types";
2+
import { alignFragmentWithSchema } from "../../components/graph/utils/fragmentSchemaAligner";
3+
import { fetchProcessDefinition } from "./processDefinitionData";
4+
import { Scenario } from "../../components/Process/types";
5+
import HttpService from "../../http/HttpService";
6+
import { ThunkAction } from "../reduxTypes";
7+
8+
type EditPropertiesAction = {
9+
type: "EDIT_PROPERTIES";
10+
validationResult: ValidationResult;
11+
scenarioGraphAfterChange: ScenarioGraph;
12+
};
13+
14+
type RenameProcessAction = {
15+
type: "PROCESS_RENAME";
16+
name: string;
17+
};
18+
19+
export type PropertiesActions = EditPropertiesAction | RenameProcessAction;
20+
21+
// TODO: We synchronize fragment changes with a scenario in case of properties changes. We need to find a better way to hande it
22+
function alignFragmentsNodeWithSchema(scenarioGraph: ScenarioGraph, processDefinitionData: ProcessDefinitionData): ScenarioGraph {
23+
return {
24+
...scenarioGraph,
25+
nodes: scenarioGraph.nodes.map((node) => {
26+
return node.type === "FragmentInput" ? alignFragmentWithSchema(processDefinitionData, node) : node;
27+
}),
28+
};
29+
}
30+
31+
const calculateProperties = (scenario: Scenario, changedProperties: PropertiesType): ThunkAction<Promise<ScenarioGraphWithName>> => {
32+
return async (dispatch) => {
33+
const processDefinitionData = await dispatch(fetchProcessDefinition(scenario.processingType, scenario.isFragment));
34+
const processWithNewFragmentSchema = alignFragmentsNodeWithSchema(scenario.scenarioGraph, processDefinitionData);
35+
36+
if (scenario.name !== changedProperties.name) {
37+
dispatch({ type: "PROCESS_RENAME", name: changedProperties.name });
38+
}
39+
40+
return {
41+
processName: changedProperties.name,
42+
scenarioGraph: { ...processWithNewFragmentSchema, properties: changedProperties },
43+
};
44+
};
45+
};
46+
47+
export function editProperties(scenario: Scenario, changedProperties: PropertiesType): ThunkAction {
48+
return async (dispatch) => {
49+
const { processName, scenarioGraph } = await dispatch(calculateProperties(scenario, changedProperties));
50+
const response = await HttpService.validateProcess(scenario.name, processName, scenarioGraph);
51+
52+
dispatch({
53+
type: "EDIT_PROPERTIES",
54+
validationResult: response.data,
55+
scenarioGraphAfterChange: scenarioGraph,
56+
});
57+
};
58+
}

designer/client/src/actions/nk/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export * from "./ui/layout";
1212
export * from "./zoom";
1313
export * from "./nodeDetails";
1414
export * from "./loadProcessToolbarsConfiguration";
15+
export * from "./editProperties";

designer/client/src/actions/nk/node.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getScenarioGraph } from "../../reducers/selectors/graph";
55
import { getProcessDefinitionData } from "../../reducers/selectors/settings";
66
import { Edge, EdgeType, NodeId, NodeType, ProcessDefinitionData, ValidationResult } from "../../types";
77
import { ThunkAction } from "../reduxTypes";
8-
import { EditNodeAction, EditScenarioLabels, RenameProcessAction } from "./editNode";
8+
import { EditNodeAction, EditScenarioLabels } from "./editNode";
99
import { toggleSelection } from "./selection";
1010
import { layoutChanged, Position } from "./ui/layout";
1111

@@ -156,5 +156,4 @@ export type NodeActions =
156156
| NodesWithEdgesAddedAction
157157
| ValidationResultAction
158158
| EditNodeAction
159-
| RenameProcessAction
160159
| EditScenarioLabels;

designer/client/src/actions/nk/nodeDetails.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,7 @@ const validate = debounce(
5757
validationRequestData: ValidationRequest,
5858
callback: (nodeId: NodeId, data?: ValidationData | void) => void,
5959
) => {
60-
const validate = (node: NodeType) =>
61-
NodeUtils.nodeIsProperties(node)
62-
? //NOTE: we don't validationRequestData contains processProperties, but they are refreshed only on modal open
63-
HttpService.validateProperties(processName, { additionalFields: node.additionalFields, name: node.id })
64-
: HttpService.validateNode(processName, { ...validationRequestData, nodeData: node });
60+
const validate = (node: NodeType) => HttpService.validateNode(processName, { ...validationRequestData, nodeData: node });
6561

6662
const nodeId = validationRequestData.nodeData.id;
6763
const nodeWithChangedName = applyIdFromFakeName(validationRequestData.nodeData);

designer/client/src/actions/reduxTypes.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { AnyAction, Reducer as ReduxReducer } from "redux";
22
import { ThunkAction as TA, ThunkDispatch as TD } from "redux-thunk";
33

44
import { ActionTypes } from "./actionTypes";
5-
import { CountsActions, NodeActions, ScenarioActions, SelectionActions, NodeDetailsActions } from "./nk";
5+
import { CountsActions, NodeActions, ScenarioActions, SelectionActions, NodeDetailsActions, PropertiesActions } from "./nk";
66
import { UserSettingsActions } from "./nk/userSettings";
77
import { UiActions } from "./nk/ui/uiActions";
88
import { SettingsActions } from "./settingsActions";
@@ -25,7 +25,8 @@ type TypedAction =
2525
| NotificationActions
2626
| DisplayTestResultsDetailsAction
2727
| CountsActions
28-
| ScenarioActions;
28+
| ScenarioActions
29+
| PropertiesActions;
2930

3031
interface UntypedAction extends AnyAction {
3132
type: Exclude<ActionTypes, TypedAction["type"]>;

designer/client/src/assets/json/nodeAttributes.json

-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@
3838
"Aggregate": {
3939
"name": "Aggregate"
4040
},
41-
"Properties": {
42-
"name": "Properties"
43-
},
4441
"CustomNode": {
4542
"name": "CustomNode"
4643
},

designer/client/src/components/ComponentDragPreview.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ export const ComponentDragPreview = forwardRef<HTMLDivElement, { scale: () => nu
4949
willChange: "transform",
5050
});
5151

52+
if (!node) {
53+
return null;
54+
}
55+
5256
return createPortal(
5357
<div ref={forwardedRef} className={wrapperStyles} style={{ transform: `translate(${x}px, ${y}px)` }}>
5458
<div

designer/client/src/components/ComponentPreview.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function ComponentPreview({ node, isActive, isOver }: { node: NodeType; i
5353
});
5454

5555
const imageColors = css({
56-
background: theme.palette.custom.getNodeStyles(node)?.fill,
56+
background: theme.palette.custom.getNodeStyles(node.type)?.fill,
5757
color: theme.palette.common.white,
5858
});
5959

designer/client/src/components/graph/EspNode/element.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export function makeElement(processDefinitionData: ProcessDefinitionData, theme:
146146
opacity: node.isDisabled ? 0.5 : 1,
147147
},
148148
iconBackground: {
149-
fill: theme.palette.custom.getNodeStyles(node).fill,
149+
fill: theme.palette.custom.getNodeStyles(node.type).fill,
150150
opacity: node.isDisabled ? 0.5 : 1,
151151
},
152152
icon: {

designer/client/src/components/graph/Graph.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,7 @@ export class Graph extends React.Component<Props> {
429429
addNode(node: NodeType, position: Position): void {
430430
if (this.props.isFragment === true) return;
431431

432-
const canAddNode =
433-
this.props.capabilities.editFrontend && NodeUtils.isNode(node) && NodeUtils.isAvailable(node, this.props.processDefinitionData);
432+
const canAddNode = this.props.capabilities.editFrontend && NodeUtils.isAvailable(node, this.props.processDefinitionData);
434433

435434
if (canAddNode) {
436435
this.props.nodeAdded(node, position);

0 commit comments

Comments
 (0)