From 0f229083222e298c94af619824c5eafb5ba25630 Mon Sep 17 00:00:00 2001 From: Arun Kumar Madesh <56151567+arunkumar461@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:26:10 +0000 Subject: [PATCH 1/3] CCMSPUI-466 | Add details component --- .../dialect/ButtonElementTagProcessor.java | 27 +-------- .../dialect/DetailsElementTagProcessor.java | 56 +++++++++++++++++++ .../ccms/springboot/dialect/GovUkDialect.java | 2 +- .../springboot/dialect/ProcessorUtils.java | 43 ++++++++++++++ .../DetailsElementTagProcessorTest.java | 31 ++++++++++ .../resources/templates/test-details.html | 12 ++++ 6 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/DetailsElementTagProcessor.java create mode 100644 laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/ProcessorUtils.java create mode 100644 laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/java/uk/gov/laa/ccms/springboot/dialect/DetailsElementTagProcessorTest.java create mode 100644 laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/resources/templates/test-details.html diff --git a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/ButtonElementTagProcessor.java b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/ButtonElementTagProcessor.java index b9c2a09..c7444e3 100644 --- a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/ButtonElementTagProcessor.java +++ b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/ButtonElementTagProcessor.java @@ -1,6 +1,5 @@ package uk.gov.laa.ccms.springboot.dialect; -import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; import org.apache.logging.log4j.util.Strings; @@ -10,11 +9,9 @@ import org.thymeleaf.model.IProcessableElementTag; import org.thymeleaf.processor.element.AbstractElementTagProcessor; import org.thymeleaf.processor.element.IElementTagStructureHandler; -import org.thymeleaf.standard.expression.IStandardExpression; -import org.thymeleaf.standard.expression.IStandardExpressionParser; -import org.thymeleaf.standard.expression.StandardExpressions; import org.thymeleaf.templatemode.TemplateMode; + /** * Transforms elements into standard HTML button elements. */ @@ -32,7 +29,7 @@ public ButtonElementTagProcessor() { protected void doProcess(ITemplateContext context, IProcessableElementTag tag, IElementTagStructureHandler structureHandler) { - Map attributes = parseAttributes(context, tag); + Map attributes = ProcessorUtils.parseAttributes(context, tag); String classNames = buildClassNames(attributes); String commonAttributes = buildCommonAttributes(classNames, attributes); String buttonAttributes = buildButtonAttributes(attributes); @@ -43,26 +40,6 @@ protected void doProcess(ITemplateContext context, IProcessableElementTag tag, replaceElementWithHtml(context, structureHandler, html); } - private Map parseAttributes(ITemplateContext context, - IProcessableElementTag tag) { - Map attributes = tag.getAttributeMap(); - Map resolvedAttributes = new HashMap<>(); - IStandardExpressionParser parser = - StandardExpressions.getExpressionParser(context.getConfiguration()); - - for (Map.Entry entry : attributes.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - if (key.startsWith("th:")) { - IStandardExpression expression = parser.parseExpression(context, value); - resolvedAttributes.put(key.replace("th:", ""), (String) expression.execute(context)); - } else { - resolvedAttributes.put(key, value); - } - } - - return resolvedAttributes; - } private String buildClassNames(Map attributes) { String classNames = "govuk-button"; diff --git a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/DetailsElementTagProcessor.java b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/DetailsElementTagProcessor.java new file mode 100644 index 0000000..640941e --- /dev/null +++ b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/DetailsElementTagProcessor.java @@ -0,0 +1,56 @@ +package uk.gov.laa.ccms.springboot.dialect; + +import java.util.Map; +import org.thymeleaf.context.ITemplateContext; +import org.thymeleaf.model.IModel; +import org.thymeleaf.model.IModelFactory; +import org.thymeleaf.model.IProcessableElementTag; +import org.thymeleaf.processor.element.AbstractElementTagProcessor; +import org.thymeleaf.processor.element.IElementTagStructureHandler; +import org.thymeleaf.templatemode.TemplateMode; + +/** + * Transforms elements into standard HTML button elements. + */ +public class DetailsElementTagProcessor extends AbstractElementTagProcessor { + + private static final String TAG_NAME = "details"; + private static final int PRECEDENCE = 900; + + public DetailsElementTagProcessor() { + super(TemplateMode.HTML, "govuk", TAG_NAME, true, null, false, PRECEDENCE); + } + + @Override + protected void doProcess(ITemplateContext context, IProcessableElementTag tag, + IElementTagStructureHandler structureHandler) { + + // Parse attributes + Map attributes = ProcessorUtils.parseAttributes(context, tag); + String summaryText = attributes.getOrDefault("summaryText", ""); + String text = attributes.getOrDefault("text", ""); + + // Build the HTML structure + String detailsHtml = buildDetailsHtml(summaryText, text); + + // Create the model and replace the tag + final IModelFactory modelFactory = context.getModelFactory(); + final IModel model = modelFactory.parse(context.getTemplateData(), detailsHtml); + structureHandler.replaceWith(model, false); + } + + private String buildDetailsHtml(String summaryText, String text) { + return new StringBuilder() + .append("
") + .append("") + .append("") + .append(summaryText) + .append("") + .append("") + .append("
") + .append(text) + .append("
") + .append("
") + .toString(); + } +} diff --git a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/GovUkDialect.java b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/GovUkDialect.java index 9bb0918..e744608 100644 --- a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/GovUkDialect.java +++ b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/GovUkDialect.java @@ -19,6 +19,6 @@ public GovUkDialect() { @Override public Set getProcessors(String dialectPrefix) { - return Set.of(new ButtonElementTagProcessor()); + return Set.of(new ButtonElementTagProcessor(), new DetailsElementTagProcessor()); } } \ No newline at end of file diff --git a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/ProcessorUtils.java b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/ProcessorUtils.java new file mode 100644 index 0000000..596a03a --- /dev/null +++ b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/main/java/uk/gov/laa/ccms/springboot/dialect/ProcessorUtils.java @@ -0,0 +1,43 @@ +package uk.gov.laa.ccms.springboot.dialect; + +import java.util.HashMap; +import java.util.Map; +import org.thymeleaf.context.ITemplateContext; +import org.thymeleaf.model.IProcessableElementTag; +import org.thymeleaf.standard.expression.IStandardExpression; +import org.thymeleaf.standard.expression.IStandardExpressionParser; +import org.thymeleaf.standard.expression.StandardExpressions; + +/** + * ProcessorUtils for common code. + */ +public class ProcessorUtils { + + private ProcessorUtils() { + } + + /** + * Evaluate thymeleaf expressions. + */ + public static Map parseAttributes(ITemplateContext context, + IProcessableElementTag tag) { + Map attributes = tag.getAttributeMap(); + Map resolvedAttributes = new HashMap<>(); + IStandardExpressionParser parser = + StandardExpressions.getExpressionParser(context.getConfiguration()); + + for (Map.Entry entry : attributes.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + if (key.startsWith("th:")) { + IStandardExpression expression = parser.parseExpression(context, value); + resolvedAttributes.put(key.replace("th:", ""), (String) expression.execute(context)); + } else { + resolvedAttributes.put(key, value); + } + } + + return resolvedAttributes; + } + +} diff --git a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/java/uk/gov/laa/ccms/springboot/dialect/DetailsElementTagProcessorTest.java b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/java/uk/gov/laa/ccms/springboot/dialect/DetailsElementTagProcessorTest.java new file mode 100644 index 0000000..606ab5b --- /dev/null +++ b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/java/uk/gov/laa/ccms/springboot/dialect/DetailsElementTagProcessorTest.java @@ -0,0 +1,31 @@ +package uk.gov.laa.ccms.springboot.dialect; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.thymeleaf.context.Context; +import org.thymeleaf.spring6.SpringTemplateEngine; + +@SpringBootTest(classes = ThymeleafTestConfig.class) +class DetailsElementTagProcessorTest { + + @Autowired + private SpringTemplateEngine templateEngine; + + @Test + void shouldRenderGovukButton() { + + Context context = new Context(); + String renderedHtml = templateEngine.process("test-details", context); + assertThat(renderedHtml) + .contains( + "
" + + "Help with nationality" + + "
We need to know your nationality " + + "so we can work out which elections you're entitled to vote in.
"); + + } + +} \ No newline at end of file diff --git a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/resources/templates/test-details.html b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/resources/templates/test-details.html new file mode 100644 index 0000000..d8cf396 --- /dev/null +++ b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/resources/templates/test-details.html @@ -0,0 +1,12 @@ + + + + Button Test + + + + + + + \ No newline at end of file From da4d4a55a63626ccd74223f4caec855c14a41f6c Mon Sep 17 00:00:00 2001 From: Arun Kumar Madesh <56151567+arunkumar461@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:29:28 +0000 Subject: [PATCH 2/3] CCMSPUI-466 | Add documentation --- .../Readme.md | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/Readme.md b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/Readme.md index a9309ae..8443a2d 100644 --- a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/Readme.md +++ b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/Readme.md @@ -60,4 +60,23 @@ This ensures that all attributes, including conditional and computed values, are -``` \ No newline at end of file +``` + +### Details Element Tag Processor + +The `DetailsElementTagProcessor` is a custom Thymeleaf tag processor that enables the use of a `` tag to generate a `
` HTML element styled with the GOV.UK Design System classes. + +#### Features +- Generates a `
` element with the `govuk-details` class. +- Includes a `` element with a customizable summary text. +- Includes a `
` element for detailed content. + +#### Usage +To use this processor, define a `govuk:details` tag in your Thymeleaf templates and provide the following attributes: + +- **`summaryText`**: The text displayed in the summary section of the `
` element. +- **`text`**: The content displayed inside the `
` when the details are expanded. + +#### Example +```html + From 9171ee7a11bf7c267702ba19cd3ae8ea7f17cf96 Mon Sep 17 00:00:00 2001 From: Arun Kumar Madesh <56151567+arunkumar461@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:35:05 +0000 Subject: [PATCH 3/3] CCMSPUI-466 | fix text --- .../src/test/resources/templates/test-details.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/resources/templates/test-details.html b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/resources/templates/test-details.html index d8cf396..42b564a 100644 --- a/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/resources/templates/test-details.html +++ b/laa-ccms-spring-boot-starters/laa-ccms-spring-boot-starter-govuk-dialect/src/test/resources/templates/test-details.html @@ -1,7 +1,7 @@ - Button Test + Details Test