diff --git a/CHANGELOG.md b/CHANGELOG.md index eabd0f69d3867d0443c4082288e2ec375f47210f..3e4d366793be43321fa66da60851a2cb473e9186 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * `BUILD_MODULE_EXT_ENTITY_ACL_USER_MANAGEMENT_BUTTON` build variable with which a button to the user management is added to the navbar for users with role administration if `BUILD_MODULE_EXT_ENTITY_ACL=ENABLED`. +* [#202](https://gitlab.com/caosdb/caosdb-webui/-/issues/202) - handle long + text properties. Introcution of the + `BUILD_LONG_TEXT_PROPERTY_THRESHOLD_SINGLE` and + `BUILD_LONG_TEXT_PROPERTY_THRESHOLD_LIST` build variables. Any numeric + value>0 will cause text properties with values longer than the threshold to + be put into a `details` tag with a shortened summary. `DISABLED` will disable + this feature. Defaults: 140 characters for single values, 40 for list values. ### Changed (for changes in existing functionality) diff --git a/build.properties.d/00_default.properties b/build.properties.d/00_default.properties index d21943b6fc51abf370b2939a7ac8a6bad72e9a04..7b6b38a6af7ec59522e4bd07de1d8ce45330b15b 100644 --- a/build.properties.d/00_default.properties +++ b/build.properties.d/00_default.properties @@ -66,6 +66,10 @@ BUILD_EXT_REFERENCES_CUSTOM_RESOLVER=caosdb_default_person_reference BUILD_MODULE_EXT_EDITMODE_WYSIWYG_TEXT=DISABLED BUILD_MODULE_EXT_PROPERTY_DISPLAY=DISABLED +### Put long text property values into a details tag. "DISABLED" means disabled. +BUILD_LONG_TEXT_PROPERTY_THRESHOLD_LIST=40 +BUILD_LONG_TEXT_PROPERTY_THRESHOLD_SINGLE=140 + ############################################################################## # Navbar properties ############################################################################## diff --git a/src/core/css/webcaosdb.css b/src/core/css/webcaosdb.css index 248f3444962a839193016a42dc4e9f730ba7d448..ba4bedebc95f571fb09ee73dea0781cf94e7f8b3 100644 --- a/src/core/css/webcaosdb.css +++ b/src/core/css/webcaosdb.css @@ -819,3 +819,96 @@ details p { margin-right: 4px; font-size: 11px; } + +/* handle long text properties (single value) */ + +.caosdb-f-property-value details summary { + display: inline; +} + +.caosdb-f-property-value .spacer::after { + margin: 0; + content: "(show less)"; + visibility: hidden; +} + +.caosdb-f-property-value details[open] summary * { + display: none; +} + +.caosdb-f-property-value details[open] summary { + float: right; +} + +.caosdb-f-property-value details summary::after { + content: "... (show more)"; + color: blue; +} + +.caosdb-f-property-value details[open] summary::after { + content: "(show less)"; + + padding-right: calc(var(--bs-gutter-x) * .5); + position: absolute; + bottom: 0; + right: 0; +} + +/* handle long text properties (list) */ + +.caosdb-f-property-value .caosdb-value-list .spacer::after { + display: block; +} + +.caosdb-f-property-value .caosdb-value-list details summary::after { + content: "..."; +} + + +.caosdb-f-property-value .caosdb-value-list details[open] summary { + float: none; +} + +.caosdb-f-property-value .caosdb-value-list details[open] summary::after { + content: "(show less)"; + padding-right: calc(var(--bs-gutter-x) * .5); + position: absolute; + bottom: 0; + left: 0; + right: unset; +} + +.caosdb-f-property-value .caosdb-value-list details[open] { + position: relative; + max-width: 80vw; +} + +@media (min-width: 576px) { + .caosdb-f-property-value .caosdb-value-list details[open] { + max-width: 200px; + } +} + +@media (min-width: 768px) { + .caosdb-f-property-value .caosdb-value-list details[open] { + max-width: 400px; + } +} + +@media (min-width: 992px) { + .caosdb-f-property-value .caosdb-value-list details[open] { + max-width: 530px; + } +} + +@media (min-width: 1200px) { + .caosdb-f-property-value .caosdb-value-list details[open] { + max-width: 670px; + } +} + +@media (min-width: 1400px) { + .caosdb-f-property-value .caosdb-value-list details[open] { + max-width: 800px; + } +} diff --git a/src/core/xsl/entity.xsl b/src/core/xsl/entity.xsl index 3881e722608c6013b433a815f2db72a1896cd76e..ae195afc07920bce0aac84da0027911017840502 100644 --- a/src/core/xsl/entity.xsl +++ b/src/core/xsl/entity.xsl @@ -298,6 +298,7 @@ <xsl:param name="reference"/> <xsl:param name="boolean"/> <xsl:param name="datetime"/> + <xsl:param name="long-text-threshold"/> <xsl:choose> <xsl:when test="normalize-space($value)!=''"> <xsl:choose> @@ -331,23 +332,38 @@ <xsl:value-of select="$value"/> </xsl:element> </xsl:when> + <!-- DEPRECATED css class .caosdb-property-text-value - Use + .caosdb-f-property-single-raw-value or introduce new + .caosdb-v-property-text-value --> <xsl:otherwise> - <xsl:element name="span"> - <xsl:attribute name="class"> - <!-- DEPRECATED css class .caosdb-property-text-value - Use - .caosdb-f-property-single-raw-value or introduce new - .caosdb-v-property-text-value --> - <xsl:value-of select="'caosdb-f-property-single-raw-value caosdb-property-text-value caosdb-f-property-text-value caosdb-v-property-text-value'"/> - </xsl:attribute> - <xsl:call-template name="trim"> - <xsl:with-param name="str"> - <xsl:value-of select="$value"/> - </xsl:with-param> - </xsl:call-template> - </xsl:element> + <xsl:choose> + <xsl:when test="$long-text-threshold != 'DISABLED' and string-length(normalize-space($value))>$long-text-threshold"> + <details> + <span class="caosdb-f-property-single-raw-value caosdb-property-text-value caosdb-f-property-text-value caosdb-v-property-text-value"> + <xsl:call-template name="trim"> + <xsl:with-param name="str"> + <xsl:value-of select="$value"/> + </xsl:with-param> + </xsl:call-template> + </span> + <span class="spacer"></span> + <summary><div title="show more"><span class="caosdb-f-property-text-value"><xsl:value-of select="substring(normalize-space($value),0,$long-text-threshold + 1)"/></span></div></summary> + </details> + </xsl:when> + <xsl:otherwise> + <span class="caosdb-f-property-single-raw-value caosdb-property-text-value caosdb-f-property-text-value caosdb-v-property-text-value"> + <xsl:call-template name="trim"> + <xsl:with-param name="str"> + <xsl:value-of select="$value"/> + </xsl:with-param> + </xsl:call-template> + </span> + </xsl:otherwise> + </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:when> + <!-- this is for empty values --> <xsl:otherwise> <!-- DEPRECATED css class .caosdb-property-text-value - Use .caosdb-f-property-single-raw-value or introduce new @@ -416,6 +432,9 @@ <xsl:with-param name="datetime"> <xsl:value-of select="../@datatype='LIST<DATETIME>'"/> </xsl:with-param> + <xsl:with-param name="long-text-threshold"> + <xsl:value-of select="'${BUILD_LONG_TEXT_PROPERTY_THRESHOLD_LIST}'"/> + </xsl:with-param> </xsl:call-template> </xsl:element> </xsl:for-each> @@ -470,6 +489,9 @@ <xsl:with-param name="datetime"> <xsl:value-of select="@datatype='DATETIME'"/> </xsl:with-param> + <xsl:with-param name="long-text-threshold"> + <xsl:value-of select="'${BUILD_LONG_TEXT_PROPERTY_THRESHOLD_SINGLE}'"/> + </xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> diff --git a/test/core/js/modules/entity.xsl.js b/test/core/js/modules/entity.xsl.js index 04ec35a6fc14cbad81c731908e28f788999c3563..69f553c76c57143ea7b10560c304ba2ffa7da209 100644 --- a/test/core/js/modules/entity.xsl.js +++ b/test/core/js/modules/entity.xsl.js @@ -168,6 +168,27 @@ QUnit.test("single-value template with reference property.", function(assert) { assert.equal($(link).find('.caosdb-id').length, 1, 'has caosdb-id span'); }) +QUnit.test("single-value template with long text property.", function(assert) { + assert.equal(xml2str(callTemplate(this.entityXSL, 'single-value', { + 'value': 'the feature is disabled', + 'reference': 'false', + 'boolean': 'false', + 'long-text-threshold': 'DISABLED' + })), "<span xmlns=\"http://www.w3.org/1999/xhtml\" class=\"caosdb-f-property-single-raw-value caosdb-property-text-value caosdb-f-property-text-value caosdb-v-property-text-value\">the feature is disabled</span>", "disabled -> not in details tag"); + assert.equal(xml2str(callTemplate(this.entityXSL, 'single-value', { + 'value': 'this is too long', + 'reference': 'false', + 'boolean': 'false', + 'long-text-threshold': '4' + })), "<details xmlns=\"http://www.w3.org/1999/xhtml\"><span class=\"caosdb-f-property-single-raw-value caosdb-property-text-value caosdb-f-property-text-value caosdb-v-property-text-value\">this is too long</span><span class=\"spacer\"></span><summary><div title=\"show more\"><span class=\"caosdb-f-property-text-value\">this</span></div></summary></details>", "too long -> shorted to 'this'"); + assert.equal(xml2str(callTemplate(this.entityXSL, 'single-value', { + 'value': 'this is not too long', + 'reference': 'false', + 'boolean': 'false', + 'long-text-threshold': '140' + })), "<span xmlns=\"http://www.w3.org/1999/xhtml\" class=\"caosdb-f-property-single-raw-value caosdb-property-text-value caosdb-f-property-text-value caosdb-v-property-text-value\">this is not too long</span>", "not too long -> not details tag."); +}) + QUnit.test("old version warning", function(assert) { // with successor tag var xmlstr = '<Record id="2345"><Version id="abcd1234"><Successor id="bcde2345"/></Version></Record>';