Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Martin-Pankraz
Active Contributor

Dear all,

I finished my first BO Design Studio component using the SDK recently, leveraging Google Maps and its API v3 as well as OpenStreetMap with Leaflet. As part of a Dashboard project called SPoT-U, I wanted to display geo-referenceable data derived from a SAP Business Warehouse in an intuitive manner. The technologies mentioned above were an obvious choice to start from. I’d like to give a short introduction to the components features before I go over the difficult implementation “war stories”.

Extension Features and Context


My maps components serve as an entry point into the dashboard to equip the user with a general overview of the current analysis status and answer questions such as:

  • How much cost for example related to a technical or functional object are incurred in a certain area?
  • Is there a trend in key figures compared to a past period? (indicated by arrows and percentages next to the cluster marker)
  • Are there some objects always hitting the top 10 cost? Do they have something in common? Can we do better in this special case?

     Figure 1: OpenStreetMap integrated in Dashboard (click image to enlarge)


Groups of markers get clustered dynamically depending on the zoom level, viewport and chosen key figure in order to enhance ad-hoc analysis and mimic BW capabilities to aggregate data. At the moment two separate key figure datasets are supported due to the SAP Design Studio restriction of a maximum of 10,000 data cells that can be transported to SDK components. Figures to be displayed can be integers as well as floating points.

Markers, or more precisely clusters, shown above can be clicked to trigger events that the map extensions in turn expose to Design Studio and other components of the dashboard. By utilizing our maps API implementation other components are able to learn the clicked cluster’s properties via Design Studio’s scripting language. That way we are able to adjust DataSources and chart filterings or even simple text-based key figure displays accordingly in a dynamic manner during runtime. Modifying map or cluster state via DataSource manipulation is also possible during runtime. The component always reflects current DataSource state.

     Figure 2: OpenStreetMap properties view (click image to enlarge)

These features enable the maps component to serve as a pretty good overall view into analysis applications that can make use of geo-referenceable data.

At this point, as promised, I would like to share some insights I gained throughout this adventurous task of developing a rich Design Studio Maps extension.

App Lifecycle


To begin with, the Google Maps example SDK project, provided by SAP, only serves as a proof of concept that using maps within Design Studio is possible but nothing more. To really use it for production purposes, you need to understand the Design Studio components Lifecycle and code your application accordingly. For example, every data update to your component (DataSource filtering, Map listeners, etc.) will trigger the afterUpdate function. So you need to separate the function flow through your application at this point. At the very least, you will want to avoid several executions of your initialization code. Unfortunately, you cannot move all initializations to the init method if you need property input from outside the application, which will only be available when afterUpdate is called by the Design Studio framework.

The same goes for coding within property getter/setter functions. They are called unordered and in bulk every time you execute firePropertiesChanged event. So this might result in strange app behavior. The following link helped me a lot on this matter: http://scn.sap.com/thread/3590837.

Maps rendering issue with jQuery


Once you use your maps component within a container like gridlayout and change tabs, you will notice that your maps canvas does something like this (notice map leftovers, top left corner):

     Figure 3: render issue on resize (click image to enlarge)

This happens because changing tabs results in hiding currently inactive child components and losing their bounds for now. To solve this you need to reset the bounds and trigger repaint when changing tabs back again. More information on this issue can be found here for example: http://stackoverflow.com/questions/17059816/google-maps-v3-load-partially-on-top-left-corner-resize-...


Parsing ResultSet


This caused me a couple of headaches in particular. You might notice in the maps properties view above that I put in “{}” for the field Runtime JSON Data, which results in complete transfer of the data entries and their dimensions to the component. So far so good, but the tricky part is matching corresponding information on extension level again because all of the dimension data gets transferred in separate arrays. You might think the data looks the same as it does in your initial view or crosstab. Unfortunately, it doesn’t. Have a look into the SAP Design Studio developer guide SDK1.3 for reference (page 35 onward). Let’s consider this example:

     Figure 4: DataSource View (click image to enlarge)


The following figures will show how the data is structured when submitted to SDK components. Those screenshots were taken from a browser developer tool after my runtimedata property was updated by the Design Studio Framework right before afterUpdate gets called.

     Figure 5: component properties view in browser devel tools (click image to enlarge)


The objects “dimensions” contain meta data concerning all the columns you can see in Figure 3. My Screenshots above show an non-collapsed tree view of column named “Kennzahlen” (navigate “dimensions[0].members[0]”). The object “data,” however, contains the data that really interests us, our key figures. Let’s have a look at them. As you can see on the right, it is just a plain array containing all the key figures from our DataSource (compare array size to live preview data cells). This means we somehow need an index that tells us at which position in the data array to look for corresponding entries. Now the object “tuples” comes into play. For every row in the DataSource view and every key figure there is a tuple array containing all the indexes for the dimensions array.

     Figure 6: component tuples view in browser devel tools (click image to enlarge)


In order to recreate the structure from DataSource view we have to iterate over tuples and dimensions arrays to determine the values in the data array. That should give you a brief idea on how to handle complex data structures issued to your SDK components.

The Source code and the App for our maps implementations are available on GitHub (new version as of 12th of October 2015😞

ConVista-ds-sdk-visualizations by MartinPankraz

Addition: Development on the OpenStreetMap version was stopped due to the new SAP GeoMap as of DesignStudio 1.5. Development on the Google Maps version continues though. The newest feature covers loading lat-long values from standard data sources just like SAP's GeoMap. Now you can work either with lat-long values right away or geocode you addresses like before.

Let me know what you guys think and feel free to ask lots of follow-up questions if you like to make use of my component. Or just contact my magnificent employer ConVista Consulting. They are also eager to get some feedback.

Yours

Martin

18 Comments
Labels in this area