Skip to content
Snippets Groups Projects
Commit 302d64b7 authored by Manuel Leduc's avatar Manuel Leduc
Browse files

XWIKI-22059: Allow for the definition of extra classes on Live Data icons

parent 68b0d173
No related branches found
No related tags found
No related merge requests found
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<artifactId>xwiki-platform-livedata-api</artifactId> <artifactId>xwiki-platform-livedata-api</artifactId>
<name>XWiki Platform - Live Data - API</name> <name>XWiki Platform - Live Data - API</name>
<properties> <properties>
<xwiki.jacoco.instructionRatio>0.69</xwiki.jacoco.instructionRatio> <xwiki.jacoco.instructionRatio>0.70</xwiki.jacoco.instructionRatio>
<checkstyle.suppressions.location>${basedir}/src/checkstyle/checkstyle-suppressions.xml</checkstyle.suppressions.location> <checkstyle.suppressions.location>${basedir}/src/checkstyle/checkstyle-suppressions.xml</checkstyle.suppressions.location>
<!-- Name to display by the Extension Manager --> <!-- Name to display by the Extension Manager -->
<xwiki.extension.name>Live Data API</xwiki.extension.name> <xwiki.extension.name>Live Data API</xwiki.extension.name>
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
/** /**
* Resolves the live data configuration from a JSON string input. * Resolves the live data configuration from a JSON string input.
...@@ -89,6 +90,10 @@ public class StringLiveDataConfigurationResolver implements LiveDataConfiguratio ...@@ -89,6 +90,10 @@ public class StringLiveDataConfigurationResolver implements LiveDataConfiguratio
private static final String ACTIONS = "actions"; private static final String ACTIONS = "actions";
private static final String CSS_CLASS = "cssClass";
private static final String EXTRA_ICON_CLASSES = "extraIconClasses";
@Inject @Inject
private Logger logger; private Logger logger;
...@@ -253,6 +258,33 @@ private void normalizeIcon(ObjectNode descriptor, ObjectMapper objectMapper) ...@@ -253,6 +258,33 @@ private void normalizeIcon(ObjectNode descriptor, ObjectMapper objectMapper)
} else if (!icon.isObject()) { } else if (!icon.isObject()) {
descriptor.remove(ICON); descriptor.remove(ICON);
} }
normalizeIconClasses(descriptor);
}
/**
* Adds the {@link #EXTRA_ICON_CLASSES} to the icon's CSS classes. It is done by looking for an
* {@link #EXTRA_ICON_CLASSES} field on the descriptor. If the {@link #EXTRA_ICON_CLASSES} field is not found,
* nothing happen. If it is found, it is concatenated at the end of the {@link #CSS_CLASS} field of the
* {@link #ICON} object. If the {@link #CSS_CLASS} is not present, it is initialized with the value of
* {@link #EXTRA_ICON_CLASSES}. The {@link #EXTRA_ICON_CLASSES} field is removed for the descriptor in all cases.
*
* @param descriptor the descriptor to normalize
*/
private static void normalizeIconClasses(ObjectNode descriptor)
{
JsonNode icon = descriptor.path(ICON);
if (icon.isObject()) {
JsonNode extraClasses = descriptor.path(EXTRA_ICON_CLASSES);
if (extraClasses.isTextual()) {
String cssClasses = extraClasses.textValue().trim();
if (icon.path(CSS_CLASS).isTextual()) {
cssClasses = icon.path(CSS_CLASS).textValue().trim() + " " + cssClasses;
}
((ObjectNode) icon).set(CSS_CLASS, new TextNode(cssClasses));
}
// Does not need to be preserved once the icon is fully resolved.
descriptor.remove(EXTRA_ICON_CLASSES);
}
} }
private void normalizeLayouts(ObjectNode metaConfig, ObjectMapper objectMapper) private void normalizeLayouts(ObjectNode metaConfig, ObjectMapper objectMapper)
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
import org.xwiki.test.junit5.mockito.MockComponent; import org.xwiki.test.junit5.mockito.MockComponent;
import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
...@@ -73,15 +74,32 @@ void before() throws Exception ...@@ -73,15 +74,32 @@ void before() throws Exception
tableIconMetaData.put(IconManager.META_DATA_ICON_SET_NAME, "Silk"); tableIconMetaData.put(IconManager.META_DATA_ICON_SET_NAME, "Silk");
tableIconMetaData.put(IconManager.META_DATA_URL, "/path/to/table.png"); tableIconMetaData.put(IconManager.META_DATA_URL, "/path/to/table.png");
Map<String, Object> crossIconMetadata = Map.of(
IconManager.META_DATA_ICON_SET_TYPE, "font",
IconManager.META_DATA_ICON_SET_NAME, "Font Awesome",
IconManager.META_DATA_CSS_CLASS, "fa fa-times"
);
Map<String, Object> testIconMetadata = Map.of(
IconManager.META_DATA_ICON_SET_TYPE, "test",
IconManager.META_DATA_ICON_SET_NAME, "Test"
);
when(this.iconManager.getMetaData("file")).thenReturn(fileIconMetaData); when(this.iconManager.getMetaData("file")).thenReturn(fileIconMetaData);
when(this.iconManager.getMetaData("table")).thenReturn(tableIconMetaData); when(this.iconManager.getMetaData("table")).thenReturn(tableIconMetaData);
when(this.iconManager.getMetaData("cross")).thenReturn(crossIconMetadata);
when(this.iconManager.getMetaData("test")).thenReturn(testIconMetadata);
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("getTestData") @MethodSource("getTestData")
void resolve(String message, String input, String output) throws Exception void resolve(String message, String input, String output) throws Exception
{ {
assertEquals(output, this.objectMapper.writeValueAsString(this.resolver.resolve(input)), message); JsonNode expect = this.objectMapper.readValue(output, JsonNode.class);
JsonNode actual =
this.objectMapper.readValue(this.objectMapper.writeValueAsString(this.resolver.resolve(input)),
JsonNode.class);
assertEquals(expect, actual, message);
} }
private static Stream<String[]> getTestData() throws Exception private static Stream<String[]> getTestData() throws Exception
......
...@@ -170,7 +170,11 @@ ...@@ -170,7 +170,11 @@
"visible":false "visible":false
} }
], ],
"actions":["edit"] "actions":[
"edit",
{"id": "delete", "icon": "cross", "extraIconClasses": "text-danger"},
{"id": "test", "icon": "test", "extraIconClasses": "text-test"}
]
} }
} }
--- ---
...@@ -193,7 +197,9 @@ ...@@ -193,7 +197,9 @@
} }
], ],
"actions":[ "actions":[
{"id":"edit"} {"id":"edit"},
{"id":"delete","icon":{"iconSetName":"Font Awesome","iconSetType":"font","cssClass":"fa fa-times text-danger"}},
{"id":"test","icon":{"iconSetName":"Test","iconSetType":"test","cssClass":"text-test"}}
] ]
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment