Skip to content

SHACL UI spec examples in development ​

In development

SHACL UI support and the elody: ontology are in development and not part of a release yet. The platform changes they rely on are on feature branches of baseGraphql, the PWA and collection-api; elody-ontology (0.2.0) and elody-generator are new, and no client uses them yet. Terms, results and these pages may still change.

Every example of the SHACL 1.2 UI specification put through the Elody pipeline described in SHACL UI in Elody: the spec's shapes are converted to an Elody UI declaration, the declaration is generated into GraphQL, the GraphQL is validated and executed by baseGraphql, and the result is rendered by the PWA. The screenshots show the create form (left) and the detail page (right), filled with the spec's own data where it gives any.

An example is rendered in part only when it uses a SHACL UI feature Elody does not support. Each example lists what Elody did with it, by kind: not supported; left out by choice (complex paths, to keep view and edit symmetric); not applicable (settings for applications that write RDF themselves, such as shui:timeZone); handled (a third-party widget Elody does not know, left to the spec's scoring as intended — Elody's own widgets work the same way); and note.

This page is generated by elody-generator/scripts/showcase.sh and scripts/showcase-docs.ts; regenerate it after the spec or the pipeline changes.

#ExampleSpec sectionResult
01Sample Data Graphgetting-startedRendered
02Sample Shapes Graphgetting-startedRendered
03Sample Data Graph with Related Resourcegetting-startedRendered
04Sample Instance Dataglobal-configurationRendered
05Predicate and inverse paths in view modeview-predicate-pathsRendered
06Complex paths in view modeview-complex-pathsLeft out by choice
07Predicate and inverse paths in edit modeedit-predicate-pathsRendered
08Alternative paths in edit modeedit-alternative-pathsLeft out by choice
09Ambiguous complex paths in edit modeedit-other-complex-pathsLeft out by choice
10Language selection based on sh:languageInlang-resolutionRendered
11Label resolution using sh:name and rdfs:labellabel-resolution-local-nameRendered
12Label resolution fallback to local namelabel-resolution-local-nameRendered
13Ordering without shui:defaultOrderpatternsRendered
14Ordering with shui:defaultOrderpatternsRendered
15Full-text search using shui:searchQuerysearch-queryRendered
16Federated full-text search using shui:searchQuerysearch-queryRendered
17AutoCompleteEditorAutoCompleteEditorRendered
18BooleanEditorBooleanEditorRendered
19DatePickerEditorDatePickerEditorRendered
20DateTimePickerEditorDateTimePickerEditorRendered
21DetailsEditorDetailsEditorRendered
22EnumSelectEditorEnumSelectEditorRendered
23InstancesSelectEditorInstancesSelectEditorRendered
24IRIEditorIRIEditorRendered
25NumberFieldEditorNumberFieldEditorRendered
26RichTextEditorRichTextEditorRendered
27SubClassEditorSubClassEditorRendered
28TextAreaEditorTextAreaEditorRendered
29TextFieldEditorTextFieldEditorRendered
30TextFieldWithLangEditorTextFieldWithLangEditorRendered
31ValueTableViewerValueTableViewerRendered
32Direct role annotationproperty-rolesRendered
33Qualified role annotationproperty-rolesRendered
34Qualified role annotation using triple annotationsproperty-rolesRendered

01 · Sample Data Graph ​

Rendered Spec section getting-started

Sample Data Graph rendered by Elody

What Elody did with it

  • Note: "honorificPrefix" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:PersonShape a sh:NodeShape ;
    sh:targetClass schema:Person ;
    sh:property [
        sh:path schema:honorificPrefix ;
        sh:datatype xsd:string ;
        sh:order 0 ;
        sh:group ex:PersonShapeNameGroup ;
        sh:maxCount 1 ;
    ],
    [
        sh:path schema:givenName ;
        sh:datatype xsd:string ;
        sh:order 1 ;
        sh:group ex:PersonShapeNameGroup ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ],
    [
        sh:path schema:additionalName ;
        sh:datatype xsd:string ;
        sh:order 2 ;
        sh:group ex:PersonShapeNameGroup ;
    ],
    [
        sh:path schema:familyName ;
        sh:datatype xsd:string ;
        sh:order 3 ;
        sh:group ex:PersonShapeNameGroup ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ],
    [
        sh:path schema:birthDate ;
        sh:datatype xsd:date ;
        sh:order 4 ;
        sh:maxCount 1 ;
    ] ;
.

ex:PersonShapeNameGroup a sh:PropertyGroup ;
    sh:order 0 ;
    rdfs:label "Name" ;
.
Data graph (from the spec)
turtle
ex:TimBL a schema:Person ;
    schema:honorificPrefix "Sir" ;
    schema:givenName "Tim" ;
    schema:additionalName "John" ;
    schema:familyName "Berners-Lee" ;
    schema:birthDate "1955-06-08"^^xsd:date ;
.
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example01
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:targetClass schema:Person ;
  sh:property
    ui:example01-honorificPrefix ,
    ui:example01-givenName ,
    ui:example01-additionalName ,
    ui:example01-familyName ,
    ui:example01-birthDate ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Sample Data Graph" ;
        elody:panel ex:PersonShapeNameGroup , ui:example01-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample01" ;
  elody:form ui:example01-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:PersonShapeNameGroup
  a sh:PropertyGroup ;
  rdfs:label "Name" ;
  sh:order 0 ;
  elody:alias "personShapeNameGroup" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel .

ui:example01-additionalName
  sh:path schema:additionalName ;
  sh:order 2 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup .

ui:example01-birthDate
  sh:path schema:birthDate ;
  sh:order 4 ;
  sh:datatype xsd:date ;
  sh:maxCount 1 .

ui:example01-create
  a elody:Form ;
  rdfs:label "Sample Data Graph" ;
  elody:queryName "SpecExample01CreateForm" ;
  elody:shape
    [ sh:property
      ui:example01-honorificPrefix ,
      ui:example01-givenName ,
      ui:example01-additionalName ,
      ui:example01-familyName ,
      ui:example01-birthDate ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example01-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 4 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .

ui:example01-familyName
  sh:path schema:familyName ;
  sh:order 3 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup ;
  sh:maxCount 1 ;
  sh:minCount 1 .

ui:example01-givenName
  sh:path schema:givenName ;
  sh:order 1 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup ;
  sh:maxCount 1 ;
  sh:minCount 1 .

ui:example01-honorificPrefix
  sh:path schema:honorificPrefix ;
  sh:order 0 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup ;
  sh:maxCount 1 ;
  shui:propertyRole shui:LabelRole .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample01 on BaseEntity {
    intialValues {
      honorificPrefix: keyValue(key: "honorificPrefix", source: metadata)
      givenName: keyValue(key: "givenName", source: metadata)
      additionalName: keyValue(key: "additionalName", source: metadata)
      familyName: keyValue(key: "familyName", source: metadata)
      birthDate: keyValue(key: "birthDate", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      honorificPrefix: metaData {
        label(input: "honorificPrefix")
        key(input: "honorificPrefix")
      }
      givenName: metaData {
        label(input: "givenName")
        key(input: "givenName")
      }
      additionalName: metaData {
        label(input: "additionalName")
        key(input: "additionalName")
      }
      familyName: metaData {
        label(input: "familyName")
        key(input: "familyName")
      }
      birthDate: metaData {
        label(input: "birthDate")
        key(input: "birthDate")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample01 on BaseEntity {
    intialValues {
      honorificPrefix: keyValue(key: "honorificPrefix", source: metadata)
      givenName: keyValue(key: "givenName", source: metadata)
      additionalName: keyValue(key: "additionalName", source: metadata)
      familyName: keyValue(key: "familyName", source: metadata)
      birthDate: keyValue(key: "birthDate", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Sample Data Graph")
            personShapeNameGroup: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "Name" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              honorificPrefix: metaData {
                label(input: "honorificPrefix")
                key(input: "honorificPrefix")
                inputField(type: baseTextField) {
                  ...inputfield
                }
              }
              givenName: metaData {
                label(input: "givenName")
                key(input: "givenName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
              additionalName: metaData {
                label(input: "additionalName")
                key(input: "additionalName")
                inputField(type: specExample01AdditionalNameField) {
                  ...inputfield
                }
              }
              familyName: metaData {
                label(input: "familyName")
                key(input: "familyName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
            }
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample01.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              birthDate: metaData {
                label(input: "birthDate")
                key(input: "birthDate")
                inputField(type: baseDateField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample01BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample01CreateForm {
    GetDynamicForm {
      label(input: "Sample Data Graph")
      name: formTab {
        formFields {
          personShapeNameGroupSection: formSection {
            label(input: "Name")
            formFields {
              honorificPrefix: metaData {
                label(input: "honorificPrefix")
                key(input: "honorificPrefix")
                inputField(type: baseTextField) {
                  ...inputfield
                }
              }
              givenName: metaData {
                label(input: "givenName")
                key(input: "givenName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
              additionalName: metaData {
                label(input: "additionalName")
                key(input: "additionalName")
                inputField(type: specExample01AdditionalNameField) {
                  ...inputfield
                }
              }
              familyName: metaData {
                label(input: "familyName")
                key(input: "familyName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
            }
          }
          birthDate: metaData {
            label(input: "birthDate")
            key(input: "birthDate")
            inputField(type: baseDateField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample01AdditionalNameField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

02 · Sample Shapes Graph ​

Rendered Spec section getting-started

Sample Shapes Graph rendered by Elody

What Elody did with it

  • Note: "honorificPrefix" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:PersonShape a sh:NodeShape ;
    sh:targetClass schema:Person ;
    sh:property [
        sh:path schema:honorificPrefix ;
        sh:datatype xsd:string ;
        sh:order 0 ;
        sh:group ex:PersonShapeNameGroup ;
        sh:maxCount 1 ;
    ],
    [
        sh:path schema:givenName ;
        sh:datatype xsd:string ;
        sh:order 1 ;
        sh:group ex:PersonShapeNameGroup ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ],
    [
        sh:path schema:additionalName ;
        sh:datatype xsd:string ;
        sh:order 2 ;
        sh:group ex:PersonShapeNameGroup ;
    ],
    [
        sh:path schema:familyName ;
        sh:datatype xsd:string ;
        sh:order 3 ;
        sh:group ex:PersonShapeNameGroup ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ],
    [
        sh:path schema:birthDate ;
        sh:datatype xsd:date ;
        sh:order 4 ;
        sh:maxCount 1 ;
    ] ;
.

ex:PersonShapeNameGroup a sh:PropertyGroup ;
    sh:order 0 ;
    rdfs:label "Name" ;
.
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example02
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:targetClass schema:Person ;
  sh:property
    ui:example02-honorificPrefix ,
    ui:example02-givenName ,
    ui:example02-additionalName ,
    ui:example02-familyName ,
    ui:example02-birthDate ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Sample Shapes Graph" ;
        elody:panel ex:PersonShapeNameGroup , ui:example02-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample02" ;
  elody:form ui:example02-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:PersonShapeNameGroup
  a sh:PropertyGroup ;
  rdfs:label "Name" ;
  sh:order 0 ;
  elody:alias "personShapeNameGroup" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel .

ui:example02-additionalName
  sh:path schema:additionalName ;
  sh:order 2 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup .

ui:example02-birthDate
  sh:path schema:birthDate ;
  sh:order 4 ;
  sh:datatype xsd:date ;
  sh:maxCount 1 .

ui:example02-create
  a elody:Form ;
  rdfs:label "Sample Shapes Graph" ;
  elody:queryName "SpecExample02CreateForm" ;
  elody:shape
    [ sh:property
      ui:example02-honorificPrefix ,
      ui:example02-givenName ,
      ui:example02-additionalName ,
      ui:example02-familyName ,
      ui:example02-birthDate ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example02-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 4 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .

ui:example02-familyName
  sh:path schema:familyName ;
  sh:order 3 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup ;
  sh:maxCount 1 ;
  sh:minCount 1 .

ui:example02-givenName
  sh:path schema:givenName ;
  sh:order 1 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup ;
  sh:maxCount 1 ;
  sh:minCount 1 .

ui:example02-honorificPrefix
  sh:path schema:honorificPrefix ;
  sh:order 0 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup ;
  sh:maxCount 1 ;
  shui:propertyRole shui:LabelRole .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample02 on BaseEntity {
    intialValues {
      honorificPrefix: keyValue(key: "honorificPrefix", source: metadata)
      givenName: keyValue(key: "givenName", source: metadata)
      additionalName: keyValue(key: "additionalName", source: metadata)
      familyName: keyValue(key: "familyName", source: metadata)
      birthDate: keyValue(key: "birthDate", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      honorificPrefix: metaData {
        label(input: "honorificPrefix")
        key(input: "honorificPrefix")
      }
      givenName: metaData {
        label(input: "givenName")
        key(input: "givenName")
      }
      additionalName: metaData {
        label(input: "additionalName")
        key(input: "additionalName")
      }
      familyName: metaData {
        label(input: "familyName")
        key(input: "familyName")
      }
      birthDate: metaData {
        label(input: "birthDate")
        key(input: "birthDate")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample02 on BaseEntity {
    intialValues {
      honorificPrefix: keyValue(key: "honorificPrefix", source: metadata)
      givenName: keyValue(key: "givenName", source: metadata)
      additionalName: keyValue(key: "additionalName", source: metadata)
      familyName: keyValue(key: "familyName", source: metadata)
      birthDate: keyValue(key: "birthDate", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Sample Shapes Graph")
            personShapeNameGroup: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "Name" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              honorificPrefix: metaData {
                label(input: "honorificPrefix")
                key(input: "honorificPrefix")
                inputField(type: baseTextField) {
                  ...inputfield
                }
              }
              givenName: metaData {
                label(input: "givenName")
                key(input: "givenName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
              additionalName: metaData {
                label(input: "additionalName")
                key(input: "additionalName")
                inputField(type: specExample02AdditionalNameField) {
                  ...inputfield
                }
              }
              familyName: metaData {
                label(input: "familyName")
                key(input: "familyName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
            }
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample02.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              birthDate: metaData {
                label(input: "birthDate")
                key(input: "birthDate")
                inputField(type: baseDateField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample02BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample02CreateForm {
    GetDynamicForm {
      label(input: "Sample Shapes Graph")
      name: formTab {
        formFields {
          personShapeNameGroupSection: formSection {
            label(input: "Name")
            formFields {
              honorificPrefix: metaData {
                label(input: "honorificPrefix")
                key(input: "honorificPrefix")
                inputField(type: baseTextField) {
                  ...inputfield
                }
              }
              givenName: metaData {
                label(input: "givenName")
                key(input: "givenName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
              additionalName: metaData {
                label(input: "additionalName")
                key(input: "additionalName")
                inputField(type: specExample02AdditionalNameField) {
                  ...inputfield
                }
              }
              familyName: metaData {
                label(input: "familyName")
                key(input: "familyName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
            }
          }
          birthDate: metaData {
            label(input: "birthDate")
            key(input: "birthDate")
            inputField(type: baseDateField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample02AdditionalNameField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

03 · Sample Data Graph with Related Resource ​

Rendered Spec section getting-started

Sample Data Graph with Related Resource rendered by Elody

What Elody did with it

  • Note: "honorificPrefix" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:PersonShape a sh:NodeShape ;
    sh:targetClass schema:Person ;
    sh:property [
        sh:path schema:honorificPrefix ;
        sh:datatype xsd:string ;
        sh:order 0 ;
        sh:group ex:PersonShapeNameGroup ;
        sh:maxCount 1 ;
    ],
    [
        sh:path schema:givenName ;
        sh:datatype xsd:string ;
        sh:order 1 ;
        sh:group ex:PersonShapeNameGroup ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ],
    [
        sh:path schema:additionalName ;
        sh:datatype xsd:string ;
        sh:order 2 ;
        sh:group ex:PersonShapeNameGroup ;
    ],
    [
        sh:path schema:familyName ;
        sh:datatype xsd:string ;
        sh:order 3 ;
        sh:group ex:PersonShapeNameGroup ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ],
    [
        sh:path schema:birthDate ;
        sh:datatype xsd:date ;
        sh:order 4 ;
        sh:maxCount 1 ;
    ] ;
.

ex:PersonShapeNameGroup a sh:PropertyGroup ;
    sh:order 0 ;
    rdfs:label "Name" ;
.
Data graph (from the spec)
turtle
ex:TimBL a schema:Person ;
    schema:honorificPrefix "Sir" ;
    schema:givenName "Tim" ;
    schema:additionalName "John" ;
    schema:familyName "Berners-Lee" ;
    schema:birthDate "1955-06-08"^^xsd:date ;
    schema:affiliation ex:W3C ;
.

ex:W3C a schema:Organization ;
    schema:name "World Wide Web Consortium"@en ,
        "Consorcio World Wide Web"@es ;
    schema:foundingDate "1994-10-01"^^xsd:date ;
    schema:url <https://www.w3.org> ;
.
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example03
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:targetClass schema:Person ;
  sh:property
    ui:example03-honorificPrefix ,
    ui:example03-givenName ,
    ui:example03-additionalName ,
    ui:example03-familyName ,
    ui:example03-birthDate ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Sample Data Graph with Related Resource" ;
        elody:panel ex:PersonShapeNameGroup , ui:example03-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample03" ;
  elody:form ui:example03-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:PersonShapeNameGroup
  a sh:PropertyGroup ;
  rdfs:label "Name" ;
  sh:order 0 ;
  elody:alias "personShapeNameGroup" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel .

ui:example03-additionalName
  sh:path schema:additionalName ;
  sh:order 2 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup .

ui:example03-birthDate
  sh:path schema:birthDate ;
  sh:order 4 ;
  sh:datatype xsd:date ;
  sh:maxCount 1 .

ui:example03-create
  a elody:Form ;
  rdfs:label "Sample Data Graph with Related Resource" ;
  elody:queryName "SpecExample03CreateForm" ;
  elody:shape
    [ sh:property
      ui:example03-honorificPrefix ,
      ui:example03-givenName ,
      ui:example03-additionalName ,
      ui:example03-familyName ,
      ui:example03-birthDate ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example03-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 4 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .

ui:example03-familyName
  sh:path schema:familyName ;
  sh:order 3 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup ;
  sh:maxCount 1 ;
  sh:minCount 1 .

ui:example03-givenName
  sh:path schema:givenName ;
  sh:order 1 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup ;
  sh:maxCount 1 ;
  sh:minCount 1 .

ui:example03-honorificPrefix
  sh:path schema:honorificPrefix ;
  sh:order 0 ;
  sh:datatype xsd:string ;
  sh:group ex:PersonShapeNameGroup ;
  sh:maxCount 1 ;
  shui:propertyRole shui:LabelRole .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample03 on BaseEntity {
    intialValues {
      honorificPrefix: keyValue(key: "honorificPrefix", source: metadata)
      givenName: keyValue(key: "givenName", source: metadata)
      additionalName: keyValue(key: "additionalName", source: metadata)
      familyName: keyValue(key: "familyName", source: metadata)
      birthDate: keyValue(key: "birthDate", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      honorificPrefix: metaData {
        label(input: "honorificPrefix")
        key(input: "honorificPrefix")
      }
      givenName: metaData {
        label(input: "givenName")
        key(input: "givenName")
      }
      additionalName: metaData {
        label(input: "additionalName")
        key(input: "additionalName")
      }
      familyName: metaData {
        label(input: "familyName")
        key(input: "familyName")
      }
      birthDate: metaData {
        label(input: "birthDate")
        key(input: "birthDate")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample03 on BaseEntity {
    intialValues {
      honorificPrefix: keyValue(key: "honorificPrefix", source: metadata)
      givenName: keyValue(key: "givenName", source: metadata)
      additionalName: keyValue(key: "additionalName", source: metadata)
      familyName: keyValue(key: "familyName", source: metadata)
      birthDate: keyValue(key: "birthDate", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Sample Data Graph with Related Resource")
            personShapeNameGroup: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "Name" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              honorificPrefix: metaData {
                label(input: "honorificPrefix")
                key(input: "honorificPrefix")
                inputField(type: baseTextField) {
                  ...inputfield
                }
              }
              givenName: metaData {
                label(input: "givenName")
                key(input: "givenName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
              additionalName: metaData {
                label(input: "additionalName")
                key(input: "additionalName")
                inputField(type: specExample03AdditionalNameField) {
                  ...inputfield
                }
              }
              familyName: metaData {
                label(input: "familyName")
                key(input: "familyName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
            }
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample03.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              birthDate: metaData {
                label(input: "birthDate")
                key(input: "birthDate")
                inputField(type: baseDateField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample03BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample03CreateForm {
    GetDynamicForm {
      label(input: "Sample Data Graph with Related Resource")
      name: formTab {
        formFields {
          personShapeNameGroupSection: formSection {
            label(input: "Name")
            formFields {
              honorificPrefix: metaData {
                label(input: "honorificPrefix")
                key(input: "honorificPrefix")
                inputField(type: baseTextField) {
                  ...inputfield
                }
              }
              givenName: metaData {
                label(input: "givenName")
                key(input: "givenName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
              additionalName: metaData {
                label(input: "additionalName")
                key(input: "additionalName")
                inputField(type: specExample03AdditionalNameField) {
                  ...inputfield
                }
              }
              familyName: metaData {
                label(input: "familyName")
                key(input: "familyName")
                inputField(type: baseTextField) {
                  ...inputfield
                  validation(input: { value: required }) {
                    ...validation
                  }
                }
              }
            }
          }
          birthDate: metaData {
            label(input: "birthDate")
            key(input: "birthDate")
            inputField(type: baseDateField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample03AdditionalNameField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

04 · Sample Instance Data ​

Rendered Spec section global-configuration

Sample Instance Data rendered by Elody

What Elody did with it

  • Not applicable: shui:timeZone has no Elody counterpart (Elody stores documents, not triples) and is ignored
  • Not applicable: shui:defaultNamespace has no Elody counterpart (Elody stores documents, not triples) and is ignored
  • Handled: "name": Elody has no MyCustomEditor; the declared editor is left out and the spec's scoring picks one
  • Note: shui:languagePreference orders the label texts after sh:languageIn; values follow the language chosen in Elody, which the spec allows as the application's language selection
  • Note: "name" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:config a shui:Configuration ;
    shui:defaultNamespace "http://example.com/ns#" ;
    shui:languagePreference ("" "en" "de") ;
    shui:timeZone "Europe/Vienna" ;
    shui:labelPreference (skos:prefLabel dcterms:title rdfs:label) . 
ex:PersonShapeName
    a sh:PropertyShape ;
    sh:path ex:name ;
    shui:editor ex:MyCustomEditor ;
.
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example04
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:PersonShapeName ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Sample Instance Data" ;
        elody:panel ui:example04-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample04" ;
  elody:form ui:example04-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:PersonShapeName
  a sh:PropertyShape ;
  sh:path ex:name ;
  shui:propertyRole shui:LabelRole .

ex:config
  a shui:Configuration ;
  shui:defaultNamespace "http://example.com/ns#" ;
  shui:labelPreference ( skos:prefLabel dct:title rdfs:label ) ;
  shui:languagePreference ( "" "en" "de" ) ;
  shui:timeZone "Europe/Vienna" .

ui:example04-create
  a elody:Form ;
  rdfs:label "Sample Instance Data" ;
  elody:queryName "SpecExample04CreateForm" ;
  elody:shape [ sh:property ex:PersonShapeName ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example04-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample04 on BaseEntity {
    intialValues {
      name: keyValue(key: "name", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      name: metaData {
        label(input: "name")
        key(input: "name")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample04 on BaseEntity {
    intialValues {
      name: keyValue(key: "name", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Sample Instance Data")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample04.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              name: metaData {
                label(input: "name")
                key(input: "name")
                inputField(type: specExample04NameField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample04BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample04CreateForm {
    GetDynamicForm {
      label(input: "Sample Instance Data")
      name: formTab {
        formFields {
          name: metaData {
            label(input: "name")
            key(input: "name")
            inputField(type: specExample04NameField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample04NameField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

05 · Predicate and inverse paths in view mode ​

Rendered Spec section view-predicate-paths

Predicate and inverse paths in view mode rendered by Elody

What Elody did with it

  • Note: "Name" is used as the card title (the shapes declare no shui:LabelRole)
  • Note: "Department": inverse path without sh:class: the IRI is typed in (as shui:IRIEditor) and stored as the relation's key
SHACL UI shapes (from the spec)
turtle
ex:PersonShape
    a sh:NodeShape ;
    sh:property [
        sh:path foaf:name ;
        sh:name "Name" ;
        sh:datatype xsd:string ;
    ] ;
    sh:property [
        sh:path [ sh:inversePath ex:member ] ;
        sh:name "Department" ;
    ] .
Data graph (from the spec)
turtle
ex:alice a ex:Person ;
    foaf:name "Alice" .

ex:researchDept a ex:Department ;
    ex:member ex:alice ;
    rdfs:label "Research Department" .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example05
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ui:example05-isMemberFor , ui:example05-name ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Predicate and inverse paths in view mode" ;
        elody:panel ui:example05-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample05" ;
  elody:form ui:example05-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ui:example05-create
  a elody:Form ;
  rdfs:label "Predicate and inverse paths in view mode" ;
  elody:queryName "SpecExample05CreateForm" ;
  elody:shape [ sh:property ui:example05-isMemberFor , ui:example05-name ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example05-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .

ui:example05-isMemberFor
  sh:path [ sh:inversePath ex:member ] ;
  sh:name "Department" .

ui:example05-name
  sh:path foaf:name ;
  sh:name "Name" ;
  sh:datatype xsd:string ;
  shui:propertyRole shui:LabelRole .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample05 on BaseEntity {
    intialValues {
      isMemberFor: keyValue(key: "isMemberFor", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
      name: keyValue(key: "name", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      isMemberFor: metaData {
        label(input: "Department")
        key(input: "isMemberFor")
      }
      name: metaData {
        label(input: "Name")
        key(input: "name")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample05 on BaseEntity {
    intialValues {
      isMemberFor: keyValue(key: "isMemberFor", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
      name: keyValue(key: "name", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Predicate and inverse paths in view mode")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample05.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              isMemberFor: metaData {
                label(input: "Department")
                key(input: "isMemberFor")
              }
              name: metaData {
                label(input: "Name")
                key(input: "name")
                inputField(type: specExample05NameField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample05BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample05CreateForm {
    GetDynamicForm {
      label(input: "Predicate and inverse paths in view mode")
      name: formTab {
        formFields {
          isMemberFor: metaData {
            label(input: "Department")
            key(input: "isMemberFor")
            inputField(type: specExample05IsMemberForField) {
              ...inputfield
            }
          }
          name: metaData {
            label(input: "Name")
            key(input: "name")
            inputField(type: specExample05NameField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample05NameField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  },
  "specExample05IsMemberForField": {
    "type": "inputFieldWithSubFields",
    "isMetadataField": false,
    "relationType": "isMemberFor",
    "subFields": [
      {
        "label": "IRI",
        "key": "key",
        "inputField": {
          "type": "text",
          "isMetadataField": false
        }
      }
    ]
  }
}

06 · Complex paths in view mode ​

Left out by choice Spec section view-complex-paths

What Elody did with it

  • Left out by choice: "Title": alternative path, left out: Elody keeps view and edit symmetric (a field it shows, it can edit), as the spec allows; an Elody field reads and writes one metadata key or one relation
  • Note: no property Elody can carry: the declaration has no fields
SHACL UI shapes (from the spec)
turtle
ex:PersonShape
    a sh:NodeShape ;
    sh:property [
        sh:path ( ex:address ex:cityName ) ;
        sh:name "City" ;
        sh:datatype xsd:string ;
    ] .

ex:BookShape
    a sh:NodeShape ;
    sh:property [
        sh:path [
            sh:alternativePath ( dct:title rdfs:label )
        ] ;
        sh:name "Title" ;
        sh:datatype xsd:string ;
    ] .
Data graph (from the spec)
turtle
ex:alice a ex:Person ;
    ex:address ex:aliceAddress .

ex:aliceAddress ex:cityName "Ghent" .

ex:book1 a ex:Book ;
    dct:title "Linked Data Design" .

07 · Predicate and inverse paths in edit mode ​

Rendered Spec section edit-predicate-paths

Predicate and inverse paths in edit mode rendered by Elody

What Elody did with it

  • Note: "Name" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:PersonShape
    a sh:NodeShape ;
    sh:property [
        sh:path foaf:name ;
        sh:name "Name" ;
        sh:datatype xsd:string ;
    ] ;
    sh:property [
        sh:path [ sh:inversePath ex:member ] ;
        sh:name "Department" ;
        sh:class ex:Department ;
    ] .
Data graph (from the spec)
turtle
ex:bob a ex:Person ;
    foaf:name "Bob" .

ex:engDept a ex:Department ;
    ex:member ex:bob ;
    rdfs:label "Engineering Department" .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example07
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ui:example07-isMemberFor , ui:example07-name ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Predicate and inverse paths in edit mode" ;
        elody:panel ui:example07-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample07" ;
  elody:form ui:example07-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ui:example07-create
  a elody:Form ;
  rdfs:label "Predicate and inverse paths in edit mode" ;
  elody:queryName "SpecExample07CreateForm" ;
  elody:shape [ sh:property ui:example07-isMemberFor , ui:example07-name ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example07-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .

ui:example07-isMemberFor
  sh:path [ sh:inversePath ex:member ] ;
  sh:name "Department" ;
  sh:class ex:Department .

ui:example07-name
  sh:path foaf:name ;
  sh:name "Name" ;
  sh:datatype xsd:string ;
  shui:propertyRole shui:LabelRole .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample07 on BaseEntity {
    intialValues {
      isMemberFor: keyValue(key: "isMemberFor", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
      name: keyValue(key: "name", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      isMemberFor: metaData {
        label(input: "Department")
        key(input: "isMemberFor")
      }
      name: metaData {
        label(input: "Name")
        key(input: "name")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample07 on BaseEntity {
    intialValues {
      isMemberFor: keyValue(key: "isMemberFor", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
      name: keyValue(key: "name", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Predicate and inverse paths in edit mode")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample07.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              isMemberFor: metaData {
                label(input: "Department")
                key(input: "isMemberFor")
                inputField(type: specExample07IsMemberForField) {
                  ...inputfield
                }
              }
              name: metaData {
                label(input: "Name")
                key(input: "name")
                inputField(type: specExample07NameField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample07BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample07CreateForm {
    GetDynamicForm {
      label(input: "Predicate and inverse paths in edit mode")
      name: formTab {
        formFields {
          isMemberFor: metaData {
            label(input: "Department")
            key(input: "isMemberFor")
            inputField(type: specExample07IsMemberForField) {
              ...inputfield
            }
          }
          name: metaData {
            label(input: "Name")
            key(input: "name")
            inputField(type: specExample07NameField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample07IsMemberForField": {
    "type": "dropdownMultiselectRelations",
    "relationType": "isMemberFor",
    "advancedFilterInputForRetrievingOptions": [
      {
        "type": "type",
        "value": "department"
      }
    ],
    "relationFilter": {
      "type": "selection",
      "key": [
        "elody:1|identifiers"
      ],
      "value": "$relationValues.isMemberFor.key",
      "match_exact": true,
      "item_types": [
        "department"
      ]
    }
  },
  "specExample07NameField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

08 · Alternative paths in edit mode ​

Left out by choice Spec section edit-alternative-paths

What Elody did with it

  • Left out by choice: "Title": alternative path, left out: Elody keeps view and edit symmetric (a field it shows, it can edit), as the spec allows; an Elody field reads and writes one metadata key or one relation
  • Note: no property Elody can carry: the declaration has no fields
SHACL UI shapes (from the spec)
turtle
ex:BookShape
    a sh:NodeShape ;
    sh:property [
        sh:path [
            sh:alternativePath ( dct:title rdfs:label )
        ] ;
        sh:name "Title" ;
        sh:datatype xsd:string ;
    ] .
Data graph (from the spec)
turtle
ex:book2 a ex:Book ;
    rdfs:label "Semantic Web Foundations" .

09 · Ambiguous complex paths in edit mode ​

Left out by choice Spec section edit-other-complex-paths

What Elody did with it

  • Left out by choice: "All Descendant Parts": complex path, left out: Elody keeps view and edit symmetric (a field it shows, it can edit), as the spec allows; an Elody field reads and writes one metadata key or one relation
  • Note: no property Elody can carry: the declaration has no fields
SHACL UI shapes (from the spec)
turtle
ex:CompoundThingShape
    a sh:NodeShape ;
    sh:property [
        sh:path [
            sh:zeroOrMorePath ex:hasPart
        ] ;
        sh:name "All Descendant Parts" ;
        sh:description "Traverses all parts and sub-parts using a zero-or-more path of hasPart relationships." ;
    ] .
Data graph (from the spec)
turtle
ex:compounded-thing
    ex:hasPart ex:part-a ;
    ex:hasPart ex:part-b .

ex:part-a
    ex:hasPart ex:screw .

ex:part-b
    ex:hasPart ex:screw .

10 · Language selection based on sh:languageIn ​

Rendered Spec section lang-resolution

Language selection based on sh:languageIn rendered by Elody

What Elody did with it

  • Note: "Nom" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:PersonShape
    a sh:NodeShape ;
    sh:property [
        sh:path foaf:name ;
        sh:name "Name"@en ;
        sh:name "Nom"@fr ;
        sh:languageIn ( "fr" "en" ) ;
    ] .
Data graph (from the spec)
turtle
ex:alice a ex:Person ;
    foaf:name "Alice"@en ;
    foaf:name "Alice"@fr .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example10
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ui:example10-name ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Language selection based on sh:languageIn" ;
        elody:panel ui:example10-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample10" ;
  elody:form ui:example10-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ui:example10-create
  a elody:Form ;
  rdfs:label "Language selection based on sh:languageIn" ;
  elody:queryName "SpecExample10CreateForm" ;
  elody:shape [ sh:property ui:example10-name ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example10-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .

ui:example10-name
  sh:path foaf:name ;
  sh:name "Name"@en , "Nom"@fr ;
  sh:languageIn ( "fr" "en" ) ;
  shui:propertyRole shui:LabelRole .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample10 on BaseEntity {
    intialValues {
      name: keyValue(key: "name", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      name: metaData {
        label(input: "ui.specExample10.name")
        key(input: "name")
        isMultilingual(input: true)
        languageIn(input: ["fr", "en"])
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample10 on BaseEntity {
    intialValues {
      name: keyValue(key: "name", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Language selection based on sh:languageIn")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample10.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              name: metaData {
                label(input: "ui.specExample10.name")
                key(input: "name")
                isMultilingual(input: true)
                languageIn(input: ["fr", "en"])
                inputField(type: baseTextField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample10BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample10CreateForm {
    GetDynamicForm {
      label(input: "Language selection based on sh:languageIn")
      name: formTab {
        formFields {
          name: metaData {
            label(input: "ui.specExample10.name")
            key(input: "name")
            isMultilingual(input: true)
            languageIn(input: ["fr", "en"])
            inputField(type: baseTextField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }

11 · Label resolution using sh:name and rdfs:label ​

Rendered Spec section label-resolution-local-name

Label resolution using sh:name and rdfs:label rendered by Elody

What Elody did with it

  • Note: "First Name" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:PersonShape
    a sh:NodeShape ;
    sh:targetClass ex:Person ;
    sh:property [
        sh:path foaf:firstName ;
        sh:name "First Name"@en ;
        sh:name "Vorname"@de ;
    ] ;
    sh:property [
        sh:path ex:employer ;
        sh:name "Employer"@en ;
        sh:class ex:Organization ;
    ] .
Data graph (from the spec)
turtle
ex:alice a ex:Person ;
    foaf:firstName "Alice" ;
    ex:employer ex:acme .

ex:acme a ex:Organization ;
    rdfs:label "ACME Corp"@en ;
    rdfs:label "ACME GmbH"@de .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example11
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:targetClass ex:Person ;
  sh:property ui:example11-employer , ui:example11-firstName ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Label resolution using sh:name and rdfs:label" ;
        elody:panel ui:example11-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample11" ;
  elody:form ui:example11-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ui:example11-create
  a elody:Form ;
  rdfs:label "Label resolution using sh:name and rdfs:label" ;
  elody:queryName "SpecExample11CreateForm" ;
  elody:shape [ sh:property ui:example11-employer , ui:example11-firstName ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example11-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .

ui:example11-employer
  sh:path ex:employer ;
  sh:name "Employer"@en ;
  sh:class ex:Organization .

ui:example11-firstName
  sh:path foaf:firstName ;
  sh:name "First Name"@en , "Vorname"@de ;
  shui:propertyRole shui:LabelRole .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample11 on BaseEntity {
    intialValues {
      employer: keyValue(key: "hasEmployer", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
      firstName: keyValue(key: "firstName", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      employer: metaData {
        label(input: "ui.specExample11.employer")
        key(input: "employer")
      }
      firstName: metaData {
        label(input: "ui.specExample11.firstName")
        key(input: "firstName")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample11 on BaseEntity {
    intialValues {
      employer: keyValue(key: "hasEmployer", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
      firstName: keyValue(key: "firstName", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Label resolution using sh:name and rdfs:label")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample11.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              employer: metaData {
                label(input: "ui.specExample11.employer")
                key(input: "employer")
                inputField(type: specExample11EmployerField) {
                  ...inputfield
                }
              }
              firstName: metaData {
                label(input: "ui.specExample11.firstName")
                key(input: "firstName")
                inputField(type: specExample11FirstNameField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample11BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample11CreateForm {
    GetDynamicForm {
      label(input: "Label resolution using sh:name and rdfs:label")
      name: formTab {
        formFields {
          employer: metaData {
            label(input: "ui.specExample11.employer")
            key(input: "employer")
            inputField(type: specExample11EmployerField) {
              ...inputfield
            }
          }
          firstName: metaData {
            label(input: "ui.specExample11.firstName")
            key(input: "firstName")
            inputField(type: specExample11FirstNameField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample11EmployerField": {
    "type": "dropdownMultiselectRelations",
    "relationType": "hasEmployer",
    "advancedFilterInputForRetrievingOptions": [
      {
        "type": "type",
        "value": "organization"
      }
    ],
    "relationFilter": {
      "type": "selection",
      "key": [
        "elody:1|identifiers"
      ],
      "value": "$relationValues.hasEmployer.key",
      "match_exact": true,
      "item_types": [
        "organization"
      ]
    }
  },
  "specExample11FirstNameField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

12 · Label resolution fallback to local name ​

Rendered Spec section label-resolution-local-name

Label resolution fallback to local name rendered by Elody

What Elody did with it

  • Note: "creator" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:BookShape
    a sh:NodeShape ;
    sh:targetClass ex:Book ;
    sh:property [
        sh:path dct:creator ;
    ] .
Data graph (from the spec)
turtle
ex:book1 a ex:Book ;
    dct:creator ex:author1 .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example12
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:targetClass ex:Book ;
  sh:property ui:example12-creator ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Label resolution fallback to local name" ;
        elody:panel ui:example12-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample12" ;
  elody:form ui:example12-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ui:example12-create
  a elody:Form ;
  rdfs:label "Label resolution fallback to local name" ;
  elody:queryName "SpecExample12CreateForm" ;
  elody:shape [ sh:property ui:example12-creator ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example12-creator
  sh:path dct:creator ;
  shui:propertyRole shui:LabelRole .

ui:example12-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample12 on BaseEntity {
    intialValues {
      creator: keyValue(key: "creator", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      creator: metaData {
        label(input: "creator")
        key(input: "creator")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample12 on BaseEntity {
    intialValues {
      creator: keyValue(key: "creator", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Label resolution fallback to local name")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample12.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              creator: metaData {
                label(input: "creator")
                key(input: "creator")
                inputField(type: specExample12CreatorField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample12BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample12CreateForm {
    GetDynamicForm {
      label(input: "Label resolution fallback to local name")
      name: formTab {
        formFields {
          creator: metaData {
            label(input: "creator")
            key(input: "creator")
            inputField(type: specExample12CreatorField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample12CreatorField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

13 · Ordering without shui:defaultOrder ​

Rendered Spec section patterns

Ordering without shui:defaultOrder rendered by Elody

What Elody did with it

  • Note: "id" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:PersonShape
    a sh:NodeShape ;
    sh:property ex:description ;
    sh:property ex:identifier ;
    sh:property ex:name .

ex:description
    sh:path dct:description ;
    sh:order 5 .

ex:identifier
    sh:path ex:id ;
    sh:order -10 .

ex:name
    sh:path rdfs:label .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example13
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:identifier , ex:description , ex:name ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Ordering without shui:defaultOrder" ;
        elody:panel ui:example13-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample13" ;
  elody:form ui:example13-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:description
  sh:path dct:description ;
  sh:order 5 .

ex:identifier
  sh:path ex:id ;
  sh:order -10 ;
  shui:propertyRole shui:LabelRole .

ex:name
  sh:path rdfs:label .

ui:example13-create
  a elody:Form ;
  rdfs:label "Ordering without shui:defaultOrder" ;
  elody:queryName "SpecExample13CreateForm" ;
  elody:shape [ sh:property ex:identifier , ex:description , ex:name ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example13-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order -10 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample13 on BaseEntity {
    intialValues {
      id: keyValue(key: "id", source: metadata)
      description: keyValue(key: "description", source: metadata)
      label: keyValue(key: "label", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      id: metaData {
        label(input: "id")
        key(input: "id")
      }
      description: metaData {
        label(input: "description")
        key(input: "description")
      }
      label: metaData {
        label(input: "label")
        key(input: "label")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample13 on BaseEntity {
    intialValues {
      id: keyValue(key: "id", source: metadata)
      description: keyValue(key: "description", source: metadata)
      label: keyValue(key: "label", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Ordering without shui:defaultOrder")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample13.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              id: metaData {
                label(input: "id")
                key(input: "id")
                inputField(type: specExample13IdField) {
                  ...inputfield
                }
              }
              description: metaData {
                label(input: "description")
                key(input: "description")
                inputField(type: specExample13DescriptionField) {
                  ...inputfield
                }
              }
              label: metaData {
                label(input: "label")
                key(input: "label")
                inputField(type: specExample13LabelField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample13BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample13CreateForm {
    GetDynamicForm {
      label(input: "Ordering without shui:defaultOrder")
      name: formTab {
        formFields {
          id: metaData {
            label(input: "id")
            key(input: "id")
            inputField(type: specExample13IdField) {
              ...inputfield
            }
          }
          description: metaData {
            label(input: "description")
            key(input: "description")
            inputField(type: specExample13DescriptionField) {
              ...inputfield
            }
          }
          label: metaData {
            label(input: "label")
            key(input: "label")
            inputField(type: specExample13LabelField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample13IdField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  },
  "specExample13DescriptionField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  },
  "specExample13LabelField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

14 · Ordering with shui:defaultOrder ​

Rendered Spec section patterns

Ordering with shui:defaultOrder rendered by Elody

What Elody did with it

  • Note: "id" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:PersonShape
    a sh:NodeShape ;
    sh:property ex:description ;
    sh:property ex:identifier ;
    sh:property ex:name .

ex:description
    sh:path dct:description ;
    sh:order 5 .

ex:identifier
    sh:path ex:id ;
    sh:order -10 .

ex:name
    sh:path rdfs:label .

ex:config
    a shui:Configuration ;
    shui:defaultOrder 0 .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example14
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:identifier , ex:name , ex:description ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Ordering with shui:defaultOrder" ;
        elody:panel ui:example14-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample14" ;
  elody:form ui:example14-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:config
  a shui:Configuration ;
  shui:defaultOrder 0 .

ex:description
  sh:path dct:description ;
  sh:order 5 .

ex:identifier
  sh:path ex:id ;
  sh:order -10 ;
  shui:propertyRole shui:LabelRole .

ex:name
  sh:path rdfs:label .

ui:example14-create
  a elody:Form ;
  rdfs:label "Ordering with shui:defaultOrder" ;
  elody:queryName "SpecExample14CreateForm" ;
  elody:shape [ sh:property ex:identifier , ex:name , ex:description ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example14-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order -10 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample14 on BaseEntity {
    intialValues {
      id: keyValue(key: "id", source: metadata)
      label: keyValue(key: "label", source: metadata)
      description: keyValue(key: "description", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      id: metaData {
        label(input: "id")
        key(input: "id")
      }
      label: metaData {
        label(input: "label")
        key(input: "label")
      }
      description: metaData {
        label(input: "description")
        key(input: "description")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample14 on BaseEntity {
    intialValues {
      id: keyValue(key: "id", source: metadata)
      label: keyValue(key: "label", source: metadata)
      description: keyValue(key: "description", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Ordering with shui:defaultOrder")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample14.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              id: metaData {
                label(input: "id")
                key(input: "id")
                inputField(type: specExample14IdField) {
                  ...inputfield
                }
              }
              label: metaData {
                label(input: "label")
                key(input: "label")
                inputField(type: specExample14LabelField) {
                  ...inputfield
                }
              }
              description: metaData {
                label(input: "description")
                key(input: "description")
                inputField(type: specExample14DescriptionField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample14BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample14CreateForm {
    GetDynamicForm {
      label(input: "Ordering with shui:defaultOrder")
      name: formTab {
        formFields {
          id: metaData {
            label(input: "id")
            key(input: "id")
            inputField(type: specExample14IdField) {
              ...inputfield
            }
          }
          label: metaData {
            label(input: "label")
            key(input: "label")
            inputField(type: specExample14LabelField) {
              ...inputfield
            }
          }
          description: metaData {
            label(input: "description")
            key(input: "description")
            inputField(type: specExample14DescriptionField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample14IdField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  },
  "specExample14LabelField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  },
  "specExample14DescriptionField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

15 · Full-text search using shui:searchQuery ​

Rendered Spec section search-query

Full-text search using shui:searchQuery rendered by Elody

What Elody did with it

  • Handled: "Assignee": shui:searchQuery (SPARQL) left out; the relation dropdown searches Elody's own index of that class live, as the query intends
  • Note: "Assignee" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:TaskShape
    a sh:NodeShape ;
    sh:targetClass ex:Task ;
    sh:property [
        sh:name "Assignee" ;
        sh:path ex:assignee ;
        sh:class ex:Person ;
        shui:searchQuery """
            PREFIX ex: <http://example.com/>
            PREFIX text: <http://jena.apache.org/text#>
            SELECT ?value WHERE {
                ?value text:query ($searchTerm $uiLanguage) .
                ?value a ex:Person .
            }
        """ ;
    ] .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example15
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:targetClass ex:Task ;
  sh:property ui:example15-assignee ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Full-text search using shui:searchQuery" ;
        elody:panel ui:example15-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample15" ;
  elody:form ui:example15-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ui:example15-assignee
  sh:path ex:assignee ;
  sh:name "Assignee" ;
  sh:class ex:Person ;
  shui:propertyRole shui:LabelRole ;
  shui:searchQuery
    "\n            PREFIX ex: <http://example.com/>\n            PREFIX text: <http://jena.apache.org/text#>\n            SELECT ?value WHERE {\n                ?value text:query ($searchTerm $uiLanguage) .\n                ?value a ex:Person .\n            }\n        " .

ui:example15-create
  a elody:Form ;
  rdfs:label "Full-text search using shui:searchQuery" ;
  elody:queryName "SpecExample15CreateForm" ;
  elody:shape [ sh:property ui:example15-assignee ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example15-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample15 on BaseEntity {
    intialValues {
      assignee: keyValue(key: "hasAssignee", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      assignee: metaData {
        label(input: "Assignee")
        key(input: "assignee")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample15 on BaseEntity {
    intialValues {
      assignee: keyValue(key: "hasAssignee", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Full-text search using shui:searchQuery")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample15.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              assignee: metaData {
                label(input: "Assignee")
                key(input: "assignee")
                inputField(type: specExample15AssigneeField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample15BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample15CreateForm {
    GetDynamicForm {
      label(input: "Full-text search using shui:searchQuery")
      name: formTab {
        formFields {
          assignee: metaData {
            label(input: "Assignee")
            key(input: "assignee")
            inputField(type: specExample15AssigneeField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample15AssigneeField": {
    "type": "dropdownMultiselectRelations",
    "relationType": "hasAssignee",
    "advancedFilterInputForRetrievingOptions": [
      {
        "type": "type",
        "value": "person"
      }
    ],
    "relationFilter": {
      "type": "selection",
      "key": [
        "elody:1|identifiers"
      ],
      "value": "$relationValues.hasAssignee.key",
      "match_exact": true,
      "item_types": [
        "person"
      ]
    }
  }
}

16 · Federated full-text search using shui:searchQuery ​

Rendered Spec section search-query

Federated full-text search using shui:searchQuery rendered by Elody

What Elody did with it

  • Note: "Author": shui:searchQuery runs against http://example.com/sparql through collection-api's SPARQL engine (a source in SPARQL_SOURCES); the field is a relation dropdown that searches it
  • Note: "Author" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:BookShape
    a sh:NodeShape ;
    sh:targetClass ex:Book ;
    sh:property [
        sh:name "Author" ;
        sh:path dct:creator ;
        sh:in [
            sh:select """
                PREFIX ex: <http://example.com/>
                SELECT ?value WHERE {
                    SERVICE <http://example.com/sparql> {
                        ?value a ex:Person .
                    }
                }
            """ ;
        ] ;
        shui:searchQuery """
            PREFIX ex: <http://example.com/>
            PREFIX text: <http://jena.apache.org/text#>
            SELECT ?value WHERE {
                SERVICE <http://example.com/sparql> {
                    ?value text:query ($searchTerm $uiLanguage) .
                    ?value a ex:Person .
                }
            }
        """ ;
    ] .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example16
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:targetClass ex:Book ;
  sh:property ui:example16-creator ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Federated full-text search using shui:searchQuery" ;
        elody:panel ui:example16-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample16" ;
  elody:form ui:example16-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ui:example16-create
  a elody:Form ;
  rdfs:label "Federated full-text search using shui:searchQuery" ;
  elody:queryName "SpecExample16CreateForm" ;
  elody:shape [ sh:property ui:example16-creator ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example16-creator
  sh:path dct:creator ;
  sh:name "Author" ;
  sh:in
    [ sh:select
      "\n                PREFIX ex: <http://example.com/>\n                SELECT ?value WHERE {\n                    SERVICE <http://example.com/sparql> {\n                        ?value a ex:Person .\n                    }\n                }\n            " ] ;
  shui:propertyRole shui:LabelRole ;
  shui:searchQuery
    "\n            PREFIX ex: <http://example.com/>\n            PREFIX text: <http://jena.apache.org/text#>\n            SELECT ?value WHERE {\n                SERVICE <http://example.com/sparql> {\n                    ?value text:query ($searchTerm $uiLanguage) .\n                    ?value a ex:Person .\n                }\n            }\n        " .

ui:example16-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample16 on BaseEntity {
    intialValues {
      creator: keyValue(key: "hasCreator", source: relations, keyAsLabel: { origin: metadata, key: "title" })
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      creator: metaData {
        label(input: "Author")
        key(input: "creator")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample16 on BaseEntity {
    intialValues {
      creator: keyValue(key: "hasCreator", source: relations, keyAsLabel: { origin: metadata, key: "title" })
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Federated full-text search using shui:searchQuery")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample16.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              creator: metaData {
                label(input: "Author")
                key(input: "creator")
                inputField(type: specExample16CreatorField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample16BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample16CreateForm {
    GetDynamicForm {
      label(input: "Federated full-text search using shui:searchQuery")
      name: formTab {
        formFields {
          creator: metaData {
            label(input: "Author")
            key(input: "creator")
            inputField(type: specExample16CreatorField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample16CreatorField": {
    "type": "dropdownMultiselectRelations",
    "relationType": "hasCreator",
    "advancedFilterInputForRetrievingOptions": [
      {
        "type": "type",
        "value": "specExample16Creator"
      }
    ],
    "relationFilter": {
      "type": "selection",
      "key": [
        "elody:1|identifiers"
      ],
      "value": "$relationValues.hasCreator.key",
      "match_exact": true,
      "item_types": [
        "specExample16Creator"
      ]
    },
    "advancedFilterInputForSearchingOptions": {
      "type": "text",
      "key": [
        "elody:1|metadata.title.value"
      ],
      "value": "*",
      "match_exact": false,
      "item_types": [
        "specExample16Creator"
      ]
    }
  }
}

17 · AutoCompleteEditor ​

Rendered Spec section AutoCompleteEditor

AutoCompleteEditor rendered by Elody

What Elody did with it

  • Note: "bornIn" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Person-bornIn
	a sh:PropertyShape ;
	sh:path ex:bornIn ;
	sh:class ex:Country  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example17
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Person-bornIn ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "AutoCompleteEditor" ;
        elody:panel ui:example17-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample17" ;
  elody:form ui:example17-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Person-bornIn
  a sh:PropertyShape ;
  sh:path ex:bornIn ;
  sh:class ex:Country ;
  shui:propertyRole shui:LabelRole .

ui:example17-create
  a elody:Form ;
  rdfs:label "AutoCompleteEditor" ;
  elody:queryName "SpecExample17CreateForm" ;
  elody:shape [ sh:property ex:Person-bornIn ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example17-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample17 on BaseEntity {
    intialValues {
      bornIn: keyValue(key: "hasBornIn", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      bornIn: metaData {
        label(input: "bornIn")
        key(input: "bornIn")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample17 on BaseEntity {
    intialValues {
      bornIn: keyValue(key: "hasBornIn", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "AutoCompleteEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample17.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              bornIn: metaData {
                label(input: "bornIn")
                key(input: "bornIn")
                inputField(type: specExample17BornInField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample17BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample17CreateForm {
    GetDynamicForm {
      label(input: "AutoCompleteEditor")
      name: formTab {
        formFields {
          bornIn: metaData {
            label(input: "bornIn")
            key(input: "bornIn")
            inputField(type: specExample17BornInField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample17BornInField": {
    "type": "dropdownMultiselectRelations",
    "relationType": "hasBornIn",
    "advancedFilterInputForRetrievingOptions": [
      {
        "type": "type",
        "value": "country"
      }
    ],
    "relationFilter": {
      "type": "selection",
      "key": [
        "elody:1|identifiers"
      ],
      "value": "$relationValues.hasBornIn.key",
      "match_exact": true,
      "item_types": [
        "country"
      ]
    }
  }
}

18 · BooleanEditor ​

Rendered Spec section BooleanEditor

BooleanEditor rendered by Elody

What Elody did with it

  • Note: "married" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Person-married
	a sh:PropertyShape ;
	sh:path ex:married ;
	sh:datatype xsd:boolean  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example18
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Person-married ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "BooleanEditor" ;
        elody:panel ui:example18-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample18" ;
  elody:form ui:example18-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Person-married
  a sh:PropertyShape ;
  sh:path ex:married ;
  sh:datatype xsd:boolean ;
  shui:propertyRole shui:LabelRole .

ui:example18-create
  a elody:Form ;
  rdfs:label "BooleanEditor" ;
  elody:queryName "SpecExample18CreateForm" ;
  elody:shape [ sh:property ex:Person-married ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example18-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample18 on BaseEntity {
    intialValues {
      married: keyValue(key: "married", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      married: metaData {
        label(input: "married")
        key(input: "married")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample18 on BaseEntity {
    intialValues {
      married: keyValue(key: "married", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "BooleanEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample18.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              married: metaData {
                label(input: "married")
                key(input: "married")
                inputField(type: baseCheckbox) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample18BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample18CreateForm {
    GetDynamicForm {
      label(input: "BooleanEditor")
      name: formTab {
        formFields {
          married: metaData {
            label(input: "married")
            key(input: "married")
            inputField(type: baseCheckbox) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }

19 · DatePickerEditor ​

Rendered Spec section DatePickerEditor

DatePickerEditor rendered by Elody

What Elody did with it

  • Note: "dateOfBirth" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Person-dateOfBirth
	a sh:PropertyShape ;
	sh:path ex:dateOfBirth ;
	sh:datatype xsd:date  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example19
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Person-dateOfBirth ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "DatePickerEditor" ;
        elody:panel ui:example19-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample19" ;
  elody:form ui:example19-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Person-dateOfBirth
  a sh:PropertyShape ;
  sh:path ex:dateOfBirth ;
  sh:datatype xsd:date ;
  shui:propertyRole shui:LabelRole .

ui:example19-create
  a elody:Form ;
  rdfs:label "DatePickerEditor" ;
  elody:queryName "SpecExample19CreateForm" ;
  elody:shape [ sh:property ex:Person-dateOfBirth ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example19-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample19 on BaseEntity {
    intialValues {
      dateOfBirth: keyValue(key: "dateOfBirth", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      dateOfBirth: metaData {
        label(input: "dateOfBirth")
        key(input: "dateOfBirth")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample19 on BaseEntity {
    intialValues {
      dateOfBirth: keyValue(key: "dateOfBirth", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "DatePickerEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample19.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              dateOfBirth: metaData {
                label(input: "dateOfBirth")
                key(input: "dateOfBirth")
                inputField(type: baseDateField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample19BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample19CreateForm {
    GetDynamicForm {
      label(input: "DatePickerEditor")
      name: formTab {
        formFields {
          dateOfBirth: metaData {
            label(input: "dateOfBirth")
            key(input: "dateOfBirth")
            inputField(type: baseDateField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }

20 · DateTimePickerEditor ​

Rendered Spec section DateTimePickerEditor

DateTimePickerEditor rendered by Elody

What Elody did with it

  • Note: "lastVisitTime" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Customer-lastVisitTime
	a sh:PropertyShape ;
	sh:path ex:lastVisitTime ;
	sh:datatype xsd:dateTime  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example20
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Customer-lastVisitTime ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "DateTimePickerEditor" ;
        elody:panel ui:example20-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample20" ;
  elody:form ui:example20-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Customer-lastVisitTime
  a sh:PropertyShape ;
  sh:path ex:lastVisitTime ;
  sh:datatype xsd:dateTime ;
  shui:propertyRole shui:LabelRole .

ui:example20-create
  a elody:Form ;
  rdfs:label "DateTimePickerEditor" ;
  elody:queryName "SpecExample20CreateForm" ;
  elody:shape [ sh:property ex:Customer-lastVisitTime ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example20-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample20 on BaseEntity {
    intialValues {
      lastVisitTime: keyValue(key: "lastVisitTime", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      lastVisitTime: metaData {
        label(input: "lastVisitTime")
        key(input: "lastVisitTime")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample20 on BaseEntity {
    intialValues {
      lastVisitTime: keyValue(key: "lastVisitTime", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "DateTimePickerEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample20.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              lastVisitTime: metaData {
                label(input: "lastVisitTime")
                key(input: "lastVisitTime")
                inputField(type: baseDateTimeField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample20BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample20CreateForm {
    GetDynamicForm {
      label(input: "DateTimePickerEditor")
      name: formTab {
        formFields {
          lastVisitTime: metaData {
            label(input: "lastVisitTime")
            key(input: "lastVisitTime")
            inputField(type: baseDateTimeField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }

21 · DetailsEditor ​

Rendered Spec section DetailsEditor

DetailsEditor rendered by Elody

What Elody did with it

  • Note: "weight" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Product
	a owl:Class ;
	a sh:NodeShape ;
	rdfs:label "Product" ;
	rdfs:subClassOf owl:Thing ;
	sh:property ex:Product-weight .

ex:Product-weight
	a sh:PropertyShape ;
	sh:path ex:weight ;
	shui:editor shui:DetailsEditor ;
	shui:viewer shui:DetailsViewer ;
	sh:description "A blank node with a numeric field and a unit which is one of the QUDT mass units." ;
	sh:maxCount 1 ;
	sh:name "weight" ;
	sh:node ex:ValueWithWeight ;
	sh:nodeKind sh:BlankNode .

ex:ValueWithWeight
	a sh:NodeShape ;
	rdfs:label "Value with weight" ;
	sh:property ex:ValueWithWeight-numericValue ;
	sh:property ex:ValueWithWeight-unit .

ex:ValueWithWeight-numericValue
	a sh:PropertyShape ;
	sh:path ex:numericValue ;
	sh:datatype xsd:decimal ;
	sh:maxCount 1 ;
	sh:minCount 1 ;
	sh:name "numeric value" .

ex:ValueWithWeight-unit
	a sh:PropertyShape ;
	sh:path ex:unit ;
	sh:class <http://qudt.org/schema/qudt/Unit> ;
	sh:maxCount 1 ;
	sh:minCount 1 ;
	sh:name "unit" ;
	sh:node [
		rdfs:label "Permissible values must have quantity kind Mass." ;
		sh:property [
			sh:path <http://qudt.org/schema/qudt/hasQuantityKind> ;
			sh:hasValue <http://qudt.org/vocab/quantitykind/Mass> ;
		] ;
	] .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example21
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Product-weight ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "DetailsEditor" ;
        elody:panel ui:example21-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample21" ;
  elody:form ui:example21-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Product-weight
  a sh:PropertyShape ;
  sh:path ex:weight ;
  sh:name "weight" ;
  sh:description
    "A blank node with a numeric field and a unit which is one of the QUDT mass units." ;
  sh:maxCount 1 ;
  sh:node ex:ValueWithWeight ;
  sh:nodeKind sh:BlankNode ;
  shui:editor shui:DetailsEditor ;
  shui:propertyRole shui:LabelRole ;
  shui:viewer shui:DetailsViewer .

ex:ValueWithWeight
  a sh:NodeShape ;
  rdfs:label "Value with weight" ;
  sh:property ex:ValueWithWeight-numericValue , ex:ValueWithWeight-unit .

ex:ValueWithWeight-numericValue
  a sh:PropertyShape ;
  sh:path ex:numericValue ;
  sh:name "numeric value" ;
  sh:datatype xsd:decimal ;
  sh:maxCount 1 ;
  sh:minCount 1 .

ex:ValueWithWeight-unit
  a sh:PropertyShape ;
  sh:path ex:unit ;
  sh:name "unit" ;
  sh:class <http://qudt.org/schema/qudt/Unit> ;
  sh:maxCount 1 ;
  sh:minCount 1 ;
  sh:node
    [ rdfs:label "Permissible values must have quantity kind Mass." ;
    sh:property
      [ sh:path <http://qudt.org/schema/qudt/hasQuantityKind> ;
      sh:hasValue <http://qudt.org/vocab/quantitykind/Mass> ] ] .

ui:example21-create
  a elody:Form ;
  rdfs:label "DetailsEditor" ;
  elody:queryName "SpecExample21CreateForm" ;
  elody:shape [ sh:property ex:Product-weight ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example21-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample21 on BaseEntity {
    intialValues {
      weight: keyValue(key: "weight", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      weight: metaData {
        label(input: "weight")
        key(input: "weight")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample21 on BaseEntity {
    intialValues {
      weight: keyValue(key: "weight", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "DetailsEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample21.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              weight: metaData {
                label(input: "weight")
                key(input: "weight")
                inputField(type: specExample21WeightField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample21BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample21CreateForm {
    GetDynamicForm {
      label(input: "DetailsEditor")
      name: formTab {
        formFields {
          weight: metaData {
            label(input: "weight")
            key(input: "weight")
            inputField(type: specExample21WeightField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample21WeightField": {
    "type": "inputFieldWithSubFields",
    "isMetadataField": true,
    "subFields": [
      {
        "label": "numeric value",
        "key": "numericValue",
        "inputField": {
          "type": "number",
          "validation": {
            "value": [
              "required"
            ]
          }
        }
      },
      {
        "label": "unit",
        "key": "unit",
        "inputField": {
          "type": "text",
          "validation": {
            "value": [
              "required"
            ]
          }
        }
      }
    ]
  }
}

22 · EnumSelectEditor ​

Rendered Spec section EnumSelectEditor

EnumSelectEditor rendered by Elody

What Elody did with it

  • Note: "addressRegion" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:AustralianAddressShape-addressRegion
	a sh:PropertyShape ;
	sh:path schema:addressRegion ;
	sh:in ( "ACT" "NSW" "NT" "QLD" "SA" "TAS" "VIC" "WA" )  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example22
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:AustralianAddressShape-addressRegion ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "EnumSelectEditor" ;
        elody:panel ui:example22-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample22" ;
  elody:form ui:example22-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:AustralianAddressShape-addressRegion
  a sh:PropertyShape ;
  sh:path schema:addressRegion ;
  sh:in ( "ACT" "NSW" "NT" "QLD" "SA" "TAS" "VIC" "WA" ) ;
  shui:propertyRole shui:LabelRole .

ui:example22-create
  a elody:Form ;
  rdfs:label "EnumSelectEditor" ;
  elody:queryName "SpecExample22CreateForm" ;
  elody:shape [ sh:property ex:AustralianAddressShape-addressRegion ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example22-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample22 on BaseEntity {
    intialValues {
      addressRegion: keyValue(key: "addressRegion", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      addressRegion: metaData {
        label(input: "addressRegion")
        key(input: "addressRegion")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample22 on BaseEntity {
    intialValues {
      addressRegion: keyValue(key: "addressRegion", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "EnumSelectEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample22.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              addressRegion: metaData {
                label(input: "addressRegion")
                key(input: "addressRegion")
                inputField(type: specExample22AddressRegionField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample22BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample22CreateForm {
    GetDynamicForm {
      label(input: "EnumSelectEditor")
      name: formTab {
        formFields {
          addressRegion: metaData {
            label(input: "addressRegion")
            key(input: "addressRegion")
            inputField(type: specExample22AddressRegionField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample22AddressRegionField": {
    "type": "dropdownMultiselectMetadata",
    "options": [
      {
        "label": "ACT",
        "value": "ACT"
      },
      {
        "label": "NSW",
        "value": "NSW"
      },
      {
        "label": "NT",
        "value": "NT"
      },
      {
        "label": "QLD",
        "value": "QLD"
      },
      {
        "label": "SA",
        "value": "SA"
      },
      {
        "label": "TAS",
        "value": "TAS"
      },
      {
        "label": "VIC",
        "value": "VIC"
      },
      {
        "label": "WA",
        "value": "WA"
      }
    ]
  }
}

23 · InstancesSelectEditor ​

Rendered Spec section InstancesSelectEditor

InstancesSelectEditor rendered by Elody

What Elody did with it

  • Note: "homeCountry" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Person-homeCountry
	a sh:PropertyShape ;
	sh:path ex:homeCountry ;
	sh:class ex:Country ;
	shui:editor shui:InstancesSelectEditor  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example23
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Person-homeCountry ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "InstancesSelectEditor" ;
        elody:panel ui:example23-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample23" ;
  elody:form ui:example23-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Person-homeCountry
  a sh:PropertyShape ;
  sh:path ex:homeCountry ;
  sh:class ex:Country ;
  shui:editor shui:InstancesSelectEditor ;
  shui:propertyRole shui:LabelRole .

ui:example23-create
  a elody:Form ;
  rdfs:label "InstancesSelectEditor" ;
  elody:queryName "SpecExample23CreateForm" ;
  elody:shape [ sh:property ex:Person-homeCountry ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example23-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample23 on BaseEntity {
    intialValues {
      homeCountry: keyValue(key: "hasHomeCountry", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      homeCountry: metaData {
        label(input: "homeCountry")
        key(input: "homeCountry")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample23 on BaseEntity {
    intialValues {
      homeCountry: keyValue(key: "hasHomeCountry", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "InstancesSelectEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample23.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              homeCountry: metaData {
                label(input: "homeCountry")
                key(input: "homeCountry")
                inputField(type: specExample23HomeCountryField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample23BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample23CreateForm {
    GetDynamicForm {
      label(input: "InstancesSelectEditor")
      name: formTab {
        formFields {
          homeCountry: metaData {
            label(input: "homeCountry")
            key(input: "homeCountry")
            inputField(type: specExample23HomeCountryField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample23HomeCountryField": {
    "type": "dropdownMultiselectRelations",
    "relationType": "hasHomeCountry",
    "advancedFilterInputForRetrievingOptions": [
      {
        "type": "type",
        "value": "country"
      }
    ],
    "relationFilter": {
      "type": "selection",
      "key": [
        "elody:1|identifiers"
      ],
      "value": "$relationValues.hasHomeCountry.key",
      "match_exact": true,
      "item_types": [
        "country"
      ]
    }
  }
}

24 · IRIEditor ​

Rendered Spec section IRIEditor

IRIEditor rendered by Elody

What Elody did with it

  • Note: "seeAlso" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Thing-seeAlso
	a sh:PropertyShape ;
	sh:path rdfs:seeAlso ;
	sh:nodeKind sh:IRI ;
	shui:editor shui:IRIEditor  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example24
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Thing-seeAlso ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "IRIEditor" ;
        elody:panel ui:example24-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample24" ;
  elody:form ui:example24-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Thing-seeAlso
  a sh:PropertyShape ;
  sh:path rdfs:seeAlso ;
  sh:nodeKind sh:IRI ;
  shui:editor shui:IRIEditor ;
  shui:propertyRole shui:LabelRole .

ui:example24-create
  a elody:Form ;
  rdfs:label "IRIEditor" ;
  elody:queryName "SpecExample24CreateForm" ;
  elody:shape [ sh:property ex:Thing-seeAlso ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example24-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample24 on BaseEntity {
    intialValues {
      seeAlso: keyValue(key: "seeAlso", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      seeAlso: metaData {
        label(input: "seeAlso")
        key(input: "seeAlso")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample24 on BaseEntity {
    intialValues {
      seeAlso: keyValue(key: "seeAlso", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "IRIEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample24.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              seeAlso: metaData {
                label(input: "seeAlso")
                key(input: "seeAlso")
                inputField(type: baseTextField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample24BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample24CreateForm {
    GetDynamicForm {
      label(input: "IRIEditor")
      name: formTab {
        formFields {
          seeAlso: metaData {
            label(input: "seeAlso")
            key(input: "seeAlso")
            inputField(type: baseTextField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }

25 · NumberFieldEditor ​

Rendered Spec section NumberFieldEditor

NumberFieldEditor rendered by Elody

What Elody did with it

  • Note: "price" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Product-price
    a sh:PropertyShape ;
    sh:path ex:price ;
    sh:datatype xsd:decimal ;
    shui:editor shui:NumberFieldEditor  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example25
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Product-price ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "NumberFieldEditor" ;
        elody:panel ui:example25-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample25" ;
  elody:form ui:example25-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Product-price
  a sh:PropertyShape ;
  sh:path ex:price ;
  sh:datatype xsd:decimal ;
  shui:editor shui:NumberFieldEditor ;
  shui:propertyRole shui:LabelRole .

ui:example25-create
  a elody:Form ;
  rdfs:label "NumberFieldEditor" ;
  elody:queryName "SpecExample25CreateForm" ;
  elody:shape [ sh:property ex:Product-price ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example25-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample25 on BaseEntity {
    intialValues {
      price: keyValue(key: "price", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      price: metaData {
        label(input: "price")
        key(input: "price")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample25 on BaseEntity {
    intialValues {
      price: keyValue(key: "price", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "NumberFieldEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample25.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              price: metaData {
                label(input: "price")
                key(input: "price")
                inputField(type: baseNumberField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample25BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample25CreateForm {
    GetDynamicForm {
      label(input: "NumberFieldEditor")
      name: formTab {
        formFields {
          price: metaData {
            label(input: "price")
            key(input: "price")
            inputField(type: baseNumberField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }

26 · RichTextEditor ​

Rendered Spec section RichTextEditor

RichTextEditor rendered by Elody

What Elody did with it

  • Note: "definition" is used as the card title (the shapes declare no shui:LabelRole)
  • Note: "definition": shui:RichTextEditor is Elody's rich-text editor in the detail panel, edited there; the create form has no rich-text field, so it is left out of the form
SHACL UI shapes (from the spec)
turtle
ex:Concept-definition
	a sh:PropertyShape ;
	sh:path skos:definition ;
	sh:datatype rdf:HTML  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example26
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Concept-definition ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "RichTextEditor" ;
        elody:panel ui:example26-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample26" ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Concept-definition
  a sh:PropertyShape ;
  sh:path skos:definition ;
  sh:datatype rdf:HTML ;
  shui:propertyRole shui:LabelRole .

ui:example26-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample26 on BaseEntity {
    intialValues {
      definition: keyValue(key: "definition", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      definition: metaData {
        label(input: "definition")
        key(input: "definition")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample26 on BaseEntity {
    intialValues {
      definition: keyValue(key: "definition", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "RichTextEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample26.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              definition: wysiwygElement {
                label(input: "definition")
                metadataKey(input: "definition")
                extensions(input: [starterKit])
                wysiwygElementConfiguration {
                  showLineNumbers(input: false)
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample26BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

27 · SubClassEditor ​

Rendered Spec section SubClassEditor

SubClassEditor rendered by Elody

What Elody did with it

  • Note: "impactedCell" is used as the card title (the shapes declare no shui:LabelRole)
  • Note: "impactedCell": shui:SubClassEditor offers sh:rootClass and its 0 subclasses found in the shapes and data graph, read when generating (as sh:in): a dropdown in tree order, the value the class IRI
SHACL UI shapes (from the spec)
turtle
ex:Drug-impactedCell
	a sh:PropertyShape ;
	sh:path ex:impactedCell ;
	sh:rootClass obo:CL_0000000 ;
	shui:editor shui:SubClassEditor  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example27
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Drug-impactedCell ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "SubClassEditor" ;
        elody:panel ui:example27-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample27" ;
  elody:form ui:example27-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Drug-impactedCell
  a sh:PropertyShape ;
  sh:path ex:impactedCell ;
  sh:rootClass obo:CL_0000000 ;
  shui:editor shui:SubClassEditor ;
  shui:propertyRole shui:LabelRole .

ui:example27-create
  a elody:Form ;
  rdfs:label "SubClassEditor" ;
  elody:queryName "SpecExample27CreateForm" ;
  elody:shape [ sh:property ex:Drug-impactedCell ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example27-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample27 on BaseEntity {
    intialValues {
      impactedCell: keyValue(key: "impactedCell", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      impactedCell: metaData {
        label(input: "impactedCell")
        key(input: "impactedCell")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample27 on BaseEntity {
    intialValues {
      impactedCell: keyValue(key: "impactedCell", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "SubClassEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample27.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              impactedCell: metaData {
                label(input: "impactedCell")
                key(input: "impactedCell")
                inputField(type: specExample27ImpactedCellField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample27BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample27CreateForm {
    GetDynamicForm {
      label(input: "SubClassEditor")
      name: formTab {
        formFields {
          impactedCell: metaData {
            label(input: "impactedCell")
            key(input: "impactedCell")
            inputField(type: specExample27ImpactedCellField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample27ImpactedCellField": {
    "type": "dropdownMultiselectMetadata",
    "options": [
      {
        "label": "CL_0000000",
        "value": "http://purl.obolibrary.org/obo/CL_0000000"
      }
    ]
  }
}

28 · TextAreaEditor ​

Rendered Spec section TextAreaEditor

TextAreaEditor rendered by Elody

What Elody did with it

  • Note: "description" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Country-description
	a sh:PropertyShape ;
	sh:path ex:description ;
	sh:datatype xsd:string ;
	sh:singleLine false  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example28
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Country-description ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "TextAreaEditor" ;
        elody:panel ui:example28-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample28" ;
  elody:form ui:example28-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Country-description
  a sh:PropertyShape ;
  sh:path ex:description ;
  sh:datatype xsd:string ;
  sh:singleLine false ;
  shui:propertyRole shui:LabelRole .

ui:example28-create
  a elody:Form ;
  rdfs:label "TextAreaEditor" ;
  elody:queryName "SpecExample28CreateForm" ;
  elody:shape [ sh:property ex:Country-description ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example28-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample28 on BaseEntity {
    intialValues {
      description: keyValue(key: "description", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      description: metaData {
        label(input: "description")
        key(input: "description")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample28 on BaseEntity {
    intialValues {
      description: keyValue(key: "description", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "TextAreaEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample28.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              description: metaData {
                label(input: "description")
                key(input: "description")
                inputField(type: baseTextareaField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample28BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample28CreateForm {
    GetDynamicForm {
      label(input: "TextAreaEditor")
      name: formTab {
        formFields {
          description: metaData {
            label(input: "description")
            key(input: "description")
            inputField(type: baseTextareaField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }

29 · TextFieldEditor ​

Rendered Spec section TextFieldEditor

TextFieldEditor rendered by Elody

What Elody did with it

  • Note: "code" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Country-code
	a sh:PropertyShape ;
	sh:path ex:code ;
	sh:datatype xsd:string  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example29
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Country-code ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "TextFieldEditor" ;
        elody:panel ui:example29-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample29" ;
  elody:form ui:example29-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Country-code
  a sh:PropertyShape ;
  sh:path ex:code ;
  sh:datatype xsd:string ;
  shui:propertyRole shui:LabelRole .

ui:example29-create
  a elody:Form ;
  rdfs:label "TextFieldEditor" ;
  elody:queryName "SpecExample29CreateForm" ;
  elody:shape [ sh:property ex:Country-code ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example29-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample29 on BaseEntity {
    intialValues {
      code: keyValue(key: "code", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      code: metaData {
        label(input: "code")
        key(input: "code")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample29 on BaseEntity {
    intialValues {
      code: keyValue(key: "code", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "TextFieldEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample29.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              code: metaData {
                label(input: "code")
                key(input: "code")
                inputField(type: specExample29CodeField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample29BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample29CreateForm {
    GetDynamicForm {
      label(input: "TextFieldEditor")
      name: formTab {
        formFields {
          code: metaData {
            label(input: "code")
            key(input: "code")
            inputField(type: specExample29CodeField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample29CodeField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

30 · TextFieldWithLangEditor ​

Rendered Spec section TextFieldWithLangEditor

TextFieldWithLangEditor rendered by Elody

What Elody did with it

  • Note: "prefLabel" is used as the card title (the shapes declare no shui:LabelRole)
SHACL UI shapes (from the spec)
turtle
ex:Concept-prefLabel
	a sh:PropertyShape ;
	sh:path skos:prefLabel ;
	sh:datatype rdf:langString  .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example30
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Concept-prefLabel ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "TextFieldWithLangEditor" ;
        elody:panel ui:example30-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample30" ;
  elody:form ui:example30-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Concept-prefLabel
  a sh:PropertyShape ;
  sh:path skos:prefLabel ;
  sh:datatype rdf:langString ;
  shui:propertyRole shui:LabelRole .

ui:example30-create
  a elody:Form ;
  rdfs:label "TextFieldWithLangEditor" ;
  elody:queryName "SpecExample30CreateForm" ;
  elody:shape [ sh:property ex:Concept-prefLabel ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example30-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample30 on BaseEntity {
    intialValues {
      prefLabel: keyValue(key: "prefLabel", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      prefLabel: metaData {
        label(input: "prefLabel")
        key(input: "prefLabel")
        isMultilingual(input: true)
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample30 on BaseEntity {
    intialValues {
      prefLabel: keyValue(key: "prefLabel", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "TextFieldWithLangEditor")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample30.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              prefLabel: metaData {
                label(input: "prefLabel")
                key(input: "prefLabel")
                isMultilingual(input: true)
                inputField(type: baseTextField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample30BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample30CreateForm {
    GetDynamicForm {
      label(input: "TextFieldWithLangEditor")
      name: formTab {
        formFields {
          prefLabel: metaData {
            label(input: "prefLabel")
            key(input: "prefLabel")
            isMultilingual(input: true)
            inputField(type: baseTextField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }

31 · ValueTableViewer ​

Rendered Spec section ValueTableViewer

ValueTableViewer rendered by Elody

What Elody did with it

  • Note: "narrower (table)": shui:ValueTableViewer is Elody's list of the related entities in the panel; columns: "narrower concept" is the list item, "type" its teaser (the entity's type), "alt labels" its teaser
  • Note: "narrower (table)" is used as the card title (the shapes declare no shui:LabelRole)
  • Note: "narrower (table)": inverse path without sh:class: the IRI is typed in (as shui:IRIEditor) and stored as the relation's key
SHACL UI shapes (from the spec)
turtle
skos:Concept
    sh:property ex:Concept-broader-inverse .

ex:Concept-broader-inverse
    a sh:PropertyShape ;
    sh:path [ sh:inversePath skos:broader ] ;
    sh:group skos:HierarchicalRelationships ;
    sh:name "narrower (table)" ;
    shui:viewer shui:ValueTableViewer ;
    sh:node ex:ConceptTableShape .

ex:ConceptTableShape
    a sh:NodeShape ;
    sh:targetClass skos:Concept ;
    rdfs:comment "A node shape defining the columns for a shui:ValueTableViewer." ;
    rdfs:label "Concept table shape" ;
    sh:property ex:ConceptTableShape-self ;
    sh:property ex:ConceptTableShape-type ;
    sh:property ex:ConceptTableShape-altLabel .

ex:ConceptTableShape-self
    a sh:PropertyShape ;
    sh:path ex:self ;
    sh:description "This column is used to render the (narrower) concept itself." ;
    sh:name "narrower concept" ;
    sh:nodeKind sh:IRI ;
    sh:order "0"^^xsd:decimal ;
    sh:values sh:this .

ex:ConceptTableShape-type
    a sh:PropertyShape ;
    sh:path rdf:type ;
    sh:description "The second column shows the type of each value." ;
    sh:name "type" ;
    sh:nodeKind sh:IRI ;
    sh:order "1"^^xsd:decimal .

ex:ConceptTableShape-altLabel
    a sh:PropertyShape ;
    sh:path skos:altLabel ;
    sh:description "The third column shows the alternative labels." ;
    sh:name "alt labels" ;
    sh:datatype ( xsd:string rdf:langString ) ;
    sh:order "2"^^xsd:decimal .
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example31
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property
    ex:ConceptTableShape-type ,
    ex:ConceptTableShape-altLabel ,
    ex:Concept-broader-inverse ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "ValueTableViewer" ;
        elody:panel skos:HierarchicalRelationships ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample31" ;
  elody:form ui:example31-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Concept-broader-inverse
  a sh:PropertyShape ;
  sh:path [ sh:inversePath skos:broader ] ;
  sh:name "narrower (table)" ;
  sh:group skos:HierarchicalRelationships ;
  sh:node ex:ConceptTableShape ;
  shui:propertyRole shui:LabelRole ;
  shui:viewer shui:ValueTableViewer ;
  elody:teaser false .

ex:ConceptTableShape
  a sh:NodeShape ;
  sh:targetClass skos:Concept ;
  rdfs:label "Concept table shape" ;
  rdfs:comment "A node shape defining the columns for a shui:ValueTableViewer." ;
  sh:property
    ex:ConceptTableShape-self ,
    ex:ConceptTableShape-type ,
    ex:ConceptTableShape-altLabel .

ex:ConceptTableShape-altLabel
  a sh:PropertyShape ;
  sh:path skos:altLabel ;
  sh:name "alt labels" ;
  sh:order 2 ;
  sh:datatype ( xsd:string rdf:langString ) ;
  sh:description "The third column shows the alternative labels." .

ex:ConceptTableShape-self
  a sh:PropertyShape ;
  sh:path ex:self ;
  sh:name "narrower concept" ;
  sh:order 0 ;
  sh:description "This column is used to render the (narrower) concept itself." ;
  sh:nodeKind sh:IRI ;
  sh:values sh:this .

ex:ConceptTableShape-type
  a sh:PropertyShape ;
  sh:path rdf:type ;
  sh:name "type" ;
  sh:order 1 ;
  sh:description "The second column shows the type of each value." ;
  sh:nodeKind sh:IRI ;
  elody:source elody:RootSource .

skos:HierarchicalRelationships
  a sh:PropertyGroup ;
  rdfs:label "HierarchicalRelationships" ;
  elody:alias "hierarchicalRelationships" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel .

ui:example31-create
  a elody:Form ;
  rdfs:label "ValueTableViewer" ;
  elody:queryName "SpecExample31CreateForm" ;
  elody:shape [ sh:property ex:Concept-broader-inverse ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample31 on BaseEntity {
    intialValues {
      type: keyValue(key: "type", source: root)
      altLabel: keyValue(key: "altLabel", source: metadata)
      isBroaderFor: keyValue(key: "isBroaderFor", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      type: metaData {
        label(input: "type")
        key(input: "type")
      }
      altLabel: metaData {
        label(input: "alt labels")
        key(input: "altLabel")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample31 on BaseEntity {
    intialValues {
      type: keyValue(key: "type", source: root)
      altLabel: keyValue(key: "altLabel", source: metadata)
      isBroaderFor: keyValue(key: "isBroaderFor", source: relations, keyAsLabel: { origin: metadata, key: "label|title|name" })
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "ValueTableViewer")
            hierarchicalRelationships: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "HierarchicalRelationships" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              isBroaderFor: entityListElement {
                label(input: "narrower (table)")
                isCollapsed(input: false)
                entityTypes(input: [concept])
                relationType: label(input: "isBroaderFor")
                viewMode(input: Library)
                customQuery(input: "GetEntities")
                customQueryFilters(input: "SpecExample31IsBroaderForListFilters")
              }
            }
          }
        }
      }
    }
  }

  fragment specExample31BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample31CreateForm {
    GetDynamicForm {
      label(input: "ValueTableViewer")
      name: formTab {
        formFields {
          hierarchicalRelationshipsSection: formSection {
            label(input: "HierarchicalRelationships")
            formFields {
              isBroaderFor: metaData {
                label(input: "narrower (table)")
                key(input: "isBroaderFor")
                inputField(type: specExample31IsBroaderForField) {
                  ...inputfield
                }
              }
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }

  query SpecExample31IsBroaderForListFilters($entityType: String!) {
    EntityTypeFilters(type: $entityType) {
      advancedFilters {
        type: advancedFilter(type: type) {
          type
          defaultValue(value: ["concept"])
          hidden(value: true)
        }
        relation: advancedFilter(type: selection, key: ["elody:1|identifiers"]) {
          type
          key
          defaultValue(value: "$entity.relationValues.isBroaderFor.key")
          hidden(value: true)
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample31IsBroaderForField": {
    "type": "inputFieldWithSubFields",
    "isMetadataField": false,
    "relationType": "isBroaderFor",
    "subFields": [
      {
        "label": "IRI",
        "key": "key",
        "inputField": {
          "type": "text",
          "isMetadataField": false
        }
      }
    ]
  }
}

32 · Direct role annotation ​

Rendered Spec section property-roles

Direct role annotation rendered by Elody

SHACL UI shapes (from the spec)
turtle
ex:Label a sh:PropertyShape ;
    sh:path skos:prefLabel ;
    shui:propertyRole shui:LabelRole ;
.
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example32
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Label ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Direct role annotation" ;
        elody:panel ui:example32-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample32" ;
  elody:form ui:example32-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Label
  a sh:PropertyShape ;
  sh:path skos:prefLabel ;
  shui:propertyRole shui:LabelRole .

ui:example32-create
  a elody:Form ;
  rdfs:label "Direct role annotation" ;
  elody:queryName "SpecExample32CreateForm" ;
  elody:shape [ sh:property ex:Label ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example32-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample32 on BaseEntity {
    intialValues {
      prefLabel: keyValue(key: "prefLabel", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      prefLabel: metaData {
        label(input: "prefLabel")
        key(input: "prefLabel")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample32 on BaseEntity {
    intialValues {
      prefLabel: keyValue(key: "prefLabel", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Direct role annotation")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample32.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              prefLabel: metaData {
                label(input: "prefLabel")
                key(input: "prefLabel")
                inputField(type: specExample32PrefLabelField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample32BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample32CreateForm {
    GetDynamicForm {
      label(input: "Direct role annotation")
      name: formTab {
        formFields {
          prefLabel: metaData {
            label(input: "prefLabel")
            key(input: "prefLabel")
            inputField(type: specExample32PrefLabelField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample32PrefLabelField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

33 · Qualified role annotation ​

Rendered Spec section property-roles

Qualified role annotation rendered by Elody

SHACL UI shapes (from the spec)
turtle
ex:PrefLabel a sh:PropertyShape ;
sh:path skos:prefLabel ;
shui:propertyRole [
    shui:propertyRole shui:LabelRole ;
    sh:order 0
]
.

ex:Name a sh:PropertyShape ;
sh:path schema:name ;
shui:propertyRole [
    shui:propertyRole shui:LabelRole ;
    sh:order 1
]
.
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example33
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Name , ex:PrefLabel ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Qualified role annotation" ;
        elody:panel ui:example33-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample33" ;
  elody:form ui:example33-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Name
  a sh:PropertyShape ;
  sh:path schema:name ;
  shui:propertyRole
    [ sh:order 1 ;
    shui:propertyRole shui:LabelRole ] .

ex:PrefLabel
  a sh:PropertyShape ;
  sh:path skos:prefLabel ;
  shui:propertyRole
    [ sh:order 0 ;
    shui:propertyRole shui:LabelRole ] .

ui:example33-create
  a elody:Form ;
  rdfs:label "Qualified role annotation" ;
  elody:queryName "SpecExample33CreateForm" ;
  elody:shape [ sh:property ex:Name , ex:PrefLabel ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example33-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample33 on BaseEntity {
    intialValues {
      name: keyValue(key: "name", source: metadata)
      prefLabel: keyValue(key: "prefLabel", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      name: metaData {
        label(input: "name")
        key(input: "name")
      }
      prefLabel: metaData {
        label(input: "prefLabel")
        key(input: "prefLabel")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample33 on BaseEntity {
    intialValues {
      name: keyValue(key: "name", source: metadata)
      prefLabel: keyValue(key: "prefLabel", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Qualified role annotation")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample33.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              name: metaData {
                label(input: "name")
                key(input: "name")
                inputField(type: specExample33NameField) {
                  ...inputfield
                }
              }
              prefLabel: metaData {
                label(input: "prefLabel")
                key(input: "prefLabel")
                inputField(type: specExample33PrefLabelField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample33BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample33CreateForm {
    GetDynamicForm {
      label(input: "Qualified role annotation")
      name: formTab {
        formFields {
          name: metaData {
            label(input: "name")
            key(input: "name")
            inputField(type: specExample33NameField) {
              ...inputfield
            }
          }
          prefLabel: metaData {
            label(input: "prefLabel")
            key(input: "prefLabel")
            inputField(type: specExample33PrefLabelField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample33NameField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  },
  "specExample33PrefLabelField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

34 · Qualified role annotation using triple annotations ​

Rendered Spec section property-roles

Qualified role annotation using triple annotations rendered by Elody

What Elody did with it

  • Note: several shapes carry a LabelRole with RDF 1.2 annotations; written as qualified roles (shui:propertyRole [ shui:propertyRole shui:LabelRole ; sh:order n ])
SHACL UI shapes (from the spec)
turtle
ex:PrefLabel a sh:PropertyShape ;
    sh:path skos:prefLabel ;
    shui:propertyRole shui:LabelRole {| sh:order 0 |}
.

ex:Name a sh:PropertyShape ;
    sh:path schema:name ;
    shui:propertyRole shui:LabelRole {| sh:order 1 |}
.
Elody declaration (generated by fromShacl)
turtle
@prefix elody:  <https://elody.eu/ns/ui#> .
@prefix sh:     <http://www.w3.org/ns/shacl#> .
@prefix shui:   <http://www.w3.org/ns/shacl-ui/> .
@prefix dash:   <http://datashapes.org/dash#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
@prefix ui:     <https://elody.eu/examples/shacl-ui#> .
@prefix ex:     <http://example.org/ns#> .
@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix skos:   <http://www.w3.org/2004/02/skos/core#> .
@prefix dct:    <http://purl.org/dc/terms/> .
@prefix schema: <http://schema.org/> .
@prefix obo:    <http://purl.obolibrary.org/obo/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .
@prefix geo:    <http://www.opengis.net/ont/geosparql#> .
@prefix sdo:    <https://schema.org/> .

ui:example34
  a elody:EntityUi ;
  elody:graphqlType "BaseEntity" ;
  elody:emit "file" ;
  sh:property ex:Name , ex:PrefLabel ;
  elody:detail
    [ elody:column
      [ elody:element
        [ a elody:WindowElement ;
        rdfs:label "Qualified role annotation using triple annotations" ;
        elody:panel ui:example34-details ] ;
      elody:size elody:Width100 ] ] ;
  elody:documentName "SpecExample34" ;
  elody:form ui:example34-create ;
  elody:viewMode [ elody:mode elody:ListView ] .

ex:Name
  a sh:PropertyShape ;
  sh:path schema:name ;
  shui:propertyRole
    [ sh:order 1 ;
    shui:propertyRole shui:LabelRole ] .

ex:PrefLabel
  a sh:PropertyShape ;
  sh:path skos:prefLabel ;
  shui:propertyRole
    [ sh:order 0 ;
    shui:propertyRole shui:LabelRole ] .

ui:example34-create
  a elody:Form ;
  rdfs:label "Qualified role annotation using triple annotations" ;
  elody:queryName "SpecExample34CreateForm" ;
  elody:shape [ sh:property ex:Name , ex:PrefLabel ] ;
  elody:submit
    [ rdfs:label "actions.labels.create" ;
    elody:actionQuery "CreateEntity" ;
    elody:creationType "BaseEntity" ;
    elody:icon "Create" ] .

ui:example34-details
  a sh:PropertyGroup ;
  rdfs:label "Details"@en , "Details"@nl ;
  sh:order 0 ;
  elody:alias "details" ;
  elody:collapsed false ;
  elody:panelKind elody:MetadataPanel ;
  elody:showsUngrouped true .
GraphQL (generated by elody-ui generate)
graphql
fragment minimalSpecExample34 on BaseEntity {
    intialValues {
      name: keyValue(key: "name", source: metadata)
      prefLabel: keyValue(key: "prefLabel", source: metadata)
    }
    relationValues
    allowedViewModes {
      viewModes(
        input: [
          { viewMode: ViewModesList }
        ]
      ) {
        ...viewModes
      }
    }
    teaserMetadata {
      name: metaData {
        label(input: "name")
        key(input: "name")
      }
      prefLabel: metaData {
        label(input: "prefLabel")
        key(input: "prefLabel")
      }
    }
    ...minimalBaseEntity
  }

  fragment fullSpecExample34 on BaseEntity {
    intialValues {
      name: keyValue(key: "name", source: metadata)
      prefLabel: keyValue(key: "prefLabel", source: metadata)
    }
    relationValues
    entityView {
      column {
        size(size: hundred)
        elements {
          windowElement {
            label(input: "Qualified role annotation using triple annotations")
            details: panels {
              panelHeaderContent(panelHeaderContentInput: { label: "ui.specExample34.group.details" }) {
                label
              }
              panelType(input: metadata)
              isCollapsed(input: false)
              isEditable(input: true)
              name: metaData {
                label(input: "name")
                key(input: "name")
                inputField(type: specExample34NameField) {
                  ...inputfield
                }
              }
              prefLabel: metaData {
                label(input: "prefLabel")
                key(input: "prefLabel")
                inputField(type: specExample34PrefLabelField) {
                  ...inputfield
                }
              }
            }
          }
        }
      }
    }
  }

  fragment specExample34BulkOperations on BaseEntity {
    bulkOperationOptions {
      options(input: []) {
        icon
        label
        value
        primary
        can
        actionContext {
          ...actionContext
        }
        bulkOperationModal {
          ...bulkOperationModal
        }
      }
    }
  }

  query SpecExample34CreateForm {
    GetDynamicForm {
      label(input: "Qualified role annotation using triple annotations")
      name: formTab {
        formFields {
          name: metaData {
            label(input: "name")
            key(input: "name")
            inputField(type: specExample34NameField) {
              ...inputfield
            }
          }
          prefLabel: metaData {
            label(input: "prefLabel")
            key(input: "prefLabel")
            inputField(type: specExample34PrefLabelField) {
              ...inputfield
            }
          }
          createAction: action {
            label(input: "actions.labels.create")
            icon(input: Create)
            actionType(input: submit)
            actionQuery(input: "CreateEntity")
            creationType(input: BaseEntity)
            showsFormErrors(input: true)
          }
        }
      }
    }
  }
Generated custom input fields
json
{
  "specExample34NameField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  },
  "specExample34PrefLabelField": {
    "type": "dropdownMultiselectMetadata",
    "isMetadataField": true,
    "canCreateEntityFromOption": true,
    "multiple": true
  }
}

Powered by Elody - Open Source Semantic Data Platform