[BLOSSOM-202] Customize tab sorting Created: 17/Feb/15  Updated: 13/Nov/15  Resolved: 06/Mar/15

Status: Closed
Project: Blossom
Component/s: None
Affects Version/s: 3.0.4, 3.0.5
Fix Version/s: 2.0.8, 3.0.6

Type: Improvement Priority: Critical
Reporter: Frank Sommer Assignee: Tobias Mattsson
Resolution: Fixed Votes: 0
Labels: support
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Relates
relates to BLOSSOM-228 Compatibility with new I18n API Closed
Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Date of First Response:

 Description   

The ordering of dialog tabs with the TabOrder annotation does not work properly. Reason is that the sortTabs method uses for comparing the internationalized tab labels instead of the static tab names.

@see info.magnolia.module.blossom.dialog.DefaultDialogCreator#sortTabs



 Comments   
Comment by Tobias Mattsson [ 20/Feb/15 ]

I fail to reproduce this.

Sorting of tabs is indeed done on the tab labels. Blossom will set the name and the label of a tab to the same value. The value specified in the @TabFactory annotations. This value can be a key into a message bundle for i18n. Sorting of tabs happens before resolving such message keys so the order should not be influenced or disrupted by what the keys translate to.

In this example the tab with label 'label.tab1' will be the first one regardless what it translates to.

@I18nBasename("com.acme.message")
@TabOrder({"label.tab1", "label.tab2"})
public class TextComponent {

    @TabFactory("label.tab2")
    public void contentTab2(UiConfig cfg, DamConfig dam, TabBuilder tab) {}

    @TabFactory("label.tab1")
    public void contentTab(UiConfig cfg, DamConfig dam, TabBuilder tab) {}
}
Comment by Frank Sommer [ 24/Feb/15 ]

The usage of the label for sorting is confusing. So the tab name should be used instead. If you specify the label of the tab in an additional call, the ordering does not work like expected.

@DialogFactory("homeProperties")
@TabOrder({"intro", "section"})
public class HomePropertiesDialog {

    @TabFactory("intro")
    public void createContextTab(UiConfig cfg, TabBuilder tab) {
        tab.label("dialogs.homeProperties.intro.tab");
        tab.fields(...);
    }

    @TabFactory("section")
    public void createContextTab(UiConfig cfg, TabBuilder tab) {
        tab.label("dialogs.homeProperties.section.tab");
        tab.fields(...);
    }
    
    ...
}
Comment by Tobias Mattsson [ 24/Feb/15 ]

Hi Frank,

The string you give to TabFactory is the label. Names of tabs are rarely used in Blossom.

When using i18n keys you should use them in both annotations.

You've probably observed that TabFactory will also set the tab name, that's because the tabs have to have name, so their names are set to their labels.

Your example of using names instead is actually quite compelling. Unfortunately this decision was made a long time ago and changing it would break every Blossom based project out there.

What I can do though is make the sortTabs() method protected so that you can customize it to your liking. The fact that TabFactory also sets the name will allow you to use your example as is.

import info.magnolia.ui.dialog.definition.FormDialogDefinition;
import info.magnolia.ui.form.definition.TabDefinition;

import java.util.Collections;
import java.util.Comparator;

import org.apache.commons.lang.ArrayUtils;

public class MyCustomDialogCreator extends DefaultDialogCreator {

    @Override
    protected void sortTabs(FormDialogDefinition dialog, final String[] order) {
        Collections.sort(dialog.getForm().getTabs(), new Comparator<Object>() {

            @Override
            public int compare(Object o1, Object o2) {
                switch (((o1 instanceof TabDefinition) ? 2 : 0) + ((o2 instanceof TabDefinition) ? 1 : 0)) {
                case 0:
                    return 0;
                case 1:
                    return -1;
                case 2:
                    return 1;
                case 3:
                    return ArrayUtils.indexOf(order, ((TabDefinition) o1).getName()) - ArrayUtils.indexOf(order, ((TabDefinition) o2).getName());
                }
                return 0; // Will never happen
            }
        });
    }
}

To configure the custom DialogCreator do this:

<bean id="templateExporter" class="info.magnolia.module.blossom.template.TemplateExporter">
  <property name="dialogDescriptionBuilder">
    <bean class="info.magnolia.module.blossom.dialog.DialogDescriptionBuilder">
      <property name="dialogCreator">
        <bean class="MyCustomDialogCreator" />
      </property>
    </bean>
  </property>
</bean>

<bean id="dialogExporter" class="info.magnolia.module.blossom.dialog.DialogExporter">
  <property name="dialogDescriptionBuilder">
    <bean class="info.magnolia.module.blossom.dialog.DialogDescriptionBuilder">
      <property name="dialogCreator">
        <bean class="MyCustomDialogCreator" />
      </property>
    </bean>
  </property>
</bean>
Comment by Tobias Mattsson [ 13/Nov/15 ]

BLOSSOM-228 proposes a change that addresses this issue with a solution that does not require subclassing.

Generated at Sun Feb 11 23:31:09 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.