diff --git a/kie-server-parent/kie-server-api/src/main/java/org/kie/server/api/marshalling/json/JSONMarshaller.java b/kie-server-parent/kie-server-api/src/main/java/org/kie/server/api/marshalling/json/JSONMarshaller.java index f992b19918..853ff02535 100644 --- a/kie-server-parent/kie-server-api/src/main/java/org/kie/server/api/marshalling/json/JSONMarshaller.java +++ b/kie-server-parent/kie-server-api/src/main/java/org/kie/server/api/marshalling/json/JSONMarshaller.java @@ -235,10 +235,16 @@ protected void configureMarshaller(Set> classes, final ClassLoader clas if (classes == null) { classes = new HashSet>(); } + // add byte array handling support to allow byte[] to be send as payload classes.add(JaxbByteArray.class); + if (!formatDate) { classes.add(Date.class); + classes.add(java.time.LocalDateTime.class); + classes.add(java.time.LocalTime.class); + classes.add(java.time.OffsetDateTime.class); + classes.add(java.time.LocalDate.class); } List customClasses = prepareCustomClasses(classes); diff --git a/kie-server-parent/kie-server-api/src/test/java/org/kie/server/api/marshalling/JSONMarshallerTest.java b/kie-server-parent/kie-server-api/src/test/java/org/kie/server/api/marshalling/JSONMarshallerTest.java index b6f7543a22..23839c410b 100644 --- a/kie-server-parent/kie-server-api/src/test/java/org/kie/server/api/marshalling/JSONMarshallerTest.java +++ b/kie-server-parent/kie-server-api/src/test/java/org/kie/server/api/marshalling/JSONMarshallerTest.java @@ -34,6 +34,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.apache.commons.io.IOUtils; import org.assertj.core.util.Arrays; import org.assertj.core.util.Files; import org.drools.core.command.runtime.BatchExecutionCommandImpl; @@ -317,4 +318,170 @@ public void testLegalizeWrapObjectFieldnames() throws Exception { BatchExecutionCommandImpl unconverted = marshaller.unmarshall(converted, BatchExecutionCommandImpl.class); assertEquals("all", ((Order) ((InsertObjectCommand) unconverted.getCommands().get(0)).getObject()).getORDER_ID()); } + + @Test + public void testLocalDateTimeWithClasses() throws Exception { + HashSet hs = new HashSet<>(); + hs.add(org.kie.server.api.marshalling.Person.class); + hs.add(org.kie.server.api.marshalling.SupportedlDate.class); + Marshaller marshaller = new JSONMarshaller(hs, getClass().getClassLoader(), false, false); + + String wrapLocalDateTimeWithType = "{\"person\":{\"org.kie.server.api.marshalling.Person\":{\"fullname\":\"123\",\"dateBirth\":{\"java.time.LocalDateTime\":\"2022-05-19T00:00\"},\"age\":\"21\"}}}"; + Map converted = marshaller.unmarshall(wrapLocalDateTimeWithType, Map.class); + assertEquals(org.kie.server.api.marshalling.Person.class, converted.get("person").getClass()); + assertEquals(java.time.LocalDateTime.class, ((Person) converted.get("person")).getDateBirth().getClass()); + + String wrapLocalDateTimeWithoutType = "{\"person\":{\"org.kie.server.api.marshalling.Person\":{\"fullname\":\"123\",\"dateBirth\":\"2022-05-19T00:00\",\"age\":\"21\"}}}"; + Map converted1 = marshaller.unmarshall(wrapLocalDateTimeWithoutType, Map.class); + assertEquals(org.kie.server.api.marshalling.Person.class, converted1.get("person").getClass()); + assertEquals(java.time.LocalDateTime.class, ((Person) converted1.get("person")).getDateBirth().getClass()); + + String localDateTimeStringWithType = "{\n" + + " \"bdate\":{\"java.time.LocalDateTime\":\"2022-05-17T14:54\"},\n" + + " \"name\":\"123\",\n" + + " \"bbdate\":{\"java.time.LocalDateTime\":\"2022-05-18T00:00\"}\n" + + "}"; + Map converted2 = marshaller.unmarshall(localDateTimeStringWithType, Map.class); + assertEquals(java.time.LocalDateTime.class, converted2.get("bdate").getClass()); + + String localDateTimeStringWithoutType = "{\n" + + " \"bdate\":\"2022-05-17T14:54\",\n" + + " \"name\":\"123\",\n" + + " \"bbdate\":\"2022-05-18T00:00\"}\n" + + "}"; + Map converted3 = marshaller.unmarshall(localDateTimeStringWithoutType, Map.class); + assertEquals(String.class, converted3.get("bdate").getClass()); + + Map convertedSupportedDateType = marshaller.unmarshall(IOUtils.toString(this.getClass().getResourceAsStream("/supportedDateType.json")), Map.class); + assertEquals(java.time.LocalDateTime.class, convertedSupportedDateType.get("bdate").getClass()); + assertEquals(java.time.LocalDateTime.class, convertedSupportedDateType.get("bbdate").getClass()); + assertEquals(java.time.LocalDate.class, convertedSupportedDateType.get("localdate").getClass()); + assertEquals(java.time.LocalTime.class, convertedSupportedDateType.get("localtime").getClass()); + assertEquals(java.time.OffsetDateTime.class, convertedSupportedDateType.get("offsetDateTime").getClass()); + assertEquals(java.util.Date.class, convertedSupportedDateType.get("utildate").getClass()); + + assertEquals(SupportedlDate.class, convertedSupportedDateType.get("sqldate").getClass()); + + SupportedlDate supportedDate = (SupportedlDate) convertedSupportedDateType.get("sqldate"); + assertEquals(java.util.Date.class, supportedDate.getUtildate().getClass()); + assertEquals(java.time.LocalDateTime.class, supportedDate.getLocalDateTime().getClass()); + assertEquals(java.time.LocalDate.class, supportedDate.getLocalDate().getClass()); + assertEquals(java.time.LocalTime.class, supportedDate.getLocalTime().getClass()); + assertEquals(java.time.OffsetDateTime.class, supportedDate.getOffsetDateTime().getClass()); + } +} + +class SupportedlDate { + + private java.util.Date utildate; + private java.time.LocalDate localDate; + private java.time.LocalDateTime localDateTime; + private java.time.LocalTime localTime; + private java.time.OffsetDateTime offsetDateTime; + + public SupportedlDate() { + } + + public java.util.Date getUtildate() { + return this.utildate; + } + + public void setUtildate(java.util.Date utildate) { + this.utildate = utildate; + } + + public java.time.LocalDate getLocalDate() { + return this.localDate; + } + + public void setLocalDate(java.time.LocalDate localDate) { + this.localDate = localDate; + } + + public java.time.LocalDateTime getLocalDateTime() { + return this.localDateTime; + } + + public void setLocalDateTime(java.time.LocalDateTime localDateTime) { + this.localDateTime = localDateTime; + } + + public java.time.LocalTime getLocalTime() { + return this.localTime; + } + + public void setLocalTime(java.time.LocalTime localTime) { + this.localTime = localTime; + } + + public java.time.OffsetDateTime getOffsetDateTime() { + return this.offsetDateTime; + } + + public void setOffsetDateTime(java.time.OffsetDateTime offsetDateTime) { + this.offsetDateTime = offsetDateTime; + } } + +class Person { + + private java.lang.String fullname; + private java.lang.Integer age; + private java.time.LocalDateTime dateBirth; + private java.util.Date date; + private java.time.LocalTime localTime; + private java.time.OffsetDateTime offsetDateTime; + + public LocalTime getLocalTime() { + return localTime; + } + + public void setLocalTime(LocalTime localTime) { + this.localTime = localTime; + } + + public OffsetDateTime getOffsetDateTime() { + return offsetDateTime; + } + + public void setOffsetDateTime(OffsetDateTime offsetDateTime) { + this.offsetDateTime = offsetDateTime; + } + + public Person() { + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public java.lang.String getFullname() { + return this.fullname; + } + + public void setFullname(java.lang.String fullname) { + this.fullname = fullname; + } + + public java.lang.Integer getAge() { + return this.age; + } + + public void setAge(java.lang.Integer age) { + this.age = age; + } + + public java.time.LocalDateTime getDateBirth() { + return this.dateBirth; + } + + public void setDateBirth(java.time.LocalDateTime dateBirth) { + this.dateBirth = dateBirth; + } +} + + diff --git a/kie-server-parent/kie-server-api/src/test/resources/supportedDateType.json b/kie-server-parent/kie-server-api/src/test/resources/supportedDateType.json new file mode 100644 index 0000000000..c776205e5c --- /dev/null +++ b/kie-server-parent/kie-server-api/src/test/resources/supportedDateType.json @@ -0,0 +1,40 @@ +{ + "bbdate": { + "java.time.LocalDateTime": "2022-05-19T10:00" + }, + "bdate": { + "java.time.LocalDateTime": "2022-05-19T00:00" + }, + "localdate": { + "java.time.LocalDate": "2022-05-19" + }, + "localtime": { + "java.time.LocalTime": "17:32" + }, + "name": "", + "offsetDateTime": { + "java.time.OffsetDateTime": "2007-12-03T10:15:30+01:00" + }, + "sqldate": { + "org.kie.server.api.marshalling.SupportedlDate": { + "utildate": { + "java.util.Date": "2022-05-21" + }, + "localDate": { + "java.time.LocalDate": "2022-05-19T00:00" + }, + "localDateTime": { + "java.time.LocalDateTime": "2022-05-19T10:00" + }, + "localTime": { + "java.time.LocalTime": "17:32" + }, + "offsetDateTime": { + "java.time.OffsetDateTime": "2007-12-03T10:15:30+01:00" + } + } + }, + "utildate": { + "java.util.Date": "2022-05-21" + } +} \ No newline at end of file diff --git a/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/java/org/kie/server/services/jbpm/ui/form/render/AbstractFormRenderer.java b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/java/org/kie/server/services/jbpm/ui/form/render/AbstractFormRenderer.java index 34434078e3..395f653f29 100644 --- a/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/java/org/kie/server/services/jbpm/ui/form/render/AbstractFormRenderer.java +++ b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/java/org/kie/server/services/jbpm/ui/form/render/AbstractFormRenderer.java @@ -24,6 +24,8 @@ import java.io.InputStreamReader; import java.io.StringWriter; import java.nio.charset.Charset; +import java.time.LocalDate; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Base64; import java.util.Collection; @@ -71,6 +73,17 @@ public abstract class AbstractFormRenderer implements FormRenderer { public static final String TASK_LAYOUT_TEMPLATE = "task-layout"; public static final String TABLE_LAYOUT_TEMPLATE = "table"; + public static final Map FUNCTION_MAPPING = new HashMap<>(); + + static { + FUNCTION_MAPPING.put("java.time.LocalDateTime","getFormattedLocalDateTime"); + FUNCTION_MAPPING.put("java.time.LocalDate","getFormattedLocalDate"); + FUNCTION_MAPPING.put("java.util.Date","getFormattedUtilDate"); + FUNCTION_MAPPING.put("java.time.LocalTime","getFormattedLocalTime"); + FUNCTION_MAPPING.put("java.time.OffsetDateTime","getFormattedOffsetDateTime"); + + } + private Map inputTypes; private StringTemplateLoader stringLoader = new StringTemplateLoader(); private Configuration cfg; @@ -82,8 +95,7 @@ public abstract class AbstractFormRenderer implements FormRenderer { private String serverPath; private String resourcePath; - - + public AbstractFormRenderer(String serverPath, String resources) { this.serverPath = serverPath; this.resourcePath = serverPath + resources; @@ -184,7 +196,6 @@ public String renderCase(String containerId, CaseDefinition caseDefinition, Form return finalOutput; } - public String renderProcess(String containerId, ProcessDefinition processDesc, FormInstance form) { List scriptDataList = new ArrayList<>(); @@ -401,6 +412,7 @@ protected void processFormLayout(FormInstance topLevelForm, item.setMax(field.getMax()); item.setPrecision(field.getPrecision()); item.setStep(field.getStep()); + item.setShowTime(field.isShowTime()); Object value = ""; if (inputs.get(field.getBinding()) != null) { @@ -409,9 +421,25 @@ protected void processFormLayout(FormInstance topLevelForm, if (outputs.get(field.getBinding()) != null) { value = outputs.get(field.getBinding()); } - - + switch(fieldType) { + case "Date": + if ("java.util.Date".equals(field.getType())) { + if (value != null && value instanceof java.util.Date) { + LocalDate utilDate = ((java.util.Date) value).toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + value = utilDate.toString(); + } else if (value != null && value.toString().length() >= 10) { + value = value.toString().substring(0, 10); + } + } + item.setValue((value != null) ? value.toString() : ""); + break; + case "datetime-local": + if (value != null && value.toString().length() >= 10 && !field.isShowTime()) { + value = value.toString().substring(0, 10); + } + item.setValue((value != null) ? value.toString() : ""); + break; case "documentCollection": if (value instanceof DocumentCollection) { DocumentCollection docCollection = (DocumentCollection) value; @@ -471,9 +499,9 @@ protected void processFormLayout(FormInstance topLevelForm, String output = renderTemplate(FORM_GROUP_LAYOUT_TEMPLATE, parameters); // append rendered content to the column content content.append(output); - + // add the field to json template - appendFieldJSON(jsonTemplate, fieldType, field.getBinding(), field.getId(), jsType); + appendFieldJSON(jsonTemplate, fieldType, field, jsType); } else { logger.warn("Field type {} is not supported, skipping it...", field.getCode()); } @@ -495,25 +523,28 @@ protected void processFormLayout(FormInstance topLevelForm, private String getFieldType(FormField field) { String type = inputTypes.get(field.getCode()); + switch (type) { case "documentCollection": case "multipleSelector": case "multipleInput": return type; - default: - switch (field.getType()) { - case "java.time.LocalDateTime": - case "java.util.Date": - case "java.sql.Date": - case "java.sql.Timestamp": - return "datetime-local"; - case "java.time.LocalTime": - return "time"; - case "java.time.OffsetDateTime": - return "datetime"; - default: - return type; - } + default: + switch (field.getType()) { + case "java.time.LocalDateTime": + return "datetime-local"; + case "java.util.Date": + return "Date"; + case "java.sql.Date": + case "java.sql.Timestamp": + return "datetime-local"; + case "java.time.LocalTime": + return "time"; + case "java.time.OffsetDateTime": + return "datetime"; + default: + return type; + } } } @@ -689,16 +720,38 @@ protected String renderTemplate(Configuration cfg, String templateName, Map options; + public boolean isShowTime() { + return showTime; + } + + public void setShowTime(boolean showTime) { + this.showTime = showTime; + } + public String getFormId() { return formId; } diff --git a/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/bootstrap/input-form-group-template.html b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/bootstrap/input-form-group-template.html index 9b33105adf..de2c7159ef 100644 --- a/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/bootstrap/input-form-group-template.html +++ b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/bootstrap/input-form-group-template.html @@ -60,7 +60,19 @@ <#if item.required> * - + + +<#elseif item.type == "datetime-local"> +
+ + <#if item.required> + * + + <#if item.showTime > + + <#elseif !item.showTime > + +
<#elseif item.type == "slider">
diff --git a/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/js/kieserver-ui.js b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/js/kieserver-ui.js index 1e7b515e59..d8018109ba 100644 --- a/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/js/kieserver-ui.js +++ b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/js/kieserver-ui.js @@ -324,30 +324,25 @@ function validate(start) { var fileData = new Map(); - function encodeImageFileAsURL(input) { - var filesSelected = input.files; if (filesSelected.length > 0) { var fileToLoad = filesSelected[0]; - var fileInfo = { - 'name' : fileToLoad.name, - 'size' : fileToLoad.size, - 'data' : null + 'name': fileToLoad.name, + 'size': fileToLoad.size, + 'data': null }; fileData.set(input.id, fileInfo); - - var fileReader = new FileReader(); - fileReader.onload = function(fileLoadedEvent) { - var local = fileLoadedEvent.target.result; // <--- data: base64 - var srcData = local.replace(/^data:.*\/.*;base64,/, ""); + var fileReader = new FileReader(); - fileData.get(input.id).data = srcData; - - console.log("Converted Base64 version is " + srcData); - } + fileReader.onload = function (event) { + if (event.target.readyState == FileReader.DONE) { + var b64 = event.target.result.replace(/^data:.+;base64,/, ''); + fileData.get(input.id).data = b64; + } + }; fileReader.readAsDataURL(fileToLoad); } else { alert("Please select a file"); @@ -355,7 +350,6 @@ function encodeImageFileAsURL(input) { } function getDocumentData(inputId) { - if (fileData.has(inputId)) { var fileInfo = fileData.get(inputId); var document = { @@ -556,3 +550,36 @@ function closeCreationForm(fieldId) { currentRow = null; } +function getFormattedLocalDateTime(jsondate) { + return {'java.time.LocalDateTime': jsondate}; +} + +function getFormattedUtilDate(jsondate) { + return {'java.util.Date': jsondate}; +} + +function getFormattedLocalDate(jsondate) { + return {'java.time.LocalDate': jsondate}; +} + +function getFormattedLocalTime(jsondate) { + return {'java.time.LocalTime': jsondate}; +} + +function getFormattedOffsetDateTime(jsondate) { + return {'java.time.OffsetDateTime': jsondate}; +} + +function getDate(elementId, getDateValueByType) { + var value = document.getElementById(elementId).value; + return getDateValueByType(value); +} + +function getDateWithoutTime(elementId, getDateValueByType) { + var value = document.getElementById(elementId).value; + if (value === '') { + return getDateValueByType(value); + } else { + return getDateValueByType(value + 'T00:00'); + } +} diff --git a/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/patternfly/input-form-group-template.html b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/patternfly/input-form-group-template.html index d15e9f3fce..953bc8bab4 100644 --- a/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/patternfly/input-form-group-template.html +++ b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/main/resources/form-templates-providers/patternfly/input-form-group-template.html @@ -59,7 +59,19 @@ <#if item.required> * - + +
+<#elseif item.type == "datetime-local"> +
+ + <#if item.required> + * + + <#if item.showTime > + + <#elseif !item.showTime > + +
<#elseif item.type == "documentCollection">
diff --git a/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/test/java/org/kie/server/services/jbpm/ui/form/render/BootstrapFormRendererTest.java b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/test/java/org/kie/server/services/jbpm/ui/form/render/BootstrapFormRendererTest.java new file mode 100644 index 0000000000..9d3eaf72a0 --- /dev/null +++ b/kie-server-parent/kie-server-services/kie-server-services-jbpm-ui/src/test/java/org/kie/server/services/jbpm/ui/form/render/BootstrapFormRendererTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates. + * + * Licensed 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.kie.server.services.jbpm.ui.form.render; + +import org.jbpm.kie.services.impl.model.ProcessAssetDesc; +import org.junit.Test; +import org.kie.server.services.jbpm.ui.form.render.model.FormInstance; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BootstrapFormRendererTest { + + @Test + public void testProcessFormRendererWithDate() { + FormReader reader = new FormReader(); + + FormInstance form = reader.readFromStream(this.getClass().getResourceAsStream("/date-form.json")); + ProcessAssetDesc processAssetDesc = new ProcessAssetDesc(); + processAssetDesc.setId("test-id"); + + BootstrapFormRenderer bootstrapFormRenderer = new BootstrapFormRenderer(); + String outString = bootstrapFormRenderer.renderProcess("test-containerId", processAssetDesc, form); + assertThat(outString).contains("'dateBirth' : getDateWithoutTime('field_1703386699666296E12',getFormattedLocalDateTime)"); + assertThat(outString).contains("