From 6919d9d810e4f6ce77c05be5cb7baaad6c77073b Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Tue, 27 Feb 2024 19:39:46 -0600 Subject: [PATCH] CE-878 add helpContent to widgetMetaData --- .../QInstanceHelpContentManager.java | 214 +++++++++++------- .../metadata/dashboard/QWidgetMetaData.java | 34 +++ .../dashboard/QWidgetMetaDataInterface.java | 21 ++ .../frontend/QFrontendWidgetMetaData.java | 17 +- .../QInstanceHelpContentManagerTest.java | 38 ++++ 5 files changed, 244 insertions(+), 80 deletions(-) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceHelpContentManager.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceHelpContentManager.java index 739e8a74..f0e6968c 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceHelpContentManager.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceHelpContentManager.java @@ -30,12 +30,14 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; import com.kingsrook.qqq.backend.core.actions.tables.QueryAction; +import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.helpcontent.HelpContent; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.help.HelpFormat; import com.kingsrook.qqq.backend.core.model.metadata.help.HelpRole; @@ -109,6 +111,8 @@ public class QInstanceHelpContentManager String processName = nameValuePairs.get("process"); String fieldName = nameValuePairs.get("field"); String sectionName = nameValuePairs.get("section"); + String widgetName = nameValuePairs.get("widget"); + String slotName = nameValuePairs.get("slot"); /////////////////////////////////////////////////////////// // build a help content meta-data object from the record // @@ -137,89 +141,16 @@ public class QInstanceHelpContentManager /////////////////////////////////////////////////////////////////////////////////// if(StringUtils.hasContent(tableName)) { - QTableMetaData table = qInstance.getTable(tableName); - if(table == null) - { - LOG.info("Unrecognized table in help content", logPair("key", key)); - return; - } - - if(StringUtils.hasContent(fieldName)) - { - ////////////////////////// - // handle a table field // - ////////////////////////// - QFieldMetaData field = table.getFields().get(fieldName); - if(field == null) - { - LOG.info("Unrecognized table field in help content", logPair("key", key)); - return; - } - - if(helpContent != null) - { - field.withHelpContent(helpContent); - } - else - { - field.removeHelpContent(roles); - } - } - else if(StringUtils.hasContent(sectionName)) - { - //////////////////////////// - // handle a table section // - //////////////////////////// - Optional optionalSection = table.getSections().stream().filter(s -> sectionName.equals(s.getName())).findFirst(); - if(optionalSection.isEmpty()) - { - LOG.info("Unrecognized table section in help content", logPair("key", key)); - return; - } - - if(helpContent != null) - { - optionalSection.get().withHelpContent(helpContent); - } - else - { - optionalSection.get().removeHelpContent(roles); - } - } + processHelpContentForTable(key, tableName, sectionName, fieldName, roles, helpContent); } else if(StringUtils.hasContent(processName)) { - QProcessMetaData process = qInstance.getProcess(processName); - if(process == null) - { - LOG.info("Unrecognized process in help content", logPair("key", key)); - return; - } + processHelpContentForProcess(key, processName, fieldName, roles, helpContent); + } + else if(StringUtils.hasContent(widgetName)) + { + processHelpContentForWidget(key, widgetName, slotName, helpContent); - if(StringUtils.hasContent(fieldName)) - { - //////////////////////////// - // handle a process field // - //////////////////////////// - Optional optionalField = CollectionUtils.mergeLists(process.getInputFields(), process.getOutputFields()) - .stream().filter(f -> fieldName.equals(f.getName())) - .findFirst(); - - if(optionalField.isEmpty()) - { - LOG.info("Unrecognized process field in help content", logPair("key", key)); - return; - } - - if(helpContent != null) - { - optionalField.get().withHelpContent(helpContent); - } - else - { - optionalField.get().removeHelpContent(roles); - } - } } } catch(Exception e) @@ -230,6 +161,131 @@ public class QInstanceHelpContentManager + /******************************************************************************* + ** + *******************************************************************************/ + private static void processHelpContentForTable(String key, String tableName, String sectionName, String fieldName, Set roles, QHelpContent helpContent) + { + QTableMetaData table = QContext.getQInstance().getTable(tableName); + if(table == null) + { + LOG.info("Unrecognized table in help content", logPair("key", key)); + } + else if(StringUtils.hasContent(fieldName)) + { + ////////////////////////// + // handle a table field // + ////////////////////////// + QFieldMetaData field = table.getFields().get(fieldName); + if(field == null) + { + LOG.info("Unrecognized table field in help content", logPair("key", key)); + } + else if(helpContent != null) + { + field.withHelpContent(helpContent); + } + else + { + field.removeHelpContent(roles); + } + } + else if(StringUtils.hasContent(sectionName)) + { + //////////////////////////// + // handle a table section // + //////////////////////////// + Optional optionalSection = table.getSections().stream().filter(s -> sectionName.equals(s.getName())).findFirst(); + if(optionalSection.isEmpty()) + { + LOG.info("Unrecognized table section in help content", logPair("key", key)); + } + else if(helpContent != null) + { + optionalSection.get().withHelpContent(helpContent); + } + else + { + optionalSection.get().removeHelpContent(roles); + } + } + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private static void processHelpContentForProcess(String key, String processName, String fieldName, Set roles, QHelpContent helpContent) + { + QProcessMetaData process = QContext.getQInstance().getProcess(processName); + if(process == null) + { + LOG.info("Unrecognized process in help content", logPair("key", key)); + } + else if(StringUtils.hasContent(fieldName)) + { + //////////////////////////// + // handle a process field // + //////////////////////////// + Optional optionalField = CollectionUtils.mergeLists(process.getInputFields(), process.getOutputFields()) + .stream().filter(f -> fieldName.equals(f.getName())) + .findFirst(); + + if(optionalField.isEmpty()) + { + LOG.info("Unrecognized process field in help content", logPair("key", key)); + } + else if(helpContent != null) + { + optionalField.get().withHelpContent(helpContent); + } + else + { + optionalField.get().removeHelpContent(roles); + } + } + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private static void processHelpContentForWidget(String key, String widgetName, String slotName, QHelpContent helpContent) + { + QWidgetMetaDataInterface widget = QContext.getQInstance().getWidget(widgetName); + if(!StringUtils.hasContent(slotName)) + { + LOG.info("Missing slot name in help content", logPair("key", key)); + } + else if(widget == null) + { + LOG.info("Unrecognized widget in help content", logPair("key", key)); + } + else + { + Map widgetHelpContent = widget.getHelpContent(); + if(widgetHelpContent == null) + { + widgetHelpContent = new HashMap<>(); + } + + if(helpContent != null) + { + widgetHelpContent.put(slotName, helpContent); + } + else + { + widgetHelpContent.remove(slotName); + } + + widget.setHelpContent(widgetHelpContent); + } + } + + + /******************************************************************************* ** add a help content object to a list - replacing an entry in the list with the ** same roles if one is found. diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java index edab6c6e..03688222 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java @@ -29,6 +29,7 @@ import java.util.List; import java.util.Map; import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; +import com.kingsrook.qqq.backend.core.model.metadata.help.QHelpContent; import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon; import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRules; @@ -60,6 +61,8 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface protected Map icons; + protected Map helpContent; + protected Map defaultValues = new LinkedHashMap<>(); @@ -687,4 +690,35 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface return (this); } + + /******************************************************************************* + ** Getter for helpContent + *******************************************************************************/ + public Map getHelpContent() + { + return (this.helpContent); + } + + + + /******************************************************************************* + ** Setter for helpContent + *******************************************************************************/ + public void setHelpContent(Map helpContent) + { + this.helpContent = helpContent; + } + + + + /******************************************************************************* + ** Fluent setter for helpContent + *******************************************************************************/ + public QWidgetMetaData withHelpContent(Map helpContent) + { + this.helpContent = helpContent; + return (this); + } + + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaDataInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaDataInterface.java index 779658d3..1c702e39 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaDataInterface.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaDataInterface.java @@ -25,9 +25,11 @@ package com.kingsrook.qqq.backend.core.model.metadata.dashboard; import java.io.Serializable; import java.util.List; import java.util.Map; +import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.TopLevelMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; +import com.kingsrook.qqq.backend.core.model.metadata.help.QHelpContent; import com.kingsrook.qqq.backend.core.model.metadata.permissions.MetaDataWithPermissionRules; import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRules; @@ -38,6 +40,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRule *******************************************************************************/ public interface QWidgetMetaDataInterface extends MetaDataWithPermissionRules, TopLevelMetaDataInterface { + QLogger LOG = QLogger.getLogger(QWidgetMetaDataInterface.class); + /******************************************************************************* ** Getter for name *******************************************************************************/ @@ -228,6 +232,23 @@ public interface QWidgetMetaDataInterface extends MetaDataWithPermissionRules, T return (null); } + /******************************************************************************* + ** + *******************************************************************************/ + default Map getHelpContent() + { + return (null); + } + + + /******************************************************************************* + ** + *******************************************************************************/ + default void setHelpContent(Map helpContent) + { + LOG.debug("Setting help content in a widgetMetaData type that doesn't support it (because it didn't override the getter/setter)"); + } + /******************************************************************************* ** *******************************************************************************/ diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendWidgetMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendWidgetMetaData.java index 3d710251..374650bf 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendWidgetMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendWidgetMetaData.java @@ -31,6 +31,7 @@ import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.WidgetDropdownData; +import com.kingsrook.qqq.backend.core.model.metadata.help.QHelpContent; import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon; @@ -57,7 +58,8 @@ public class QFrontendWidgetMetaData private boolean showReloadButton = false; private boolean showExportButton = false; - protected Map icons; + protected Map icons; + protected Map helpContent; private final boolean hasPermission; @@ -92,6 +94,8 @@ public class QFrontendWidgetMetaData this.icons = qWidgetMetaData.getIcons(); } + this.helpContent = widgetMetaData.getHelpContent(); + hasPermission = PermissionsHelper.hasWidgetPermission(actionInput, name); } @@ -259,4 +263,15 @@ public class QFrontendWidgetMetaData { return tooltip; } + + + + /******************************************************************************* + ** Getter for helpContent + ** + *******************************************************************************/ + public Map getHelpContent() + { + return helpContent; + } } diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceHelpContentManagerTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceHelpContentManagerTest.java index 123c6392..6e52c49d 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceHelpContentManagerTest.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceHelpContentManagerTest.java @@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.instances; import java.util.List; import java.util.Set; import com.kingsrook.qqq.backend.core.BaseTest; +import com.kingsrook.qqq.backend.core.actions.dashboard.PersonsByCreateDateBarChart; import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction; import com.kingsrook.qqq.backend.core.actions.tables.InsertAction; import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction; @@ -37,13 +38,16 @@ import com.kingsrook.qqq.backend.core.model.helpcontent.HelpContent; import com.kingsrook.qqq.backend.core.model.helpcontent.HelpContentMetaDataProvider; import com.kingsrook.qqq.backend.core.model.helpcontent.HelpContentRole; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.help.HelpRole; import com.kingsrook.qqq.backend.core.model.metadata.help.QHelpContent; import com.kingsrook.qqq.backend.core.model.metadata.help.QHelpRole; +import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.TestUtils; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; /******************************************************************************* @@ -183,6 +187,40 @@ class QInstanceHelpContentManagerTest extends BaseTest + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testWidget() throws QException + { + ///////////////////////////////////// + // get the instance from base test // + ///////////////////////////////////// + QInstance qInstance = QContext.getQInstance(); + new HelpContentMetaDataProvider().defineAll(qInstance, TestUtils.MEMORY_BACKEND_NAME, null); + + ////////////////////////////////////////////////////////// + // first, assert there's no help content on the section // + ////////////////////////////////////////////////////////// + QWidgetMetaDataInterface widget = qInstance.getWidget(PersonsByCreateDateBarChart.class.getSimpleName()); + assertTrue(CollectionUtils.nullSafeIsEmpty(widget.getHelpContent())); + + HelpContent recordEntity = new HelpContent() + .withId(1) + .withKey("widget:" + widget.getName() + ";slot:label") + .withContent("i need somebody") + .withRole(HelpContentRole.ALL_SCREENS.getId()); + new InsertAction().execute(new InsertInput(HelpContent.TABLE_NAME).withRecordEntity(recordEntity)); + + /////////////////////////////////////////////////////////////////////////////////////////////// + // now - post-insert customizer should have automatically added help content to the instance // + /////////////////////////////////////////////////////////////////////////////////////////////// + assertTrue(widget.getHelpContent().containsKey("label")); + assertEquals("i need somebody", widget.getHelpContent().get("label").getContent()); + } + + + /******************************************************************************* ** *******************************************************************************/