We had a particular issue with dynamic branding. It is our practice to color the banners of each of our environments a different color (Red for DEV, Orange for Staging/Test, Green for a working copy of Production, and Blue for Production). No matter where we looked, there were no solutions to our problem. Let me present to you my solution to the problem of Dynamically changing the banner color, displaying the product name, and displaying the Database name (the database name was really easy, and Sasank actually provided a working solution to that problem).
Coloring the banner was by far the most difficult problem. I'll go over the others first though.
Navigate to: PeopleTools > Portal > Branding > System Data > Define Element Types.
This is a place where the pieces used in building headers are contained. We can create a new one here that references code from an Application Package.
There an Element Types in here which were helpful to display the database name: Basic HTML. When you build your own custom header, you can but in basic HTML and tell that HTML to display %DBName. However, this was not quite what we wished for testing purposes, because if you change the short name of the Environment in PeopleTools Options, then this %DBName will not reflect that change, at least not immediately. Not a huge issue, but it is an easy fix.
All of the Element Types reference code in an Application Class (e.g. PTBR_BRANDING:Elements:BasicHTML, PTBR_BRANDING:Elements:BasicContainer, etc). In turn, all of these inherit from PTBR_BRANDING:Elements:BaseElement. This is the bare-bones piece of code that allows something to be returned in HTML form. In this class, there is a method called getHTML(&pPreview As boolean). This is the key piece to building your own custom elements in your personalized themes.
This is the entire contents of the method:
method getHTML
/+ &pPreview as Boolean +/
/+ Returns String +/
Return "";
end-method;
As you can see, there is nothing here, so it is simple to build something that returns some HTML. Here is some of the code that we used for ours to display the Database name.
SQLExec("select longname, systemtype from %Table(:1)", Record.PSOPTIONS, &db_descr, &db_type);
If (&pPreview) Then
&getHTML = EscapeHTML(MsgGetText(25000, 3, "DBName: %1", &db_descr));
Else
If &db_type <> "PRD" Then
&getHTML = EscapeHTML(&db_descr);
End-If;
End-If;
&getHTML = GetHTMLText(HTML.PTBR_ELM_CONTAINER_DIV, EscapeHTML(%This.ID), EscapeHTML(%This.StyleClass), &getHTML);
Return &getHTML;
Couple of things to note here. %This.ID and %This.StyleClass are both declared in the constructor to be the CSS id and class names that we want. This builds and returns a HTML <div> that has the id, class, and content that you desire. Simple, right?
It's only slightly different to display the product name, as we call it. For us, there were four products that each needed individual branding names. Human Resources/Payroll, University Financials, Campus Solutions, and Utility/Phire Environment. These were to be determined from the PSOPTIONS table, as above. A simple Evaluate statement took care of it.
Now, for the more difficult problem, changing the color of the banner according to what database type we were in. Unfortunately, there isn't really a way to do If statements or Evaluate statements in CSS. So, instead of that, we decided to create a div with a particular id: byubgcolor, and different id's based on the color that we wanted. byubgcolorprod, byubgcolordev, byubgcolorstg, byubgcolordemo, byubgcolorcpy, and byubgcolorother.
This was the complicated part.
In branding, it is simple to create a custom Element Type, as long as it is just a basic element. If it has any children, it's slightly harder, we found out. BaseElement does not allow for children. BasicContainer, on the other hand, does. However, Basic container also doesn't by default return an empty string. It returns the HTML of all of its children, as well as it's own HTML. We created our own Custom Element type that inherited from BasicContainer, and tried to get it to work. It wasn't immediately clear what to do. To get this to work, you need to rely heavily on the already written class, which makes sense.
We needed to do an Evaluate statement to determine the database type, and we needed to set the style of the current element. This is something that wasn't easy at first. It is necessary to set %Super.StyleClass, not %This.StyleClass. In addition, this cannot be changed dynamically if set in the constructor, and needs to be done in the getHTML method.
Evaluate &db_type
When = "PRD"
%Super.StyleClass = "byubgcolorprod";
When = "DEV"
%Super.StyleClass = "byubgcolordev";
When = "STG"
%Super.StyleClass = "byubgcolorstg";
When = "DMO"
%Super.StyleClass = "byubgcolordemo";
When = "PAR"
%Super.StyleClass = "byubgcolorcpy";
When-Other
%Super.StyleClass = "byubgcolorother";
End-Evaluate;
Next, the parent class conveniently provides a setter for a property, CustomContainerObject. We needed out own custom div to handle this container, and so we specified this: There is another way to use a custom container. In the Additional Options on the Define Headers and Footers page, there is an Attribute at the bottom for Custom Container Object. This can specify the HTML element to place this Element Type in. However, the code we have populates this field anyways.
%Super.CustomContainerObject = "Y_BASIC_DIV";
&getHTML = %Super.getHTML(&pPreview);
The last thing would be to place this custom element in the header. We put in in place of the original banner container, pthdr2container, as seen below. Note that the "Style" box was populated from the code in our Application Package.
The branding classes really have a lot of useful things in them, but without knowing how to use those classes, it is really hard to create a branding that works well and efficiently.
No comments:
Post a Comment