Broadleaf Microservices
  • v1.0.0-latest-prod

Metadata Release Notes

2.0.8-GA

Spring Upgrade

  • As of Broadleaf Release Train 2.3.0-GA, support for Spring Boot 3.3 & 3.5 for all common libraries has been added.

Features/Notable Changes

  • Added new attribute augmentable to Component that allows to disable form modification for views. Defaults to true.

    • This attribute cascades to child components overriding their settings.

  • Introduce Global Components to the registry

    • Global components are reusable components that can be shared across multiple containers. For instance, defining a modal once that can be triggered by multiple links in one or more forms.

      Example Usage of Global component
      registry.addGlobalComponent("test-modal", Views.modalView()
             .label("Terms and Conditions")
             .addField("testField", Fields.string()
                  .label("Test Field")));
  • Added new DSL for defining Modal Views.

    • Introduced ModalView interface and Views.modalView() builder method.

    • ModalView is a specialized form view designed for modal dialog presentations.

    • ModalViewCreate and ModalViewUpdate interfaces can be used for entity creation and update scenarios.

  • Introduced new DSL for CheckboxField component.

    • Introduced CheckboxField interface and Fields.checkbox() builder method.

    • CheckboxField is used to represent a boolean value as a checkbox in forms.

  • Added new DSL for BadgeColumn and BadgeTileComponent.

    • Introduced BadgeColumn interface and Columns.badge() builder method.

    • Introduced BadgeTileComponent interface and TileComponents.badge() builder method.

    • BadgeColumn and BadgeTileComponent are used to display badges in grid views.

  • Introduced new Simple classifier for components to handle simple components that don’t require or support all of the configuration options of Form Components, Groups, Views, Externals, etc.

    • Simple components can be added to other components using Component#addSimpleComponent, which will autogenerate the key to be in the form simple:{type}:{order}. Generally this will be sufficient, but they can also be added like normal components and supplied a manually defined key.

  • Introduced a Divider component to render a horizontal rule within forms or groups.

    • Takes a width attribute, indicating the width of the horizontal rule—default is sm indicating 1px.

    • Takes a spacing attribute indicating the spacing above and below the rule in rem—default is md indicating 2rem.

      Example usage of Simple component
      Groups.basic()
              .label("product.groups.basic-information")
              .addField(ProductProps.NAME, Fields.string()
                      .label("product.fields.name")
                      .required()
                      .translatable()
                      .readOnly(!isCreate)
                      .hidden(!isCreate)
                      .order(1000))
              .addSimpleComponent(SimpleComponents.divider()
                      .order(1500)
                      .width(Divider.Width.SMALL)
                      .spacing(Divider.Spacing.MEDIUM))
  • Added a new DSL for LargeContentColumn and its default implementation DefaultLargeContentColumn. This renders a column for the LARGE_CONTENT type with large contents like embedded collections, which displays the content as truncated strings. The column value is clickable, which will show a modal with the full contents formatted similar to YAML style.

    • This component can take a lines attribute to configure the number of lines to truncate to for the column value. Out of box, the default value is 1 and the maximum value is 6.

    • There is also a clearLines() method that will clear the lines attribute from the column.

      Example usage of LargeContentColumn
      Fields.residentGrid()
              .label("sandbox.grid.change-summaries")
              .addColumn(SandboxProps.DETAILS, Columns.largeContentColumn()
                      .label("sandbox.columns.details")
                      .lines()
                      .order(1000))
  • Added a new DSL for ModalLinkColumn and its default implementation DefaultModalLinkColumn. This renders a column for the MODAL_LINK type whose column value is clickable, and upon clicking will show a modal form with the fields and components configured via metadata.

    • Aside from being able to add fields and components, the endpoint to submit the modal form to can be configured via metadata as well.

      Example usage of ModalLinkColumn
      Externals.grid()
              .label("product.externals.promotional-product")
              .scope(ProductScopes.PRODUCT)
              .sandboxTrackable(CatalogChangeContainers.PROMOTIONAL_PRODUCT)
              .catalogTrackable()
              .sortable()
              .addColumn(ProductProps.Marketing.TYPE, Columns.modalLink()
                      .label("Update Promotional Product")
                      .order(1000)
                      .sandboxTrackable(CatalogChangeContainers.PROMOTIONAL_PRODUCT)
                      .catalogTrackable()
                      .submitEndpoint(Endpoints.put()
                              .uri(ProductPaths.PROMOTIONAL_PRODUCT)
                              .scope(ProductScopes.PRODUCT))
                      .addField(ProductProps.Marketing.TYPE, Fields.select()
                              .label("Type")
                              .required()
                              .defaultValue(PromotionalProductTypeOptionEnum.FEATURED)
                              .options(PromotionalProductTypeOptionEnum.toOptions())
                              .order(1000))
                      .addField(ProductProps.Marketing.RELATED_PRODUCT_ID,
                              ProductLookupHelpers.createProductIdLookup()
                                      .label("Select a Product")
                                      .required()
                                      .order(2000))
                      .addField(ProductProps.Marketing.PROMOTION_MESSAGE, Fields.string()
                              .label("Promotional Message")
                              .translatable()
                              .order(3000)));
  • Added displayOnly and displayOnly(boolean displayOnly) attribute methods to the Field DSL in order to display it as a plain or raw text representation of the field.

  • Introduce FORM_FIELD column type.

    • This column type allows for inline editing of the row entity by displaying an editable form field in the column.

    • Changes are submitted on blurring the field (moving focus away from it or just toggling for a boolean).

    • It supports the following field types:

      • BOOLEAN

      • DATE

      • DECIMAL

      • INTEGER

      • LONG

      • LOOKUP

      • MONEY

      • PHONE

      • SELECT

      • STRING

        Example Usage of FORM_FIELD column
        externalGrid
            // define an update endpoint to perform the save operation
            .updateEndpoint(endpoint -> endpoint
                .uri(EntityPaths.ENTITY)
                .scope(EntityScopes.ENTITY))
            // add a form field column
            .addColumn(EntityProps.DATE, Columns.formField()
                .label("Date")
                .field(Fields.bool()
                    .name("date")
                    // required to avoid displaying decorations inside the grid cell
                    .decorated(false))
                .order(3000))
  • Added new DSL for MoneyTileComponent to display monetary amount fields on tile grids

  • Added new DSL for CheckboxField component type.

  • Updated EntityFormView to be able to configure an UPDATE endpoint on the form itself that overrides the parent View’s UPDATE endpoint

    Example usage of overriding the UPDATE endpoint per form
    UpdateEntityView view = Views.entityViewUpdate()
            .label("Update View")
            .submitUrl("/main-entity", Scopes.SCOPE)
            // ...
            .addForm("separateEntityForm", Views.entityForm()
                    .label("Form with External Related Entity")
                    .updateUrl("/external-entity", Scopes.EXTERNAL_SCOPE);
  • Improved support for ExternalFieldGroup

    Note
    This work was done in support of allowing a fields within an ExternalFieldGroup to be updated using a form’s override update endpoint where the actual parent entity’s state wasn’t being modified and wouldn’t be returned from the submit endpoint, which was in a different microservice.
    • Added explicit DSL support for ExternalFieldGroup

    • Updated ExternalTypes & Externals to be able to expose the DefaultExternalFieldGroup DSL for metadata configuration

    • Added attributes map to Endpoints metadata with relevant helper methods

    • Added Endpoint attribute, responseIsPartialState: Indicates that this endpoint’s response will be a partial state that should be merged with the existing entity state, similar to a PATCH request. This is useful for APIs that do not support PATCH requests directly or that are backing external field groups on a different entity’s form. In those cases, the parent entity state should be merged with the new state returned by the endpoint to maintain the full view state.

    • Fixed Groups not getting their IDs set when using Form#addGroup(String type, Group<?> group)

    • Expanded javadocs on various metadata DSL interfaces

    • Added attribute to ExternalFieldGroup, useParentFormState. Indicates that the state for the fields in this group will be backed by the parent form’s.

    • If false, then a nested form state will be created to hold the field values in isolation from the parent. Note that this currently makes the group effectively read-only.

    • If true, then users should ensure that the field names are prefixed with the Group.getId() since this is used in the admin to ensure that the values do not collide with other fields in the parent form. TransformBody and MappingList can be used to map the form state to the appropriate structure expected by the form or entity submit endpoint (if any) and vice versa.

      Example Usage of ExternalFieldGroup
      public void exampleUsage() {
          form.updateEndpoint(Endpoints.post()  // <-- overrides the View's endpoint
                  .responseIsPartialState()
                  .uri("/dto-endpoint")
                  .transformRequest(t -> t.mappings(transformEntityToRequestDto("externalGroupId")))
                  .transformResponse(t -> t.mappings(transformEntityFromRequestDto("externalGroupId")))
                  .scope("DTO"))
                  .addGroup("externalGroupId", getExternalGroup());
      }
      
      public static MappingList transformEntityToRequestDto(String groupId) {
          return new MappingList(Arrays.asList(
                  Mappings.mapValue("%s.%s".formatted(groupId, "field1"), "field1"),
                  Mappings.mapValue("%s.%s".formatted(groupId, "field2"), "field2"),
                  Mappings.mapValue("%s.%s".formatted(groupId, "field3"), "field3")));
      }
      
      public static MappingList transformEntityFromRequestDto(String groupId) {
          return new MappingList(Arrays.asList(
                  Mappings.mapValue("field1", "%s.%s".formatted(groupId, "field1")),
                  Mappings.mapValue("field2", "%s.%s".formatted(groupId, "field2")),
                  Mappings.mapValue("field3", "%s.%s".formatted(groupId, "field3")));
      }
  • Added DateRangeColumn class to define a type of column that takes in a start date and end date to display a date range.

  • Added a DurationColumn class to define a type of column that takes in an integer value and displays it in a user-friendly format.

    • Includes a baseUnits attribute to specify the base units of the given duration.

    • Introduced DurationBaseUnits utility class to define the available base units:

      • DAY

      • WEEK

      • MONTH

      • YEAR

        Example Usage:
        grid
            .addColumn(DURATION, Columns.duration()
                    // The duration will be displayed in days
                    .baseUnits(DurationBaseUnits.DAY));
  • Added support for date fields to be computed based on another date field and a duration, e.g., allow active end date to be computed as the active start date plus 30 days.

    • Added computedFromDate, computedFromDuration, and computedFromDurationUnit attributes to the DateField, along with corresponding DSL methods.

      Example Usage:
      form
          // Add a duration field that will be used to compute the end date
          .addField(DURATION, Fields.duration())
          // Add a start date field
          .addField(ACTIVE_START_DATE, Fields.date())
          // Add an end date field that will be computed based on the start date and duration field
          .addField(ACTIVE_END_DATE, Fields.date()
                  .computedFrom(
                          ACTIVE_START_DATE,
                          OFFER_DURATION,
                          // Specify the base units for the duration field
                          DurationBaseUnits.DAY
                      )
                  );
  • Added new DSL methods to CreateEntityView to configure toast notifications to display on succesful create of an entity:

    • Introduced successNotificationOnCreate() method to configure a success notification with a default message.

    • Introduced successNotificationOnCreate(String message) method to configure a success notification with a custom message.

    • Introduced successNotificationOnCreate(InternationalizedMessage message) method to configure a success notification with a custom internationalized message.

  • Added new iconName DSL method to allow setting a custom icon to be displayed by the following components:

    • FilterAction

    • CommonStartExportAction

    • ExportGridAction

    • ImportGridAction

    • See Import Services 2.1.1 for StartImportAction component changes.

  • Added ComputedField & DefaultComputedField DSL support for Form components to allow defining fields whose values are computed based on other field values using a specified function. .Example Usage:

form
    .addField("shopPrice", Fields.money()
            .label("Shop Price")
            .validationSchema(ValidationSchemas.money()
                    .method(ValidationMethods.positive(
                            "Must be positive")))
            .order(1000))
    .addField("shopMarkup", Fields.money()
            .label("Shop Markup")
            .validationSchema(ValidationSchemas.money()
                    .method(ValidationMethods.positive(
                            "Must be positive")))
            .order(2000))
    .addField("productMarkup", Fields.money()
            .label("Product Markup")
            .validationSchema(ValidationSchemas.money()
                    .method(ValidationMethods.positive(
                            "Must be positive")))
            .order(3000))
    .addField("finalPrice", Fields.computed()
            .label("Final Price")
            .computationType(ComputedField.ComputationTypes.SUM)
            .fieldsToCompute(List.of("shopPrice", "shopMarkup", "productMarkup"))
            .order(4000));
  • Added ToggleTileComponent as a new type of TileComponent that represents a boolean value as a toggle switch on a tile grid. .Example Usage:

browseComponent.getDefaultGrid()
        .addTileComponent("thumbnail", TileComponents.thumbnail()
                .toggle(TileComponents.toggle()
                        .name("featured")
                        .label("product.browse.columns.featured")
                        .icon("star")
                        .submitEndpoint(endpoint -> endpoint
                                .uri(ProductPaths.TOGGLE_FEATURED_TAG)
                                .scope(ProductScopes.PRODUCT)
                                .param("toggleValue", "${toggleValue}"))
                        .order(1000)));
  • Added skipSandboxing attribute to GridExternal. This allows grids that pull data from external sources to opt out of sandboxing if the external source is not expected to be affected by sandboxing or if the grid is intended to show unsandboxed data for some reason.

  • Introduced InterdependentExternalGridsGroup concept to allow grouping together multiple instances of GridExternal that are related to each other and have interdependent data such that they should have their state changes tracked together in the admin and be displayed together in the UI.

    • For instance, this can be used for a group of grids that all pull from the same external source and should be tracked together in the admin since they will all be affected by the same external state changes, or if a change in one grid should trigger a refresh in the other grids since they are related and likely displayed together in the UI.

    • The following methods & attributes were added to support this feature:

      • listensFor(Map<String, List<String>>) & listensForGridsAndOperations: This method adds the listensForGridsAndOperations attribute and configures the other external grids within the InterdependentExternalGridsGroup that this grid will be listening for. This means that if a change is made to any of the configured grids, then this grid will be refreshed (i.e. the configured READ endpoint for the grid will be called). Operations can also be defined for each dependent grid to allow for conditional updates, but are not required. The operations are expected to be GridExternal.GridListenerOperations so that this grid is refreshed depending on the operation done on the grid being listened to. .Example Usage:

private Group<?> getPromotionsGroup() {
        return Groups.interdependentExternalGrids()
        .addExternal("CURRENT_PROMOTIONS", Externals.grid()
                .id("CURRENT_PROMOTIONS")
                .label("Current Promotions")
                ...
                .listensFor(Map.of("UPCOMING_PROMOTIONS", List.of())))
        .addExternal("UPCOMING_PROMOTIONS", Externals.grid()
                .id("UPCOMING_PROMOTIONS")
                .label("Upcoming Promotions")
                ...
                .listensFor(Map.of("CURRENT_PROMOTIONS", List.of(GridExternal.GridListenerOperations.ON_CREATE))));
}
  • Added the readOnSuccess attribute to ModalFormAction to specify whether a re-fetch should be executed after the modal form action is successfully executed. The read endpoint that is configured for the grid will be used to trigger this re-fetch.

2.0.7-GA

Features/Notable Changes

New Component System for Tiled Grid Views

  • Introduced support for defining tile*based UI components within the metadata DSL.

  • Added the TileComponent interface and supporting types.

  • Created the TileGrid interface to enable grid views with tile support.

  • Provided default implementations:

    • DefaultTileComponent

    • DefaultLinkTileComponent

    • DefaultThumbnailTileComponent

  • Added specialized interfaces:

    • LinkTileComponent

    • ThumbnailTileComponent

  • Introduced utility classes:

    • TileComponentTypes for standard tile types.

    • TileComponents for convenient creation of tile components.

    • AbstractTileComponent as a base class for custom tiles.

  • Updated Classifiers to include a TILE_COMPONENT identifier.

  • Extended EntityGridView to support TileGrid features.

    Example Usage:
    EntityGridView<?> entityGridView = productGrid
                    ...
                    .tiled(Arrays.asList(
                            TileComponents.thumbnail()
                                    .name(ProductProps.PRIMARY_ASSET_URL_SEARCH)
                                    .order(1000),
                            TileComponents.linkById("catalog:products:${businessType}:update")
                                    .name(ProductProps.NAME)
                                    .label("product.columns.name")
                                    .order(2000)))
                    .defaultTiled()
                    ...

Enhancements

  • Added support for specifying additional form state fields and response fields in SlideOverFormAction, allowing more flexible data transfer between actions and forms. Introduced new methods additionalFormState and additionalResponseFields to facilitate this functionality.

  • Introduced LOOKUP column type.

  • Added support for restricting routes by matching all security scopes not just any.

    • The previous default behavior when matching a Route’s security scopes was to match any.

    • ComponentRoute now has a scopeMatchType property that can be set to either ANY or ALL, with ANY as the default.

    • Related changes have been made to Admin Metadata Service 2.1.4-GA.

      Example Usage
      @Bean
      public ComponentRouteLocator productMetadataRoutes(RoutesBuilder routesBuilder) {
          RoutesSpec routes = routesBuilder.routes()
                  .route("/products", r -> r.componentId("catalog:porducts:browse")
                          .scope("PRODUCT")
                          .scope("CUSTOM_ADMIN_VIEW_SCOPE")
                          .allMatchScopes(); // <-- NEW, default is `.anyMatchScopes()`
          return routes.build();
      }
  • Deprecate the Pricing Consumer Metadata Module

    • The use of this module produced unwanted coupling between separate consumer services and versions, so it was deprecated for ease of customization across the affected services' views.

    • Important: All the metadata contained in this module is now defined by the consumer services themselves.

  • Added new attributes to EntityGridView to support restricting visibility of grids to tenant-only, application-only, or specific application contexts.

    • tenantOnly: Boolean flag.

    • applicationOnly: Boolean flag.

    • restrictionApplications: Array of strings that are the IDs of the applications the grid is restricted to.

  • Added support for UpdateEntityView to be able to define a confirmation message on the view that will be displayed in a confirmation dialog when the user attempts to submit changes from the view that will affect dependent entities.

    • Added the following attributes & methods to UpdateEntityView to support this feature:

      • confirmDialogBtnLabel - The preferred label of the confirmation dialog submit/confirm button.

      • confirmationDialogConfirmed - The key of the value that will be set on the submission request context when the user confirms the dialog, which can be used to conditionally perform logic in the endpoint based on whether the user confirmed or not.

      • confirmDialogMessage - The message to be displayed in the confirmation dialog when triggered.

      • confirmDialogTitle - The title to be displayed in the confirmation dialog when triggered.

      • dependentEntities - A map of entity types that are mapped to their respective endpoints that will be used to fetch the details of existing dependent entities that match the given types.

      • dependentEntitiesAction & dependentEntitiesLabel - The action configuration and label for an optional action that will be displayed in the the UpdateEntityView that allows users to view the dependent entities that will be affected by the update operation. This is intended to help users make informed decisions when confirming the dialog by allowing them to see what entities will be affected by their action

      • showConfirmationDialog - A boolean flag to indicate whether to show the confirmation dialog or not. .Example Usage

 Views.entityLongFormViewUpdate()
      ...
       .submitEndpoint(endpoint -> endpoint
                       .uri(Paths.URI)
                       .scope(Scopes.SCOPE)
                       .param("acceptedConfirmationDialog", "${$confirmationDialogConfirmed}"))
        .confirmationDialog("entity.update.confirm-dialog.title",
                       "entity.update.confirm-dialog.message",
                        "entity.update.confirm-dialog.button-label",
                      "$confirmationDialogConfirmed")
        .dependentEntity("PRODUCT", Endpoints.get()
                        .uri(ProductPaths.PRODUCTS_IGNORE_CATALOG_NARROWING)
                        .scope(ProductScopes.PRODUCT)
                        .param("cq", "businessType=eqic=(${typeKey})"))
        .dependentEntitiesLabel("business-type.update.actions.dependent-entities")

2.0.6-GA

Features/Notable Changes

  • Introduce rowMessage concept to Grid.

  • Introduce support for a 'notification' message type in Messages/MessageTypes.

  • Introduce SlideOverFormAction concept.

  • Update ResidentGridField to have CREATE_VIEW and UPDATE_VIEW action types.

  • Update PropertyConditional to support empty, notEmpty, and blank conditions.

  • Introduce maxRows concept to FieldArrayGridField.

  • Introduce Orderable interface to FieldArrayGridField.

  • Introduce new enums, properties, and form fields to support new PriceData concepts from PricingServices 2.1.0.

  • Added first class support for allowCustomFields attribute for rule and query builders.

  • Introduce new metadata dsl for EntityAssetCollections to make use of new drag-and-drop sorting in the admin.

  • Added custom CSS support to grids.

  • Added metadata changes to allow hints and help texts on select grids.

  • Introduce support for InlineGridSelectAction that will display a list of options to select from.

  • Added conditional price data view types to split subscription and non-subscription price data metadata components.

  • Updated pricing metadata to support various pricing strategies.

  • Added auditable behavior attribute flags for metadata components.

  • Fix behavior of orderable, selectable, and sortable grid options

    • A bug in this behavior caused some grids to not be disabled when set as disabled in the metadata.

  • Add explicit support for EnumSwitchField.

    • This is a special field used to display enumerated values in a boolean-like toggle switch.

  • Added support to MoneyColumn to display simple values.

    • This makes it comparable with MoneyField to allow displaying decimal fields that inherit currency from the parent entity.

  • Introduced AddAdjustmentModalFormAction as secondary action for the UpdateEntityView.

  • Added a secondary action to display a basic modal form with submit support.

    • Registered a new FORM secondary action for entity views that simply renders a form configured via metadata and allows submitting to an endpoint.

  • Enhanced the default ComponentRegistry to register components with case-insensitive keys.

2.0.5-GA

Features/Notable Changes

  • Added collapseFiltersByDefault attribute to FilterableGrid to control whether the filters in a grid should be collapsed by default

2.0.4-GA

Features/Notable Changes

  • Amended export related metadata to accommodate new filter parameters and fields

    • Added ability to define passFilterStringAsParam attribute for SelectTargetEntityGridView and ExportGridAction.

    • Set passFilterStringAsParam attribute to false by default for ExportGrid.

    • Deprecated filterTargetEntities for filterTargetEntitiesField, which adds QueryBuilderField as a field to SelectTargetEntityGridView for the passing of a filter to the export endpoint.

    • Added ability to fetch all fields from QueryBuilderFilterAction.

    • Added new URI/endpoint definitions to CommonStartExportAction for starting an export that includes the filter string from the QueryBuilderField as the filter parameter value for backwards compatibility.

  • Amended Grid validation logic to allow SelectTargetEntityGridView to have QueryBuilderField as a field component without having to be a column component

2.0.3-GA

Features/Notable Changes

  • Added ability to define displayShowInQueryBuilder attribute for AugmentableView.

2.0.2-GA

Features/Notable Changes

  • Added ability to define refreshButton attribute for FetchGrid.

2.0.1-GA

Important
Requires AdminWeb 1.10.7 for admin compatibility.

Features/Notable Changes

  • Added support to use Search Facets on Entity Browse List Grids.

    • Allowed defining attribute to enable faceted search, useFacetedSearch

    • Allowed defining a fallback endpoint to use if search is disabled or in a problem state

      • This may be configured similarly to any read endpoint using #fallbackEndpoint builder methods.

    • Allowed defining search-appropriate parameters for the main read endpoint

      • FilterableGrid.FilterParams#FACET_RULES: Allows passing Facet Rules to Search. Value is cq.

      • FilterableGrid.FilterParams#FACETABLE_TYPE: Allows passing the indexable type to Search. Value is indexableType.

      • FilterableGrid.FilterParams#FACET_QUERY: Allows passing regular a text query. Value is query.

        entityGridView
                // for fallback endpoint
                .filterByTextQuery(FilterableGrid.FilterParams.QUERY,
                        UnaryOperator.identity(),
                        FilterableGrid.EndpointTypes.FACETED_SEARCH_FALLBACK)
                .filterByQueryBuilder(FilterableGrid.FilterParams.QUERY_BUILDER,
                        UnaryOperator.identity(),
                        FilterableGrid.EndpointTypes.FACETED_SEARCH_FALLBACK)
                .facetedSearch("PRODUCT",
                        readEndpoint -> readEndpoint
                                .narrowedPaging()
                                .uri(ProductPaths.PRODUCTS)
                                .scope(ProductScopes.PRODUCT))
                .readEndpoint(readEndpoint -> readEndpoint
                        .numberedPaging()
                        .uri(ProductPaths.CATALOG_SEARCH)
                        .scope(ProductScopes.PRODUCT));
  • Enable search group tracking & discrimination via metadata

    • This works similarly to Catalog and Profile discrimination using searchGroupTrackable().

      DefaultSearchSettingsFormView formView = new DefaultSearchSettingsFormView()
              .searchGroupTrackable()
              .sandboxTrackable(SearchSettingsChangeContainers.SEARCH_SETTINGS)
              .addExternal(SearchSettingsGrids.FACET_GROUPS, Externals.grid()
                      .id("facetGroups")
                      .label("search-settings.external-grid.facet-groups")
                      .searchGroupTrackable()
                      .sandboxTrackable(
                              SearchSettingsChangeContainers.SETTINGS_FACET_GROUP));
  • Allow adding Form Views to EntityBrowseView easily Forms added to views will appear as separate "tabs".

  • Added support for defining "Action Groups" on ActionGrids. These are used to create a dropdown with the included actions rather than listing them in line in the grid header.

    .addGridActionGroup("Bulk Operations",
            Actions.bulkAction()
                    .bulkOperationType("SET_ACTIVE_PRODUCT")
                    .entityType(entityType)
                    .generateFriendlyName()
                    .label("product.bulk-operation.update-active")
                    .addField(ProductProps.ONLINE, Fields.bool()
                            .label("product.columns.online")
                            .required())
                    .addField(ProductProps.ACTIVE_START_DATE, Fields.date()
                            .label("product.fields.active-start-date"))
                    .addField(ProductProps.ACTIVE_END_DATE, Fields.date()
                            .label("product.fields.active-end-date")
                            .validationSchema(ValidationSchemas.date()
                                    .method(ValidationMethods.isAfter(
                                            "product.fields.active-end-date.must-be-after")
                                            .arg(ProductProps.ACTIVE_START_DATE))))
                    .addSubmitEndpoint(Endpoints.post()
                            .uri(BulkOperationPaths.EXECUTE_BULK_OPERATION)
                            .scope(BulkOperationScopes.BULK_OPERATION)),
            Actions.bulkAction()
                    .bulkOperationType("ARCHIVE_PRODUCT")
                    .entityType(entityType)
                    .generateFriendlyName()
                    .label("product.bulk-operation.archive")
                    .addGroup("warning", Groups.inline()
                            .addMessage("deleteWarning", Messages.warningMessage()
                                    .message("product.bulk-operation.archive.warning")
                                    .order(1000)))
                    .addSubmitEndpoint(Endpoints.post()
                            .uri(BulkOperationPaths.EXECUTE_BULK_OPERATION)
                            .scope(BulkOperationScopes.BULK_OPERATION)))
  • Added support for "singleValue" flag to the ResidentMapField and removed grid column validation if the grid has the "singleValue" attribute.

2.0.0-GA

Spring Boot Upgrade

  • As of Broadleaf Release Train 2.0.0-GA, all common libraries have been upgraded to Spring Boot 3.

  • This version includes all changes up to 1.7.16-GA

Release Notes for 1.7.16-GA

Features/Notable Changes

  • Added new Action class ConditionalAction to allow for rendering actions based on specified conditions.

    • This is currently only implemented for secondary entity actions.

Bug Fixes

  • Added missing locale definitions for correct metadata rendering

Release Notes for 1.7.15-GA

Features/Notable Changes

  • Added Message metadata classifier and class

    • Added WARNING message type

  • Added type field to ExplanatoryMessage metadata class

  • Changes to ImplicitFilter metadata:

    • Added attributes map field.

    • Added attribute and removeAttribute methods.

  • Add support to build implicit filters using metadata

    • Added targetField, operator, objectPath, and objectAttributeKey metadata attributes to ImplicitFilter

    • The values specified by these attributes will later be used to dynamically build a query string, for instance:

      • The following metadata definition of an implicit filter

    ----
    .implicitFilters(ImplicitFilter.customFilter("cq")
        .targetField("contextId")
        .operator("=out=")
        .objectPath("parent.$parent.isolatedCatalogs")
        .objectAttributeKey("id"))
    ----
  • Will result in a cq string result like the following: contextId=out=(isolatedCatalogId1,isolatedCatalogId2,isolatedCatalogId3)

  • If the system fails to build a filter string using these attributes, the implicit filter will not be added

    • Add MODAL_SIZE attribute to ModalFormAction

Bug Fixes

  • Fix price data showing incorrect currency due to missing components in PriceDataHelpers

    • Add PRICE_LIST_CURRENCY to PriceDataProps

    • Add CURRENCY to PriceListProps

Release Notes for 1.7.14

Features/Notable Changes

  • Update LookupField metadata to add catalog selector attributes

  • Improved DerivedFields:

    • Allow derived values other than strings. Use .fieldType(String). Default is DerivedField.SupportedFieldTypes.STRING.

      • Boolean, Color Picker, Date, Decimal, HTML, Integer, Long, Money, String Array, and Text Area

    • Allow specifying more transformation types for strings

      • Upper, lower, start, and pascal case and capitalize

    • Allow specifying if a derived field’s value should actually be persisted or if the derived value should merely be displayed. Use .persist(boolean). Default is true.

  • Added DerivedColumn component:

    • Takes a source and columnType similar to DerivedField

    • Can set deriveIfNull to allow deriving the value if the column’s value is null

    • Does not support transformations like DerivedField

  • Added applicationTrackable flag to Trackable

  • Added decorated flag to Field

  • Added creatable and catalogSelector flags to LookupField

Release Notes for 1.7.13

  • Notes consolidated with 1.7.14

Release Notes for 1.7.12

Bug Fixes

  • Updated validation methods to skip endpoint and orderable checks on resident grids

    • Fixes startup validation warnings that do not apply to resident grids

Release Notes for 1.7.11

Features/Notable Changes

  • Updated Option Template terminology from "generate" to "add"

  • Support only ISO 639-1 two-letter language code and ISO 3166 two-letter country code based locales for Broadleaf system compatibility when using the SelectOption for all available languages.

Bug Fixes

  • Fixed external form components to have read-only properties

Release Notes for 1.7.10

Features/Notable Changes

  • Add java documentation on how to swap the colors for the boolean Column

Release Notes for 1.7.9

Features/Notable Changes

  • Support adding templates by reference

  • Added support for none-type for derived fields

Release Notes for 1.7.8

Bug Fixes

  • Added supported validation methods and brief docs

Release Notes for 1.7.7

Features/Notable Changes

  • Added JDK 17 support

Release Notes for 1.7.6

Features/Notable Changes

  • Make individual validation errors more visible

  • Add color attribute to RowModalFormAction

  • Add filter key to param map endpoint

Bug Fixes

  • Fixed ComponentValidatorManager not reporting the actual errors by printing the actual individual error messages from the Validator

  • Fixed readonly conditionals issue

Release Notes for 1.7.5

Features/Notable Changes

  • Added quantity information to RuleBuilders

Release Notes for 1.7.4

Features/Notable Changes

  • Added RSQL rule column type

Release Notes for 1.7.3

Features/Notable Changes

  • Added SpEL rule column type

Release Notes for 1.7.2

  • Added support for arabic translations

  • Added support for view filters

Release Notes for 1.7.1

  • Add ability to show or hide a label

  • Support flag indicating a rule-builder can target a collection

  • Support toggle for integer fields where 0 means unlimited

Release Train Compatibility

Compatible with all Release Trains after 1.7 unless otherwise noted.