@@ -179,7 +179,25 @@ async function renderWithShaclForm(jsonData) {
179179 if ( ! response . ok ) {
180180 throw new Error ( `Failed to load official SHACL shapes: ${ response . statusText } ` ) ;
181181 }
182- const shapesData = await response . text ( ) ;
182+ let shapesData = await response . text ( ) ;
183+
184+ // Fix the SHACL target query to allow datasets with incoming schema:about references
185+ // This is needed because subjectOf/about creates a circular reference
186+ shapesData = shapesData . replace (
187+ / S E L E C T D I S T I N C T \? t h i s \s + W H E R E \{ \s + \? t h i s a s c h e m a : D a t a s e t \. \s + F I L T E R \( \s + N O T E X I S T S \{ \? s \? p \? t h i s \. \} \s + \) \s + \} / ,
188+ `SELECT DISTINCT ?this
189+ WHERE {
190+ ?this a schema:Dataset .
191+ FILTER (
192+ NOT EXISTS {
193+ ?s ?p ?this .
194+ FILTER(?p != schema:about)
195+ }
196+ )
197+ }`
198+ ) ;
199+
200+ console . log ( '[CDI Previewer] Modified SHACL shapes to allow schema:about incoming edges' ) ;
183201
184202 // Wait for the shacl-form custom element to be defined
185203 await customElements . whenDefined ( 'shacl-form' ) ;
@@ -197,11 +215,131 @@ async function renderWithShaclForm(jsonData) {
197215 shaclFormElement . setAttribute ( 'data-collapse' , 'open' ) ;
198216 shaclFormElement . setAttribute ( 'data-language' , locale || 'en' ) ;
199217
200- // Don't set data-values-subject - let shacl-form auto-detect the root from SHACL shapes
201- // The SHACL shapes define targets (e.g., schema:Dataset) that will be matched automatically
218+ // Explicitly set the shape subject to avoid ambiguity when multiple root shapes exist
219+ shaclFormElement . setAttribute ( 'data-shape-subject' , 'https://cdif.org/validation/0.1/shacl#CDIFDatasetRecommendedShape' ) ;
220+
221+ // Try to detect the root dataset subject from the data
222+ if ( jsonData [ '@graph' ] ) {
223+ const datasets = jsonData [ '@graph' ] . filter ( node => {
224+ const types = Array . isArray ( node [ '@type' ] ) ? node [ '@type' ] : [ node [ '@type' ] ] ;
225+ return types && types . some ( t => t === 'schema:Dataset' || t === 'http://schema.org/Dataset' ) ;
226+ } ) ;
227+
228+ if ( datasets . length > 0 && datasets [ 0 ] [ '@id' ] ) {
229+ console . log ( '[CDI Previewer] Setting data-values-subject to:' , datasets [ 0 ] [ '@id' ] ) ;
230+ shaclFormElement . setAttribute ( 'data-values-subject' , datasets [ 0 ] [ '@id' ] ) ;
231+ }
232+ }
233+
234+ console . log ( '[CDI Previewer] ===== DIAGNOSTIC INFO =====' ) ;
235+ console . log ( '[CDI Previewer] JSON-LD data loaded. Keys:' , Object . keys ( jsonData ) ) ;
236+ console . log ( '[CDI Previewer] @context:' , jsonData [ '@context' ] ) ;
237+ console . log ( '[CDI Previewer] @graph length:' , jsonData [ '@graph' ] ?. length ) ;
238+ console . log ( '[CDI Previewer] Looking for schema:Dataset nodes...' ) ;
239+
240+ // Debug: Find all Dataset nodes in the data
241+ if ( jsonData [ '@graph' ] ) {
242+ const allTypes = new Set ( ) ;
243+ jsonData [ '@graph' ] . forEach ( node => {
244+ const types = Array . isArray ( node [ '@type' ] ) ? node [ '@type' ] : [ node [ '@type' ] ] ;
245+ types . forEach ( t => t && allTypes . add ( t ) ) ;
246+ } ) ;
247+ console . log ( '[CDI Previewer] All @type values in graph:' , Array . from ( allTypes ) ) ;
248+
249+ const datasets = jsonData [ '@graph' ] . filter ( node => {
250+ const types = Array . isArray ( node [ '@type' ] ) ? node [ '@type' ] : [ node [ '@type' ] ] ;
251+ return types . some ( t => t === 'schema:Dataset' || t === 'http://schema.org/Dataset' ) ;
252+ } ) ;
253+ console . log ( '[CDI Previewer] Found' , datasets . length , 'Dataset node(s):' , datasets . map ( d => d [ '@id' ] ) ) ;
254+
255+ if ( datasets . length > 0 ) {
256+ console . log ( '[CDI Previewer] First Dataset node:' , JSON . stringify ( datasets [ 0 ] , null , 2 ) . substring ( 0 , 500 ) ) ;
257+ }
258+ }
259+
260+ console . log ( '[CDI Previewer] data-shape-subject:' , shaclFormElement . getAttribute ( 'data-shape-subject' ) ) ;
261+ console . log ( '[CDI Previewer] data-values-subject:' , shaclFormElement . getAttribute ( 'data-values-subject' ) ) ;
262+ console . log ( '[CDI Previewer] Shapes data length:' , shapesData . length , 'characters' ) ;
263+ console . log ( '[CDI Previewer] Values data length:' , valuesString . length , 'characters' ) ;
264+ console . log ( '[CDI Previewer] ===== END DIAGNOSTIC INFO =====' ) ;
265+
266+ // Listen for ALL events from shacl-form for debugging
267+ [ 'shacl-form-ready' , 'shacl-validation-complete' , 'error' , 'load' , 'change' ] . forEach ( eventName => {
268+ shaclFormElement . addEventListener ( eventName , ( event ) => {
269+ console . log ( `[CDI Previewer] Event: ${ eventName } ` , event . detail || event ) ;
270+ } ) ;
271+ } ) ;
272+
273+ // Listen for form rendering events
274+ shaclFormElement . addEventListener ( 'shacl-form-ready' , ( ) => {
275+ console . log ( '[CDI Previewer] SHACL form is ready and rendered' ) ;
276+ } ) ;
277+
278+ shaclFormElement . addEventListener ( 'shacl-validation-complete' , ( event ) => {
279+ console . log ( '[CDI Previewer] SHACL validation complete:' , event . detail ) ;
280+ if ( event . detail ?. validationReport ) {
281+ displayValidationReport ( event . detail . validationReport ) ;
282+ }
283+ } ) ;
284+
285+ // Add comprehensive error logging
286+ window . addEventListener ( 'error' , ( event ) => {
287+ console . error ( '[CDI Previewer] Global error:' , event . error ) ;
288+ } ) ;
289+
290+ window . addEventListener ( 'unhandledrejection' , ( event ) => {
291+ console . error ( '[CDI Previewer] Unhandled promise rejection:' , event . reason ) ;
292+ } ) ;
202293
203294 // Create a container for the form
204295 const formContainer = $ ( '<div/>' ) . addClass ( 'cdi-form-container' ) ;
205296 formContainer . append ( shaclFormElement ) ;
206297 $ ( '.preview' ) . append ( formContainer ) ;
298+
299+ // Check after a delay if the form is empty
300+ setTimeout ( ( ) => {
301+ const formContent = $ ( shaclFormElement ) . find ( 'shacl-property, .shacl-group' ) . length ;
302+ if ( formContent === 0 ) {
303+ console . error ( '[CDI Previewer] Form appears empty - no properties rendered' ) ;
304+ $ ( '.preview' ) . append (
305+ $ ( '<div/>' ) . addClass ( 'alert alert-warning' ) . css ( 'margin-top' , '20px' ) . html (
306+ '<strong>Warning:</strong> The SHACL form appears empty. This may indicate:<br>' +
307+ '<ul>' +
308+ '<li>No root <code>schema:Dataset</code> node was found in the data</li>' +
309+ '<li>The SHACL target query did not match any nodes</li>' +
310+ '<li>There is a structural issue with the CDI JSON-LD document</li>' +
311+ '</ul>' +
312+ 'Check the browser console for detailed debugging information.'
313+ )
314+ ) ;
315+ }
316+ } , 2000 ) ;
317+ }
318+
319+ function displayValidationReport ( report ) {
320+ if ( ! report || ! report . violations || report . violations . length === 0 ) {
321+ return ; // No violations to display
322+ }
323+
324+ console . log ( '[CDI Previewer] Validation violations:' , report . violations ) ;
325+
326+ const violationContainer = $ ( '<div/>' ) . addClass ( 'alert alert-info' ) . css ( 'margin-top' , '20px' ) ;
327+ violationContainer . append ( '<strong>SHACL Validation Report:</strong>' ) ;
328+
329+ const violationList = $ ( '<ul/>' ) ;
330+ report . violations . forEach ( ( violation , index ) => {
331+ const item = $ ( '<li/>' ) ;
332+ item . append ( $ ( '<strong/>' ) . text ( `Violation ${ index + 1 } : ` ) ) ;
333+ item . append ( violation . message || 'No message provided' ) ;
334+ if ( violation . focusNode ) {
335+ item . append ( $ ( '<br/>' ) ) . append ( $ ( '<em/>' ) . text ( `Focus node: ${ violation . focusNode } ` ) ) ;
336+ }
337+ if ( violation . path ) {
338+ item . append ( $ ( '<br/>' ) ) . append ( $ ( '<em/>' ) . text ( `Property path: ${ violation . path } ` ) ) ;
339+ }
340+ violationList . append ( item ) ;
341+ } ) ;
342+
343+ violationContainer . append ( violationList ) ;
344+ $ ( '.preview' ) . append ( violationContainer ) ;
207345}
0 commit comments