diff --git a/app/cdap/components/hydrator/components/Canvas/index.tsx b/app/cdap/components/hydrator/components/Canvas/index.tsx
index afcb2487143..686988cb68a 100644
--- a/app/cdap/components/hydrator/components/Canvas/index.tsx
+++ b/app/cdap/components/hydrator/components/Canvas/index.tsx
@@ -56,6 +56,7 @@ import { IComment } from 'components/AbstractWidget/Comment/CommentConstants';
import IconSVG from 'components/shared/IconSVG';
import { copyToClipBoard } from 'services/Clipboard';
import { INodePosition, ISelectedElements } from './types';
+import { useDispatch, useSelector } from 'react-redux';
interface ICanvasProps {
angularNodes: any;
@@ -222,6 +223,10 @@ const Canvas = ({
return reactflowNode;
});
};
+ const {angularNodes2} = useSelector((state) => ({
+ angularNodes2: state.nodesStore.nodes
+ }))
+ const dispatch = useDispatch();
const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
@@ -380,14 +385,17 @@ const Canvas = ({
};
const updateNodesUIPosition = (node: Node) => {
- updateNodePositions({
- id: node.data.node.id,
- position: {
- _uiPosition: {
- top: node.position.y + 'px',
- left: node.position.x + 'px',
+ dispatch({
+ type: 'UPDATE_NODE_UI_POSITION',
+ payload: {
+ id: node.data.node.id,
+ position: {
+ _uiPosition: {
+ top: node.position.y + 'px',
+ left: node.position.x + 'px',
+ },
},
- },
+ }
});
};
@@ -417,9 +425,9 @@ const Canvas = ({
useEffect(() => {
setNodes((nds) => {
- return [].concat(getNodesForDisplay(getAngularNodes(), nds));
+ return [].concat(getNodesForDisplay(angularNodes2, nds));
});
- }, [JSON.stringify(angularNodes), previewMode, metricsData]);
+ }, [JSON.stringify(angularNodes2), previewMode, metricsData]);
useEffect(() => {
setEdges(() => {
diff --git a/app/cdap/components/hydrator/components/StudioRoutes/Studio.tsx b/app/cdap/components/hydrator/components/StudioRoutes/Studio.tsx
index 84cf0d55b99..123c0036999 100644
--- a/app/cdap/components/hydrator/components/StudioRoutes/Studio.tsx
+++ b/app/cdap/components/hydrator/components/StudioRoutes/Studio.tsx
@@ -34,11 +34,11 @@ export interface IStudioCreateState {
export const Studio = ({leftPanelCtrl, topPanelCtrl, canvasCtrl, dagCtrl, metadataExpanded}: IStudioCreateState) => {
return (
-
+
+
);
};
diff --git a/app/cdap/components/hydrator/reducers/DAGNodesStore.ts b/app/cdap/components/hydrator/reducers/DAGNodesStore.ts
index e69de29bb2d..f88911491cb 100644
--- a/app/cdap/components/hydrator/reducers/DAGNodesStore.ts
+++ b/app/cdap/components/hydrator/reducers/DAGNodesStore.ts
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2023 Cask Data, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+import { createAction, createReducer, current } from '@reduxjs/toolkit';
+import { GLOBALS } from 'services/global-constants';
+import uuidV4 from 'uuid/v4';
+import { santizeStringForHTMLID } from 'services/helpers';
+
+const addNode = createAction
('ADD_NODE')
+const updateNodeUIPosition = createAction('UPDATE_NODE_UI_POSITION')
+const reset = createAction('LEFTPANELSTORE_RESET');
+
+const getInitialState = () => {
+ return {
+ nodes: [],
+ connections: [],
+ activeNodeId: null,
+ currentSourceCount: 0,
+ currentTransformCount: 0,
+ currentSinkCount: 0,
+ canvasPanning: {
+ top: 0,
+ left: 0
+ },
+ }
+}
+
+const setNodeInitialPosition = (config, state) => {
+ const canvasPanning = state.canvasPanning;
+
+ const sourcePosition = {
+ top: 150 - canvasPanning.top,
+ left: (10/100 * document.documentElement.clientWidth) - canvasPanning.left
+ };
+ const transformPosition = {
+ top: 150 - canvasPanning.top,
+ left: (30/100 * document.documentElement.clientWidth) - canvasPanning.left
+ };
+ const sinkPosition = {
+ top: 150 - canvasPanning.top,
+ left: (50/100 * document.documentElement.clientWidth) - canvasPanning.left
+ };
+
+ const offset = 35;
+
+ // set initial position
+ switch (GLOBALS.pluginConvert[config.type]) {
+ case 'source':
+ const sourceOffset = state.currentSourceCount * offset;
+ config._uiPosition = {
+ top: (sourcePosition.top + sourceOffset) + 'px',
+ left: (sourcePosition.left + sourceOffset) + 'px'
+ };
+ break;
+ case 'sink':
+ const sinkOffset = state.currentSinkCount * offset;
+ config._uiPosition = {
+ top: (sinkPosition.top + sinkOffset) + 'px',
+ left: (sinkPosition.left + sinkOffset) + 'px'
+ };
+ break;
+ default:
+ const transformOffset = state.currentTransformCount * offset;
+ config._uiPosition = {
+ top: (transformPosition.top + transformOffset) + 'px',
+ left: (transformPosition.left + transformOffset) + 'px'
+ };
+ break;
+ }
+ if (!config.name) {
+ config.name = config.plugin.label + '-' + uuidV4();
+ }
+ if (!config.id) {
+ config.id = santizeStringForHTMLID(config.plugin.label) + '-' + uuidV4();
+ }
+ return config;
+}
+
+export const nodeReducer = createReducer({
+ ...getInitialState()
+}, (builder) => {
+ builder.addCase(addNode, (state, action) => {
+ const config = setNodeInitialPosition(action.payload.config, state)
+ switch (GLOBALS.pluginConvert[config.type]) {
+ case 'source':
+ state.currentSourceCount++
+ break;
+ case 'sink':
+ state.currentSinkCount++
+ break;
+ default:
+ state.currentTransformCount++
+ break;
+ }
+ state.nodes.push(config);
+ })
+ .addCase(updateNodeUIPosition, (state, action) => {
+ const {id, position} = action.payload
+ const nodeToUpdate = state.nodes.filter(node => node.id === id)[0]
+ nodeToUpdate._uiPosition = position._uiPosition
+ })
+ .addCase(reset, (state, action) => {
+ state = getInitialState()
+ })
+})
\ No newline at end of file
diff --git a/app/cdap/components/hydrator/reducers/index.ts b/app/cdap/components/hydrator/reducers/index.ts
index d1ad6cc72be..e10e143f330 100644
--- a/app/cdap/components/hydrator/reducers/index.ts
+++ b/app/cdap/components/hydrator/reducers/index.ts
@@ -15,6 +15,7 @@
*/
import { configureStore } from '@reduxjs/toolkit';
import reduxThunk from 'redux-thunk';
+import { nodeReducer } from './DAGNodesStore';
import { pluginReducer, extensionsReducer, artifactReducer } from './leftPanelStore';
export const configureStores = configureStore({
@@ -22,6 +23,7 @@ export const configureStores = configureStore({
artifact: artifactReducer,
extensions: extensionsReducer,
plugins: pluginReducer,
+ nodesStore: nodeReducer,
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
serializableCheck: {
diff --git a/app/directives/dag-plus/services/stores/nodes-store.js b/app/directives/dag-plus/services/stores/nodes-store.js
index c0f17f50a2b..ab9fcbd5bf7 100644
--- a/app/directives/dag-plus/services/stores/nodes-store.js
+++ b/app/directives/dag-plus/services/stores/nodes-store.js
@@ -229,9 +229,9 @@ class DAGPlusPlusNodesStore {
resetActiveNode() {
this.state.activeNodeId = null;
- angular.forEach(this.state.nodes, (node) => {
- node.selected = false;
- });
+ // angular.forEach(this.state.nodes, (node) => {
+ // node.selected = false;
+ // });
this.emitChange();
}
diff --git a/app/hydrator/controllers/create/leftpanel-ctrl.js b/app/hydrator/controllers/create/leftpanel-ctrl.js
index 8b3a191245d..c1a8f69cbd2 100644
--- a/app/hydrator/controllers/create/leftpanel-ctrl.js
+++ b/app/hydrator/controllers/create/leftpanel-ctrl.js
@@ -502,6 +502,12 @@ export class HydratorPlusPlusLeftPanelCtrl {
};
}
this.DAGPlusPlusNodesActionsFactory.addNode(config);
+ this.ReactStores.dispatch({
+ type: 'ADD_NODE',
+ payload: {
+ config
+ }
+ })
}
}