From 6ab20963063132de5340822f8d95045f387e86e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20tom=20W=C3=B6rden?= <h.tomwoerden@indiscale.com>
Date: Sun, 8 Oct 2023 10:07:58 +0200
Subject: [PATCH 1/4] FIX: trim whitespace around timestamp

---
 CHANGELOG.md          | 1 +
 src/core/js/caosdb.js | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d731af58..0cce5a25 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -50,6 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
   [caosdb-webui#226](https://gitlab.com/caosdb/caosdb-webui/-/issues/226)
 * Fixed broken download of referenced files in the export of select statements.
   https://gitlab.com/linkahead/linkahead-webui/-/issues/238
+* Fixed breaking timestamps due to whitespace [caosdb-webui#239](https://gitlab.com/caosdb/caosdb-webui/-/issues/239)
 
 ### Security ###
 
diff --git a/src/core/js/caosdb.js b/src/core/js/caosdb.js
index c0eacab9..a5483d64 100644
--- a/src/core/js/caosdb.js
+++ b/src/core/js/caosdb.js
@@ -376,7 +376,8 @@ var getAllEntityPermissions = function (entity) {
  */
 function caosdb2InputDate(text) {
     if (text.includes("T")) {
-        var spl = text.split("T");
+        var spl = text.trim().split("T");
+        //TODO subsecond resolution is IGNORED!!!
         return [spl[0], spl[1].substring(0, 8)];
     }
     return [text];
-- 
GitLab


From d29f7c47f7d94152fb9e4739ea4471a417ffba5d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20tom=20W=C3=B6rden?= <h.tomwoerden@indiscale.com>
Date: Sun, 8 Oct 2023 11:56:58 +0200
Subject: [PATCH 2/4] FIX: preserver subsec resolution

---
 src/core/js/caosdb.js    | 14 +++++++++++---
 src/core/js/edit_mode.js |  7 ++++---
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/src/core/js/caosdb.js b/src/core/js/caosdb.js
index a5483d64..5eb53a46 100644
--- a/src/core/js/caosdb.js
+++ b/src/core/js/caosdb.js
@@ -335,8 +335,12 @@ var getEntityIdVersion = function (entity) {
  * @param time A time
  * @return A CaosDB compatible representation.
  */
-function input2caosdbDate(date, time) {
-    return date + "T" + time;
+function input2caosdbDate(date, time, subsec) {
+    let res = date + "T" + time;
+    if (subsec!=""){
+        res = res +"." + subsec;
+    }
+    return  res
 }
 
 /**
@@ -377,8 +381,12 @@ var getAllEntityPermissions = function (entity) {
 function caosdb2InputDate(text) {
     if (text.includes("T")) {
         var spl = text.trim().split("T");
+        var subsec=""
+        if (spl[1].includes(".")) {
+            subsec = spl[1].split('.')[1]
+        }
         //TODO subsecond resolution is IGNORED!!!
-        return [spl[0], spl[1].substring(0, 8)];
+        return [spl[0], spl[1].substring(0, 8), subsec];
     }
     return [text];
 }
diff --git a/src/core/js/edit_mode.js b/src/core/js/edit_mode.js
index d9c5d193..beff84e1 100644
--- a/src/core/js/edit_mode.js
+++ b/src/core/js/edit_mode.js
@@ -513,8 +513,9 @@ var edit_mode = new function () {
         var _parse_single_datetime = function (field) {
             let time = $(field).find(":input[type='time']").val()
             let date = $(field).find(":input[type='date']").val();
+            let subsec = $(field).find(":input[type='time']").attr('subsec');
             if (time) {
-                return input2caosdbDate(date, time);
+                return input2caosdbDate(date, time, subsec);
             } else {
                 return date;
             }
@@ -975,10 +976,10 @@ var edit_mode = new function () {
                 dateandtime = caosdb2InputDate(property.value);
             }
             let date = dateandtime[0];
-            if (dateandtime.length == 2) {
+            if (dateandtime.length > 1) {
                 let time = dateandtime[1];
                 result = "<span><input type='date' value='" + date + "'/>" +
-                    "<input type='time' value='" + time + "'/></span>";
+                    "<input type='time' subsec='"+dateandtime[2]+"' value='" + time + "'/></span>";
             } else if (property.value && ((property.name || "").toLowerCase() == "year" || (date.match(/-/g) || []).length == 0)) {
                 // Year
                 result = "<input type='number' value='" + date + "'/>";
-- 
GitLab


From 663d105d3a9bd0b3c8905c17d705f6ec622e6836 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20tom=20W=C3=B6rden?= <h.tomwoerden@indiscale.com>
Date: Mon, 9 Oct 2023 21:09:39 +0200
Subject: [PATCH 3/4] DOC: add in code documentation

---
 src/core/js/caosdb.js    | 9 +++++----
 src/core/js/edit_mode.js | 2 ++
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/core/js/caosdb.js b/src/core/js/caosdb.js
index 5eb53a46..e834c3f7 100644
--- a/src/core/js/caosdb.js
+++ b/src/core/js/caosdb.js
@@ -330,9 +330,11 @@ var getEntityIdVersion = function (entity) {
 }
 
 /**
- * Take a date and a time and format it into a CaosDB compatible representation.
+ * Take a date, a time and subseconds and format it into a CaosDB compatible representation.
  * @param date A date
  * @param time A time
+ * @param subsec fractions of a seconds part of the time stamp; Must be empty
+ *               string if not used
  * @return A CaosDB compatible representation.
  */
 function input2caosdbDate(date, time, subsec) {
@@ -370,13 +372,13 @@ var getAllEntityPermissions = function (entity) {
 }
 
 /**
- * Take a datetime from caosdb and return a date and a time
+ * Take a datetime from caosdb and return a date, a time and the subseconds
  * suitable for html inputs.
  *
  * If the text contains only a date it is returned.
  *
  * @param text The string from CaosDB.
- * @return A new string for the input element.
+ * @return A list of strings for the input elements.
  */
 function caosdb2InputDate(text) {
     if (text.includes("T")) {
@@ -385,7 +387,6 @@ function caosdb2InputDate(text) {
         if (spl[1].includes(".")) {
             subsec = spl[1].split('.')[1]
         }
-        //TODO subsecond resolution is IGNORED!!!
         return [spl[0], spl[1].substring(0, 8), subsec];
     }
     return [text];
diff --git a/src/core/js/edit_mode.js b/src/core/js/edit_mode.js
index beff84e1..1148f0cb 100644
--- a/src/core/js/edit_mode.js
+++ b/src/core/js/edit_mode.js
@@ -513,6 +513,7 @@ var edit_mode = new function () {
         var _parse_single_datetime = function (field) {
             let time = $(field).find(":input[type='time']").val()
             let date = $(field).find(":input[type='date']").val();
+            // subseconds are stored in the subsec attribue of the input element
             let subsec = $(field).find(":input[type='time']").attr('subsec');
             if (time) {
                 return input2caosdbDate(date, time, subsec);
@@ -978,6 +979,7 @@ var edit_mode = new function () {
             let date = dateandtime[0];
             if (dateandtime.length > 1) {
                 let time = dateandtime[1];
+                // subseconds are stored in the subsec attribue of the input element
                 result = "<span><input type='date' value='" + date + "'/>" +
                     "<input type='time' subsec='"+dateandtime[2]+"' value='" + time + "'/></span>";
             } else if (property.value && ((property.name || "").toLowerCase() == "year" || (date.match(/-/g) || []).length == 0)) {
-- 
GitLab


From f6bd17b659b1aedd4977502cc14302503e47f2af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20tom=20W=C3=B6rden?= <h.tomwoerden@indiscale.com>
Date: Tue, 10 Oct 2023 09:45:29 +0200
Subject: [PATCH 4/4] TST: add unit test for two functions

---
 test/core/js/modules/caosdb.js.js | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/test/core/js/modules/caosdb.js.js b/test/core/js/modules/caosdb.js.js
index d4b4c509..2e98e341 100644
--- a/test/core/js/modules/caosdb.js.js
+++ b/test/core/js/modules/caosdb.js.js
@@ -661,3 +661,19 @@ QUnit.test("getPropertyFromElement", async function(assert) {
     });
 
 });
+
+QUnit.test("input2caosdbDate", function(assert) {
+    assert.ok(input2caosdbDate);
+    assert.equal(input2caosdbDate("2023-10-18","10:10:10", "1234"), "2023-10-18T10:10:10.1234")
+    assert.equal(input2caosdbDate("2023-10-18","10:10:10", ""), "2023-10-18T10:10:10")
+});
+
+QUnit.test("caosdb2InputDate", function(assert) {
+    assert.ok(caosdb2InputDate);
+    arr1 = caosdb2InputDate("2023-10-18T10:10:10.1234")
+    arr2=["2023-10-18","10:10:10", "1234"]
+    assert.ok(arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]))
+    assert.ok(arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]))
+    arr1 = caosdb2InputDate("2023-10-18T10:10:10")
+    arr2=["2023-10-18","10:10:10", ""]
+});
-- 
GitLab