-
-
-
-
- setIsCollapsed(true)}
- defaultSize={20}
- minSize={10}
- maxSize={50}
- >
-
-
- {!isCollapsed && (
-
- )}
-
-
-
-
-
+
+
+
+
+
+ setIsCollapsed(true)}
+ defaultSize={20}
+ minSize={10}
+ maxSize={50}
+ >
+
+
+ {!isCollapsed && (
+
+ )}
+
+
+
+
-
+
);
};
diff --git a/app/src/pages/mapping_page/state.ts b/app/src/pages/mapping_page/state.ts
index 75ac069..46efb76 100644
--- a/app/src/pages/mapping_page/state.ts
+++ b/app/src/pages/mapping_page/state.ts
@@ -1,3 +1,7 @@
+import {
+ XYEdgeType,
+ XYNodeTypes,
+} from '@/pages/mapping_page/components/MainPanel/types';
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import MappingService from '../../lib/api/mapping_service';
@@ -24,7 +28,9 @@ interface MappingPageStateActions {
saveMapping: (
workspaceUuid: string,
mappingUuid: string,
- mapping: MappingGraph,
+ mappingGraph: MappingGraph,
+ nodes: XYNodeTypes[],
+ edges: XYEdgeType[],
) => Promise
;
}
@@ -73,9 +79,29 @@ const functions: ZustandActions = (
async saveMapping(
workspaceUuid: string,
mappingUuid: string,
- mapping: MappingGraph,
+ mappingGraph: MappingGraph,
+ nodes: XYNodeTypes[],
+ edges: XYEdgeType[],
) {
set({ isLoading: 'Saving mapping...' });
+ // Convert nodes and edges to MappingGraph, sync nodes position and id with node.data
+ // and edges source, sourceHandle, target, targetHandle and id with edge.data
+ const mapping = {
+ ...mappingGraph,
+ nodes: nodes.map(node => ({
+ ...node.data,
+ position: node.position,
+ id: node.id,
+ })),
+ edges: edges.map(edge => ({
+ ...edge.data,
+ source: edge.source,
+ target: edge.target,
+ source_handle: edge.sourceHandle,
+ target_handle: edge.targetHandle,
+ id: edge.id,
+ })),
+ } as MappingGraph;
try {
await MappingService.updateMapping(workspaceUuid, mappingUuid, mapping);
set({ error: null });
diff --git a/server/logger.py b/server/logger.py
index 4748503..b144e00 100644
--- a/server/logger.py
+++ b/server/logger.py
@@ -32,6 +32,7 @@ def setup_logging(
drop_color_message_key,
timestamper,
structlog.processors.StackInfoRenderer(),
+ structlog.processors.format_exc_info,
]
if json_logs:
diff --git a/server/models/mapping.py b/server/models/mapping.py
index 41f4f27..dbc8503 100644
--- a/server/models/mapping.py
+++ b/server/models/mapping.py
@@ -1,8 +1,6 @@
from dataclasses import dataclass
from enum import StrEnum
-from server.models.ontology import Property
-
class MappingNodeType(StrEnum):
ENTITY = "entity"
@@ -10,6 +8,37 @@ class MappingNodeType(StrEnum):
URIRef = "uri_ref"
+@dataclass(kw_only=True)
+class Position:
+ """
+ A position in a mapping graph.
+
+ Attributes:
+ x (int): The x-coordinate of the position
+ y (int): The y-coordinate of the position
+ """
+
+ x: int
+ y: int
+
+ def to_dict(self):
+ return {
+ "x": self.x,
+ "y": self.y,
+ }
+
+ @classmethod
+ def from_dict(cls, data):
+ if "x" not in data:
+ raise ValueError("x is required")
+ if "y" not in data:
+ raise ValueError("y is required")
+ return cls(
+ x=data["x"],
+ y=data["y"],
+ )
+
+
@dataclass(kw_only=True)
class MappingNode:
"""
@@ -22,6 +51,7 @@ class MappingNode:
uri_pattern (str): The URI pattern of the node
rdf_type (list[str]): The RDF type/s of the node
properties (list[str]): The properties of the node
+ position (Position): The position of the node
"""
id: str
@@ -30,6 +60,7 @@ class MappingNode:
uri_pattern: str
rdf_type: list[str]
properties: list[str]
+ position: Position
def to_dict(self):
return {
@@ -39,6 +70,7 @@ def to_dict(self):
"uri_pattern": self.uri_pattern,
"rdf_type": self.rdf_type,
"properties": self.properties,
+ "position": self.position.to_dict(),
}
@classmethod
@@ -51,6 +83,8 @@ def from_dict(cls, data):
raise ValueError("label is required")
if "uri_pattern" not in data:
raise ValueError("uri_pattern is required")
+ if "position" not in data:
+ raise ValueError("position is required")
if "rdf_type" not in data:
data["rdf_type"] = []
if "properties" not in data:
@@ -62,6 +96,7 @@ def from_dict(cls, data):
uri_pattern=data["uri_pattern"],
rdf_type=data["rdf_type"],
properties=data["properties"],
+ position=Position.from_dict(data["position"]),
)
@@ -76,6 +111,7 @@ class MappingLiteral:
label (str): The label of the literal
value (str): The value of the literal
literal_type (str): The type of the literal
+ position (Position): The position of the literal
"""
id: str
@@ -83,6 +119,7 @@ class MappingLiteral:
label: str
value: str
literal_type: str
+ position: Position
def to_dict(self):
return {
@@ -91,6 +128,7 @@ def to_dict(self):
"label": self.label,
"value": self.value,
"literal_type": self.literal_type,
+ "position": self.position.to_dict(),
}
@classmethod
@@ -105,12 +143,15 @@ def from_dict(cls, data):
raise ValueError("value is required")
if "literal_type" not in data:
raise ValueError("literal_type is required")
+ if "position" not in data:
+ raise ValueError("position is required")
return cls(
id=data["id"],
type=data["type"],
label=data["label"],
value=data["value"],
literal_type=data["literal_type"],
+ position=Position.from_dict(data["position"]),
)
@@ -122,18 +163,21 @@ class MappingURIRef:
Attributes:
id (str): The ID of the URI reference
type (MappingNodeType): The type of the URI reference
- uri (str): The URI of the URI reference
+ uri_pattern (str): The URI pattern of the URI reference
+ position (Position): The position of the URI reference
"""
id: str
type: MappingNodeType
uri_pattern: str
+ position: Position
def to_dict(self):
return {
"id": self.id,
"type": self.type,
"uri_pattern": self.uri_pattern,
+ "position": self.position.to_dict(),
}
@classmethod
@@ -144,10 +188,13 @@ def from_dict(cls, data):
raise ValueError("type is required")
if "uri_pattern" not in data:
raise ValueError("uri_pattern is required")
+ if "position" not in data:
+ raise ValueError("position is required")
return cls(
id=data["id"],
type=data["type"],
uri_pattern=data["uri_pattern"],
+ position=Position.from_dict(data["position"]),
)
diff --git a/server/services/local/local_mapping_service.py b/server/services/local/local_mapping_service.py
index 9769907..1776414 100644
--- a/server/services/local/local_mapping_service.py
+++ b/server/services/local/local_mapping_service.py
@@ -79,8 +79,11 @@ def update_mapping(
self.logger.info(f"Updating mapping {mapping_id}")
self._fs_service.upload_file(
- mapping_id,
- json.dumps(graph.to_dict()).encode("utf-8"),
+ name=mapping_id,
+ content=json.dumps(graph.to_dict()).encode(
+ "utf-8"
+ ),
+ uuid=mapping_id,
allow_overwrite=True,
)