Skip to content

Commit 45e2ff6

Browse files
committed
[data edition] fix bug in node edition
Editing node was resetting its position when done from the data table. Bug corrected by refactoring the update/create/node/edge methods specs. we now semantically separate attribute; technical attribute and dynamic attributes.
1 parent 07b2271 commit 45e2ff6

File tree

5 files changed

+63
-55
lines changed

5 files changed

+63
-55
lines changed

packages/gephi-lite/src/components/data/EditEdge.tsx

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,20 +96,16 @@ const useEditEdgeForm = ({
9696
return;
9797
}
9898

99-
const allAttributes = {
100-
...fromPairs(
101-
data.attributes
102-
.filter(({ value }) => value !== "" || value === undefined)
103-
.map(({ key, value }) => {
104-
// value are all string because input are all text whatever the data model
105-
// for now we cast value as number if they are number to help downstream algo to create appropriate data model
106-
const valueAsNumber = toNumber(value);
107-
return [key, valueAsNumber ? valueAsNumber : value];
108-
}),
109-
),
110-
...pick(data, "label", "color", "weight"),
111-
};
112-
99+
const allAttributes = fromPairs(
100+
data.attributes
101+
.filter(({ value }) => value !== "" || value === undefined)
102+
.map(({ key, value }) => {
103+
// value are all string because input are all text whatever the data model
104+
// for now we cast value as number if they are number to help downstream algo to create appropriate data model
105+
const valueAsNumber = toNumber(value);
106+
return [key, valueAsNumber ? valueAsNumber : value];
107+
}),
108+
);
113109
// Create new edge:
114110
if (isNew) {
115111
try {
@@ -134,7 +130,7 @@ const useEditEdgeForm = ({
134130
// Update existing edge:
135131
else {
136132
try {
137-
updateEdge(id, allAttributes, { directed: data.isDirected });
133+
updateEdge(id, { itemData: allAttributes, dynamic: { directed: data.isDirected } });
138134
select({ type: "edges", items: new Set([id]), replace: true });
139135
notify({
140136
type: "success",

packages/gephi-lite/src/components/data/EditNode.tsx

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,24 +86,22 @@ const useEditNodeForm = ({
8686
return;
8787
}
8888

89-
const allAttributes = {
90-
...fromPairs(
91-
data.attributes
92-
.filter(({ value }) => value !== "" || value === undefined)
93-
.map(({ key, value }) => {
94-
// value are all string because input are all text whatever the data model
95-
// for now we cast value as number if they are number to help downstream algo to create appropriate data model
96-
const valueAsNumber = toNumber(value);
97-
return [key, valueAsNumber ? valueAsNumber : value];
98-
}),
99-
),
100-
...pick(data, "x", "y"),
101-
};
89+
const allAttributes = fromPairs(
90+
data.attributes
91+
.filter(({ value }) => value !== "" || value === undefined)
92+
.map(({ key, value }) => {
93+
// value are all string because input are all text whatever the data model
94+
// for now we cast value as number if they are number to help downstream algo to create appropriate data model
95+
const valueAsNumber = toNumber(value);
96+
return [key, valueAsNumber ? valueAsNumber : value];
97+
}),
98+
);
99+
const coordinates = pick(data, "x", "y");
102100

103101
// Create new node:
104102
if (isNew) {
105103
try {
106-
createNode(id, allAttributes);
104+
createNode(id, { itemData: allAttributes, technical: coordinates });
107105
select({ type: "nodes", items: new Set([id]), replace: true });
108106
notify({
109107
type: "success",
@@ -124,7 +122,7 @@ const useEditNodeForm = ({
124122
// Update existing node:
125123
else {
126124
try {
127-
updateNode(id, allAttributes);
125+
updateNode(id, { itemData: allAttributes, technical: coordinates });
128126
select({ type: "nodes", items: new Set([id]), replace: true });
129127
notify({
130128
type: "success",

packages/gephi-lite/src/core/graph/index.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
FilteredGraph,
66
FiltersState,
77
ItemData,
8+
NodeCoordinates,
89
Scalar,
910
getEmptyAppearanceState,
1011
} from "@gephi/gephi-lite-sdk";
@@ -280,10 +281,13 @@ const deleteItemsAttribute: Producer<GraphDataset, [ItemType, string]> = (type,
280281
};
281282
};
282283
};
283-
const createNode: MultiProducer<[GraphDataset, SearchState], [string, Attributes]> = (node, attributes) => {
284+
const createNode: MultiProducer<
285+
[GraphDataset, SearchState],
286+
[string, { itemData: ItemData; technical: NodeCoordinates }]
287+
> = (node, { itemData = {}, technical }) => {
284288
return [
285289
(state) => {
286-
const { data, position } = cleanNode(node, attributes);
290+
const { data, position } = cleanNode(node, itemData, technical);
287291
state.fullGraph.addNode(node);
288292
const newNodeFieldModel = newItemModel<"nodes">("nodes", data, state.nodeFields);
289293
return {
@@ -297,7 +301,7 @@ const createNode: MultiProducer<[GraphDataset, SearchState], [string, Attributes
297301
];
298302
};
299303

300-
const createEdge: MultiProducer<[GraphDataset, SearchState], [string, Attributes, string, string, boolean]> = (
304+
const createEdge: MultiProducer<[GraphDataset, SearchState], [string, ItemData, string, string, boolean]> = (
301305
edge,
302306
attributes,
303307
source,
@@ -329,11 +333,15 @@ const createEdge: MultiProducer<[GraphDataset, SearchState], [string, Attributes
329333
};
330334
const updateNode: MultiProducer<
331335
[GraphDataset, SearchState, AppearanceState],
332-
[string, Attributes, { merge?: boolean }?]
333-
> = (node, attributes, { merge } = {}) => {
336+
[string, { itemData?: ItemData; technical?: NodeCoordinates; dynamic?: Attributes; merge?: boolean }]
337+
> = (node, { itemData = {}, technical, merge }) => {
334338
return [
335-
(state) => {
336-
const { data, position } = cleanNode(node, merge ? { ...state.nodeData[node], ...attributes } : attributes);
339+
(state): GraphDataset => {
340+
const { data, position } = cleanNode(
341+
node,
342+
merge ? { ...state.nodeData[node], ...itemData } : itemData,
343+
technical || state.layout[node],
344+
);
337345
const newNodeFieldModel = newItemModel<"nodes">("nodes", data, state.nodeFields);
338346
return {
339347
...state,
@@ -343,16 +351,18 @@ const updateNode: MultiProducer<
343351
};
344352
},
345353
nodeIndex(node),
346-
checkAppearanceAfterAttributeUpdate("nodes", node, attributes),
354+
checkAppearanceAfterAttributeUpdate("nodes", node, itemData),
347355
];
348356
};
349357
const updateEdge: MultiProducer<
350358
[GraphDataset, SearchState, AppearanceState],
351-
[string, Attributes, { merge?: boolean; directed?: boolean }?]
352-
> = (edge, attributes, { merge, directed } = {}) => {
359+
[string, { itemData?: ItemData; technical?: NodeCoordinates; dynamic?: Attributes; merge?: boolean }]
360+
> = (edge, { itemData = {}, merge, dynamic }) => {
361+
const directed = dynamic?.directed;
362+
353363
return [
354-
(state) => {
355-
const { data } = cleanEdge(edge, merge ? { ...state.edgeData[edge], ...attributes } : attributes);
364+
(state): GraphDataset => {
365+
const { data } = cleanEdge(edge, merge ? { ...state.edgeData[edge], ...itemData } : itemData);
356366
const newEdgeFieldModel = newItemModel<"edges">("edges", data, state.edgeFields);
357367

358368
// Validate new edge direction:
@@ -373,8 +383,6 @@ const updateEdge: MultiProducer<
373383
fullGraph = newFullGraph;
374384
}
375385

376-
// Index the edge
377-
searchActions.edgeIndex(edge);
378386
return {
379387
...state,
380388
fullGraph,
@@ -383,7 +391,7 @@ const updateEdge: MultiProducer<
383391
};
384392
},
385393
edgeIndex(edge),
386-
checkAppearanceAfterAttributeUpdate("edges", edge, attributes),
394+
checkAppearanceAfterAttributeUpdate("edges", edge, itemData),
387395
];
388396
};
389397
const updateItems: MultiProducer<[GraphDataset, SearchState], [ItemType, Set<string>, string, Scalar]> = (

packages/gephi-lite/src/core/graph/utils.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NodeCoordinates, getEmptyGraphDataset, toNumber, toScalar } from "@gephi/gephi-lite-sdk";
22
import Graph, { MultiGraph } from "graphology";
33
import { Attributes } from "graphology-types";
4-
import { flatMap, forEach, isNil, isNumber, keyBy, keys, mapValues, omit, sortBy, uniq, values } from "lodash";
4+
import { flatMap, forEach, isNil, isNumber, keyBy, keys, mapValues, omit, pick, sortBy, uniq, values } from "lodash";
55

66
import { ItemType, Scalar } from "../types";
77
import { inferFieldType } from "./fieldModel";
@@ -24,16 +24,22 @@ export function getRandomNodeCoordinate(): number {
2424
return Math.random() * 1000;
2525
}
2626

27-
export function cleanNode(_node: string, attributes: Attributes): { data: ItemData; position: NodeCoordinates } {
28-
const x = toNumber(attributes.x);
29-
const y = toNumber(attributes.y);
27+
export function cleanNode(
28+
_node: string,
29+
attributes: Attributes,
30+
coordinates?: { x: Scalar; y: Scalar },
31+
): { data: ItemData; position: NodeCoordinates } {
32+
// ensure coordinate format
33+
const x = toNumber(coordinates?.x);
34+
const y = toNumber(coordinates?.y);
3035

3136
const position: NodeCoordinates = {
3237
x: typeof x === "number" ? x : getRandomNodeCoordinate(),
3338
y: typeof y === "number" ? y : getRandomNodeCoordinate(),
3439
};
3540

36-
const data: ItemData = mapValues(omit(attributes, "x", "y"), (v) => toScalar(v));
41+
// cast attributes to scalar
42+
const data: ItemData = mapValues(attributes, (v) => toScalar(v));
3743

3844
return { data, position };
3945
}
@@ -60,7 +66,7 @@ export function initializeGraphDataset(
6066

6167
const nodeAttributeValues: Record<string, Scalar[]> = {};
6268
graph.forEachNode((node, attributes) => {
63-
const { data, position } = cleanNode(node, attributes);
69+
const { data, position } = cleanNode(node, omit(attributes, ["x", "y"]), pick(attributes, ["x", "y"]));
6470

6571
for (const key in data) {
6672
nodeAttributeValues[key] = nodeAttributeValues[key] || [];

packages/gephi-lite/src/views/dataPage/dataTable/DataCell.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ export const InlineEditDataCell: FC<{
4141
onChange={(value) => {
4242
const update = type === "nodes" ? updateNode : updateEdge;
4343
if (field.dynamic) {
44-
update(id, {}, { merge: true, [field.id]: value });
44+
update(id, { merge: true, dynamic: { [field.id]: value } });
4545
} else {
46-
update(id, { [field.id]: value }, { merge: true });
46+
update(id, { itemData: { [field.id]: value }, merge: true });
4747
}
4848
}}
4949
/>
@@ -108,9 +108,9 @@ export const EditDataCell: FC<{
108108
onSubmit={(e) => {
109109
e.preventDefault();
110110
if (field.dynamic) {
111-
update(id, {}, { merge: true, [field.id]: value });
111+
update(id, { merge: true, dynamic: { [field.id]: value } });
112112
} else {
113-
update(id, { [field.id]: value }, { merge: true });
113+
update(id, { itemData: { [field.id]: value }, merge: true });
114114
}
115115
close();
116116
}}

0 commit comments

Comments
 (0)