Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
2be9a0b
fix(665): REVERT LATER
IgorKrupenja Aug 13, 2025
8726814
fix(665): Install
IgorKrupenja Aug 13, 2025
bc26a89
fix(665): drag-dorp poc lib 2
IgorKrupenja Aug 13, 2025
c352f67
fix(665): drag-dorp poc lib 2 SIMPLER
IgorKrupenja Aug 13, 2025
34e0577
Revert "fix(665): drag-dorp poc lib 2 SIMPLER"
IgorKrupenja Aug 13, 2025
87b9a0b
fix(665): clean
IgorKrupenja Aug 13, 2025
c456231
fix(665): drag-dorp poc lib 2 + trans
IgorKrupenja Aug 13, 2025
89d5dd8
fix(665): drag-dorp poc lib 3 BASIC
IgorKrupenja Aug 13, 2025
8401e46
Revert "fix(665): drag-dorp poc lib 3 BASIC"
IgorKrupenja Aug 14, 2025
cc75945
fix(665): drag-dorp poc lib 2 hover css
IgorKrupenja Aug 14, 2025
0f5f015
fix(665): to do
IgorKrupenja Aug 14, 2025
4ff51f9
fix(665): tyoes
IgorKrupenja Aug 14, 2025
2ac18cb
fix(665): rename
IgorKrupenja Aug 14, 2025
e98c115
fix(665): Clean up
IgorKrupenja Aug 15, 2025
c4bec5b
fix(665): Clean up
IgorKrupenja Aug 15, 2025
2eeafc6
fix(665): Clean up
IgorKrupenja Aug 15, 2025
e164cd0
fix(665): Clean up
IgorKrupenja Aug 15, 2025
9db3a26
fix(665): PoC fix drop
IgorKrupenja Aug 15, 2025
43dd6d2
fix(665): To do
IgorKrupenja Aug 15, 2025
dfe627c
fix(665): Clean up
IgorKrupenja Aug 15, 2025
5fd7a50
fix(665): Clean up
IgorKrupenja Aug 15, 2025
bed284f
fix(665): Clean up
IgorKrupenja Aug 15, 2025
2799780
fix(665): PoC array drop
IgorKrupenja Aug 15, 2025
63309b1
fix(665): Clean up
IgorKrupenja Aug 15, 2025
61f0130
fix(665): Simplify
IgorKrupenja Aug 15, 2025
2069e1c
fix(665): Simplify
IgorKrupenja Aug 15, 2025
26aaece
fix(665): Simplify
IgorKrupenja Aug 15, 2025
2980af1
fix(665): Simplify
IgorKrupenja Aug 15, 2025
91dcaeb
fix(665): Clean up
IgorKrupenja Aug 15, 2025
f57aa53
fix(665): Clean up
IgorKrupenja Aug 15, 2025
2546ddc
fix(665): Clean up
IgorKrupenja Aug 15, 2025
589a9ba
fix(665): Clean up
IgorKrupenja Aug 15, 2025
90b1738
fix(665): Clean up
IgorKrupenja Aug 15, 2025
5fb9c8e
fix(665): Clean up
IgorKrupenja Aug 15, 2025
d9119f9
fix(665): Fix types
IgorKrupenja Aug 15, 2025
7e3b847
fix(665): Clean upo
IgorKrupenja Aug 15, 2025
269c4e6
fix(665): Trans
IgorKrupenja Aug 15, 2025
890d12b
fix(665): Clea
IgorKrupenja Aug 15, 2025
fa70860
fix(665): Clean up
IgorKrupenja Aug 15, 2025
d4a1e99
fix(665): Clean up
IgorKrupenja Aug 15, 2025
05cd3e6
fix(665): Clean up
IgorKrupenja Aug 15, 2025
7e6b64a
fix(665): fix drag drop on array elements
IgorKrupenja Aug 15, 2025
b574258
fix(665): remove console logs
IgorKrupenja Aug 15, 2025
f6fbb21
fix(665): Clean up
IgorKrupenja Aug 15, 2025
31b1f4b
fix(665): Clean up
IgorKrupenja Aug 15, 2025
0ef138f
chore(685): Added show error flag to saving flow
1AhmedYasser Aug 16, 2025
1544c26
chore(685): Enhanced Continue Error Handling
1AhmedYasser Aug 16, 2025
05d9c4d
fix(686): Added Enhancment checks to ensure saving and continue execu…
1AhmedYasser Aug 16, 2025
397abba
chore(686): Enhanced Service Deletion Button
1AhmedYasser Aug 16, 2025
13a6e71
chore(686): Enhanced Continue Button
1AhmedYasser Aug 16, 2025
12b6ab1
chore(686): Enhanced Delete Button Enabling
1AhmedYasser Aug 16, 2025
39b37ad
chore(686): Enhanced intent connection button
1AhmedYasser Aug 16, 2025
025bd97
fix(665): WIP button
IgorKrupenja Aug 18, 2025
0ddba79
fix(665): WIP button
IgorKrupenja Aug 18, 2025
711a792
fix(665): WIP button
IgorKrupenja Aug 18, 2025
a614750
fix(665): WIP state
IgorKrupenja Aug 18, 2025
8382768
fix(665): WIP state
IgorKrupenja Aug 18, 2025
55ae7f1
fix(665): WIP state
IgorKrupenja Aug 18, 2025
77d8a78
fix(665): WIP state
IgorKrupenja Aug 18, 2025
5120aa3
fix(665): WIP state
IgorKrupenja Aug 18, 2025
418f9f3
fix(665): WIP state
IgorKrupenja Aug 18, 2025
35b276a
fix(665): WIP state
IgorKrupenja Aug 18, 2025
6366faa
fix(665): WIP state
IgorKrupenja Aug 18, 2025
7572013
fix(665): WIP state
IgorKrupenja Aug 18, 2025
06892fc
fix(665): WIP style
IgorKrupenja Aug 18, 2025
90c9d12
fix(665): WIP state
IgorKrupenja Aug 18, 2025
304503f
fix(665): Fix typing bug
IgorKrupenja Aug 18, 2025
3e02ded
fix(665): Fix tree state
IgorKrupenja Aug 18, 2025
b951e04
fix(665): Fix drag styles
IgorKrupenja Aug 18, 2025
28ac7bf
fix(665): WIP styles
IgorKrupenja Aug 18, 2025
eb50cdd
fix(665): styles
IgorKrupenja Aug 18, 2025
d57b822
fix(665): WIP toggle
IgorKrupenja Aug 18, 2025
81ebf2e
fix(665): WIP toggle
IgorKrupenja Aug 18, 2025
1848691
fix(665): WIP toggle
IgorKrupenja Aug 18, 2025
7ff952d
fix(665): WIP parsing
IgorKrupenja Aug 18, 2025
fb583d4
fix(665): WIP parsing
IgorKrupenja Aug 18, 2025
630d1db
fix(665): WIP parsing
IgorKrupenja Aug 18, 2025
bcbf984
fix(665): WIP parsing
IgorKrupenja Aug 18, 2025
bf2e6e4
fix(665): WIP parsing
IgorKrupenja Aug 18, 2025
cf1d6c1
fix(665): parsing
IgorKrupenja Aug 18, 2025
0b9ac1e
fix(665): clean
IgorKrupenja Aug 18, 2025
1ac0a65
fix(665): clean
IgorKrupenja Aug 18, 2025
e679f63
fix(665): clean
IgorKrupenja Aug 18, 2025
1f0fbcd
fix(665): clean
IgorKrupenja Aug 18, 2025
90a442b
fix(665): clean
IgorKrupenja Aug 18, 2025
1f4bf52
fix(665): clean
IgorKrupenja Aug 18, 2025
f35b2ab
fix(665): fix soinar
IgorKrupenja Aug 18, 2025
3be0fd7
fix(665): fix sonar
IgorKrupenja Aug 18, 2025
73b8eb7
chore(686): Enhanced Activate Button
1AhmedYasser Aug 18, 2025
aedea9f
Merge pull request #688 from IgorKrupenja/665-obnject-editor
jaX10bt Aug 19, 2025
42ff691
Merge pull request #689 from 1AhmedYasser/Bug-Unexpected-"Connect-Int…
jaX10bt Aug 19, 2025
d61f3a7
Merge pull request #687 from 1AhmedYasser/Bug-Flow-validation-on-Save…
jaX10bt Aug 19, 2025
6eb453e
Hot-fix: Form Select Font Size (#690)
1AhmedYasser Aug 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions DSL/Ruuter/services/POST/services/edit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ declaration:
- field: id
type: string
description: "Parameter 'id'"
headers:
- field: cookie
type: string
description: "Cookie field"

extract_request_data:
assign:
Expand Down Expand Up @@ -169,6 +173,7 @@ assign_values:
old_name: ${old_service_result.response.body[0].name}
old_structure: ${old_service_result.response.body[0].structure}
old_state: ${old_service_result.response.body[0].state}
service_type: ${old_service_result.response.body[0].type}

check_new_structure:
switch:
Expand Down Expand Up @@ -209,6 +214,25 @@ service_edit:
state: ${state ?? 'draft'}
result: editedService

check for_state:
switch:
- condition: ${state === 'draft'}
next: change_state_to_draft
next: return_ok

change_state_to_draft:
call: http.post
args:
url: "[#SERVICE_RUUTER]/services/status"
headers:
cookie: ${incoming.headers.cookie}
body:
id: ${id}
state: "draft"
type: ${service_type ?? 'POST'}
result: changeStateResult
next: return_ok

return_ok:
reloadDsl: true
status: 200
Expand Down
2 changes: 2 additions & 0 deletions GUI/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"howler": "^2.2.4",
"i18next": "^22.4.9",
"i18next-browser-languagedetector": "^7.0.1",
"jsoneditor": "^10.3.0",
"moment": "^2.29.4",
"msw": "^0.49.2",
"node-html-markdown": "^1.3.0",
Expand Down Expand Up @@ -83,6 +84,7 @@
"@types/d3-hierarchy": "^3.1.7",
"@types/d3-timer": "^3.0.2",
"@types/howler": "^2.2.11",
"@types/jsoneditor": "^9.9.6",
"@types/react": "^18.2.0",
"@types/react-datepicker": "^4.8.0",
"@types/react-dom": "^18.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const EndpointCustom: React.FC<EndpointCustomProps> = ({
<FormSelect
name={"request-type"}
label={""}
style={{ borderRadius: "4px 0 0 4px", borderRight: 0 }}
style={{ borderRadius: "4px 0 0 4px", borderRight: 0, fontSize: "15px" }}
options={[
{ label: "GET", value: "GET" },
{ label: "POST", value: "POST" },
Expand Down
1 change: 1 addition & 0 deletions GUI/src/components/ApiEndpointCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const ApiEndpointCard: FC<EndpointCardProps> = ({
placeholder={t("newService.endpoint.type").toString()}
options={options}
disabled={selectedTab === EndpointEnv.Test}
style={{ fontSize: "15px" }}
onSelectionChange={(selection) => {
setOption(selection);
endpoint.type = selection?.value as EndpointType;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import "src/styles/tools/color";

.assignElement {
padding: 8px 16px 8px 16px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@import "src/styles/tools/color";

.dragHoverHighlight {
background-color: get-color(sea-green-1) !important;
border: 1px solid get-color(sea-green-10) !important;
border-radius: 4px !important;
box-shadow: 0 0 8px get-color(sea-green-3) !important;
transition: all 0.2s ease-in-out !important;
}

.editor {
height: 200px;
padding-top: 8px;
}
221 changes: 221 additions & 0 deletions GUI/src/components/FlowElementsPopup/AssignBuilder/ObjectEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import React, { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import JSONEditor from "jsoneditor";
import "jsoneditor/dist/jsoneditor.css";
import { getDragData } from "utils/component-util";
import { isObject, updateValueAtPath } from "utils/object-util";
import styles from "./ObjectEditor.module.scss";
import { stringToTemplate } from "utils/string-util";

// Helper function to find the path to a node in the JSON structure
const findNodePath = (node: Element, data: Record<string, unknown>): string | null => {
// Try to find by text content (for values)
const textContent = node.textContent?.trim();
if (textContent) {
const path = searchInCollection(data, textContent);
return path;
}

return null;
};

// Helper function to check if values match (handling different types)
const isValueMatch = (objValue: unknown, value: string): boolean => {
// Handle boolean conversion
let booleanValue: boolean | null = null;
if (value.toLowerCase() === "true") {
booleanValue = true;
} else if (value.toLowerCase() === "false") {
booleanValue = false;
}

return (
objValue === value ||
(typeof objValue === "number" && !isNaN(Number(value)) && objValue === Number(value)) ||
(typeof objValue === "boolean" && objValue === booleanValue) ||
(objValue === null && value.toLowerCase() === "null")
);
};

// Helper function to search for value in an array
const searchInArray = (array: unknown[], value: string, currentPath = ""): string | null => {
for (let index = 0; index < array.length; index++) {
const objValue = array[index];
const newPath = currentPath ? `${currentPath}[${index}]` : `[${index}]`;

if (isValueMatch(objValue, value)) return newPath;

if (isObject(objValue)) {
const result = searchInCollection(objValue, value, newPath);
if (result) return result;
}
}

return null;
};

// Helper function to search for value in an object
const searchInObject = (obj: Record<string, unknown>, value: string, currentPath = ""): string | null => {
for (const [key, objValue] of Object.entries(obj)) {
const newPath = currentPath ? `${currentPath}.${key}` : String(key);

if (isValueMatch(objValue, value)) return newPath;

if (isObject(objValue)) {
const result = searchInCollection(objValue, value, newPath);
if (result) return result;
}
}

return null;
};

// Helper function to search for value in a collection
const searchInCollection = (collection: object, value: string, currentPath = ""): string | null => {
if (Array.isArray(collection)) {
return searchInArray(collection, value, currentPath);
}

return searchInObject(collection as Record<string, unknown>, value, currentPath);
};

interface ObjectEditorProps {
onChange: (value: string) => void;
data: Record<string, unknown> | unknown[];
}

const ObjectEditor: React.FC<ObjectEditorProps> = ({ onChange, data }) => {
const { t, i18n } = useTranslation();
const jsonEditor = t("objectEditor", { returnObjects: true });
const editorRef = useRef<HTMLDivElement>(null);
const jsonEditorRef = useRef<JSONEditor | null>(null);
const [hoveredElement, setHoveredElement] = useState<Element | null>(null);

useEffect(() => {
if (editorRef.current && !jsonEditorRef.current) {
const editor = new JSONEditor(editorRef.current, {
language: i18n.language,
languages: {
[i18n.language]: jsonEditor,
},
onChange: () => {
onChange(stringToTemplate(JSON.stringify(jsonEditorRef.current?.get())));
},
});

editor.set(data);
jsonEditorRef.current = editor;
}

return () => {
if (jsonEditorRef.current) {
jsonEditorRef.current.destroy();
jsonEditorRef.current = null;
}
};
}, []);

// Cleanup effect to remove highlight when component unmounts
useEffect(() => {
return () => {
if (hoveredElement) {
hoveredElement.classList.remove(styles.dragHoverHighlight);
}
};
}, [hoveredElement]);

const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();

// Get the element under the cursor
const element = document.elementFromPoint(e.clientX, e.clientY);
if (element) {
const jsonNode = element.closest(".jsoneditor-value");

// Remove highlight from previously hovered element
if (hoveredElement && hoveredElement !== jsonNode) {
hoveredElement.classList.remove(styles.dragHoverHighlight);
}

// Add highlight to currently hovered element
if (jsonNode && jsonNode !== hoveredElement) {
jsonNode.classList.add(styles.dragHoverHighlight);
setHoveredElement(jsonNode);
}
}
};

const handleDragLeave = () => {
// Remove highlight when leaving the drop zone
if (hoveredElement) {
hoveredElement.classList.remove(styles.dragHoverHighlight);
setHoveredElement(null);
}
};

const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();

// Clean up highlight
if (hoveredElement) {
hoveredElement.classList.remove(styles.dragHoverHighlight);
setHoveredElement(null);
}

try {
const dragData = getDragData(e);
if (dragData && jsonEditorRef.current) {
// Extract just the value from the drag data
const valueToReplace = dragData.value;

// Get the element under the cursor
const element = document.elementFromPoint(e.clientX, e.clientY);
if (element) {
const jsonNode = element.closest(".jsoneditor-value");

if (jsonNode) {
// Get the current JSON data
const currentData = jsonEditorRef.current.get();

// Try to find the path to the dropped node
const path = findNodePath(jsonNode, currentData);

if (path) {
// Update the value at the specific path
const newData = updateValueAtPath(currentData, path, valueToReplace);

jsonEditorRef.current.update(newData);

onChange(stringToTemplate(JSON.stringify(newData)));
}
}
}
}
} catch (error) {
console.error("Error processing drop:", error);
}
};

return (
<div
ref={editorRef}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
className={styles.editor}
role="application"
aria-label={t("objectEditor.editor")!}
tabIndex={0}
onKeyDown={(e) => {
// Handle keyboard interactions for accessibility
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
// Focus the editor for keyboard navigation
editorRef.current?.focus();
}
}}
/>
);
};

export default ObjectEditor;
Loading
Loading