Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CCMSPUI-466 | create details component #23

Merged
merged 3 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,23 @@ This ensures that all attributes, including conditional and computed values, are
<govuk:button th:text="'Click Me!'" href="'/test'" id="'button-id'" classes="'custom-class'"/>
</body>
</html>
```
```

### Details Element Tag Processor

The `DetailsElementTagProcessor` is a custom Thymeleaf tag processor that enables the use of a `<govuk:details>` tag to generate a `<details>` HTML element styled with the GOV.UK Design System classes.

#### Features
- Generates a `<details>` element with the `govuk-details` class.
- Includes a `<summary>` element with a customizable summary text.
- Includes a `<div>` 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 `<details>` element.
- **`text`**: The content displayed inside the `<div>` when the details are expanded.

#### Example
```html
<govuk:details summaryText="Click to view details" text="This is the detailed content."></govuk:details>
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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 <govuk:button/> elements into standard HTML button elements.
*/
Expand All @@ -32,7 +29,7 @@ public ButtonElementTagProcessor() {
protected void doProcess(ITemplateContext context, IProcessableElementTag tag,
IElementTagStructureHandler structureHandler) {

Map<String, String> attributes = parseAttributes(context, tag);
Map<String, String> attributes = ProcessorUtils.parseAttributes(context, tag);
String classNames = buildClassNames(attributes);
String commonAttributes = buildCommonAttributes(classNames, attributes);
String buttonAttributes = buildButtonAttributes(attributes);
Expand All @@ -43,26 +40,6 @@ protected void doProcess(ITemplateContext context, IProcessableElementTag tag,
replaceElementWithHtml(context, structureHandler, html);
}

private Map<String, String> parseAttributes(ITemplateContext context,
IProcessableElementTag tag) {
Map<String, String> attributes = tag.getAttributeMap();
Map<String, String> resolvedAttributes = new HashMap<>();
IStandardExpressionParser parser =
StandardExpressions.getExpressionParser(context.getConfiguration());

for (Map.Entry<String, String> 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<String, String> attributes) {
String classNames = "govuk-button";
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <govuk:button/> 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<String, String> 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("<details class=\"").append("govuk-details").append("\">")
.append("<summary class=\"").append("govuk-details__summary").append("\">")
.append("<span class=\"").append("govuk-details__summary-text").append("\">")
.append(summaryText)
.append("</span>")
.append("</summary>")
.append("<div class=\"").append("govuk-details__text").append("\">")
.append(text)
.append("</div>")
.append("</details>")
.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ public GovUkDialect() {

@Override
public Set<IProcessor> getProcessors(String dialectPrefix) {
return Set.of(new ButtonElementTagProcessor());
return Set.of(new ButtonElementTagProcessor(), new DetailsElementTagProcessor());
}
}
Original file line number Diff line number Diff line change
@@ -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<String, String> parseAttributes(ITemplateContext context,
IProcessableElementTag tag) {
Map<String, String> attributes = tag.getAttributeMap();
Map<String, String> resolvedAttributes = new HashMap<>();
IStandardExpressionParser parser =
StandardExpressions.getExpressionParser(context.getConfiguration());

for (Map.Entry<String, String> 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;
}

}
Original file line number Diff line number Diff line change
@@ -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(
"<details class=\"govuk-details\"><summary class=\"govuk-details__summary\">" +
"<span class=\"govuk-details__summary-text\">Help with nationality</span>" +
"</summary><div class=\"govuk-details__text\">We need to know your nationality " +
"so we can work out which elections you're entitled to vote in.</div></details>");

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html xmlns:govuk="http://www.thymeleaf.org" lang="EN">
<head>
<title>Details Test</title>
</head>
<body>

<govuk:details summaryText="Help with nationality"
text="We need to know your nationality so we can work out which elections you're entitled to vote in."/>

</body>
</html>
Loading