In this post, we will take a closer look at the way to perform modifications and adjustments that will allow us to properly visualize a new item on the common backoffice perspective.

Initial settings

c4tunebackoffice

Dedicated extension created with ant extgen using ybackoffice template.

C4Tune

Item created with the definition …

<itemtype code="C4TuneItem" autocreate="true" generate="true">
   <deployment table="c4tuneitem" typecode="11000"/>
   <attributes>
      <attribute qualifier="c4TuneItemString" type="java.lang.String">
         <persistence type="property"/>
      </attribute>
      <attribute qualifier="c4TuneItemBoolean" type="java.lang.Boolean">
         <persistence type="property"/>
      </attribute>
      <attribute qualifier="c4TuneItemCustomerItem" type="Customer">
         <persistence type="property"/>
      </attribute>
   </attributes>
</itemtype>

… including localization entries:

type.C4TuneItem.name=C4Tune Item
type.C4TuneItem.c4TuneItemString.name=C4Tune Item String
type.C4TuneItem.c4TuneItemBoolean.name=C4Tune Item Boolean
type.C4TuneItem.c4TuneItemCustomerItem.name=C4Tune Item Customer

Tip: The key for this excercise is to modify and adjust backoffice components so all modifications will be based on *-config.xml which stores such configurations.
For our example this configuration file is located at:
/c4tunebackoffice/resources/c4tunebackoffice-backoffice-config.xml


Tree view

The first adjustment we will take care of is adding our new item to the dedicated C4Tune navigation group with the C4TuneItems listing option on the main tree view of backoffice.

Configuration, as mentioned earlier, is done in c4tunebackoffice-backoffice-config.xml

<context type="C4TuneItem" component="explorer-tree">
   <explorer-tree:explorer-tree >
      <explorer-tree:navigation-node id="treenode.c4tune">
         <explorer-tree:type-node code="C4TuneItem" id="typenode.c4tuneitems"/>
      </explorer-tree:navigation-node>
   </explorer-tree:explorer-tree>
</context>

The above fragment creates a dedicated tree node including type node representing our new C4TuneItem.

With additional localization entries like those:

treenode.c4tune=C4Tune
typenode.c4tuneitems=C4Tune Items

located in /c4tunebackoffice/resources/c4tunebackoffice-backoffice-labels/labels.properties result view should look like this:


Tip: For changes done on *-backoffice-config.xml level there is no need to build or restart server to see changes beeing applied. You only need to reset backoffice view configuration using F4 key option on backoffice and select Reset Everything action.
For labels it is mandatory to rebuild/reset the server.


What we’ve done with the above XML configuration is …

 <context type="C4TuneItem" component="explorer-tree">

… we declared that we will create explorer-tree structure for our item …

 <explorer-tree:navigation-node id="treenode.c4tune">

… we defined a tree node/group based on the localized name …

<explorer-tree:type-node code="C4TuneItem" id="typenode.c4tuneitems"/>

… we added our new item under the tree node/group with dedicated name based on localized entry.

Now we move to creation process of our new C4TuneItem item.

Creation wizard

We now have dedicated Tree Node for our new item. Let’s now focus on the creation process of this item from the backoffice perspective.

By default, all new items are using default (or parent if they extend some other item) creation wizard which do not match a number of data item requires or allows to provide.

What we would like to do is to:

  • configure 2 step wizard with string and boolean on first and Customer on the second step
  • do String and Customer mandatory attributes for creation of C4TuneItem

Below XML shows the definition of creating wizard for C4TuneItem.

<context type="C4TuneItem" component="create-wizard">
    <wizard-config:flow id="C4TuneItemWizard" title="create.title(ctx.TYPE_CODE)">
        <wizard-config:prepare id="itemPrepare">
            <wizard-config:initialize property="newObject" type="ctx.TYPE_CODE"/>
        </wizard-config:prepare>
        <wizard-config:step id="step1" label="wizard.c4tune.step1.label" sublabel="wizard.c4tune.step1.sublabel">
            <wizard-config:content id="wizard.c4tune.step1.content">
                <wizard-config:property-list root="newObject">
                    <wizard-config:property qualifier="c4TuneItemString"/>
                    <wizard-config:property qualifier="c4TuneItemBoolean"/>
                </wizard-config:property-list>
            </wizard-config:content>
            <wizard-config:navigation id="wizard.c4tune.step1.navigation">
                <wizard-config:cancel/>
                <wizard-config:next visible="!#empty(newGrp.c4TuneString)"/>
            </wizard-config:navigation>
        </wizard-config:step>
        <wizard-config:step id="step2" label="wizard.c4tune.step2.label" sublabel="wizard.c4tune.step2.sublabel">
            <wizard-config:content id="wizard.c4tune.step2.content">
                <wizard-config:property-list root="newObject">
                    <wizard-config:property qualifier="c4TuneItemCustomerItem"/>
                </wizard-config:property-list>
            </wizard-config:content>
            <wizard-config:navigation id="wizard.c4tune.step2.navigation">
                <wizard-config:back/>
                <wizard-config:cancel/>
                <wizard-config:done visible="!#empty(newGrp.c4TuneCustomerItem)">
                    <wizard-config:save property="newObject"/>
                </wizard-config:done>
            </wizard-config:navigation>
        </wizard-config:step>
    </wizard-config:flow>
</context>

Including localization entries (on /c4tunebackoffice/resources/c4tunebackoffice-backoffice-labels/labels.properties level)

wizard.c4tune.step1.label=Essential
wizard.c4tune.step1.sublabel=Essential data
wizard.c4tune.step2.label=Customer
wizard.c4tune.step2.sublabel=Customer relation

Result visualization of the creation wizard looks like that.

Let’s take a closer look at the above configuration. What happened there is …

<context type="C4TuneItem" component="create-wizard"> 

… we declared configuration of creating wizard for our new item …

<wizard-config:initialize property="newObject" type="ctx.TYPE_CODE"/> 

… initialize the creation of our new item instance …

<wizard-config:step id="step1" label="wizard.c4tune.step1.label" sublabel="wizard.c4tune.step1.sublabel"> 

… define step for our wizard with title and subtitle based on localization entries …

<wizard-config:content id="wizard.c4tune.step1.content">
    <wizard-config:property-list root="newObject">
        <wizard-config:property qualifier="c4TuneItemString"/>
        <wizard-config:property qualifier="c4TuneItemBoolean"/>
    </wizard-config:property-list>
</wiz

… configure step content listing attributes that should be available for fulfillment on this step …

<wizard-config:navigation id="wizard.c4tune.step1.navigation">
    <wizard-config:cancel/>
    <wizard-config:next visible="!#empty(newObject.c4TuneItemString)"/>
</wizard-config:navigation>

… configure navigation box with actions that can be performed on the step including build-in validation rules checking if the string is empty or Customer is null (we define the visibility of button based on validation so until required values are provided button is not visible) …

As a result of above flow new C4TuneItem is created and listed on C4Tune Items list view. But notice how bad it look at this point. Only the primary key is presented.

Let’s change that.

List view

By default for our item on the list view, we only see a single column showing the primary key of the item.

Again we adjust this by defining new component definition as below:

<context type="C4TuneItem" component="listview">
    <list-view:list-view >
        <list-view:column qualifier="pk" width="20%"/>
        <list-view:column qualifier="c4TuneItemString" width="15%"/>
        <list-view:column qualifier="c4TuneItemBoolean" width="15%"/>
        <list-view:column qualifier="c4TuneItemCustomerItem" width="50%"/>
    </list-view:list-view>
</context>

The configuration defines the listview component for our C4TuneItem item and defines which attributes in which order should be visible. In addition, we put the width attribute that allows defining the width of each column on the list view.

And now the result.

We are almost over. The last thing we should also take care of is search and edition perspective.

But one at a time.

Search

For search, located above items list view we have to consider two aspects:

  • what data are used when we use the simple search option (available by default after entering items list view)
  • what data should be available for search when advanced search option will be enabled

Simple search

Entering the list view allows us to quickly search an item based on simple-search configuration we provided. For our example item by default only one simple search is available and that’s primary key search.

What we would like to have is the possibility to search also by whole or fragment of our c4TuneItemString attribute.

To do this we will simply define simple-search component for our item.

<context type="C4TuneItem" component="simple-search">
    <simple-search:simple-search>
        <simple-search:field name="pk" />
        <simple-search:field name="c4TuneItemString" />
        <simple-search:sort-field name="pk" asc="false" />
    </simple-search:simple-search>
</context>

Based on that definition …

<simple-search:field name="pk" />
<simple-search:field name="c4TuneItemString" /> 

… search will be executed based on bot PK and c4TuneItemString attributes …

<simple-search:sort-field name="pk" asc="false" /> 

… results by default will be ordered based on PK in descending order.

And here the result (partial search based on c4TuneItemString attribute)

Advanced search

A mentioned simple search can be extended to advanced search with the Switch search mode button. Advanced search allows selecting attributes used for search and way that search should be performed.

If available search options are not enough we can always add a new attribute to search, from available dropdown, but sometimes we already know, that attribute will be used for search extremely often so why not to prepare on that.

In our example, we would like to have already enabled c4TuneItemString search with Contains operation and c4TuneItemCustomerItem with Equals operation.

An additional possibility to add c4TuneItemBoolean search option must also be defined because otherwise, this attribute will not be available for an advanced search option.

Our configuration for advanced-search component should look like that.

<context type="C4TuneItem" component="advanced-search">
    <advanced-search:advanced-search>
        <advanced-search:field-list>
            <advanced-search:field name="pk" selected="true" operator="contains"/>
            <advanced-search:field name="c4TuneItemString" selected="true" operator="contains"/>
            <advanced-search:field name="c4TuneItemCustomerItem" selected="true" operator="equals"/>
            <advanced-search:field name="c4TuneItemBoolean" operator="equals"/>
        </advanced-search:field-list>
    </advanced-search:advanced-search>
</context>

As we can see we defined all attributes that should be available for advanced search and those already selected for fulfillment we marked with selected=”true” attribute.

Result advanced search view for our example is.

You can see that selected by default attributes are already available and c4TuneItemBoolean can be added at any time from the dropdown.

Tip: Remember that after selecting c4TuneItemBoolean you have to click + button to include it to the search (despite you selected requested value for that attribute)

Let’s move to the last configuration for our new item, and that is the edition view.

Editor view

The editor view shows all attributes of the given item and allows to modify them.

For our example, initial look of such editor without additional configuration will include all our attributes in the UNBOUND section where all unassigned and undefined attributes are located.

What we would like to achieve now is that we want to put c4TuneItemString in the ESSENTIAL attributes section and the other two c4TuneItemBoolean and c4TuneItemCustomerItem in dedicated C4Tune section.

Other/default attributes we will put in separate Other section.

Tip: ESSENTIAL attributes section is visible on the top of the editor view and is always visible on every property tab this view.

Let’s take a look at the configuration which allows us to complete our goal.

<context type="C4TuneItem" component="editor-area">
    <editorArea:editorArea>
        <editorArea:essentials>
            <editorArea:essentialSection name="c4tune.essential">
                <editorArea:attribute qualifier="c4TuneItemString"/>
            </editorArea:essentialSection>
        </editorArea:essentials>
        <editorArea:tab name="c4tune.properties" position="1">
            <editorArea:section name="c4tune.properties">
                <editorArea:attribute qualifier="c4TuneItemBoolean"/>
                <editorArea:attribute qualifier="c4TuneItemCustomerItem"/>
            </editorArea:section>
        </editorArea:tab>
        <editorArea:tab name="c4tune.others" position="2">
            <editorArea:section name="c4tune.others">
                <editorArea:attribute qualifier="pk"/>
                <editorArea:attribute qualifier="itemtype"/>
                <editorArea:attribute qualifier="creationtime"/>
                <editorArea:attribute qualifier="modifiedtime"/>
            </editorArea:section>
        </editorArea:tab>
    </editorArea:editorArea>
</context>

We also included localization entries mentioned in the configuration:

c4tune.essential=Essential
c4tune.properties=C4Tune
c4tune.others=Others

The result of such a configuration is.

As we can see attributes are there according to provided configuration. We were able to …

<editorArea:essentials>
    <editorArea:essentialSection name="c4tune.essential">
        <editorArea:attribute qualifier="c4TuneItemString"/>
    </editorArea:essentialSection>
</editorArea:essentials>

… define ESSENTIAL section which as you can see is always visible on each selected tab both …

<editorArea:tab name="c4tune.properties" position="1">
    <editorArea:section name="c4tune.properties">
        <editorArea:attribute qualifier="c4TuneItemBoolean"/>
        <editorArea:attribute qualifier="c4TuneItemCustomerItem"/>
    </editorArea:section>
</editorArea:tab>

C4Tune tab with C4TuneItem attributes positioned in the first place and …

<editorArea:tab name="c4tune.others" position="2">
    <editorArea:section name="c4tune.others">
        <editorArea:attribute qualifier="pk"/>
        <editorArea:attribute qualifier="itemtype"/>
        <editorArea:attribute qualifier="creationtime"/>
        <editorArea:attribute qualifier="modifiedtime"/>
    </editorArea:section>
</editorArea:tab>

Others tab with attributes inherited from parent/generic item.

And that would be all for our exercise.

Conclusion

As you can see modifications for the backoffice view are quite simple but influence the look-and-feel of backoffice itself, especially for Administrators or Editors, using backoffice for management and configuration.

From my experience, many developers/architects forget about such configurations or don’t properly focus on those aspects.

So remember and think of every user of the system.


0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *