Jira 9.9 EAP 01 is now on hand!

Hi, @DariaShatsylo ~ Jira 9.9 has Breaking changes for our app JMCF. The breaking changes are during the Custom Field configurations.

1. What has changed

The old UI, up to Jira 9.8.1 (included) used to list all the custom field contexts one by one with all the configuration options returned by List<FieldConfigItemType> getConfigurationItemTypes(), as shown below

With Jira 9.9 the UI has been implemented in React and uses an AtlasKit Dynamic Table to render the contexts and their configuration.
This is already a significant change, since the available horizontal space for each configuration item has been drastically reduced, but there are other challenges that we’ll see very soon.

Those changes are in jira/secure/admin/views/customfields/configurecustomfield.jsp , where we can also find that there’s an isUiLegacy flag to use the old UI.
In ConfigureCustomField#getIsUiLegacy we see that a global feature flag is used, so we can’t toggle that behavior for a single extension:

  public boolean getIsUiLegacy() {
    return !this.featureManager.isEnabled(JiraFeatureFlagRegistrar.CUSTOM_FIELDS_CONFIGURE_MODERN_UI);
  }

2. What is broken :broken_heart:

2.1. The process :business_suit_levitating:

This is not mentioned at all in the Preparing for Jira 9.9 page. Why?

2.2. The layout :lipstick:

Custom fields with multiple configuration items are displayed in a suboptimal way, requiring the user to scroll even on very large screens.

2.3. The code itself :writing_hand:

Let’s see what is going on with configurecustomfield.jsp, in the ww:else block, i.e. the new UI

<ww:else>
    <custom-field-configure-panel data-field-id="<ww:property value="fieldId"/>">
        <ww:iterator value="/configs" status="'status'">
            <ww:iterator value="./configsByConfig" status="'status'">
                <ww:iterator value="./key/configItems" status="'rowStatus'">
                    <div data-context-scheme-id="<ww:property value="../id"/>" data-context-scheme-column-name="<ww:text name="displayNameKey"/>" style="display: none;">
                        <ww:property value="viewHtml(null)" escape="false" />
                        <ww:if test="baseEditUrl && /fieldConfigureAvailable == true"><a id="<ww:property value="/fieldId"/>-edit-<ww:property value="objectKey"/>" class="actionLinks subText" href="<ww:url value="baseEditUrl"><ww:param name="'fieldConfigSchemeId'" value="../id" /><ww:param name="'fieldConfigId'" value="../key/id" /><ww:param name="'returnUrl'">ConfigureCustomField!default.jspa?fieldId=<ww:property value="/fieldId" /></ww:param></ww:url>">
                            <ww:text name="'admin.customfields.edit.value'"><ww:param name="'value0'"><ww:text name="displayNameKey" /></ww:param></ww:text></a>
                        </ww:if>
                    </div>
                </ww:iterator>
            </ww:iterator>
        </ww:iterator>
    </custom-field-configure-panel>
</ww:else>

Focus on this line:

`<div data-context-scheme-id="<ww:property value="../id"/>" data-context-scheme-column-name="<ww:text name="displayNameKey"/>" style="display: none;">`

Each configuration item is rendered using the template provided in getConfigurationItemTypes and hidden using CSS.
Also, since the code is looping over the available contexts, all the config items are stacked next to each other without any separation, which means that we can’t just inject a JS file to strip the display: none clause, otherwise we’d get a confusing mess in which the user doesn’t know which config item is related to which context, see below:

2.3.1. Wait, what?

An astute reader might have noticed that in the second screenshot in this page, the configuration options for PCFU’s SIL script fields are shown in the table, each correctly rendered in the row for the right context, and in the JMCF example there are a bunch of configuration columns, where do they come from and why would someone care about those hidden div elements?

The code for the React component that handles custom-field-configure-panel is minified and I don’t have a license to get Jira’s source code, so I can only guess that it’s parsing the DOM and moving the content of those hidden elements to dynamic columns in the contexts table, unfortunately, the behavior is extremely buggy.

With the old UI, custom fields can render custom HTML without limitations, including custom to the renderer for the “Search template” config item and all the columns after it are not shown, and neither is any configuration element for the second row: they’re available in the DOM with their hidden div elements. Notably, the elements for “Groovy formula”, “Format expression” and “Search template” items for the first context have been removed from the DOM, which suggests that there’s some kind of manipulation going on with those elements.

3. Workarounds and remediation :interrobang:

If your app needs tags in your configuration item types templates, the only way to do it is to inject a JS file globally, but you won’t have access to the Velocity context, FieldLayoutItem and all the other goodies inherited from FieldConfigItemType

If your custom fields have many configuration items, you probably need to combine them to prevent horizontal overflows

4. Atlassian pls:

It would be decently good if we could configure on a field level which layout to use

Thank you.

7 Likes