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/11/30 13:43:55 UTC

[isis] branch master updated (5d73a3e -> 30552bb)

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

joergrade pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git.


    from 5d73a3e  ISIS-2903: adds reg. test for Jaxb viewmodel w/ JPA entities embedded
     new 41d110a  ISIS-2348 EventComparison with response diff
     new 8deeff0  ISIS-2348 EventComparison with response diff
     new 30552bb  Merge branch 'master' of https://github.com/apache/isis

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/build.gradle.kts          |  2 +
 .../client/kroviz/core/event/RoXmlHttpRequest.kt   | 13 +++++-
 .../kroviz/ui/dialog/ResponseComparisonDialog.kt   | 52 +++++++++++-----------
 .../client/kroviz/utils/{Flatted.kt => Diff.kt}    | 11 +++--
 .../kroviz/utils/{Flatted.kt => Diff2Html.kt}      |  8 ++--
 incubator/clients/kroviz/src/main/web/index.html   |  1 +
 6 files changed, 53 insertions(+), 34 deletions(-)
 copy incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/{Flatted.kt => Diff.kt} (80%)
 copy incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/{Flatted.kt => Diff2Html.kt} (87%)

[isis] 02/03: ISIS-2348 EventComparison with response diff

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

joergrade pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 8deeff00b91782b007871863ef9094f5bc3a1717
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Tue Nov 30 14:43:15 2021 +0100

    ISIS-2348 EventComparison with response diff
---
 .../client/kroviz/core/event/RoXmlHttpRequest.kt   | 13 ++++++++++-
 .../apache/isis/client/kroviz/utils/Diff2HtmlUI.kt | 27 ----------------------
 2 files changed, 12 insertions(+), 28 deletions(-)

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 2a0b544..72296e8 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
@@ -28,6 +28,7 @@ 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.StringUtils
 import org.apache.isis.client.kroviz.utils.UrlUtils
+import org.apache.isis.client.kroviz.utils.XmlHelper
 import org.w3c.xhr.BLOB
 import org.w3c.xhr.TEXT
 import org.w3c.xhr.XMLHttpRequest
@@ -125,7 +126,17 @@ class RoXmlHttpRequest(val aggregator: BaseAggregator?) {
     }
 
     private fun handleResult(rs: ResourceSpecification, body: String) {
-        val response: Any? = xhr.response
+        var response: Any? = xhr.response
+       if (rs.url.contains("layout")) {
+            if (rs.subType == Constants.subTypeXml) {
+               response = XmlHelper.format(response as String)
+                console.log("[RXHR.handleResult]")
+                console.log(response)
+            }
+  /*          if (rs.subType == Constants.subTypeJson) {
+                response = StringUtils.format(response as String)
+            }*/
+        }
         val le: LogEntry? = UiManager.getEventStore().end(rs, body, response)
         if (le != null) {
             when {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff2HtmlUI.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff2HtmlUI.kt
deleted file mode 100644
index 575468a..0000000
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff2HtmlUI.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.client.kroviz.utils
-
-import kotlin.js.Json
-
-@JsModule("diff2html")
-@JsNonModule
-external object Diff2HtmlUI {
-    fun html(diff: Diff, options: Json): String
-}

[isis] 03/03: Merge branch 'master' of https://github.com/apache/isis

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

joergrade pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 30552bbfb20197c565c90565160f76d38f08e031
Merge: 8deeff0 5d73a3e
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Tue Nov 30 14:43:39 2021 +0100

    Merge branch 'master' of https://github.com/apache/isis

 .../workflows/ci-build-artifacts-no-push-maven.yml |   2 +-
 .../modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc |  35 ++
 api/applib/pom.xml                                 |   6 +
 .../org/apache/isis/applib/clock/VirtualClock.java |  79 ++-
 .../org/apache/isis/applib/id/LogicalType.java     |   4 +-
 .../JavaTimeXMLGregorianCalendarMarshalling.java   |  24 +-
 .../applib/jaxb/PersistentEntitiesAdapter.java     |   6 +-
 .../isis/applib/jaxb/PersistentEntityAdapter.java  |   2 -
 .../isis/applib/services/bookmark/Bookmark.java    |  13 +-
 .../applib/services/iactn/ActionInvocation.java    |   3 +-
 .../isis/applib/services/iactn/Execution.java      |   3 +
 .../isis/applib/services/jaxb/JaxbService.java     |  19 +-
 .../services/schema/SchemaValueMarshaller.java     | 102 ++++
 .../isis/applib/util/schema/CommonDtoUtils.java    | 558 +------------------
 .../applib/util/schema/InteractionDtoUtils.java    |  79 ++-
 .../isis/applib/util/schema/_JodaTimeHelper.java   | 139 -----
 ...{ValueSemanticsResolver.java => Converter.java} |  22 +-
 .../applib/value/semantics/EncoderDecoder.java     |   3 +-
 .../isis/applib/value/semantics/OrderRelation.java |  68 +++
 .../value/semantics/TemporalValueSemantics.java    |   2 +
 .../isis/applib/value/semantics/ValueComposer.java |  25 +-
 .../value/semantics/ValueSemanticsAbstract.java    |  13 +
 .../value/semantics/ValueSemanticsProvider.java    |  10 +
 .../value/semantics/ValueSemanticsResolver.java    |  22 +-
 .../applib/util/schema/CommonDtoUtils_Test.java    |  65 +--
 .../schema/CommonDtoUtils_setValueOn_Test.java     |  89 ---
 .../apache/isis/applib/util/schema/Roundtrip.java  | 307 -----------
 api/schema/pom.xml                                 |   4 -
 .../org/apache/isis/schema/common/common-2.0.xsd   |  45 +-
 .../commons/internal/base/_Lazy_ThreadSafe.java    |   5 +-
 .../isis/commons/internal/image/_Images.java       |  23 +-
 .../config/valuetypes/ValueSemanticsRegistry.java  |  36 --
 .../core/metamodel/IsisModuleCoreMetamodel.java    |   6 +-
 .../_testing/MetaModelContext_forTesting.java      |  20 +-
 .../metamodel/consent/InteractionInitiatedBy.java  |  28 +-
 .../actions/action/ActionOverloadingValidator.java |   4 +-
 ...ctionInvocationFacetForDomainEventAbstract.java | 102 ++--
 .../{CommandUtil.java => IdentifierUtil.java}      | 104 ++--
 .../publish/command/CommandPublishingFacet.java    |   4 +-
 ...ableObjectFacetForXmlRootElementAnnotation.java |  25 +-
 .../metamodel/facets/object/value/ValueFacet.java  |   6 +
 .../facets/object/value/ValueFacetAbstract.java    |  14 +
 ...ionOrAnyMatchingValueSemanticsFacetFactory.java |  20 +-
 .../method/PropertyChoicesFacetViaMethod.java      |  10 -
 .../interactions/managed/ManagedAction.java        |  11 +-
 .../interactions/managed/ManagedMember.java        |   6 +-
 .../managed/nonscalar/DataTableModel.java          |  13 +-
 .../identify/ObjectBookmarker_builtinHandlers.java |  28 +
 .../ObjectSpecificationPostProcessorAbstract.java  |  13 +-
 ...ectionParamDefaultsAndChoicesPostProcessor.java |   4 +-
 .../services/metamodel/MetaModelExporter.java      |   4 +-
 .../objectlifecycle/PropertyChangeRecord.java      |   4 +-
 .../spec/{ActionType.java => ActionScope.java}     |  22 +-
 .../isis/core/metamodel/spec/ManagedObjects.java   |  15 -
 .../core/metamodel/spec/ObjectSpecification.java   |   2 -
 .../core/metamodel/spec/feature/ObjectAction.java  |   8 +-
 .../spec/feature/ObjectActionContainer.java        |  77 +--
 .../spec/feature/ObjectAssociationContainer.java   |  55 +-
 .../spec/feature/memento/ActionMemento.java        |   8 +-
 .../metamodel/specloader/SpecificationLoader.java  |   7 +
 .../specloader/SpecificationLoaderDefault.java     |  18 +-
 .../specloader/specimpl/ObjectActionDefault.java   |  26 +-
 .../specloader/specimpl/ObjectMemberContainer.java |  26 +-
 .../specimpl/ObjectSpecificationAbstract.java      |  30 +-
 .../specimpl/dflt/ObjectSpecificationDefault.java  |  23 +-
 .../valuesemantics/BookmarkValueSemantics.java     |  36 +-
 .../BufferedImageValueSemantics.java               |  21 +
 .../LocalResourcePathValueSemantics.java           |   2 +-
 .../valuesemantics/MarkupValueSemantics.java       |   2 +-
 .../valuesemantics/OidDtoValueSemantics.java       |  69 +--
 .../valuesemantics/URLValueSemantics.java          |   2 +-
 .../valuesemantics/UUIDValueSemantics.java         |   2 +-
 .../temporal/LocalDateTimeValueSemantics.java      |  12 +-
 .../temporal/LocalDateValueSemantics.java          |  12 +-
 .../temporal/LocalTimeValueSemantics.java          |   8 +
 .../temporal/OffsetDateTimeValueSemantics.java     |   8 +
 .../temporal/OffsetTimeValueSemantics.java         |   8 +
 .../temporal/TemporalValueSemanticsProvider.java   |  33 +-
 .../temporal/ZonedDateTimeValueSemantics.java      |   8 +
 .../temporal/legacy/JavaSqlDateValueSemantics.java |  11 +-
 .../legacy/JavaSqlTimeStampValueSemantics.java     |  10 +-
 .../temporal/legacy/JavaSqlTimeValueSemantics.java |  10 +-
 .../legacy/JavaUtilDateValueSemantics.java         |  10 +-
 .../valuetypes/TemporalSemanticsAdapter.java       |  21 +-
 .../valuetypes/ValueSemanticsAdapter.java          |  51 +-
 ...ult.java => ValueSemanticsResolverDefault.java} |  16 +-
 .../testspec/ObjectSpecificationStub.java          |  32 +-
 core/pom.xml                                       |   8 +-
 .../IsisModuleCoreRuntimeServices.java             |   2 +
 .../command/CommandDtoFactoryDefault.java          |  49 +-
 .../command/CommandExecutorServiceDefault.java     |  73 ++-
 .../command/SchemaValueMarshallerDefault.java      | 596 +++++++++++++++++++++
 .../executor/MemberExecutorServiceDefault.java     |  36 +-
 .../interaction/InteractionDtoFactoryDefault.java  |  10 +-
 .../runtimeservices/jaxb/JaxbServiceDefault.java   |  46 +-
 .../runtimeservices/memento/_ObjectMemento.java    |   6 +-
 .../menubars/bootstrap3/MenuBarsServiceBS3.java    |   8 +-
 .../sitemap/SitemapServiceDefault.java             |   6 +-
 .../wrapper/WrapperFactoryDefault.java             |   9 +-
 examples/demo/domain/pom.xml                       |   2 +-
 .../viewmodels/jaxbrefentity/JaxbRefEntity.java    |  12 +-
 .../viewmodels/jaxbrefentity/jdo/JaxbRefJdo.java   |   2 -
 .../viewmodels/jaxbrefentity/jpa/JaxbRefJpa.java   |   2 -
 .../strings/samples/JavaLangStringSamples.java     |  40 --
 examples/demo/pom.xml                              |   2 +-
 examples/demo/vaadin/pom.xml                       |   2 +-
 .../java/demoapp/web/DemoAppManifestCommon.java    |   6 +-
 extensions/pom.xml                                 |   5 +
 extensions/security/secman/applib/pom.xml          |   5 +
 .../dom/ApplicationUserRepositoryAbstract.java     |  35 +-
 .../dom/mixins/ApplicationUser_updatePassword.java |  13 +-
 .../security/secman/encryption-jbcrypt/pom.xml     |   2 -
 .../IsisModuleExtSecmanEncryptionJbcrypt.java      |   4 +-
 ...crypt.java => PasswordEncoderUsingJBcrypt.java} |  23 +-
 .../pom.xml                                        |  15 +-
 .../IsisModuleExtSecmanEncryptionSpring.java       |  58 ++
 .../authenticator/AuthenticatorSecman.java         |  24 +-
 .../AuthenticatorSecmanAutoConfiguration.java      |   8 +-
 extensions/security/secman/pom.xml                 |   1 +
 .../shiro/IsisModuleExtSecmanShiroRealm.java       |  24 +-
 .../ui/component/EventProviderAbstract.java        |   4 +-
 isis-parent/pom.xml                                |   2 +-
 .../isis/extensions/restclient/ResponseDigest.java |  26 +-
 .../applib/IsisBookmarkConverter.java              |   2 +-
 .../_EntityPropertyChangeFactory.java              |   4 +-
 regressiontests/incubating/pom.xml                 |   2 +-
 .../isis/testdomain/shiro/ShiroSecmanLdapTest.java |   4 +-
 .../shiro/ShiroSecmanLdap_restfulStressTest.java   |   4 +-
 .../isis/testdomain/shiro/ShiroSecmanTest.java     |   4 +-
 .../testdomain/interact/ActionInteractionTest.java |   6 +-
 .../testdomain/persistence/jdo/JdoJaxbTest.java    |  94 ++++
 .../testdomain/persistence/jpa/JpaJaxbTest.java    |  94 ++++
 .../isis/testdomain/value/ValueSemanticsTest.java  | 206 ++++---
 .../testdomain/value/ValueSemanticsTester.java     |  68 ++-
 regressiontests/stable/pom.xml                     |  15 +
 .../testdomain/conf/Configuration_headless.java    |   5 +-
 .../isis/testdomain/jdo/JdoInventoryJaxbVm.java    |  95 ++++
 .../isis/testdomain/jpa/JpaInventoryJaxbVm.java    |  77 +++
 .../valuetypes/Configuration_usingValueTypes.java  |   8 +-
 .../model/valuetypes/ValueTypeExample.java         | 417 ++++++++++++--
 .../model/valuetypes/ValueTypeExampleService.java  |  31 ++
 .../interaction/DomainObjectTesterFactory.java     |   3 +-
 starters/pom.xml                                   |   2 +-
 subdomains/poi/pom.xml                             |  10 +
 testing/specsupport/applib/pom.xml                 |  70 ++-
 tooling/pom.xml                                    |   4 +-
 valuetypes/asciidoc/ui/pom.xml                     |   2 +-
 valuetypes/jodatime/applib/pom.xml                 |   8 +
 ...timeConverters.java => JodaTimeConverters.java} |   6 +-
 .../applib/value/JodaTimeConvertersTest.java       |  92 ++++
 .../valuesemantics/JodaDateTimeValueSemantics.java |  16 +-
 .../JodaLocalDateTimeValueSemantics.java           |  16 +-
 .../JodaLocalDateValueSemantics.java               |  16 +-
 .../JodaLocalTimeValueSemantics.java               |  27 +-
 .../domainobjects/ObjectActionReprRenderer.java    |   2 +-
 ...entNegotiationServiceForRestfulObjectsV1_0.java |   6 +-
 .../service/swagger/internal/Caching.java          |   2 +-
 .../service/swagger/internal/Generation.java       |  50 +-
 .../swagger/internal/{Util.java => _Util.java}     |  45 +-
 .../viewer/wicket/model/models/EntityModel.java    |   3 +-
 .../wicket/model/models/ScalarParameterModel.java  |   4 +-
 .../interaction/prop/PropertyInteractionWkt.java   |   5 +-
 .../wicket/model/util/PageParameterUtils.java      |  11 +-
 .../ui/components/scalars/ConverterTester.java     |  23 +-
 .../jodatime/JodaDateTimeConverterTest.java        |   2 +-
 .../jdk8time/OffsetDateTimeConverterTest.java      |   2 +-
 166 files changed, 3299 insertions(+), 2370 deletions(-)

[isis] 01/03: ISIS-2348 EventComparison with response diff

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

joergrade pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 41d110a963ee5d9dacb069814b334645a37720bb
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Fri Nov 26 18:10:27 2021 +0100

    ISIS-2348 EventComparison with response diff
---
 incubator/clients/kroviz/build.gradle.kts          |  2 +
 .../kroviz/ui/dialog/ResponseComparisonDialog.kt   | 52 +++++++++++-----------
 .../org/apache/isis/client/kroviz/utils/Diff.kt    | 30 +++++++++++++
 .../apache/isis/client/kroviz/utils/Diff2Html.kt   | 27 +++++++++++
 .../apache/isis/client/kroviz/utils/Diff2HtmlUI.kt | 27 +++++++++++
 incubator/clients/kroviz/src/main/web/index.html   |  1 +
 6 files changed, 112 insertions(+), 27 deletions(-)

diff --git a/incubator/clients/kroviz/build.gradle.kts b/incubator/clients/kroviz/build.gradle.kts
index 0c3ac2f..935e657 100644
--- a/incubator/clients/kroviz/build.gradle.kts
+++ b/incubator/clients/kroviz/build.gradle.kts
@@ -102,6 +102,8 @@ kotlin {
         implementation("io.kvision:kvision-maps:$kvisionVersion")
         implementation(npm("xmltojson", "1.3.5", false))
         implementation(npm("flatted", "3.2.2", false))
+        implementation(npm("diff", "5.0.0", false))
+        implementation(npm("diff2html", "3.4.13", false))
     }
     sourceSets["test"].dependencies {
         implementation(kotlin("test-js"))
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/dialog/ResponseComparisonDialog.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/dialog/ResponseComparisonDialog.kt
index 7ab8970..0c5b521 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/dialog/ResponseComparisonDialog.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/dialog/ResponseComparisonDialog.kt
@@ -18,47 +18,45 @@
  */
 package org.apache.isis.client.kroviz.ui.dialog
 
-import io.kvision.core.CssSize
-import io.kvision.core.FlexDirection
-import io.kvision.core.UNIT
-import io.kvision.form.text.TextArea
-import io.kvision.panel.Direction
-import io.kvision.panel.SplitPanel
-import io.kvision.panel.VPanel
+import io.kvision.utils.obj
 import org.apache.isis.client.kroviz.core.event.LogEntryComparison
+import org.apache.isis.client.kroviz.to.ValueType
+import org.apache.isis.client.kroviz.ui.core.FormItem
 import org.apache.isis.client.kroviz.ui.core.RoDialog
+import org.apache.isis.client.kroviz.utils.Diff
+import org.apache.isis.client.kroviz.utils.Diff2Html
 
 class ResponseComparisonDialog(obj: LogEntryComparison) : Command() {
-    private val title = "Response Diff"
-
-    private val expectedPanel = VPanel(spacing = 3) {
-        width = CssSize(50, UNIT.perc)
-    }
-    private val actualPanel = VPanel(spacing = 3) {
-        width = CssSize(50, UNIT.perc)
-    }
 
     init {
+        val html = diff2Html(obj)
+        val fi = FormItem("Diff", ValueType.HTML, html, size = 30)
+        val formItems = mutableListOf<FormItem>()
+        formItems.add(fi)
+
+        val title = "Diff: " + obj.title
         dialog = RoDialog(
             caption = title,
-            items = mutableListOf(),
+            items = formItems,
             command = this,
             widthPerc = 80,
             heightPerc = 70,
             customButtons = mutableListOf()
         )
-        val expectedText = TextArea(label = "Expected", value = obj.expectedResponse, rows = 30)
-        expectedPanel.add(expectedText)
-        val actualText = TextArea(label = "Actual", value = obj.actualResponse, rows = 30)
-        actualPanel.add(actualText)
-
-        val splitPanel = SplitPanel(direction = Direction.VERTICAL)
-        splitPanel.addCssClass("dialog-content")
-        splitPanel.flexDirection = FlexDirection.ROW
-        splitPanel.add(expectedPanel)
-        splitPanel.add(actualPanel)
-        dialog.formPanel!!.add(splitPanel)
         dialog.open()
     }
 
+    private fun diff2Html(obj: LogEntryComparison): String {
+        val oldText: String = obj.expectedResponse!!
+        val newText: String = obj.actualResponse!!
+        val diff = Diff.createTwoFilesPatch("file", "file", oldText, newText);
+        val options = obj {
+            drawFileList = false
+            matching = "lines"
+            outputFormat = "line-by-line"
+        }
+        val html = Diff2Html.html(diff, options)
+        return html
+    }
+
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff.kt
new file mode 100644
index 0000000..3a13593
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff.kt
@@ -0,0 +1,30 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.client.kroviz.utils
+
+@JsModule("diff")
+@JsNonModule
+external object Diff {
+    fun createTwoFilesPatch(
+        file1: String = definedExternally,
+        file2: String = definedExternally,
+        original: String,
+        revised: String
+    ): Diff
+}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff2Html.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff2Html.kt
new file mode 100644
index 0000000..3ed2731
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff2Html.kt
@@ -0,0 +1,27 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.client.kroviz.utils
+
+import kotlin.js.Json
+
+@JsModule("diff2html")
+@JsNonModule
+external object Diff2Html {
+    fun html(diff: Diff, options: Json): String
+}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff2HtmlUI.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff2HtmlUI.kt
new file mode 100644
index 0000000..575468a
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/Diff2HtmlUI.kt
@@ -0,0 +1,27 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.client.kroviz.utils
+
+import kotlin.js.Json
+
+@JsModule("diff2html")
+@JsNonModule
+external object Diff2HtmlUI {
+    fun html(diff: Diff, options: Json): String
+}
diff --git a/incubator/clients/kroviz/src/main/web/index.html b/incubator/clients/kroviz/src/main/web/index.html
index d420ab9..b326627 100644
--- a/incubator/clients/kroviz/src/main/web/index.html
+++ b/incubator/clients/kroviz/src/main/web/index.html
@@ -6,6 +6,7 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>kroViz</title>
+    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css" />
     <script type="text/javascript" src="main.bundle.js"></script>
 </head>
 <body>