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 2021/07/06 15:21:09 UTC

[isis] 03/07: ISIS-2505 parentedCollection (BasicTypes->String) renders two empty entries

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

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

commit 375f3262efe3a90a04be12024c72570d1340eba3
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Wed Jun 30 18:01:05 2021 +0200

    ISIS-2505 parentedCollection (BasicTypes->String) renders two empty entries
---
 .../kroviz/core/aggregator/AggregatorWithLayout.kt |  2 +-
 .../kroviz/core/aggregator/BaseAggregator.kt       |  4 ++-
 .../kroviz/core/aggregator/CollectionAggregator.kt | 12 +++----
 .../core/aggregator/DomainTypesAggregator.kt       |  1 -
 .../isis/client/kroviz/core/event/LogEntry.kt      | 17 ++++++++-
 .../client/kroviz/core/event/LogEntryDecorator.kt  |  2 --
 .../client/kroviz/core/event/RoXmlHttpRequest.kt   |  2 +-
 .../isis/client/kroviz/core/model/CollectionDM.kt  |  4 ++-
 .../kroviz/core/model/DisplayModelWithLayout.kt    | 20 +++++++++++
 .../client/kroviz/handler/DomainTypesHandler.kt    |  5 ++-
 .../isis/client/kroviz/handler/HttpErrorHandler.kt |  1 -
 .../{HttpErrorHandler.kt => IconHandler.kt}        | 18 +++++-----
 .../isis/client/kroviz/handler/LayoutHandler.kt    |  4 +--
 .../isis/client/kroviz/handler/LayoutXmlHandler.kt |  2 +-
 .../isis/client/kroviz/handler/ResponseHandler.kt  |  4 ++-
 .../org/apache/isis/client/kroviz/to/Icon.kt       |  4 ++-
 .../apache/isis/client/kroviz/to/bs3/FieldSet.kt   | 12 +++----
 .../apache/isis/client/kroviz/to/bs3/Property.kt   |  4 +--
 .../isis/client/kroviz/ui/builder/ColBuilder.kt    |  9 +++--
 .../isis/client/kroviz/ui/core/ColumnFactory.kt    | 20 +++++++----
 .../apache/isis/client/kroviz/ui/core/Constants.kt |  1 +
 .../isis/client/kroviz/ui/core/FormPanelFactory.kt |  4 +--
 .../isis/client/kroviz/ui/core/MenuFactory.kt      |  2 --
 .../apache/isis/client/kroviz/ui/core/UiManager.kt |  2 --
 .../isis/client/kroviz/ui/dialog/DiagramDialog.kt  |  1 +
 .../isis/client/kroviz/ui/panel/EventLogTable.kt   | 42 ++++++++++++++++++----
 .../snapshots/demo2_0_0/ACTIONS_STRINGS_INVOKE.kt  |  2 +-
 27 files changed, 132 insertions(+), 69 deletions(-)

diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/AggregatorWithLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/AggregatorWithLayout.kt
index d6d62cc..639f43f 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/AggregatorWithLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/AggregatorWithLayout.kt
@@ -14,7 +14,7 @@ abstract class AggregatorWithLayout : BaseAggregator() {
             dm.propertyLayoutList.forEach { p ->
                 val l = p.link!!
                 val isDn = l.href.contains("datanucleus")
-                if (isDn) {
+                if (!isDn) {
                     //invoking DN links leads to an error
                     invoke(l, this)
                 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/BaseAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/BaseAggregator.kt
index 452f78c..bb129dc 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/BaseAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/BaseAggregator.kt
@@ -56,7 +56,9 @@ abstract class BaseAggregator {
 
     protected fun log(logEntry: LogEntry) {
         logEntry.setUndefined("no handler found")
-        throw Throwable("[BaseAggregator.log] no handler found: ${this::class.simpleName}")
+        console.log("[BaseAggregator.log] ")
+        console.log(logEntry)
+        throw Throwable("no handler found: ${this::class.simpleName}")
     }
 
     fun TObject.getLayoutLink(): Link? {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregator.kt
index 6397569..12c0a46 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -79,8 +79,6 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
     }
 
     private fun handleObject(obj: TObject) {
-        console.log("[CA.handleObject]")
-        console.log(obj)
         dpm.addData(obj)
         invokeLayoutLink(obj, this)
 //        invokeIconLink(obj, this)
@@ -91,7 +89,6 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
     }
 
     private fun handleDomainType(obj: DomainType) {
-        console.log("[CA.handleDomainType]")
         obj.links.forEach {
             if (it.relation() == Relation.LAYOUT) {
                 invoke(it, this)
@@ -100,7 +97,6 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
         obj.members.forEach {
             val m = it.value
             if (m.isProperty()) {
-                console.log(m)
                 invoke(m, this)
             }
         }
@@ -112,12 +108,14 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
 
     private fun handleProperty(p: Property) {
         val dm = dpm as CollectionDM
-        console.log("[CA.handleProperty]")
         if (p.isPropertyDescription()) {
             dm.addPropertyDescription(p)
         } else {
             dm.addProperty(p)
-            invoke(p.descriptionLink()!!, this)
+            val pdl = p.descriptionLink()
+            if (pdl != null) {
+                invoke(pdl, this)
+            }
         }
     }
 
@@ -138,8 +136,6 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
     }
 
     private fun Property.descriptionLink(): Link? {
-        console.log("[CA.Property.descriptionLink]")
-        console.log(this)
         return links.find {
             it.relation() == Relation.ELEMENT_TYPE
         }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/DomainTypesAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/DomainTypesAggregator.kt
index fdaa6ca..2240756 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/DomainTypesAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/DomainTypesAggregator.kt
@@ -49,7 +49,6 @@ class DomainTypesAggregator(val url: String) : BaseAggregator() {
     }
 
     private fun handleAction(obj: Action) {
-        console.log(obj)
         throw Throwable("[DomainTypesAggregator.handleAction] not implemented yet")  //dsp.addData(obj)
     }
 
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 2b07b50..60e1d0f 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
@@ -30,6 +30,8 @@ import org.apache.isis.client.kroviz.to.Link
 import org.apache.isis.client.kroviz.to.Relation
 import org.apache.isis.client.kroviz.to.TransferObject
 import org.apache.isis.client.kroviz.ui.core.Constants
+import org.apache.isis.client.kroviz.ui.core.UiManager
+import org.apache.isis.client.kroviz.utils.Utils
 import kotlin.js.Date
 
 // use color codes from css instead?
@@ -63,10 +65,11 @@ data class LogEntry(
     var requestLength: Int = 0 // must be accessible (public) for LogEntryTable
     var response = ""
     var responseLength: Int = 0 // must be accessible (public) for LogEntryTable
+    var type: String = ""
 
     init {
         state = EventState.RUNNING
-        title = url // stripHostPort(url)
+        title = url
         requestLength = request?.length
                 ?: 0 // ?. is required, otherwise Tabulator.js/EventLogTable shows no entries
     }
@@ -152,8 +155,20 @@ data class LogEntry(
 
     fun setTransferObject(to: TransferObject) {
         this.obj = to
+        initType()
     }
 
+    fun initType() {
+        if (obj != null && obj is HasLinks) {
+            val self = (obj as HasLinks).getLinks().firstOrNull() { it.relation() == Relation.SELF }
+            if (self != null) {
+                val t = self.type.removePrefix("application/json;profile=\"urn:org.restfulobjects:repr-types/")
+                this.type = t.removeSuffix("\"")
+            }
+        }
+    }
+
+
     // region response
     /**
      * This is for access from the views only.
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/LogEntryDecorator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/LogEntryDecorator.kt
index 945755f..82cb8be 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/LogEntryDecorator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/LogEntryDecorator.kt
@@ -104,11 +104,9 @@ class LogEntryDecorator(val logEntry: LogEntry) {
 
     private fun findChildrenByReference(): Set<LogEntry> {
         val str = logEntry.response
-        console.log("[LED.findChildrenByReference]")
         val children = mutableSetOf<LogEntry>()
         linked.forEach {
             if (it != logEntry && str.contains(it.url)) {
-                console.log(it.url)
                 children.add(it)
             }
         }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/RoXmlHttpRequest.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/RoXmlHttpRequest.kt
index a716a09..d824b1d 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/RoXmlHttpRequest.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/event/RoXmlHttpRequest.kt
@@ -69,7 +69,7 @@ class RoXmlHttpRequest {
         xhr.open(method, url, true)
         xhr.setRequestHeader("Authorization", "Basic $credentials")
         xhr.setRequestHeader(CONTENT_TYPE, "application/$subType;charset=UTF-8")
-        xhr.setRequestHeader(ACCEPT, "application/$subType")
+        xhr.setRequestHeader(ACCEPT, "application/$subType, ${Constants.pngMimeType}")
 
         val body = buildBody(link, aggregator)
         val rs = buildResourceSpecificationAndSetupHandler(url, subType, body, xhr)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDM.kt
index 11e4fc2..21ed913 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDM.kt
@@ -30,11 +30,13 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
         if (!rawData.contains(obj)) {
             rawData.add(obj)
             val exo = Exposer(obj as TObject)
-            data.add(exo.dynamise())  //if exposer is not dynamised, data access in tables won't work
+            data.add(exo.dynamise())  //if exposer is not dynamised, data access in Tabulator tables won't work
         }
     }
 
     fun addIcon(obj: TransferObject?) {
+        console.log("[CDM.addIcon]")
+        console.log(obj)
         TODO("Not yet implemented")
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/DisplayModelWithLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/DisplayModelWithLayout.kt
index 66f6bc0..b6d9f70 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/DisplayModelWithLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/DisplayModelWithLayout.kt
@@ -34,6 +34,7 @@ abstract class DisplayModelWithLayout : DisplayModel() {
     var propertyLayoutList = mutableListOf<PropertyLt>()
 
     override fun canBeDisplayed(): Boolean {
+//        testPropertyNamesMatch()
         return when {
             isRendered -> false
             layout == null -> false
@@ -47,6 +48,23 @@ abstract class DisplayModelWithLayout : DisplayModel() {
         }
     }
 
+    /*
+    check that property names match in:
+    * propertyList
+    * propertyLayoutList
+    * propertyDescriptionList
+     */
+    fun testPropertyNamesMatch() {
+        val ps = propertyList.size
+        val pls = propertyLayoutList.size
+        val pds = propertyDescriptionList.size
+        val sizeOK = (ps >= pds) && (pds >= pls)
+        console.log("[DMWL.testPropertyNamesMatch] $sizeOK")
+        console.log(propertyList)
+        console.log(propertyLayoutList)
+        console.log(propertyDescriptionList)
+    }
+
     fun addLayout(layout: Layout) {
         this.layout = layout
         initPropertyLayoutList(layout)
@@ -62,6 +80,8 @@ abstract class DisplayModelWithLayout : DisplayModel() {
         r.cols.forEach { cs ->
             val c = cs.getCol()
             c.fieldSet.forEach { fs ->
+                console.log("[DMWL.initLayout4Row]")
+                console.log(fs.property)
                 propertyLayoutList.addAll(fs.property)
             }
             c.tabGroup.forEach { tg ->
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/DomainTypesHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/DomainTypesHandler.kt
index 8e3ca73..19e9188 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/DomainTypesHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/DomainTypesHandler.kt
@@ -24,8 +24,7 @@ import org.apache.isis.client.kroviz.to.DomainTypes
 import org.apache.isis.client.kroviz.to.TransferObject
 import org.apache.isis.client.kroviz.ui.core.UiManager
 
-class DomainTypesHandler : org.apache.isis.client.kroviz.handler.BaseHandler() {
-
+class DomainTypesHandler : BaseHandler() {
 
     override fun parse(response: String): TransferObject {
         return Json.decodeFromString(DomainTypes.serializer(), response)
@@ -39,5 +38,5 @@ class DomainTypesHandler : org.apache.isis.client.kroviz.handler.BaseHandler() {
             update()
         }
     }
-}
 
+}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/HttpErrorHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/HttpErrorHandler.kt
index c37b56c..1a6524e 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/HttpErrorHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/HttpErrorHandler.kt
@@ -30,7 +30,6 @@ class HttpErrorHandler : BaseHandler() {
         update()
     }
 
-    
     override fun parse(response: String): TransferObject {
         return Json.decodeFromString(HttpError.serializer(), response)
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/HttpErrorHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/IconHandler.kt
similarity index 68%
copy from incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/HttpErrorHandler.kt
copy to incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/IconHandler.kt
index c37b56c..3736ad9 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/HttpErrorHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/IconHandler.kt
@@ -18,20 +18,18 @@
  */
 package org.apache.isis.client.kroviz.handler
 
-import kotlinx.serialization.json.Json
-import org.apache.isis.client.kroviz.core.aggregator.ErrorDispatcher
-import org.apache.isis.client.kroviz.to.HttpError
+import org.apache.isis.client.kroviz.to.Icon
 import org.apache.isis.client.kroviz.to.TransferObject
+import org.w3c.files.Blob
 
-class HttpErrorHandler : BaseHandler() {
+class IconHandler : BaseHandler() {
 
-    override fun doHandle() {
-        logEntry.addAggregator(ErrorDispatcher())
-        update()
+    override fun canHandle(response: String): Boolean {
+        return logEntry.url.endsWith("object-icon")
     }
 
-    
-    override fun parse(response: String): TransferObject {
-        return Json.decodeFromString(HttpError.serializer(), response)
+    override fun parse(response: String): TransferObject? {
+        return Icon(response as Blob)
     }
+
 }
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 72fa0f7..0d5316b 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
@@ -23,7 +23,7 @@ import org.apache.isis.client.kroviz.layout.Layout
 import org.apache.isis.client.kroviz.to.TransferObject
 import org.apache.isis.client.kroviz.utils.XmlHelper
 
-class LayoutHandler : org.apache.isis.client.kroviz.handler.BaseHandler() {
+class LayoutHandler : BaseHandler() {
 
     override fun canHandle(response: String): Boolean {
         val isJsonLayout = !XmlHelper.isXml(response)
@@ -34,7 +34,7 @@ class LayoutHandler : org.apache.isis.client.kroviz.handler.BaseHandler() {
         return false
     }
 
-    
+
     override fun parse(response: String): TransferObject {
         return Json.decodeFromString(Layout.serializer(), response)
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/LayoutXmlHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/LayoutXmlHandler.kt
index ec1ddad..89af96d 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/LayoutXmlHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/LayoutXmlHandler.kt
@@ -22,7 +22,7 @@ import org.apache.isis.client.kroviz.to.TransferObject
 import org.apache.isis.client.kroviz.to.bs3.Grid
 import org.apache.isis.client.kroviz.utils.XmlHelper
 
-class LayoutXmlHandler : org.apache.isis.client.kroviz.handler.BaseHandler() {
+class LayoutXmlHandler : BaseHandler() {
 
     override fun canHandle(response: String): Boolean {
         val isLayoutXml = XmlHelper.isXml(response)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResponseHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResponseHandler.kt
index 316cc47..7391cf0 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResponseHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResponseHandler.kt
@@ -47,6 +47,7 @@ object ResponseHandler {
     private var _12 = DomainTypesHandler()
     private var _13 = DomainTypeHandler()
     private var _14 = DiagramHandler()
+    private var _15 = IconHandler()
     private var last = DefaultHandler()
 
     init {
@@ -69,7 +70,8 @@ object ResponseHandler {
         _11.successor = _12
         _12.successor = _13
         _13.successor = _14
-        _14.successor = last
+        _14.successor = _15
+        _15.successor = last
     }
 
     fun handle(logEntry: LogEntry) {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/Icon.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/Icon.kt
index e7bd8ec..2a41dba 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/Icon.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/Icon.kt
@@ -1,6 +1,8 @@
 package org.apache.isis.client.kroviz.to
 
+import kotlinx.serialization.Contextual
 import kotlinx.serialization.Serializable
+import org.w3c.files.Blob
 
 @Serializable
-data class Icon(val image: String) : TransferObject
+data class Icon(@Contextual val image: Blob) : TransferObject
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 0f8841d..8d6f16d 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
@@ -29,12 +29,8 @@ class FieldSet(node: Node) {
 
     init {
         val dyNode = node.asDynamic()
-        if (dyNode.hasOwnProperty("name")) {
-            name = dyNode.getAttribute("name") as String
-        }
-        if (dyNode.hasOwnProperty("id")) {
-            id = dyNode.getAttribute("id") as String
-        }
+        name = dyNode.getAttribute("name") as String
+        id = dyNode.getAttribute("id") as String
 
         val nl = node.childNodes.asList()
         val actList = nl.filter { it.nodeName.equals("cpt:action") }
@@ -46,7 +42,9 @@ class FieldSet(node: Node) {
         val pNl = nl.filter { it.nodeName.equals("cpt:property") }
         for (n: Node in pNl) {
             val p = Property(n)
-            propertyList.add(p)
+            if (p.hidden != "") {
+                propertyList.add(p)
+            }
         }
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/Property.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/Property.kt
index e42ee6e..9485d6a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/Property.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/bs3/Property.kt
@@ -35,9 +35,7 @@ class Property(node: Node) {
 
     init {
         val dn = node.asDynamic()
-        if (dn.hasOwnProperty("hidden")) {
-            id = dn.getAttribute("hidden") as String
-        }
+        id = dn.getAttribute("hidden")
         id = dn.getAttribute("id") as String
         typicalLength = dn.getAttribute("typicalLength")
         multiLine = dn.getAttribute("multiLine")
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/builder/ColBuilder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/builder/ColBuilder.kt
index dddb061..91876ad 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/builder/ColBuilder.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/builder/ColBuilder.kt
@@ -45,6 +45,8 @@ class ColBuilder : UiBuilder() {
         for (fs in col.fieldSetList) {
             val fsCpt = FieldSetBuilder().create(fs, tObject, dsp)!!
             val fsPanel = FieldsetPanel(legend = fs.name).add(fsCpt)
+            val tto = TooltipOptions(title = fs.id)
+            fsPanel.enableTooltip(tto)
             panel.add(fsPanel)
         }
         for (row in col.rowList) {
@@ -53,14 +55,15 @@ class ColBuilder : UiBuilder() {
         }
         for (c in col.collectionList) {
             console.log("[CB.create]")
-            console.log(c)
             // analogous to UiManager.openCollectionView
             val key = c.id  // entities
             val objectDM = dsp.displayModel
             val collectionDM = objectDM.collections.get(key)!!
-            console.log(collectionDM)
+            console.log(collectionDM.grid)
+            console.log(collectionDM.layout)
             val tblCpt = RoTable(collectionDM)
-            panel.add(tblCpt)
+            val fsPanel = FieldsetPanel(legend = key).add(tblCpt)
+            panel.add(fsPanel)
             collectionDM.isRendered = true
         }
         return panel
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/ColumnFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/ColumnFactory.kt
index bb8dbcd..6c3b951 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/ColumnFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/ColumnFactory.kt
@@ -18,9 +18,6 @@
  */
 package org.apache.isis.client.kroviz.ui.core
 
-import org.apache.isis.client.kroviz.core.event.EventStore
-import org.apache.isis.client.kroviz.core.model.Exposer
-import org.apache.isis.client.kroviz.core.model.CollectionDM
 import io.kvision.html.Button
 import io.kvision.html.ButtonStyle
 import io.kvision.tabulator.Align
@@ -29,6 +26,9 @@ import io.kvision.tabulator.Editor
 import io.kvision.tabulator.Formatter
 import io.kvision.tabulator.js.Tabulator
 import io.kvision.utils.obj
+import org.apache.isis.client.kroviz.core.event.EventStore
+import org.apache.isis.client.kroviz.core.model.CollectionDM
+import org.apache.isis.client.kroviz.core.model.Exposer
 
 /**
  * Create ColumnDefinitions for Tabulator tables
@@ -53,17 +53,18 @@ class ColumnFactory {
             displayCollection: CollectionDM,
             withCheckBox: Boolean = false): List<ColumnDefinition<dynamic>> {
 
+        console.log("[CF.buildColumns]")
+        console.log(displayCollection)
         val columns = mutableListOf<ColumnDefinition<dynamic>>()
         if (withCheckBox) {
             val checkBox = buildCheckBox()
             columns.add(checkBox)
         }
 
-        val menu = buildMenu()
-        columns.add(menu)
+        if (hasIcon(displayCollection)) {
+            val menu = buildMenu()
+            columns.add(menu)
 
-        val model = displayCollection.data as List<dynamic>
-        if (model[0].hasOwnProperty("iconName") as Boolean) {
             val icon = buildLinkIcon()
             columns.add(icon)
         }
@@ -84,6 +85,11 @@ class ColumnFactory {
         return columns
     }
 
+    private fun hasIcon(displayCollection: CollectionDM): Boolean {
+        val model = displayCollection.data as List<dynamic>
+        return (model[0].hasOwnProperty("iconName") as Boolean)
+    }
+
     private fun buildLinkIcon(): ColumnDefinition<Exposer> {
         return ColumnDefinition<dynamic>(
                 "",
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/Constants.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/Constants.kt
index 2165c4a..8e7207a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/Constants.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/Constants.kt
@@ -23,6 +23,7 @@ object Constants {
     const val restInfix = "restful/"
     const val stdMimeType = "text/plain"
     const val svgMimeType = "image/svg+xml"
+    const val pngMimeType = "image/png"
     const val xmlMimeType = "application/xml"
     const val calcHeight = "calc(100vh - 88px)"
     const val actionSeparator = "\n"
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/FormPanelFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/FormPanelFactory.kt
index 2c6b4d5..833c45f 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/FormPanelFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/FormPanelFactory.kt
@@ -203,7 +203,7 @@ class FormPanelFactory(items: List<FormItem>) : VPanel() {
         }
         panel.height = auto
         panel.width = auto
-        panel.overflow = Overflow.SCROLL
+        panel.overflow = Overflow.AUTO
         return panel
     }
 
@@ -211,7 +211,7 @@ class FormPanelFactory(items: List<FormItem>) : VPanel() {
         val panel = SvgPanel()
         panel.height = auto
         panel.width = auto
-        panel.overflow = Overflow.SCROLL
+        panel.overflow = Overflow.AUTO
         fi.callBack = panel
         return panel
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/MenuFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/MenuFactory.kt
index a1c0f4c..03df4db 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/MenuFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/MenuFactory.kt
@@ -53,8 +53,6 @@ object MenuFactory {
             val link = buildActionLink(it.id, text)
             val invokeLink = it.getInvokeLink()!!
             link.onClick {
-                console.log("[MF.buildForObject]")
-                console.log(invokeLink)
                 RoXmlHttpRequest().invoke(invokeLink)
             }
             dd.add(link)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/UiManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/UiManager.kt
index 47c95cf..7809922 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/UiManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/UiManager.kt
@@ -113,8 +113,6 @@ object UiManager {
     }
 
     fun closeView(tab: SimplePanel) {
-        console.log("[UM.closeView]")
-        console.log(tab)
         val tt = tab.title
         if (tt != null) {
             EventStore.closeView(tt)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/dialog/DiagramDialog.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/dialog/DiagramDialog.kt
index 02eb6f5..447b97a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/dialog/DiagramDialog.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/dialog/DiagramDialog.kt
@@ -47,6 +47,7 @@ class DiagramDialog(
 
         dialog = RoDialog(
                 widthPerc = 80,
+                heightPerc = 80,
                 caption = "Diagram",
                 items = formItems,
                 command = this,
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/EventLogTable.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/EventLogTable.kt
index 37c119b..15ca0a1 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/EventLogTable.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/EventLogTable.kt
@@ -27,15 +27,20 @@ import io.kvision.tabulator.*
 import io.kvision.utils.obj
 import io.kvision.utils.px
 import org.apache.isis.client.kroviz.core.event.LogEntry
+import org.apache.isis.client.kroviz.to.HasLinks
+import org.apache.isis.client.kroviz.to.Relation
 import org.apache.isis.client.kroviz.to.TObject
+import org.apache.isis.client.kroviz.to.TransferObject
 import org.apache.isis.client.kroviz.ui.core.Constants
+import org.apache.isis.client.kroviz.ui.core.UiManager
 import org.apache.isis.client.kroviz.ui.dialog.EventLogDetail
+import org.apache.isis.client.kroviz.utils.Utils
 
 class EventLogTable(val model: List<LogEntry>) : VPanel() {
     val tabulator: Tabulator<LogEntry>
 
     private val columns = listOf(
-            ColumnDefinition(
+            ColumnDefinition<LogEntry>(
                     download = false,
                     title = "",
                     field = "state",
@@ -44,17 +49,24 @@ class EventLogTable(val model: List<LogEntry>) : VPanel() {
                     hozAlign = Align.CENTER,
                     formatterComponentFunction = { _, _, data -> buildActionButton(data) }
             ),
-            ColumnDefinition<LogEntry>(
+            ColumnDefinition(
                     download = false,
                     title = "Title",
                     field = "title",
                     headerFilter = Editor.INPUT,
-                    width = "450",
+                    width = "700",
                     formatterComponentFunction = { _, _, data -> buildObjectButton(data) }
             ),
+            ColumnDefinition(
+                    download = false,
+                    title = "Type",
+                    field = "type",
+                    headerFilter = Editor.INPUT,
+                    width = "200"
+            ),
             ColumnDefinition("State", "state", width = "100", headerFilter = Editor.INPUT, download = false),
             ColumnDefinition("Method", "method", width = "100", headerFilter = Editor.INPUT, download = false),
-            ColumnDefinition<LogEntry>(
+            ColumnDefinition(
                     download = false,
                     title = "# of Agg.",
                     field = "nOfAggregators",
@@ -66,7 +78,9 @@ class EventLogTable(val model: List<LogEntry>) : VPanel() {
                     title = "response",
                     field = "response",
                     headerFilter = Editor.INPUT,
-                    width = "200"),
+                    width = "200",
+//                    tooltip = { (data) -> data.response }
+            ),
             ColumnDefinition("resp.len", field = "responseLength", width = "100", hozAlign = Align.RIGHT, download = false),
             ColumnDefinition("cacheHits", field = "cacheHits", width = "100", hozAlign = Align.RIGHT, download = false),
             ColumnDefinition("duration", field = "duration", width = "100", hozAlign = Align.RIGHT, download = false),
@@ -90,16 +104,30 @@ class EventLogTable(val model: List<LogEntry>) : VPanel() {
 
     private fun buildObjectButton(data: LogEntry): Button {
         val b = Button(
-                text = data.title,
+                text = shorten(data.title),
                 icon = data.state.iconName,
                 style = ButtonStyle.LINK)
         b.onClick {
-            console.log(data)
+            kotlinx.browser.window.open(data.title) //IMPROVE should be URL
         }
+        val tto = TooltipOptions(title = data.title)
+        b.enableTooltip(tto)
         if (data.obj is TObject) b.setDragDropData(Constants.stdMimeType, data.url)
         return b
     }
 
+    fun shorten(url: String): String {
+        var result = url
+        val signature = Constants.restInfix
+        if (url.contains(signature)) {
+            // strip off protocol, host, port
+            val protocolHostPort = UiManager.getUrl()
+            result = result.replace(protocolHostPort + signature, "")
+            result = Utils.removeHexCode(result)
+        }
+        return result
+    }
+
     private fun buildActionButton(data: LogEntry): Button {
         val b = Button(
                 text = "",
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/ACTIONS_STRINGS_INVOKE.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/ACTIONS_STRINGS_INVOKE.kt
index cfc56fb..c61c613 100644
--- a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/ACTIONS_STRINGS_INVOKE.kt
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/ACTIONS_STRINGS_INVOKE.kt
@@ -81,7 +81,7 @@ object ACTIONS_STRINGS_INVOKE : Response() {
       "value": "<div class=\"paragraph\">\n<p>The framework has built-in support for the <code>String</code> data type.</p>\n</div>\n<div class=\"paragraph\">\n<p>From here you can:</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>navigate to an entity that uses the <code>String</code> datatype</p>\n</li>\n<li>\n<p>open a view model that uses the <code>String</code> datatype</p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>Some properties on these domain objects are mandatory,  [...]
       "format": "string",
       "extensions": {
-        "x-isis-format": "string"
+        "": "string"
       },
       "disabledReason": "Contributed property"
     },