You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by jo...@apache.org on 2020/04/08 13:39:39 UTC

[isis] branch ISIS-2324-Merge-kroviz updated (e4a5a8f -> 0453724)

This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a change to branch ISIS-2324-Merge-kroviz
in repository https://gitbox.apache.org/repos/asf/isis.git.


    from e4a5a8f  ISIS-2324 Col layout with FieldSetPanel
     new 2bc21ac  ISIS-2324 Fix Tab layout parsing and rendering
     new 71b43e1  ISIS-2324 code cleanup
     new 0453724  ISIS-2324 Documentation

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 incubator/clients/kroviz/docs/seq-aggregator.adoc  |   7 +-
 .../isis/client/kroviz/core/event/LogEntry.kt      |   7 +-
 .../isis/client/kroviz/handler/BaseHandler.kt      |   4 +-
 .../isis/client/kroviz/handler/LayoutHandler.kt    |  22 ---
 .../apache/isis/client/kroviz/to/bs3/FieldSet.kt   |  12 +-
 .../org/apache/isis/client/kroviz/to/bs3/Row.kt    |  23 +--
 .../snapshots/demo2_0_0/DEMO_TAB_LAYOUT_XML.kt     | 160 +++++++++++++++++++++
 .../isis/client/kroviz/to/bs3/LayoutXmlTest.kt     |  13 ++
 8 files changed, 194 insertions(+), 54 deletions(-)
 create mode 100644 incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/DEMO_TAB_LAYOUT_XML.kt


[isis] 02/03: ISIS-2324 code cleanup

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-2324-Merge-kroviz
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 71b43e15c7f865458fdd123769f68c35640f6ee7
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Wed Apr 8 14:50:10 2020 +0200

    ISIS-2324 code cleanup
---
 .../isis/client/kroviz/core/event/LogEntry.kt      |  7 +------
 .../isis/client/kroviz/handler/BaseHandler.kt      |  4 ++--
 .../isis/client/kroviz/handler/LayoutHandler.kt    | 22 ----------------------
 3 files changed, 3 insertions(+), 30 deletions(-)

diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/LogEntry.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/LogEntry.kt
index d909fb6..37e5aaf 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/LogEntry.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/LogEntry.kt
@@ -169,16 +169,11 @@ data class LogEntry(
     }
 
     fun addAggregator(aggregator: BaseAggregator) {
-        if (aggregators.size > 0) {
-            /*           console.log("[LogEntry.addAggregator()]")
-                       console.log(aggregators)
-                       console.log(aggregator)*/
-        }
         aggregators.add(aggregator)
     }
 
     fun matches(reSpec: ResourceSpecification): Boolean {
-        return url.equals(reSpec.url) && subType.equals(reSpec.subType)
+        return url == reSpec.url && subType.equals(reSpec.subType)
     }
 
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt
index 7928ed8..4072a24 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt
@@ -4,8 +4,8 @@ import org.apache.isis.client.kroviz.core.event.LogEntry
 import org.apache.isis.client.kroviz.to.TransferObject
 
 /**
- * Superclass of Response Handlers which have to handle asynchronous XHR responses.
- * Due to the fact that XMLHttpRequests are called asynchronously, responses may arrive in random order.
+ * Handle responses to XmlHttpRequests asynchronously,
+ * since they may arrive in arbitrary order.
  * @see: https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern
  * COR simplifies implementation of Dispatcher.
  *
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/LayoutHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/LayoutHandler.kt
index 714f4f9..1eb26be 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/LayoutHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/LayoutHandler.kt
@@ -3,9 +3,6 @@ package org.apache.isis.client.kroviz.handler
 import kotlinx.serialization.UnstableDefault
 import kotlinx.serialization.json.Json
 import org.apache.isis.client.kroviz.layout.Layout
-import org.apache.isis.client.kroviz.to.Link
-import org.apache.isis.client.kroviz.to.Links
-import org.apache.isis.client.kroviz.to.Method
 import org.apache.isis.client.kroviz.to.TransferObject
 import org.apache.isis.client.kroviz.utils.XmlHelper
 
@@ -25,23 +22,4 @@ class LayoutHandler : org.apache.isis.client.kroviz.handler.BaseHandler() {
         return Json.parse(Layout.serializer(), response)
     }
 
-    fun parseProperties(response: String): TransferObject? {
-        val prefix = "\"href\":"
-        val hrefList = mutableListOf<String>()
-        val lines = response.split("\n")
-        lines.forEach { l ->
-            if (l.trim().startsWith(prefix) && l.contains("/properties/")) {
-                hrefList.add(l)
-            }
-        }
-        val propertyLinks = mutableListOf<Link>()
-        hrefList.forEach { h ->
-            val href = h.replace(prefix, "").trim().drop(1).dropLast(1)
-            val link = Link(method = Method.GET.operation, href = href)
-            propertyLinks.add(link)
-        }
-        val links = Links(propertyLinks)
-        return links
-    }
-
 }


[isis] 03/03: ISIS-2324 Documentation

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-2324-Merge-kroviz
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 0453724cd931d47188832ab704b4cb7118d5810c
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Wed Apr 8 14:50:53 2020 +0200

    ISIS-2324 Documentation
---
 incubator/clients/kroviz/docs/seq-aggregator.adoc | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/incubator/clients/kroviz/docs/seq-aggregator.adoc b/incubator/clients/kroviz/docs/seq-aggregator.adoc
index 645e6a9..0be96bc 100644
--- a/incubator/clients/kroviz/docs/seq-aggregator.adoc
+++ b/incubator/clients/kroviz/docs/seq-aggregator.adoc
@@ -20,10 +20,11 @@ XHR -> RH : handle()
 activate RH
 RH -> RH : successor.handle()
 RH -> TO : parse()
+RH -> LE : setTransferObject()
+RH -> LE : addAggegator()
 RH -> AGGT : update(logEntry)
-activate AGGT
-RH -> LE : setAggegator()
 deactivate RH
+activate AGGT
 
 AGGT -> AGGT : handleList()
 activate AGGT
@@ -49,8 +50,6 @@ LNK -> XHR: invoke(this, aggt)
 deactivate AGGT
 
 AGGT -> DM : canBeDisplayed()
-activate DM
-deactivate DM
 AGGT -> UI : openView()
 deactivate AGGT
 


[isis] 01/03: ISIS-2324 Fix Tab layout parsing and rendering

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-2324-Merge-kroviz
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 2bc21acfba7977c1aba235b3786b37cce39d58c4
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Wed Apr 8 14:49:40 2020 +0200

    ISIS-2324 Fix Tab layout parsing and rendering
---
 .../apache/isis/client/kroviz/to/bs3/FieldSet.kt   |  12 +-
 .../org/apache/isis/client/kroviz/to/bs3/Row.kt    |  23 +--
 .../snapshots/demo2_0_0/DEMO_TAB_LAYOUT_XML.kt     | 160 +++++++++++++++++++++
 .../isis/client/kroviz/to/bs3/LayoutXmlTest.kt     |  13 ++
 4 files changed, 188 insertions(+), 20 deletions(-)

diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/FieldSet.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/FieldSet.kt
index d0ef987..7cbb8a9 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/FieldSet.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/FieldSet.kt
@@ -6,13 +6,17 @@ import org.w3c.dom.asList
 class FieldSet(node: Node) {
     var actionList = mutableListOf<Action>()
     var propertyList = mutableListOf<Property>()
-    var name: String
-    var id: String
+    var name: String = ""
+    var id: String = ""
 
     init {
         val dyNode = node.asDynamic()
-        name = dyNode.getAttribute("name") as String
-        id = dyNode.getAttribute("id") as String
+        if (dyNode.hasOwnProperty("name")) {
+            name = dyNode.getAttribute("name") as String
+        }
+        if (dyNode.hasOwnProperty("id")) {
+            id = dyNode.getAttribute("id") as String
+        }
 
         val nl = node.childNodes.asList()
         val actList = nl.filter { it.nodeName.equals("cpt:action") }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/Row.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/Row.kt
index 2732425..cbeb3b3 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/Row.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/Row.kt
@@ -5,29 +5,20 @@ import org.w3c.dom.Node
 
 class Row(node: Node) {
     val colList = mutableListOf<Col>()
-    var fieldSet:FieldSet? = null
-    var tabGroupList = mutableListOf<TabGroup>()
-    lateinit var id:String
+    var id: String = ""
 
     init {
+        val dyNode = node.asDynamic()
+        if (dyNode.hasOwnProperty("id")) {
+            id = dyNode.getAttribute("id") as String
+        }
+
         val nodeList = XmlHelper.nonTextChildren(node)
         val cl = nodeList.filter { it.nodeName.equals("bs3:col") }
         for (n: Node in cl) {
-            val col =Col(n)
+            val col = Col(n)
             colList.add(col)
         }
-
-        val fsList = nodeList.filter { it.nodeName.equals("cpt:fieldSet") }
-        if (fsList.size == 1) {
-            val n = fsList.get(0)
-            fieldSet =FieldSet(n)
-        }
-
-        val tgList = nodeList.filter { it.nodeName.equals("cpt:fieldSet") }   //FIXME
-        for (n: Node in tgList) {
-            val tg =TabGroup(n)
-            tabGroupList.add(tg)
-        }
     }
 
     fun getPropertyList(): List<Property> {
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/DEMO_TAB_LAYOUT_XML.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/DEMO_TAB_LAYOUT_XML.kt
new file mode 100644
index 0000000..8fe4544
--- /dev/null
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/DEMO_TAB_LAYOUT_XML.kt
@@ -0,0 +1,160 @@
+package org.apache.isis.client.kroviz.snapshots.demo2_0_0
+
+import org.apache.isis.client.kroviz.snapshots.Response
+
+object DEMO_TAB_LAYOUT_XML: Response() {
+    override val url = "http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/object-layout"
+    override val str = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<bs3:grid xmlns:cpt="http://isis.apache.org/applib/layout/component"
+          xmlns:lnk="http://isis.apache.org/applib/layout/links"
+          xmlns:bs3="http://isis.apache.org/applib/layout/grid/bootstrap3">
+    <bs3:row>
+        <bs3:col span="12" unreferencedActions="true">
+            <cpt:domainObject>
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/element</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object"</lnk:type>
+                </cpt:link>
+            </cpt:domainObject>
+            <cpt:action id="clearHints">
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/actions/clearHints
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action id="downloadLayoutXml">
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/actions/downloadLayoutXml
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action id="openRestApi">
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/actions/openRestApi
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action id="rebuildMetamodel">
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/actions/rebuildMetamodel
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action id="doHideField">
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/actions/doHideField
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action id="doShowField">
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/actions/doShowField
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action bookmarking="NEVER" cssClassFa="fa fa-fw fa-download" cssClassFaPosition="LEFT"
+                        id="downloadMetaModelXml">
+                <cpt:named>Download Meta Model Xml</cpt:named>
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/actions/downloadMetaModelXml
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+        </bs3:col>
+    </bs3:row>
+    <bs3:row>
+        <bs3:col span="6">
+            <bs3:tabGroup>
+                <bs3:tab name="Tab 1">
+                    <bs3:row>
+                        <bs3:col span="12">
+                            <cpt:fieldSet name="Hideable Field" id="fs1">
+                                <cpt:property id="field1">
+                                    <cpt:link>
+                                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                                        <lnk:method>GET</lnk:method>
+                                        <lnk:href>
+                                            http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/properties/field1
+                                        </lnk:href>
+                                        <lnk:type>
+                                            application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                                        </lnk:type>
+                                    </cpt:link>
+                                </cpt:property>
+                            </cpt:fieldSet>
+                        </bs3:col>
+                    </bs3:row>
+                </bs3:tab>
+                <bs3:tab name="Tab 2">
+                    <bs3:row>
+                        <bs3:col span="12">
+                            <cpt:fieldSet id="fs2">
+                                <cpt:property id="field2">
+                                    <cpt:link>
+                                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                                        <lnk:method>GET</lnk:method>
+                                        <lnk:href>
+                                            http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/properties/field2
+                                        </lnk:href>
+                                        <lnk:type>
+                                            application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                                        </lnk:type>
+                                    </cpt:link>
+                                </cpt:property>
+                            </cpt:fieldSet>
+                        </bs3:col>
+                    </bs3:row>
+                </bs3:tab>
+            </bs3:tabGroup>
+        </bs3:col>
+        <bs3:col span="6" unreferencedCollections="true">
+            <cpt:fieldSet name="Description" id="description" unreferencedProperties="true">
+                <cpt:property id="description" labelPosition="NONE">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:8080/restful/objects/demo.Tab/ADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPERlbW8-CiAgICA8ZmllbGQxPmZpZWxkIDE8L2ZpZWxkMT4KICAgIDxmaWVsZDI-ZmllbGQgMjwvZmllbGQyPgogICAgPGhpZGRlbj5mYWxzZTwvaGlkZGVuPgo8L0RlbW8-Cg==/properties/description
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+            </cpt:fieldSet>
+        </bs3:col>
+    </bs3:row>
+</bs3:grid>
+"""
+}
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/to/bs3/LayoutXmlTest.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/to/bs3/LayoutXmlTest.kt
index e65dd81..e67cbab 100644
--- a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/to/bs3/LayoutXmlTest.kt
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/to/bs3/LayoutXmlTest.kt
@@ -1,6 +1,7 @@
 package org.apache.isis.client.kroviz.to.bs3
 
 import org.apache.isis.client.kroviz.handler.LayoutXmlHandler
+import org.apache.isis.client.kroviz.snapshots.demo2_0_0.DEMO_TAB_LAYOUT_XML
 import org.apache.isis.client.kroviz.snapshots.simpleapp1_16_0.SO_LAYOUT_XML
 import kotlin.test.Test
 import kotlin.test.assertEquals
@@ -8,6 +9,18 @@ import kotlin.test.assertEquals
 class LayoutXmlTest {
 
     @Test
+    fun testDemoTabGrid() {
+        //given
+        val xmlStr = DEMO_TAB_LAYOUT_XML.str
+        //when
+        val grid = LayoutXmlHandler().parse(xmlStr) as Grid
+        // then
+        console.log("[LXT.testDemoTabGrid]")
+        console.log(grid)
+        assertEquals(2, grid.rows.size)    //1
+    }
+
+    @Test
     fun testParseXmlLayout() {
         //given
         val xmlStr = SO_LAYOUT_XML.str