Skip to content
This repository has been archived by the owner on Jan 30, 2024. It is now read-only.

Scope: Forms vs Views #4

Open
tpluscode opened this issue Jun 1, 2023 · 9 comments
Open

Scope: Forms vs Views #4

tpluscode opened this issue Jun 1, 2023 · 9 comments
Labels
scope Scope

Comments

@tpluscode
Copy link

In addition to the #2 I think we should define if the interest of this task force is only forms or also "views" or pages.

In my experience, the two are quite separate and while DASH vocab comes with a set of terms for editors and viewers, I find that it is not as simple as annotation properties with both to produce good UI.

I found that a form is usually based off a SHACL Shape, describing a single resource or a set of closely related resources which form a cohesive whole. This is at least the case in a client/server, resource-oriented scenario where a client retrieves the shape and a single resource to edit and then saves it back. That said, an approach which sits closer ot the data itself is not so much different in that any modifications and shapes are closely modeling the graph model with very similar semantics to how one would model a OWL ontology, etc.

On the other hand, specialised views will likely span multiple resources and combine their descriptions in a different way, aiming to provide a different projection of the actual data. View Shapes would likely use deep property paths, partial queries, aggregations, and richer components to provide the user with an interface to fulfil a very different role than a "form turned read-only". Some examples of what I have in mind could include:

  • a view partition (page) of a set of resources, including their total count and a pager to navigate between pages
  • displaying 5 latest ("trending") articles on a home page
  • displaying most recent comments under a blog posting
  • showing links to related resources (eg. skos:related) in a side column
  • using more that one (DASH) component to model a composite UI (see further comment below)

Thus in practice, I have been maintaining a separate shape for editing and a separate for displaying.

I would consider keeping such a separation in the spec, where we'd have one spec describing how to use SHACL to build editable UI, and another one dedicated to building "pages" with SHACL.

@tpluscode
Copy link
Author

tpluscode commented Jun 1, 2023

To elaborate a little on the last bullet above, I have recently been prototyping code to render entire pages from SHACL. The important feature for me was to use web components and server-side rendering. This forced me to slightly rethink how any given shape declares the UI components to use so that declarative HTML composition is possible. The outcome is a deviation from the DASH as I understand it, where I allowed RDF List objects of dash:viewer property.

For example, in my data I have a link of precomputed filter URLs to pages where the ?i query is an initial of the brand names.

<brands> a schema:WebPage; 
  hydra:view [
    a :AlphabeticalPager ;
    :page <brands?i=a> , <brands?i=b>, <brands?i=c> ; # ...
  ] ; 
.

<brands?i=a> rdfs:label "A" . # etc

I wish to display each link in a pager component. By separating the logic of displaying a link from the pager component itself, I arrive at this markup

<ex-pager>
  <!-- for every :page, render a link -->
  <a href="brands?i=a>A</a>
  <a href="brands?i=b>B</a>
  <a href="brands?i=c>C</a>
<ex-pager>

The problem was that I could not define this composition with the current toolkit (or so I think). Thus, the dash:viewer list solution which describes the above somewhat like

<BrandsPage>
  a sh:NodeShape ;
  sh:targetNode <brands> ;
  sh:property [
    sh:path hydra:view ;
    sh:class :AlphabeticalPager ;
    dash:viewer 
      ( 
        ex:Pager # dash:MultiViewer, render the <ex-pager> wrapper component
        dash:DetailsViewer # delegate the rendering of individual links to nested shape
      ) ;
    sh:node [
      sh:property [
        sh:path :page ;
        dash:viewer dash:LabelViewer ; # render <A> link
      ] ;
    ] ;
  ] ;
.

@bergos bergos added the scope Scope label Jun 1, 2023
@danielbeeke
Copy link
Contributor

I have used a similar concept to dash:Viewers but always used views of documents. I think using multiple documents in a composition view might become very complex.

  • I agree, views often are different from the form display. In my use case I also would like to have a favorite button for the document subject. I think this is not possible at the moment with dash as the path would be hard to create.
  • Why do you want to use SHACL / RDF to define whole HTML pages? Do I understand it correctly that you would be somewhat typing HTML in turtle / RDF?

@tpluscode
Copy link
Author

Why do you want to use SHACL / RDF to define whole HTML pages?

A SHACL Shape which describes an entire page allows me to retrieve the exact data needed to populate it and then render. Both important for performance and Server-Side Rendering in some way.

Do I understand it correctly that you would be somewhat typing HTML in turtle / RDF?

Not exactly. Clearly, my focus is HTML pages and the viewers in the above example translate to composition of HTML elements but they are abstract and could be used to compose an interface in another technology which keeps a similar tree-like component structure.

@danielbeeke
Copy link
Contributor

How much of this is already in SHACL? Isn't SHACL by default meant for a one to one relationship between a shape and a document? How do you fetch multiple documents with pagination for example?

Or is that exactly what you would like to add with SHACL UI?

@tpluscode
Copy link
Author

Yes, some of what you bring up would ideally be part of SHACL-UI

Isn't SHACL by default meant for a one to one relationship between a shape and a document?

Yes, but I suppose you could dynamically load resources (documents?). The root shape may include hints for that, etc

@HolgerKnublauch
Copy link
Contributor

I am quite interested in this topic. In TopBraid we render resource forms with a generic top-to-bottom list of property widgets, grouped into sh:PropertyGroups and sorted by sh:order. I believe it would be beneficial to be able to say, for example, that a Person's firstName and lastName should appear horizontally aligned instead of vertically. This suggests some sort of

layout structure. Likewise there could be annotations on whether the label of a property widget should appear above or to the left. And there could be "static" areas such as descriptive text or other media that are placed somewhere on a form. The don't need to be completely "static" but could be computed using SHACL-AF node expressions or similar.

I am aware this is open-ended and we don't want to reinvent HTML here. But a box layout model with static parts may go a long way. And it should be declarative so that non-HTML engines can also use that information.

@tpluscode do you have a draft vocabulary for such things that you would want to share as starting point?

@tpluscode
Copy link
Author

I believe it would be beneficial to be able to say, for example, that a Person's firstName and lastName should appear horizontally aligned instead of vertically. This suggests some sort of layout structure

I agree. Good form generators out there do have some control over the layout which is more sophisticated than grouping and ordering.

What I'm trying to say is that forms and views are likely to be represented differently in SHACL Shapes. I also prefer completely separate implementations because forms and views have a very different model for the internal state of what's being rendered.

@tpluscode do you have a draft vocabulary for such things that you would want to share as starting point?

In fact I don't have much.
For forms, I too have been satisfied with sh:group/sh:order.
For views, at some point I stitched together an imperfect solution where I would property shapes or groups with CSS selectors to force specific HTML structure, styles and attributes.

In more recent implementation I rely simply on element composition and both layout and styling fall out of scope of the shape itself. Similar to the example above, a top-level dash:viewer would be set to a "layout component". The only addition is html:slot (I previously used schema:identifier) to define where the child properties are going to be rendered.

<> a sh:NodeShape ;
  dash:viewer ex:SidebarLayout ;
  sh:property [ sh:path schema:title ; sh:group <#header> ] ;
  sh:property [ 
    sh:path skos:related ; 
    sh:group <#sidebar> ; 
    dash:viewer ( ex:LinkList dash:LabelViewer ) ;
  ] ;
  sh:property [ 
    sh:path schema:articleBody ; 
    dash:viewer dash:HTMLViewer ;
  ] ;
.

<#header> html:slot "header" .
<#sidebar> html:slot "sidebar" .

The final result could be similar to

<ex-sidebar-layout>
  <span slot="header">
    <!-- render component for schema:title -->
  </span>
  <!-- 
    Notice again the rdf:List used for dash:viewer, 
    where the first is a dash:MultiViewer to act as a container 
  -->
  <ex-link-list slot="sidebar">
    <a href></a>
    <a href></a>
    <a href></a>
  </ex-link-list>

  <!-- render component for schema:articleBody -->
</ex-sidebar-layout>

As I said, there is no need for explicit layout or styling hints. Layout is defined in the implementation of <ex-sidebar-layout> where HTML slots handle placing child properties in the desired places. The nice part is that the exact same mechanism works on any nesting level.

@danielbeeke
Copy link
Contributor

I like the usage of rdf:List for dash:viewer
I also think these slots are very nice. I think it is a clean separation.

It made me think.. do we want layouts that are portable?

If we want them to be portable and be defined in rdf we could use something like css grid and grid regions.
The regions would be somewhat similar to slots. The main difference with slots and separation is that some css grid rules should be defined for the layout.

I think we could maybe grab a subset of the css grid rules that would be easy to use in native code.

I am not sure if portability of layouts would be a must. I do see one use case.. a system with federation and open data types, such as mastodon. One app could define a media type (a recipe for example) and also give a reference for how to render those recipes.

In that case simple layouts such as 'two column', or 'left sidebar' could be interesting.

@tpluscode
Copy link
Author

It made me think.. do we want layouts that are portable?

Very good point! Contrary to my remark on the last call, I am most certainly JS-only focused. That said, there is nothing other than the slot concept which is browser-specific but I surely do not consider other targets in my work.

we could use something like css grid and grid regions

CSS grid is a good suggestion. It has wide support in browsers and should be easily adoptible on other platforms too. Alternatively, we could devise a abstract grid addressing and have CSS grid an implementation detail.

While I still keep the mental separations between views and forms, the CSS grid would very much work for forms, such as in the "placing first and last name next to each other" scenario above. On second thought, a similar mechanism could also work for views, where an individual group is laid out as a grid too. I think this is slightly unrelated to the "two column"/"left sidebar" which defines a layout on a different level

Now, one potentially problem with css grids is responsiveness. If the solution was to arbitrarily assign rendered viewers and editors to specific cells in a grid, the layout would be very rigid. Compare with the approach shown in this tutorial, where the HTML elements have meaningful class and are positioned using a grid indirectly.

In that case simple layouts such as 'two column', or 'left sidebar' could be interesting.

To complement the fine-grained layouting solution (css grid, or otherwise) we could still keep these abstract layouts and a new concept. A hypothetical dash:SidebarLayout is just as portable as dash:SingleLineEditor in that any platform can provide its specific implementation while keeping the shape agnostic.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
scope Scope
Projects
None yet
Development

No branches or pull requests

4 participants