diff --git a/extensions/reports/packages/reports-sdk/src/types.ts b/extensions/reports/packages/reports-sdk/src/types.ts index 03f14c80d..77bba6595 100644 --- a/extensions/reports/packages/reports-sdk/src/types.ts +++ b/extensions/reports/packages/reports-sdk/src/types.ts @@ -122,6 +122,10 @@ export interface ReportColumn { format?: string | null; width?: string | null; upperCase: boolean; + /** CSS class name(s) the designer chose for every cell of the column, e.g. `green lighten-5`; absent when not set */ + cellStyle?: string; + /** CSS class name(s) the designer chose for the header of the column; absent when not set */ + columnStyle?: string; } /** A filter a report accepts. */ diff --git a/extensions/reports/sources/api/src/main/java/tools/dynamia/modules/reports/api/v2/ReportColumn.java b/extensions/reports/sources/api/src/main/java/tools/dynamia/modules/reports/api/v2/ReportColumn.java index bb2d0ba39..eabe048fb 100644 --- a/extensions/reports/sources/api/src/main/java/tools/dynamia/modules/reports/api/v2/ReportColumn.java +++ b/extensions/reports/sources/api/src/main/java/tools/dynamia/modules/reports/api/v2/ReportColumn.java @@ -1,5 +1,7 @@ package tools.dynamia.modules.reports.api.v2; +import com.fasterxml.jackson.annotation.JsonInclude; + /** * A column of a report result. * @@ -10,7 +12,19 @@ * @param format optional display format pattern * @param width optional width, for example {@code 120px} * @param upperCase true if the text should be shown in upper case + * @param cellStyle optional CSS class name(s) the designer chose for every cell of the column (for example {@code green lighten-5}); + * omitted from the JSON when not set + * @param columnStyle optional CSS class name(s) the designer chose for the header of the column; omitted from the JSON when not set */ public record ReportColumn(String name, String label, String dataType, String align, String format, String width, - boolean upperCase) { + boolean upperCase, + @JsonInclude(JsonInclude.Include.NON_NULL) String cellStyle, + @JsonInclude(JsonInclude.Include.NON_NULL) String columnStyle) { + + /** + * A column without designer styles. + */ + public ReportColumn(String name, String label, String dataType, String align, String format, String width, boolean upperCase) { + this(name, label, dataType, align, format, width, upperCase, null, null); + } } diff --git a/extensions/reports/sources/core/src/main/java/tools/dynamia/modules/reports/core/api/ReportColumns.java b/extensions/reports/sources/core/src/main/java/tools/dynamia/modules/reports/core/api/ReportColumns.java index f10bfef02..3944e7c79 100644 --- a/extensions/reports/sources/core/src/main/java/tools/dynamia/modules/reports/core/api/ReportColumns.java +++ b/extensions/reports/sources/core/src/main/java/tools/dynamia/modules/reports/core/api/ReportColumns.java @@ -80,7 +80,11 @@ private static ReportColumn of(ReportField field) { DataType type = field.getDataType() != null ? field.getDataType() : DataType.TEXT; TextAlign align = field.getAlign() != null ? field.getAlign() : TextAlign.LEFT; return new ReportColumn(field.getName(), field.getLabel(), type.name(), align.name(), field.getFormat(), - field.getWidth(), field.isUpperCase()); + field.getWidth(), field.isUpperCase(), blankToNull(field.getCellStyle()), blankToNull(field.getColumnStyle())); + } + + private static String blankToNull(String style) { + return style == null || style.isBlank() ? null : style.trim(); } private static DataType infer(String name, ReportData data) { diff --git a/extensions/reports/sources/core/src/test/java/tools/dynamia/modules/reports/core/api/ReportColumnStylesTest.java b/extensions/reports/sources/core/src/test/java/tools/dynamia/modules/reports/core/api/ReportColumnStylesTest.java new file mode 100644 index 000000000..b150d8946 --- /dev/null +++ b/extensions/reports/sources/core/src/test/java/tools/dynamia/modules/reports/core/api/ReportColumnStylesTest.java @@ -0,0 +1,85 @@ +package tools.dynamia.modules.reports.core.api; + +import org.junit.jupiter.api.Test; +import tools.dynamia.modules.reports.core.domain.Report; +import tools.dynamia.modules.reports.core.domain.ReportField; +import tools.jackson.databind.json.JsonMapper; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * The styles a designer chooses for a field reach the API columns, so a front end other than ZK can honor them. + */ +class ReportColumnStylesTest { + + private static ReportField field(Report report, String name, int order, String cellStyle, String columnStyle) { + var field = new ReportField(); + field.setReport(report); + field.setName(name); + field.setLabel(name); + field.setOrder(order); + field.setCellStyle(cellStyle); + field.setColumnStyle(columnStyle); + report.getFields().add(field); + return field; + } + + private static Report report() { + var report = new Report(); + report.setName("Styles"); + report.setAutofields(false); + return report; + } + + @Test + void declaredColumnsCarryTheDesignersStyles() { + var report = report(); + field(report, "total", 1, "green lighten-5", "bold"); + + var column = ReportColumns.declared(report).get(0); + + assertEquals("green lighten-5", column.cellStyle()); + assertEquals("bold", column.columnStyle()); + } + + @Test + void blankStylesAreNotSent() { + var report = report(); + field(report, "a", 1, " ", ""); + field(report, "b", 2, null, null); + + var columns = ReportColumns.declared(report); + + assertNull(columns.get(0).cellStyle()); + assertNull(columns.get(0).columnStyle()); + assertNull(columns.get(1).cellStyle()); + } + + @Test + void theJsonOmitsTheStyleKeysWhenThereAreNoneAndKeepsTheRest() { + var report = report(); + field(report, "a", 1, null, null); + field(report, "b", 2, "red lighten-4", null); + var mapper = JsonMapper.builder().build(); + + var plain = mapper.writeValueAsString(ReportColumns.declared(report).get(0)); + var styled = mapper.writeValueAsString(ReportColumns.declared(report).get(1)); + + assertFalse(plain.contains("cellStyle")); + assertFalse(plain.contains("columnStyle")); + assertTrue(plain.contains("\"format\":null"), "the existing keys keep being sent as before: " + plain); + assertTrue(styled.contains("\"cellStyle\":\"red lighten-4\"")); + assertFalse(styled.contains("columnStyle")); + } + + @Test + void theOldConstructorStillWorks() { + var column = new tools.dynamia.modules.reports.api.v2.ReportColumn("a", "A", "TEXT", "LEFT", null, null, false); + + assertNull(column.cellStyle()); + assertNull(column.columnStyle()); + } +}