ArasLabs / set-tab-color

Allows configuration of relationship tab color.
3 stars 3 forks source link

Add dynamic tab coloring based on relationship content #1

Open AngelaIp opened 6 years ago

AngelaIp commented 6 years ago

Hi,

I wonder if it´s possible to extend this project to some kind of dynamic tab coloring.

Idea: Tabs shall only be colored, if there are related items available. This way users could instantly see, which relationships are in use and which ones are empty.

Pros:

Cons:

I think the idea has its charme. What´s your opinion? Is there something to consider?

Best regards! Angela

AngelaIp commented 6 years ago

Hi,

I made a quick test of this idea and was able to create a first working draft for dynamic tab highlighting based on the relationship content. The following code works (sometimes), but it´s not in a state recommended for use in production:

// Updates relationship tabs based on the tab content
function changeTabColor() {
     //Check if relationship grid is loaded
    if (!parent.relationships) {
        setTimeout(changeTabColor, 50);
        return;
    }

    // this is the dom for the relationships grid/tabs
    var rel_dom = parent.relationships.document;

    var inn = Innovator();
    var itemId = document.thisItem.getID();

    // get tabs
    var tabIds = parent.relationships.relTabbar.getTabOrder('|');
    var relIds = tabIds.split('|');

    for (i = 0; i < relIds.length; ++i) {
        var style = "";
        var relId = relIds[i];

        // get the tab element using the relationship id
        var tab = rel_dom.querySelector('li[data-id="' + relId + '"]');

        var relshipTypeNd = aras.getRelationshipType(relId);
        var relshipTypeName = aras.getItemProperty(relshipTypeNd.node, "name");
        var relTypeId = aras.getItemProperty(relshipTypeNd.node, "related_id",""); // related type, e.g. File

        // Idea - Color ItemTypes with Relationship View
        /*if (relTypeId === ""){ // can be either Null relationship or Relationship View Item
           style += "border-bottom: 2px solid LightGrey;";
        } else {*/
            // regular relationship or Null relationship
            var relContent = inn.newItem(relshipTypeName,"get");
            relContent.setProperty("source_id", itemId);
            relContent.setAttribute("select","id");
            relContent = relContent.apply();
            if (!relContent.isError()){
                style += "border-bottom: 2px solid grey;";
            } 
    //  }
        tab.setAttribute("style", style);
    }
}
changeTabColor();

The result will look simillar like this: image

Pro:

Cons:

Is there an easier way to queck, whether the tabs have content without using additional AML queries? Does parent.relationship already contain some information about relationship content that could be used for this task?

Best regards! Angela

EliJDonahue commented 6 years ago

Hi Angela,

I have a few thoughts on your "cons" list:

Current version uses many repeating AML queries.

When an item form opens for the first time, only the parent item and the active relationship tab's items are loaded into the dom. No data is retrieved for the inactive tabs, so you'll definitely need to query the server for that data.

One possibility to reduce the number of calls to the server is to make one call that retrieves minimal data for all relationships, and then use XPath to parse out the result and decide how each tab should be styled. Example pseudocode:

// get list of relationshiptype names
var reltypes = ... ;

// build an AML query that gets the minimum helpful info about the relationships
// example query:
var query = "<AML><Item type='Part' action='get' select='id'><Relationships>";

foreach(reltype) {
    query += "<Item type='" + reltypes[i] + "' action='get' select='id' />";
}

query += "</Relationships></Item></AML>";

var structure = inn.applyAML(query);

// use XPath to count/check existence of each relationshiptype in the structure
foreach(reltype) {
    var rels = structure.getItemsByXPath(...);
    if (rels is not an error and contains one or more item)
        // get tab and style accordingly  
}

This is risky (performance-wise) because some items may have thousands of related items, but minimizing the properties returned should help reduce the performance hit (less data returned from the server).

Edit: You can also try setting the maxRecords attribute on each relationship item in your AML, since you really just want to know whether the relationships exist - not how many exist.

You can also try making the changeTabColor call asynchronous so it doesn't prevent the rest of the form from loading.

Large ItemTypes with many relationship tabs (e.g. Part) sometimes doesn´t color the tabs.

You can try increasing the timeout value to give the function more time to finish. Ex:

if (!parent.relationships) {
    setTimeout(changeTabColor, 100);
    return;
}

I underrated the amount of Relationships that use alternative content in Relationship Views (reverseItemsGrid, TreeGridViews, etc.). Highlighting these kind of content would require additional queries.

I'm not sure there is a good generic solution for this use case. I think admins would need to define their own queries for these tabs. Maybe some type of "query template" field could be added to the Ext_SetTabColor item. If the field is set, it would be used to override the query for the RelationshipType.

AngelaIp commented 6 years ago

Hi Eli,

Thanks for your very detailed feedback! This helps me a lot and I'll try to test your suggestions soon.

I don´t know yet if I really will use these kind of tab highlighting later in production. But I'm always a big friend of trials. And finally there is already a first positive and very important result: The main "set-tab-color" project works again. :-)

Angela

rneuber1 commented 5 years ago

This is risky (performance-wise) because some items may have thousands of related items,

What about setting "maxRecords='1'" on the related item, as you only need to know if there is at least one item?

\Ralf

EliJDonahue commented 5 years ago

Good suggestion, Ralf. That should help.

AngelaIp commented 5 years ago

Thanks for the additional input! I haven´t worked much on this topic. I wonder if it would make sense to split this issue into a separate GitHub project?

EliJDonahue commented 5 years ago

I think it would make more sense to update the current project instead of create a new one. If this use case is implemented as a separate project, the community would have to maintain common code between two repositories, rather than managing a single repo.

One way to implement the new use case within the current project is to add a configuration option and then update the logic to check the option. For example, maybe add a property that allows the admin to say they want a style applied when:

  1. Always (default)
  2. Has relationships
  3. Has no relationships

This would be a great Hacktoberfest contribution to the community.

AngelaIp commented 5 years ago

"It somehow would be helpful if the tabs could indicate the content..." After one of my colleagues mumbled this comment this week, I finally had the residual motivation to give it another try.

I have created a branch of the master tree that now contains static and dynamic coloring: https://github.com/AngelaIp/set-tab-color/

Known issues:

  1. Doesn´t update on change of relationship content
  2. Doesn´t color Parameters tab
  3. Code needs cleanup

Speed seems to be somehow ok. Also code needs review and more testing.

AngelaIp commented 5 years ago

I made some additional tests for my issue No. 1 - live update of tab style It seems to be possible to add some realtime coloring. Unfortunately this one needs two additional Methods and tons of addtional events.

I was able to achieve a quite good first result with this Method in two variants for "OnInsertRow" and "OnDeleteRow" RelationshipType events.

var tmpThisItem = typeof(parent.document.thisItem) == "object" ? parent.document.thisItem : parent.thisItem;

var rels = tmpThisItem.getRelationships(relationshipTypeName);
var count = rels.getItemCount();

var style = "";
var rel_dom = parent.relationships.document;
var relId = aras.getRelationshipTypeId(relationshipTypeName);

if (count > 0) // Conflict! Different counting of inserted and deleted files
// Use 0 for onInsertRow Event
// Use 1 for onDeleteRow Evenet
{
    style = "border-bottom: 2px solid grey;"; // static design used for testing purposes
}
var tab = rel_dom.querySelector('li[data-id="' + relId + '"]');
tab.setAttribute("style", style);
return;

But this one would now have to be added in any affected RelationshipType. Any ideas of how to simplify the whole thing?

AngelaIp commented 5 years ago

Hi,

I will try to add my two Methods automatically to the RelationshipTypes by extending the Method 'Ext_AddFormEvent.xml'. But before submitting a pull request to the original project, I would be happy about any additional feedback to the current code. I don´t know if my current concept is really the best approach. The current design is indented to offer a maximum of flexibility without destroying the scope of the original project. So if somebody just uses the orginal feature set (just static coloring), he shouldn´t notice negative performance impact caused by the additional functions used for the dynamic coloring.

Angela

AngelaIp commented 5 years ago

This one is interesing: http://community.aras.com/en/forums/topic/885-developers-forum-adding-relationship-count-to-tab-name/

Obviously I wasn´t the first one with this idea. I like the "writer number of relationships" in tab label idea, also it costs a lot of performance. I am also facing the limitation with federation relationships. But it´s similar to limitation that you have with reverse and tgv relationships. It does not really bother me, as the color scheme tells user about the relationship type already.

AngelaIp commented 5 years ago

Hi Eli, do you know if Aras plans some kind of 'tab highlighting' for the standard product? I heart rumours about it, but do not know details. I right now would not add the dynamic tab coloring that I used in my forked version to the main project, as it´s not fast and reliable enough. My customization would also destroy the feature scope of the original project. The static coloring of tab labels is defentitly something of interest for certain folks.

I was able to create a new version that now does the job fast and realiable. It´s mostly based on this discussion, but it´s not compatible with the original set-tab-color project anymore. My current version do not use the Set Tab Color ItemType. 100% of the work can be done with Methods. They are generic enough so I do not need the additional ItemType. I even have some ideas how to handle federated relationships, but I didn´t need this variant yet. image