@@ -359,6 +359,84 @@ function renderProperty(key, value, nodeId, nodeTypes) {
359359}
360360
361361function 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