Skip to content

Commit dd8838a

Browse files
committed
Merge branch 'feature/cdi-previewer'
2 parents c4dcfb4 + 972bfa7 commit dd8838a

2 files changed

Lines changed: 130 additions & 59 deletions

File tree

previewers/betatest/js/cdi-preview/data-extraction.js

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,24 +143,49 @@ function collectChangesFromDOM() {
143143
}
144144

145145
// Only update properties that have changed IN THIS NODE (not nested nodes)
146-
// Use children().find() to get only direct properties, not nested node properties
146+
// Use children().find() to get only properties in this card (nested JSON is handled via path)
147147
$card
148148
.children(".node-body")
149149
.find(".property-row.changed")
150150
.each(function () {
151-
const key = $(this).attr("data-property");
151+
const keyPath = $(this).attr("data-property");
152152
const inputs = $(this).find("input, textarea, select");
153153

154154
log(
155155
LOG_LEVEL.DEBUG,
156-
"collectChangesFromDOM: Updating",
156+
"collectChangesFromDOM: Updating path",
157157
nodeId,
158-
key,
158+
keyPath,
159159
"with",
160160
inputs.length,
161161
"inputs"
162162
);
163163

164+
// Helper to set a value on a potentially nested path within the node
165+
function setNestedValue(target, path, newValue) {
166+
if (!path) return;
167+
const segments = path.split(".");
168+
let current = target;
169+
170+
for (let i = 0; i < segments.length; i++) {
171+
const seg = segments[i];
172+
const isLast = i === segments.length - 1;
173+
174+
if (isLast) {
175+
current[seg] = newValue;
176+
} else {
177+
if (
178+
typeof current[seg] !== "object" ||
179+
current[seg] === null ||
180+
Array.isArray(current[seg])
181+
) {
182+
current[seg] = {};
183+
}
184+
current = current[seg];
185+
}
186+
}
187+
}
188+
164189
if (inputs.length === 1) {
165190
// Single value
166191
const input = inputs.eq(0);
@@ -179,7 +204,7 @@ function collectChangesFromDOM() {
179204
} catch (e) {
180205
// Keep as string if not valid JSON
181206
}
182-
node[key] = val;
207+
setNestedValue(node, keyPath, val);
183208
} else if (inputs.length > 1) {
184209
// Array of values
185210
const values = [];
@@ -195,11 +220,17 @@ function collectChangesFromDOM() {
195220
log(
196221
LOG_LEVEL.DEBUG,
197222
"collectChangesFromDOM: Old value:",
198-
node[key],
223+
keyPath
224+
.split(".")
225+
.reduce(
226+
(acc, seg) =>
227+
acc && typeof acc === "object" ? acc[seg] : undefined,
228+
node
229+
),
199230
"-> New value:",
200231
values
201232
);
202-
node[key] = values;
233+
setNestedValue(node, keyPath, values);
203234
}
204235
});
205236
});

previewers/betatest/js/cdi-preview/render.js

Lines changed: 92 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,84 @@ function renderProperty(key, value, nodeId, nodeTypes) {
359359
}
360360

361361
function createValueInput(key, value, nodeId, arrayIndex, classification) {
362+
// Helper to render nested JSON object (both view and edit modes)
363+
function renderNestedObject(obj, parentPath) {
364+
const container = $("<div>").addClass("nested-object").css({
365+
"margin-left": "20px",
366+
"border-left": "2px solid #ddd",
367+
"padding-left": "10px",
368+
"margin-top": "5px",
369+
});
370+
371+
Object.keys(obj).forEach((nestedKey) => {
372+
if (nestedKey === "@id" || nestedKey === "@type") return;
373+
374+
const fullPath = parentPath ? `${parentPath}.${nestedKey}` : nestedKey;
375+
376+
const nestedRow = $("<div>")
377+
.addClass("property-row nested-property")
378+
.attr("data-property", fullPath)
379+
.css({
380+
"margin-bottom": "8px",
381+
display: "flex",
382+
"align-items": "center",
383+
});
384+
385+
const nestedLabel = $("<div>")
386+
.addClass("property-label")
387+
.css({
388+
"font-weight": "500",
389+
"min-width": "150px",
390+
color: "#555",
391+
})
392+
.text(humanizeKey(nestedKey.replace("schema:", "")));
393+
394+
const nestedValueDiv = $("<div>").addClass("property-value").css({
395+
flex: "1",
396+
});
397+
398+
const nestedValue = obj[nestedKey];
399+
400+
if (isEditMode) {
401+
// For now, treat nested values as simple scalars or JSON strings
402+
let valueStr;
403+
if (typeof nestedValue === "object" && nestedValue !== null) {
404+
valueStr = JSON.stringify(nestedValue);
405+
} else {
406+
valueStr = nestedValue === undefined ? "" : String(nestedValue);
407+
}
408+
409+
let input;
410+
if (valueStr.length > 50) {
411+
input = $("<textarea>").val(valueStr);
412+
} else {
413+
input = $("<input>").attr("type", "text").val(valueStr);
414+
}
415+
416+
input.attr("data-original", valueStr);
417+
input.on("input", function () {
418+
$(this).closest(".property-row").addClass("changed");
419+
updateSaveButton();
420+
});
421+
422+
nestedValueDiv.append(input);
423+
} else {
424+
if (typeof nestedValue === "object" && nestedValue !== null) {
425+
nestedValueDiv.text(JSON.stringify(nestedValue));
426+
} else {
427+
nestedValueDiv.text(
428+
nestedValue === undefined ? "" : String(nestedValue)
429+
);
430+
}
431+
}
432+
433+
nestedRow.append(nestedLabel, nestedValueDiv);
434+
container.append(nestedRow);
435+
});
436+
437+
return container;
438+
}
439+
362440
// Check if value is a reference to another node (has @id)
363441
if (typeof value === "object" && value !== null && value["@id"]) {
364442
const refId = value["@id"];
@@ -411,11 +489,16 @@ function createValueInput(key, value, nodeId, arrayIndex, classification) {
411489
return refContainer;
412490
}
413491

414-
// Simple value (string, number, etc.) or complex object without @id
415-
const valueStr =
416-
typeof value === "object" ? JSON.stringify(value) : String(value);
417-
418492
if (isEditMode) {
493+
// Complex object without @id - render nested label+input rows
494+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
495+
const parentPath = key;
496+
return renderNestedObject(value, parentPath);
497+
}
498+
499+
// Simple value (string, number, etc.)
500+
const valueStr = value === undefined ? "" : String(value);
501+
419502
// Check if this property has enumeration values (controlled vocabulary)
420503
if (
421504
classification &&
@@ -480,56 +563,13 @@ function createValueInput(key, value, nodeId, arrayIndex, classification) {
480563

481564
return input;
482565
} else {
483-
// View mode - show as read-only text
566+
// View mode - show as read-only text or nested structure
484567
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
485-
// For complex objects, create a nested expandable section
486-
const nestedContainer = $("<div>").addClass("nested-object").css({
487-
"margin-left": "20px",
488-
"border-left": "2px solid #ddd",
489-
"padding-left": "10px",
490-
"margin-top": "5px",
491-
});
492-
493-
Object.keys(value).forEach((nestedKey) => {
494-
if (nestedKey === "@id" || nestedKey === "@type") return; // Skip JSON-LD metadata for cleaner display
495-
496-
const nestedRow = $("<div>")
497-
.addClass("property-row nested-property")
498-
.css({
499-
"margin-bottom": "8px",
500-
display: "flex",
501-
"align-items": "center",
502-
});
503-
504-
const nestedLabel = $("<div>")
505-
.addClass("property-key")
506-
.css({
507-
"font-weight": "500",
508-
"min-width": "150px",
509-
color: "#555",
510-
})
511-
.text(humanizeKey(nestedKey.replace("schema:", "")));
512-
513-
const nestedValueDiv = $("<div>").addClass("property-value").css({
514-
flex: "1",
515-
});
516-
517-
const nestedValue = value[nestedKey];
518-
if (typeof nestedValue === "object" && nestedValue !== null) {
519-
nestedValueDiv.text(JSON.stringify(nestedValue));
520-
} else {
521-
nestedValueDiv.text(String(nestedValue));
522-
}
523-
524-
nestedRow.append(nestedLabel, nestedValueDiv);
525-
nestedContainer.append(nestedRow);
526-
});
527-
528-
return nestedContainer;
529-
} else {
530-
// For simple values, show as regular text
531-
return $("<div>").addClass("value-display").text(valueStr);
568+
return renderNestedObject(value, key);
532569
}
570+
571+
const valueStr = value === undefined ? "" : String(value);
572+
return $("<div>").addClass("value-display").text(valueStr);
533573
}
534574
}
535575

0 commit comments

Comments
 (0)