Quantcast
Channel: SAP BusinessObjects Design Studio
Viewing all 662 articles
Browse latest View live

SCN Community Package: Hierarchy Members Accessors & Iterator

$
0
0

Disclaimer:

This component uses hierarchies from BW. It could be adapted to connect to Hana or a Universe, but these hierarchies have not been tested.

The component has been tested, but you may encounter some bugs. For either bugs or enhancement request, do not hesitate to post an "issue" on our GitHub.

 

Introduction

Hi, I am Franck BLAIS, Sap BW Consultant and Design Studio developper. I already posted 2 blog entries on my component "Hierarchical Menu" in the SDK Community package initiative.

The first one was "Multi level Dropdown Menu" and the second "Hierarchical menu for BW v2".


I want to share a new aspect on the menu, a utility one.

In Design studio, as far of the 1.6, you can access members of a dimension, but the hierarchy members. I juste improved the "Hierarchical Menu v 1.0" with this functionality.

 

Rendering the hierarchical menu is not necessary and it can be used in a Utility version.

 

An demo application can be found here. You just need to import it. Note it's for DS 1.6 and the datasource are CSV.

 

Component overview and explanations

 

 

The hierarchical menu look like this, with the embedded CSS:

Screen Shot 2015-10-27 at 11.37.25 PM.png

 

You can avoid to display it by using the method "hideMenu(boolean hide)", or changing its value directly in DS.

 

With the iterator, you can really easily create a navigation menu using the Tree 2.0 (or any other component, like dropdown, listbox ...):

Screen Shot 2016-02-25 at 5.05.23 PM.png

 

When you have assigned a Datasource and selected a dimension with a hierarchy, you can now use 3 new methods detailed below.

 

Loop on the members with getHierarchyMembers()

 

This method returns an array of Hierarchy Member that you can iterate using forEach.

Each member has for attributes (case-sensitive):

AttributeDescription

ID

an integer internal ID generated while exporting it. It is corresponding to the index of each node/leaf. (The fist node will be 0, second 1 ...)
key

hierarchy node key in BW format. It can be used as parameter for setFilter of setVariable on a characteristic with a hierarchy assigned.

Example: HIERARCHY_NODE/0HIER_NODE/EUROPE

text

Contains the text of the node/leaf, but not only. You see, it depends on the characteristic display mode.

In contrary of the key, which is the NodeKey (HIERARCHY_NODE/0HIER_NODE/EUROPE), this node would have:

  • Short Key: EUROPE
  • Text: "Europe"

 

If you choose to display both (Key+Text) in BEX, then the attribute text will have the concatenation of both like: "EUROPE|Europe". Only Text will give only "Europe" while Text+Key "Europe|EUROPE".

 

if you need to access one of the other, you can always use "Convert.split" or the substring extractor. Or best bet: display the hierarchy as "Text" only

LevelDepth of the node, starts at 0.
parentID

ID of the parent node, -1 if no parents.

You can directly access the parent form the table by using this ID as index:

var members = MENU.getHierarchyMembers();

var child; //Let's assume child is a member of the hierarchy accessed previously.

 

//Access the parent node of child.

var parent = members[child.parentID];

 

//Access the grand father of child.

var parent_of_parent = members[parent.parentID];

parentKeyparentKey in BW hierarchy format. Can be used in setFilter, setVariable or setDataSelection.
isLeafBoolean, tells you if you on a node or a leaf basically, meaning you cannot go further in this branch.
nodeStateIndicated wherever the node is collapsed (COLLAPSED) or expanded (EXPANDED) in the datasource. For a leaf, nodeState = leaf.
typeType of the node, exactly the same as BW, either: HIERARCHY_NODE or t)he technical name of the characteristic (0MATERIAL for example)

 

2 other methods are available, maybe less useful:

getHierarchyMembersSource()

return the DS table as a string, could be useful to debug the component ...


getHierarchyMembersAsJsonString()

Return the same table, but as a JSON String.

It could be used in conjonction with the Collection component, maybe to alter the structure, values and still be able to loop and access the hierarchy members.

I can now only hope you'll like, and of course, use it !

Let me know if you found any bug, or need support.


Migration from SAP Dashboards to SAP BusinessObjects Design Studio - Part 1

$
0
0

In 2012 SAP announced that SAP BusinessObjects Design Studio will basically succeed SAP Dashboards and they made a few recommendations on where customers should "migrate" towards. In the next couple of days I will share a few blog posts outlining the options that are available and what some of the limitations are when considering a move from SAP Dashboards to SAP BusinessObjects Design Studio and how to overcome them.

 

XC_Migration_Blog_001.jpg

Figure 1: Message in 2012

 

In 2012 the message from SAP was very clear, that customers with SAP BW and SAP HANA should consider SAP BusinessObjects Design Studio as their primary tool. Customers that were using SAP Dashboards mainly with SAP BW were given a similar recommendation and customers that were using SAP Dashboards mainly with non-SAP BW / non-SAP HANA sources - for example SQL Server or IBM DB2 - were told to still keep using SAP Dashboards.

 

XC_Migration_Blog_002.jpg

Figure 2

 

Shortly after that the message and roadmap became more concrete and SAP gave a guidance to customers with BW and HANA, "agnostic customers" as well as those customers that were mainly using SAP Dashboards as a standalone tool.

 

If you take a close look a Figure 2 then you will notice that some of the items listed on this roadmap are still outstanding:

 

  • Offline Mobile Support is planned for Q4 2016
  • A engine for local calculation is planned for Q4 2016

 

 

XC_Migration_Blog_003.jpg

Figure 3: BI Portfolio Simplification

 

Nearly 12 months ago SAP started to communicate the simplification of the overall BI portfolio and looking at the two rows in the middle there is a very important message, which is that SAP BusinessObjects Design Studio apps are now also positioned in the Discovery and Analysis area. SAP delivered several templates that provide strong self service capabilities using Design Studio capabilities and therefore it was only the next logical step to also position those templates in the Discovery and Analysis area.

 

So why should customers consider moving to SAP BusinessObjects Design Studio ?

 

  • SAP BusinessObjects Dashboards is clearly not a "strategic investment" anymore
  • SAP BusinessObjects Dashboards only provides limited Mobile BI support
  • SAP BusinessObjects Dashboards does not provide a true eventing framework

 

 

So lets compare the first set of capabilities:

 

XC_Migration_Blog_004.jpg

Figure 4

 

As you can see, SAP BusinessObjects Design Studio does cover the important connectivities such as SAP BW, SAP HANA, as well as SAP BusinessObjects Universes.

 

Connectivity towards Live Office or QaaWS (Query as a Web Service) doesn't exist at this point in time for SAP BusinessObjects Design Studio.

 

Being able to use Excel as a data source is available as partner extensions.

 

XC_Migration_Blog_005.jpg

Figure 5

 

The table above shows some of the key benefits that SAP BusinessObjects Design Studio delivers. Design Studio is able to trigger the load of the data using the scripting engine, something that SAP Dashboards never really was able to do.

 

Also SAP BusinessObjects Design Studio provides capabilities such as background processing, parallel query execution, and the ability to exchange data source and dimensions at run time.

 

XC_Migration_Blog_006.jpg

Figure 6

 

When it comes to the ability to launch / store a dashboard in the different locations, you can see the differences between SAP Dashboards and SAP BusinessObjects Design Studio shown in Figure 6.

The offline capabilities are already on the roadmap of SAP BusinessObjects Design Studio for Q4 2016 and the ability to integrate a dashboard with Microsoft Word, Powerpoint, Outlook are also available as Partner Extensions.

 

XC_Migration_Blog_007.jpg

Figure 7

 

When comparing some of the key differentiators between SAP Dashboards and SAP BusinessObjects Design Studio, you can see that SAP Dashboards was designing the dashboards for a fixed screen resolution and did not have the ability to adjust the size based on the screen resolution. In regards to the data source, SAP Dashboards only provides limited support for SAP HANA and SAP BW, but on the other hand provided strong support for non-SAP data source.

 

SAP BusinessObjects Design Studio does address all the topics on the dashboard design by not relying on a fixed screen resolution and by being able to adjust the dashboard to the screen resolution. In regards to the data source, SAP BusinessObjects Design Studio provides a strong integration with SAP BW and SAP HANA and also provides access to the SAP BusinessObjects Universes.  Access to Excel as a data source is available as a partner extensions.

 

In the first part we looked at the main differences between SAP Dashboards and SAP BusinessObjects Design Studio, as well as some of the key reasons why customers should migrate. In the next part we will look at the different components available in SAP Dashboards and SAP BusinessObjects Design Studio.

Visual BI Extensions - Using Excel and Google Sheets as data source for SAP BusinessObjects Design Studio

$
0
0

I am sure several of you have been in a situation where you simply wanted to do a quick prototype and wanted to show your business user how the dashboard good look like in SAP BusinessObjects Design Studio and what is possible from a look and feel and from a user experience point of view.... and then you faced the situation that not all the data that you were looking for was already available in SAP BW or in SAP HANA.

 

Another familiar situation could be the need to be able to use some data from an existing spreadsheet as part of the overall design because some of the critical information that you need as part of the dashboard is not in SAP BW or SAP HANA but still on people's computer in form of Excel spreadsheets.

 

For exactly those reasons we created a custom data source as part of our Visual BI Extensions, that is capable of using Microsoft Excel sheets or Google Sheets as a data source.


It is very easy to use. You start by adding the custom data source to your project.


VBX_BlOG_001.jpg


After you added the custom data source, you can then configure the details in the Additional Properties.


VBX_BlOG_002.jpg


We do support the option to use a Local Spreadsheet, a spreadsheet that is stored on the SAP BusinessObjects BI Platform, Google Sheets, or Excel files stored on DropBox.


In my example I am using a very simple Google Sheet.


VBX_BlOG_003.jpg


All I have to do, is to share the URL as part of the custom data source and to specify which of the columns represents the start of the measure columns.


VBX_BlOG_005.jpg

After specifying those details, I can use the data from Google Sheet as part of my overall dashboard and if needed, even share it with my colleagues and not just use it as part of my local dashboard.


Just with a few simple steps you can add Excel or Google Sheet information to your dashboard, be it for a quick prototype or be it for a full production ready dashboard that shows information from spreadsheets as well as SAP BW and SAP HANA.


For the next release of this feature, we will integrate the custom domain option for Google Sheets.


100 Things you can do with Visual BI Extensions and SAP BusinessObjects Design Studio

Migration from SAP Dashboards to SAP BusinessObjects Design Studio - Part 2

$
0
0

In the first part of this blog series we took a look at some of the key differences between SAP Dashboards and SAP BusinessObjects Design Studio. In this second part we will take a closer look a the available components and compare those listing between SAP Dashboards and SAP BusinessObjects Design Studio.

 

XC_Migration_Blog_008.jpg

Figure 1: Charts

 

In Figure 1 you can see the first part of the available charts and in the columns you can see which of the products - SAP Dashboards, Lumira Desktop, Design Studio 1.5 (DS 1.5), and Design Studio 1.6 (DS 1.6) provide these chart types. In the far right column you see which chart types / component types are available as part of our Visual BI Extensions for SAP BusinessObjects Design Studio.

 

You can see that there are two chart types that SAP Dashboards provides and which are not available so far for Design Studio : OHLC and Candlestick.

 

On the other hand Design Studio does provide chart types such as a Bar / Column % Stacked, which is not available in SAP Dashboards.

 

XC_Migration_Blog_009.jpg

Figure 2: Charts

 

Figure 2 shows the next set of chart types and you can see that Design Studio does provide - using partner extensions - chart types such as a Multi Axis Chart, Box Plot, Funnel, ... that are not available in SAP Dashboards.

 

XC_Migration_Blog_010.jpg

Figure 3: Charts

 

Figure 3 shows the last set of charts, and you can see that something like a Gauge is so far only available via partner extensions.

 

XC_Migration_Blog_011.jpg

Figure 4: Chart capabilities

 

Figure 4 shows some of the key capabilities provided by the charts and you can see that most of the functionalities are covered by SAP BusinessObjects Design Studio, but some of the basic functionalities such as adding a Trendline to the chart or a Drill Down capability or a hierarchical drill down is only available using partner extensions.

 

XC_Migration_Blog_012.jpg

Figure 5

 

Figure 5 shows the comparison for the selector components. You will notice that the basic selector components such as a listbox, combo box, check boxes, ... are covered by Design Studio. Also the table and the scorecard table is covered in Design Studio 1.6. The List View and List Builder are highlighted as those could easily be reproduced with the existing components and a few lines of scripting.

 

XC_Migration_Blog_013.jpg

Figure 6: Selectors

 

Figure 6 shows the second part of the Selector components and here you will notice that something like a single slider or a dual slider or a horizontal / vertical progress bar is only available via partner extensions.

 

 

XC_Migration_Blog_014.jpg

Figure 7 : Maps

 

In Figure 7 you can see the functionality around the Maps offered in SAP Dashboards compared to SAP BusinessObjects Design Studio and you can see that the main difference here is the fact, that SAP Dashboards offered several out of the box maps and in Design Studio you always have to use a GeoJSON file so far for regional type of maps. Standard maps for Design Studio are available as partner extensions.

 

XC_Migration_Blog_015.jpg

Figure 8: Additional Functionality

 

Figure 8 shows a set of additional functionality, such as a What If Scenario, Trend Icon, Export to Excel, Powerpoint, eMail, ... and so on. You can see in Figure 8 that most of those features are not coming with Design Studio out of the box and require a partner extension for the migration to Design Studio.

 

In the second part we took a look at the available components in SAP Dashboards and SAP BusinessObjects Design Studio. In the next part we will take a look at some of the reasons for migrating to Design Studio, we will make a final recommendation based on different type of customers, and discuss a migration approach for moving from SAP Dashboards to SAP BusinessObjects Design Studio.

Advanced geomapping capabilities and ESRI support for DesignStudio

$
0
0

Hi everyone,


It was one year ago now that we published our article on Location Analytics for Design Studio.

 

At that time, SAP DesignStudio 1.4 was just kicking in, but was still lacking the Location Analytics component.

 

Galigeo for DesignStudio came into action and filled that need, until native GeoMaps came into play as well.

 

Let's be honest, at the beginning, the gap was really close between what Galigeo for DesignStudio was offering, and what GeoMaps brought to the table.

 

But our world is in perpetual evolution (especially the BI one!), and we all have to adapt ourselves to stay in the race.

 

Galigeo for DesignStudio keeps evolving release after release, as the customer/prospect use-cases and feedback came in, the version 2.3 came out (a few weeks ago now), as DesignStudio 1.6 is out.

 

058885.png

 

    ESRI Compliance

 

One of the core capabilities, that exists since the first release and that will probably interest most of you, is the

out-of-the-box ESRI support

 

In fact, lots of SAP customers out there have on-premise ESRI ArcGIS Servers (v10.0+) already deployed locally, or have their GIS environment in ESRI ArcGIS Online.

And guess what, some of them also have SAP DesignStudio.


Using Galigeo for DesignStudio, the designer just has to paste its service URL (for example, http://services.arcgis.com/bAFFwOpXUz9B6dsy/ArcGIS/rest/services/USA/FeatureServer/0), configure the field to be linked both on the ESRI service and BI data side, and the geodata appears on the map.


joint.png

 

Taking this into account, the product has been adapted to meet specific customer needs, some of those needs being very specific.

Like in all my posts, I'll take you through a quick tour of what the product is capable of.


Here, we'll look at a use-case, the needs of the client, and how Galigeo for DesignStudio was able to meet these needs.


A little bit of context

 

The customer in question is a large telecom operator, indeed one of the biggest in Europe (amongst the Top 10).

The company own a lot of cell towers, each cell being able to communicate with others in the surrounding area.

WebsitePhoto3.jpg

Each cellphone creates a lot of data no matter what time of the day it is. Of course, each data is collected, computed, stored in SAP legacy database solutions like HANA, and so on.

 

You get the concept.

 

One of the customer needs in DesignStudio was to be able to get a complete overview of these cell towers, to analyse the interaction between them, but also to analyse every problem bubbled up by the cell towers, like potential downtime, or number of packets received/handled, in order to better plan where the maintenance staff would have to focus, or where the future tower cells would have to be built.

 

And this was just the tip of the iceberg.

 

The company has some on-premise ArcGIS Servers, that serve their own geodata, like the cell towers geolocation, but also custom territories for maintenance staff.


Based on these many use-cases, we worked with them to build what they needed.

 

Here are some screenshots of the POC.

 

screen5.png

 

Figure 1.The basemaps being configurable, offers the possibility to zoom up to street levels and still obtain a very good level of details, allowing the end-user to exactly know where their data are located

 

 

FINAL DS.png

 

Figure 2. A view of a possible dashboard made for a customer during a POC phase. The view combines multiple maps, each of them having the possibility to be linked to its own data source and to have its own basemap or layers configuration


 

They also add very specific requirements, for example being able to analyse the data flow between cell towers. These, of course, being "abstract" while still occurring in real life. In their dataset, a dimension was containing the ids of the cell towers (as "ID01;ID06;ID07;" for example), as well as several other dimensions containing metrics about the flows in question (as "185500;196550;124500;" according to the ids upon) calculated by SAP HANA on the fly.

 

So we integrated the capacity to display lines into Galigeo for DesignStudio - representing data flows - simply based on the dimension containing links between cell towers.

 

For example, if the cell tower A has ID 01, and is able to communicate with tower B, as we know coordinates from both towers coming from the ESRI server, it was easy to create a line between them to display KPI on it.

 

A screenshot focusing on the result above Berlin, Germany.


ds.png

 

Figure 3. This map displays a KPI on the cell towers themselves, and another KPI on the data flow between the cell towers. Like mentionned above, the flows (represented by lines) do not come from any GIS datasource, but are generated on the fly leveraging a specific development that can read links between tower cells in the BI datsource.


As this requirement is really specific for this customer, it has not been integrated in the core product.

 

But what's great is that if someone has the same needs, it could be easily replicated. Though if your business needs differ, our team of experts are of course on hand to build whatever you require.

 

That will be it for today guys, if you have any questions or feedback, feel free to post comments below and we'll be glad to answer.

 

You can also contact me via PM on this website if you have more specific questions or contact us at www.galigeo.desk.com for any support related queries.

 

And remember, the only limit is your imagination.

7788.png

A 30-days trial is available right there.


Cheers,

Vincent

Migration from SAP Dashboards to SAP BusinessObjects Design Studio - Part 3

$
0
0

In the first two parts (Part 1, Part 2) we looked at some of the major differences between SAP BusinessObjects Design Studio and SAP Dashboards (former Xcelsius).

 

I hope that I was able to provide already enough reasons for you to consider the migration from SAP Dashboards to SAP BusinessObjects Design Studio.

 

Now - how do we want to start such a migration ?

 

 

 

blog_mach_02_001.jpg

 

Above are the 5 key steps for your migration.

 

 

Step 1: "System Inventory"

 

Before starting the actual migration work you want to make sure that your landscape has all the important elements.

  • Did you already install the SAP BusinessObjects Design Studio on client and Server ?
  • Are there updates required for your SAP BusinessObjects platform based on dependencies ?
  • Did you consider SAP BusinessObjects Design Studio when you sized the SAP BusinessObjects Platform ? If not - for sure you will have to make adjustments on the sizing part.

 

Step 2: "Dashboard Inventory"

 

As next step you really want to do an inventory on all the dashboards that exist created with SAP Dashboards.

  • Which data sources are used on those dashboards ?
  • Are all data sources covered by SAP BusinessObjects Design Studio ?
  • Which are the components that are used ?
  • Are all components available in core SAP BusinessObjects Design Studio ?
  • Will you require Partner Extensions to cover the gaps ?
  • Did you use any extensions for SAP Dashboards ? do those exist for SAP BusinessObjects Design Studio ?

 

Step 3: "(Re)Design Phase"

 

This is an important step because you have to create the SAP BusinessObjects Design Studio dashboards anyway and you should use this as an opportunity to also re-evaluate the design of your dashboards. Requirements might have changed and for sure technology has move on.

Remember - SAP Dashboards was always designing for a specific screen resolution, which is not needed for SAP BusinessObjects Design Studio.

Also keep in mind that the need for mobile dashboards as increased a lot since SAP Dashboards and that will have an impact on your dashboard design.

 

Step 4: "Deployment"

 

On purpose I didn't include a phase called "Design" in here as I thought it is a given that we will have to create the dashboards in SAP BusinessObjects Design Studio. So after that you want to do your standard testing cycle in move the dashboards from Dev to QA to PROD.

 

 

Step 5: "Skill set"

 

One important item not to forget in all of this is the required skillset. Do not forget to train your team, your colleagues on topics such as Design Studio itself as well as topics such as stylesheets and Java Script and the topic of data visualization and dashboard design in general.

This is not the training for the business user that consumes the dashboard but for the people that are creating the dashboards and applications with Design Studio.

Visual BI Extensions - Drill Down Charts

$
0
0

One very common questions from customers is around the ability to drill down in charts in SAP BusinessObjects Design Studio and as probably most of you are aware, standard SAP BusinessObjects Design Studio is not delivering any drill down capabilities in charts.

 

As part of our Extensions for SAP BusinessObjects Design Studio we provide the ability to do a real drill down as well as a inplace expand and collapse and we do support this for standard dimensions as well as hierarchies.

 

So lets assume we have two different sets of data. In the first data set we are going to use a set of multiple dimensions....

 

VBX_BLOG_MARCH_03_001.jpg

 

 

... and in the second data set we are using a hierarchy from BW.

 

VBX_BLOG_MARCH_03_002.jpg

 

Now we are adding a column chart with drill down capabilities from the Extensions to our dashboard and we are assigning these two data sources to the two charts. We do not have to do any scripting for the drill down capabilities.

 

In the Additional Properties of the two charts we can now configure the details of the behaviour.

 

VBX_BLOG_MARCH_03_003.jpg

 

Here we can set the properties on how the drill down / expand is supposed to happen and how the parent is going to behave.

 

  • We can include or exclude the Root Level nodes of the hierarchy
  • We can decide to show the parent nodes on a drill down chart so that we always keep the parent node.
  • We can decide if we only would like to see the measure that was selected or if we would like to see all measures in a drill down.
  • We can activate the hierarchical labeling - will show an example below
  • We can limit the number of levels of the hierarchy
  • We can configure if the parent node is going to be displayed before or after the children in the hierarchy.
  • We can configure the events and what should happen on a click, double-click, and CTRL+click.

 

 

So lets start with the first data set and a simple column chart that allows us to do a drill down in SAP BusinessObjects Design Studio.

So the initial screen of the chart will look like shown below...

 

VBX_BLOG_MARCH_03_004.jpg

 

... and with a simple click on "Cameras" we can do an "Expand" on Product Group Cameras and we can then see the next level of details directly in the chart as an inplace Expand - as shown below

 

VBX_BLOG_MARCH_03_005.jpg

 

In the second example we will use the data set with the hierarchy and we will enable the hierarchical labelling as well. As shown below, the initial screen shows the two hierarchy nodes for Asia Pacific and Europe.

 

DSX_SELECTORS_001.jpg

With a simple click on Asia Pacific we can use the inplace Expand and and expand the hierarchy node for Asia Pacific to the next level in the hierarchy.

VBX_BLOG_MARCH_03_006.jpg

 

In addition we can see the hierarchical labelling now in the X-Axis.

 

 

In case you do require charts with drill down capabilities, you will notice that such capabilities are not part of the core Design Studio offering, but the functionality can be achieve using Partner Extensions.

 

 

100 Things you can do with Visual BI Extensions and SAP BusinessObjects Design Studio

Google Directions on DesignStudio from everywhere

$
0
0

Dear all,

 

Lately I was asked if I could integrate Google API functionality into a Design Studio dashboard without doing SDK coding. Well, thanks to Google and our awesome SCN DesignStudio SDK community repository the answer is yes. All you need is the community component EmbeddedFrame and a google account. There is a whole bunch of available google API’s for different use cases but where are going to focus on the Embed API today.

 

The actual dashboarding request was to be able to get directions from place A to B using different kinds of data feeds like BEx queries, HANA Views and free text input.

embed_1.png

How it works

Now let’s say you want to plan your next scenic bike trip along the great Rhine river from your hometown Cologne to Koblenz via the town Andernach.

 

Just put the city names in the provided boxes, choose your type of transport (in our case by bike) and hit “Get Directions”. The Google API also provides the option to put the desired unit system (metric or imperial) or intermediate waypoints on the way from your origin to your destination.

This is what you get:

 

embed_2.png

 

As you can see the Embed API just answered our request perfectly. You might notice though that you don’t have the same flexibility in terms of playing with the parameters like you are used to with the actual maps. In order to get that you can click further options on the details panel on the top left of the pane which will redirect you to a new window loading google maps itself with your route.

 

Let’s try another one. How long does it take from Cologne to Muskegon, Michigan?

embed_3.png

Wow, 14 hours? There are probably some domestic flights from Chicago which are not shown to us. It seems that there is some further testing necessary to evaluate what requests can do with the embed API and what requests might be better off if with the fully blown maps application.

 

How to integrate

In order to construct the URL to call the Google Embed API there are several options. I’d like two outline two.

 

  • Use standard Design Studio components like the dropdown and input field to expose controls for the users to choose from available data or type their own.
  • If your input comes from another application altogether and you want to call your design studio dashboard from another launchpad or Iframe you can use global Design Studio variables and make them URL parameters. That way you can pass the values from outside and use them as input for the Google Embed API call.

 

You can find the example dashboard (SCN_GOOGLE_EMBED_API-20160305125839.zip) implementing both scenarios on my GitHub page and very soon also on our SCN community applications repository:

 

https://github.com/MartinPankraz/DesignStudioSDK-Components

 

Please note that you will have to put your google API key first at the relevant spots on the component coding and don’t forget to activate the Embed API first for your account. Otherwise you might see messages like:

 

The Google Maps API server rejected your request. This API project is not authorized to use this API. Please ensure that this API is activated in the APIs Console: Learn more: https://code.google.com/apis/console

 

An example call in local mode for the second option described above looks like this:

 

http://<server>:<port>/aad/zen?APPLICATION=SCN_GOOGLE_EMBED_API&designersessionid=1234&X_ORIGIN=Berlin&X_DESTINATION=Hamburg


Google Embed API

The Embed API comes with different modes which can be defined through the API call. The pattern looks like this:

 

https://www.google.com/maps/embed/v1/<mode>?key=<YOUR_API_KEY>&<parameters>

 

Where

  • <mode> can be either place, directions, search, view, or streetview
  • <YOUR_API_KEY> is your google API key and
  • <parameters> describes optional additional parameters like the maps zoom level for example

 

Since you are using your personal API key it is also possible to have some kind of personalization when being logged in with your google account. According to google you make use of saved places indicated by the URL parameter q. The relevant section on the Google API documentation is called “Attributed Save”.

 

You can find the developer documentation here:

https://developers.google.com/maps/documentation/embed/guide

 

As of today there is a limitation on Embed API requests as follows:

  • Requests per day                                 max 2.000.000
  • Requests per 100seconds per user        unlimited

 

Daily contingents will be reset by midnight PT.

Final Words

My showcase proved how easy it is to bring some sophisticated geolocation functionality into your Design Studio dashboards without the need to do custom SDK coding by using Googles API’s. And this directions example is only one of the big amount of possibilities. The only downside is that some of the actual maps functionalities are limited for the embedded maps case.

 

Anyone willing to share his google API integration story is very welcome to do so.

 

Let me know your thoughts.

 

Yours

Martin


Design Studio 1.6 SDK - BYOData Enhancement - Use your own data in Analytical Components!

$
0
0

Change Log

 

  • 03/07/2016 - Blog posted

 

Planned Enhancements

 

  • UOM support in Key Figures?
  • Text/Key Management?
  • Master Data Management?

 

Description

Use Case:

 

Design Studio allows us to create SDK Data Source components and one that I am proud to have seen a lot of use of for a number of interesting reasons it the Bring Your Own Data component (BYOData.)  I made this one back in Design Studio 1.4 and you can read about it here: Design Studio SDK (1.4) - Bring Your Own (BYO) Datasource  Later I gave it a few functionality/cosmetic enhancements mentioned briefly here:  Sneak Peak - SCN Design Studio 1.6 SDK Components


There unfortunately is a restriction where SDK Data Source components cannot be used in Analytical Components such as the Cross Tab, Filter Panel, Filter Bar, etc.  While this is unfortunate, there's really been nothing I could do about it.  I did start to become a little envious of the new CSV Data Source Component's flexibility where it felt more like a 'true' data source and could work with anything, instead of some SDK 'mutt' that couldn't work everywhere.


The down-side of the CSV Data Source is that you've really got to start with something instead of nothing.  What I mean is, that you have to take an export of an existing data source, which really doesn't make it easy to create dummy data (one of the main points of the BYOData component).  Plus, I'm not really sure why SAP even calls it a "CSV Data Source".  It's really 2 files that are semi-colon separated, and requires metadata.  In other words, you can't just go use your own Excel CSV mock-up.  (Confession - I thought that's how the CSV Data Source was supposed to work for a long time until I tried to use it for something)


I set forward to see if I could dynamically generate the 'CSV data' needed to feed the CSV Data Source.  Below is the end-result.

 

Hello BYOData's new feature: 'Generate for CSV Data Source'

byocsv.png

 

It's pretty simple.  On purpose.  You click the button, and you are prompted to Open/Save a .ZIP file:

 

byocsv2.png

The contents of the .ZIP are simply the 2 files you need to use in a regular CSV Data Source.

 

byocsv3.png

Basically, take these 2 files, drop them in your BIAPP's folder (or wherever) and then point your CSV Data Source component at it, and you're done!

 

A quick YouTube video with the end-to-end process:

 

 

(Note, I forgot to drag the CSV Data Source onto the filter panel at the end, but it works on all components.)

 

What you have seen is available for download in the usual spot (details here: SCN Design Studio 1.6 SDK Components (ver 3.0)).



Questions/Comments/Feedback always welcomed!

SAPPHIRE / ASUG Annual Conference - Design Studio Full Day Pre Conference

$
0
0

Are you interested in learning more on those advanced topics in SAP BusinessObjects Design Studio ?

 

Are you interested in topics such as Personalization and Bookmarking ?

 

Are you interested to learn how you could use Design Studio to create a self service environment for your business users ?

 

or would you want to learn more about how you can use the new scorecard component ?

 

and last but not least how you can find out why your dashboard tool 4 seconds to start and where you can check all those 4 seconds were spent ?

 

 

If you answer most of those questions with - "YES" - perhaps you want to join us for the Pre Conference at the ASUG Annual Conference / SAPPHIRE this year.

 

We have organized a BI focused pre conference now for several years and always received outstanding feedback.

 

This year we are focusing on a deep dive into SAP BusinessObjects Design Studio (not a beginner session !)

 

In case you are interested, here the details:

 

 

 

Monday, May 16

8:00 a.m. – 5:00 p.m.

$745 ASUG Member | $845 ASUG Non-Member

 

SAP BusinessObjects Design Studio is SAP’s flagship product for the creation of dashboards and custom analytical applications. This full-day, hands-on workshop is a series of activities focused on SAP BusinessObjects Design Studio in combination with SAP BW powered by SAP HANA.

 

Attendees will learn to use the different components in SAP BusinessObjects Design Studio and how to go from simple KPI dashboards to more complex, self-service style applications.


 

Link to the Registration: http://events.sap.com/sapandasug/en/asugpreconf

 

(The Design Studio Workshop is the 6th entry from the bottom)

 

Hope to see you there.

 

Mastering Business Analytics ..... in Johannesburg, South Africa

$
0
0

I have been very fortunate and was invited to speak at the Mastering Business Analytics Conference in South Africa now 5 years in a row and I always have enjoyed my time there.

 

If you are a SAP customer in Africa and you are interested in SAP BI and Business Analytics, this is clear the conference that you want to join.

 

You can find more on the agenda here:

http://masteringsap.co.za/ba

 

 

I will be speaking about the overall SAP BusinessObjects BI portfolio and how you can use your business driven requirements and find the right tool for your projects.

 

And most important - in case you are interested in a real hands on experience - I will be conducting a full day hands on workshop of SAP BusinessObjects BI 4.2 with SAP BW on SAP HANA focusing on SAP Lumira, SAP BusinessObjects Design Studio, Analysis Office, Predictive Analysis, and Web Intelligence.

 

Perhaps we will see there in a few days.

Multiple crosstabs to Excel

$
0
0

Hi y'all,

 

I came accross an issue that I solved and I'd like to share this with you. It's about how a user can select a various number of crosstabs to export to Excel.

 

General

In this case there are 9 crosstabs defined where the user can select which need to be exported to Excel. The standard automated Excel export functionality will be used (all separate crosstabs will be exported into worksheets).

Layout user interface

In the example below there are three pre-defined reports available in totals, per region and per market.

pic1.png

Three vertical checkbox groups were created, it is currently not possible to create a 3 x 3 checkbox group (DS1.6 SP1).

 

Definition

An extra global variable type Crosstab has to be created. Did try a local variable but that didn't do the job :-)

Pic2.png

A definition of the three checkbox groups.

Pic3.png

Pic4.png

Pic5.png

 

Crosstabs

Create a new panel and place 9 crosstabs in it. Since it's only meant for exporting, the panel is kept small and placed behind an image (or anything else that covers it). Make sure the names of the crosstabs are equal to the names used for the checkbox members.

Pic6.png

Data sources

Just to clarify where the coding comes from...

Pic7.png

Export button event

The export button contains al the code to read the selected checkboxes and translate these into an array that is added to the export to Excel function.

 

// Read values from the 3 checkbox groups (CBGR).

var lv_tot_arr = CBGR_TOT.getSelectedValues();

var lv_reg_arr = CBGR_REG.getSelectedValues();

var lv_mkt_arr = CBGR_MKT.getSelectedValues();

 

// Create crosstab array

var lv_CTArr = [CT1];

// Remove element from the array

lv_CTArr.pop();

 

lv_tot_arr.forEach(function(element, index) {

  if (element == "CT1") {

         gvCT = CT1;

         lv_CTArr.push(gvCT);

         CT1.setDataSource(DS_1);

  }

  if (element == "CT2") {

         gvCT = CT2;

         lv_CTArr.push(gvCT);

         CT2.setDataSource(DS_2);

  }

  if (element == "CT3") {

         gvCT = CT3;

         lv_CTArr.push(gvCT);

         CT3.setDataSource(DS_3);

  }

});

 

lv_reg_arr.forEach(function(element, index) {

  if (element == "CT4") {

         gvCT = CT4;

         lv_CTArr.push(gvCT);

         CT4.setDataSource(DS_1_1);

  }

  if (element == "CT5") {

         gvCT = CT5;

         lv_CTArr.push(gvCT);

         CT5.setDataSource(DS_2_1);

  }

  if (element == "CT6") {

         gvCT = CT6;

         lv_CTArr.push(gvCT);

         CT6.setDataSource(DS_3_1);

  }

});

 

lv_mkt_arr.forEach(function(element, index) {

  if (element == "CT7") {

         gvCT = CT7;

         lv_CTArr.push(gvCT);

         CT7.setDataSource(DS_1_2);

  }

  if (element == "CT8") {

         gvCT = CT8;

         lv_CTArr.push(gvCT);

         CT8.setDataSource(DS_2_2);

  }

  if (element == "CT9") {

         gvCT = CT9;

         lv_CTArr.push(gvCT);

         CT9.setDataSource(DS_3_2);

  }

});

 

APPLICATION.export(ExportType.EXCEL_xlsx,lv_CTArr);

 

Have phun !

Using me in scripting

$
0
0

When you script in any component you will find the keyword me in the content assistance which you can access by pressing CTRL-SPACE.

img_3_me.jpg

The keyword me is a special kind of keyword that refers to the component in which the script is run. So the value of me depends on where you at. For the JavaScript people this looks a lot like the keyword “this”.

The keyword me is very useful when you want to pass the current component as a parameter to a central script function. One of the main advantages is that you now can copy the component and the script is still valid. “me” in the new component refers to that component. Not the first one.


How to use

Suppose you want a fancy menu with a selected item and unselected item. The menu bar could look like this

img_4_example.jpg

    img 1: example application

 

To create the layout we use two grid components. The outer one with 2 rows, the inner one in the top row with 6 columns.

img1_layout.jpg

    img 2: layout application

 

For the buttons we create two CSS classes. selected and unselected. The CSS you will find in the text attachment.

Now we will create a function that takes the clicked component and an array of all the menu items to set the CSS classes accordingly.

img2_setCSS.jpg

    img 3: Global Script Function

In the script function you see that we first loop through all the elements in the parameter array MenuComponents to set the CSS to unselected. The second step is then to set the CSS of the component that was passed via the parameter SelectedComponent.

And now we come to the point where me is useful. In each button we want to pass the current button as SelectedComponent to the function. And the complete set as an array.

We can do this with the following script line :

 

var menuItems = [MENU_1, MENU_2,MENU_3, MENU_4,MENU_5, MENU_6];
LAYOUT.setCSS(me, menuItems);

We can copy the script across all the six menu items without having to edit the script. Ideally you would want to make the variable array menuItems global so that you only have to define that once, but that is not possible yet.


Is there a way of overdoing this?

Yes I can think of a way and I’m glad you asked J

Using Karol Kalisz dynamic components  Make your Application Dynamic!

 

(with a little tweaking) you could retrieve the name of the component as a string. This string value you can use to filter a datasource. The datasource holds a set of property values.

You collect those properties and apply them to the component. That would lead to some extreme masterdata driven applications that can be maintained in tables.

 

Conclusion

The keyword me is only a small addition, but one that has many usecases. In JavaScript the equivalent this keyword is used very often. When you call central functions you can pass the current component as a parameter using this keyword.

Your First Extension: Part 10a - The "Data" in Data Driven Documents

$
0
0

This is part of a tutorial series on creating extension components for Design Studio.

 

In the last installment, we introduce an indicator needle into our gauge component.  Now we're ready to start working on refinement.  One of the refinements that we're going to add to our component is animation.  In the next set of installments, we'll animate the gauge arc and needle in the sandbox html file and then enable the animations in the SDK extension itself. 

 

But first, we have to re-examine how we've defined our geometry.

 

 

The "Data" in Data Driven Documents

 

 

Up until now, we've been doing something that works under normal circumstances, is not conformant to the philosophy behind D3 and will break animations.  We've been defining geometry attributes directly.  Let's take a look at the gauge arc as we originally defined it; all the way back in Part 2b

var arcDef = d3.svg.arc()

  .innerRadius(innerRad)

  .outerRadius(outerRad)

  .startAngle(startAngleDeg * (pi/180)) //converting from degs to radians

  .endAngle(endAngleDeg * (pi/180)); //converting from degs to radians

 

var guageArc = vis.append("path")

  .style("fill", colorCode)

  .attr("width", width).attr("height", height) // Added height and width so arc is visible

  .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")")

  .attr("d", arcDef);

 

 

In the above code, we define an svg arc and then assign it to the "d" attribute of the path that we add to our visualization.  Note that we are setting .startAngle and .endAngle directly.  This runs counter to the D3 philosophy and letting the data do the talking.   So what's wrong with the above code?  It works after all and it has so for the past 18 installments and why should we care if it does not follow the D3 philosophy?  It is blocking off some key capabilities of D3, capabilities that we've not investigated up until now.  Let's take a look at the following statement from the D3 documentation

Computed properties often refer to bound data. Data is specified as an array of values, and each value is passed as the first argument (d) to selection functions. With the default join-by-index, the first element in the data array is passed to the first node in the selection, the second element to the second node, and so on. For example, if you bind an array of numbers to paragraph elements, you can use these numbers to compute dynamic font sizes:

 

d3.selectAll("p")

    .data([4, 8, 15, 16, 23, 42])

    .style("font-size", function(d) { return d + "px"; });

 

 

So by adding data, we can then make our properties - or even the total count of svg elements - data driven.  In the above snippet, we see that we are setting the font size, based on the data.  In the next installments, we're going to be altering existing svg element properties, using D3's transition machinery, but in order to make this possible, we're going to need to remove our direct angle property assignments and replace them with data.  This way, D3 can use the data to make dynamic property value assignments.  So we're going to make a change to what it should have looked like:

var arcDef = d3.svg.arc()

  .innerRadius(innerRad)

  .outerRadius(outerRad);

 

// Add the foreground arc in orange, currently showing 12.7%.

var guageArc = vis.append("path")

  .datum({endAngle: startAngleDeg * (pi/180), startAngle: startAngleDeg * (pi/180)})

  .style("fill", "orange")

  .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")")

  .attr("d", arcDef);

 

Note that we no longer define start and end in the arc definition, but rather leave it malleable.  Instead, we define the .datum element and set it to contain our data.  We'll be leaving the direct definitions of the radii in place, though in principle, we could have moved them to data as well.  One line of code is all that need sot change.  The SVG element is now data bound.  The base pin of the needle is also an arc, so we can follow the same pattern for it as well. 

 

Instead of:

//Base Pin

 

var pinArcDefinition = d3.svg.arc()

  .innerRadius(needleIBasennerRadius)

  .outerRadius(needleBaseOuterRadius)

  .startAngle(nbTransformedStartAngle * (pi/180)) //converting from degs to radians

  .endAngle(nbTransformedEndAngle * (pi/180)); //converting from degs to radians

 

var pinArc = vis.append("path")

  .attr("d", pinArcDefinition)

  .attr("fill", needleColorCode)

  .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")");

 

 

We have:

//Base Pin

 

var pinArcDefinition = d3.svg.arc()

  .innerRadius(needleIBasennerRadius)

  .outerRadius(needleBaseOuterRadius);

 

var pinArc = vis.append("path")

  .datum({endAngle: nbTransformedEndAngle * (pi/180), startAngle: nbTransformedStartAngle * (pi/180)})

  .attr("d", pinArcDefinition)

  .attr("fill", needleColorCode)

  .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")");

 

 

The needle itself is a bit different.  Whereas with the arcs, we're defining  a D3 arc separately and then assigning it to the SVG element as a property of the path, with the line, we're drawing the line when we declare it. 

 

Instead of:

//needleWaypoints is defined with positive y axis being up

var needleWaypoints = [{x: 0,y: 100}, {x: 10,y: 0}, {x: 0,y: -10}, {x: -10,y: 0}, {x: 0,y: 100}]

 

//we need to invert the y-axis and scale the indicator to the gauge.

//  If Y = 100, then that is 100% of outer radius.  So of Y = 100 and outerRad = 70, then the scaled Y will be 70.

var needleFunction = d3.svg.line()

  .x(function(d) { return (d.x)*(outerRad/100); })

  .y(function(d) { return -1*(d.y)*(outerRad/100); })

  .interpolate("linear");

 

var needle = vis

  .append("g")

    .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")")

  .append("path")

    .attr("d", needleFunction(needleWaypoints))

  .attr("stroke", ringColorCode)

  .attr("stroke-width", bracketThickness)

  .attr("fill", ringColorCode)

  .attr("transform", "rotate(" + startAngleDeg + ")");

 

 

We have:

//needleWaypoints is defined with positive y axis being up

var needleWaypoints = [{x: 0,y: 100}, {x: 10,y: 0}, {x: 0,y: -10}, {x: -10,y: 0}, {x: 0,y: 100}]

 

//we need to invert the y-axis and scale the indicator to the gauge.

//  If Y = 100, then that is 100% of outer radius.  So of Y = 100 and outerRad = 70, then the scaled Y will be 70.

var needleFunction = d3.svg.line()

  .x(function(d) { return (d.x)*(outerRad/100); })

  .y(function(d) { return -1*(d.y)*(outerRad/100); })

  .interpolate("linear");

 

var needle = vis

  .append("g")

    .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")")

  .append("path")

  .data(needleWaypoints)

    .attr("d", needleFunction(needleWaypoints))

  .attr("stroke", ringColorCode)

  .attr("stroke-width", bracketThickness)

  .attr("fill", ringColorCode)

  .attr("transform", "rotate(" + startAngleDeg + ")");

 

 

 

Datum vs Data

 

 

You might have noticed something above.  With the arc definitions, we used .datum and with the needle, we used .data.  What's the difference and then do you use datum vs data?  Here is the simple rule:

  • datum is unchanging, static data, tied to a single SVG element.  .datum is just fine for our gauge arc.
  • data can be updated and assigned to multiple SVG elements.  You can also use it wherever you would use datum, if you want.  We could have used .data for our gauge arc, if we wanted.  If we were defining a scatterplot, we'd have to use .data.

 

 

If you use data, a whole new set of lifecycle methods become available, allowing you chances to manually handle the "entering" and "exiting" content.  In this tutorial, we are sticking with binding our data to single SVG elements and we are completely redrawing from scratch on refresh.  If we were creating elements dynamically, or had to design for a mobile device, then we'd want to go deeply into the element/data lifecycle and come to grips with joins.

 

 

We now understand the basics behind binding data to SVG paths in D3.  next time, we'll use transitions to alter this data and start animating our gauge.

Design Studio 1.6 - Data Blending with Data Iterator & Bring Your Own Data Source

$
0
0

Finally! After Mike has created ans posted the ultimative DataIterator (Design Studio 1.6 SDK - Data Iterator - Read your data row by row finally!) I could find a good way how to use the Bring Your Own Datasource (Design Studio SDK (1.4) - Bring Your Own (BYO) Datasource) and create a scenario which were not available until now.

 

* Data Blending / Joining / Mixing - creation of one (new) data source based on 2 data sources (independent of the source system)

 

Short History

For the data blending / mixing / joining I wrote a blog some time ago Mixing Data from 2 Result Sets together (join, select) with a prototype component Design Studio SDK: Result Set Mixer Component. This was prototyping - which works, but has a lot of restrictions.

 

The Scenario

Very often I hear from customers, also I have on my own requirement list, following requirement - how to bind some data which are available in 2 separate data sources (queries) and IT will not put them together - like project spends (controlling query) and project status (program management query). All are searching for putting such data together.

 

Another example I will use is following: one query has sales data (what, where, quantity, price) and second query has buying data (what, price). I would like to have a query with revenue on what and where.

 

In Pictures, I want to have:

 

Query 1:

w1.PNG

Query 2:

w2.PNG

Result:

w3.PNG

 

How is the revenue calculated?

I use standard scripting for that:

 

  var soldValue = quantity * price;  var buyValue = quantity * buingPrice;    var revenue = soldValue - buyValue;

This script executes per row of the first data source. And for this the Data Iterator is coming into work!

 

Technical Setup

From technical side, I need to have 3 data sources - the first 2 are bringing the data, the 3rd one is waiting to be filled in. In the attached example I use BYO data source to have it easier explained and offline.

 

Both data sources which are bringing the data are connected to data iterator - it means, as soon the iterators are filled in (which is currently going through browser) the work can start.

 

Script in both Data Iterators (Event: onDataChanged)

 

if(MIX_READY) {  GLOBAL_SCRIPTS.merge();
}
MIX_READY = true;

I use the global variable as semaphore to assure both are initialized

 

the "merge" function makes the magic:

 

var sellRows = DATAITERATOR_SALES.getRows();
DS_MIX.clear();
sellRows.forEach(function(row, index) {  var product = row.getDimensionValueKey("Product");  var store = row.getDimensionValueKey("Store");    var quantity = row.getMeasureValue("Quantity");  var price = row.getMeasureValue("Price");  APPLICATION.log("Line: " + product + ", " + store + ": " + quantity + " x " +price);  var buingPrice = 0.0;    var buyRows = DATAITERATOR_BUY.getRows().containing({      "dimensions": [          { "key" : "Product", "value" : product }        ]      });     // assuming only one!     buyRows.forEach(function(buyRow, index) {  buingPrice = buyRow.getMeasureValue("Buying Price");  });  var soldValue = quantity * price;  var buyValue = quantity * buingPrice;    var revenue = soldValue - buyValue;    DS_MIX.addRow(product+","+store, ""+revenue);
});

 

Logically:

1. get the "sales" rows

2. clear the target data source

3. loop and read out required information

4. pick up the buing price

5. calculate

6. add rows to the target data source

 

THAT'S IT!

Now, as this is "real data source", you can bind it to other components and you do not need to care about any update scripts for it. E.g. I have bound it to

* UI5 Table

* Nice Chart

* and ... the standard component Scorecard!

 

Outline:

w5.PNG

The App:

 

w6.PNG

 

I am sure some of you will be happy with this procedure. Of course, it is not for mass data, but works very well with reasonable number of rows (also thanks to  Mike who has improved the size of data stream in the data iterator component.

 

The example application can be downloaded from the repository.

applications/SCN_OWN_DATASOURCE_BUILDER-20160310173344.zip at master · org-scn-design-studio-community/applications · Gi…

 

Have Fun!

 


Design Studio 1.6 - Waht-If-Analysis with Data Iterator & Bring Your Own Data Source

$
0
0

One more idea - this time the old topic of what-if-analysis in design studio. It show another open direction with data iterator and byo data source. The goal is to have simple data manipulation and what-if-analysis with the changed data.


Mike has already described the option of adding data rows to BYO data source in his initial blog: Design Studio SDK (1.4) - Bring Your Own (BYO) Datasource.

Now, having the data iterator which allows mixing 2 data sources from any source system - blog here - Design Studio 1.6 - Data Blending with Data Iterator & Bring Your Own Data Source, it is even possible to bind those two options.


I have build-up the example from the data blending blog into more advanced option and combination of slider, input component and UI5 table with selection model to adjust existing data.


The Working example look like this (animated GIF, click to expand)

20160310-174532_capture.gif


What is In?


First,

the simplest case - you can add new rows to the data source (as described by Mike) and then the full blending code from my blog executes again - so you can calculate revenue for the new entry and get it in all other components bound to the result data source.


Script:

DS_SALES.addRow("Apples,University Shop", "96,43");

Second,

you can modify existing data and this will be reflected in the result, e.g. you can change the buying price in our example and the changed revenues are visible in all components bound to your result data source.


Preparation of the Target Data Source

In the target data source you should create the columns and add one dummy row. Scorecard does not see the measure w/o at least one row.


Script:

selection in the UI5 Table triggers the value population to input components (input field and slider)


var selection = UI5TABLE_BUY.getSelectionDimensionMembers();
selection.forEach(function(dim, im) {   var product = dim.member;      var buingPrice = 0.0;     var buyRows = DATAITERATOR_BUY.getRows().containing({      "dimensions": [          { "key" : "Product", "value" : product }        ]      });      // assuming only one!      buyRows.forEach(function(buyRow, index) {  buingPrice = buyRow.getMeasureValue("Buying Price");   });   VALIINPUT_1.setValue(""+buingPrice);   SLIDER_1.setValue(buingPrice);   
});

then, change on any of those input components triggers update of the data source, e.g. slider:

 

var selection = UI5TABLE_BUY.getSelectionDimensionMembers();
selection.forEach(function(dim, im) {   var prod = dim.member;      DS_BUY.addRow(prod, ""+SLIDER_1.getValue(), true);
});

the "true" parameter on 3rd place means "overwrite"

 

Now, as the data iterators are triggering data change events - the result data source will recalculate everything again and populate to the components - and this is how it works.

 

also this example is available in the repository for use:

applications/SCN_WHAT_IF-20160310175332.zip at master · org-scn-design-studio-community/applications · GitHub

 

Have Fun!

Self-Made DesignStudio SDK Dashboard Comments

$
0
0

Dear all,

 

Have you been wondering when you would finally be able to put comments on your Design Studio dashboards in a decent and tremendously customizable way for free? Well, that day is today!

 

In the following sections I will showcase my new component ConVistaEasyComment which is published open-source on GitHub, talk about the backend integration, comment saving & loading and the overall commentary architecture involved.

 

What do you get?

Obviously to put some comments you need a place where you can do that. I decided to use a WYSIWYG (What You See Is What You Get) HTML editor. There are a couple of libraries out there providing editors like that. My choice was CKEditor because of a well documented API, a suitable developer license and the ability to Paste from MS Word. You could also look into tinymce and Froala just to mention a few more.

 

You can extend gracefully by implementing your own editor plugins by the way.

 

comment1.png

     Fig.1 Demo dashboard

 

My SDK component ConVista EasyComment comes with lots of built in functionality like spell-checking, multi-language support, the ability to add images, an option to adjust the reading direction and many more. These features are provided by the CKEditor library out of the box.

 

The save button (icon on the bottom right of the toolbars) exposes its functionality to the DesignStudio SDK component event On Save Button Clicked. You can also extract/modify HTML content on the editor using the scripting methods getHTMLString and setHTMLString.

 

You can customize the toolbars to be shown through the component property Toolbar Settings. I used the new SDK 1.6 feature that allows to put complex objects on the contribution file for that. That way DesignStudio creates a table like input window:

 

comment7.png

     Fig 2 Properties


You can activate/deactivate the toolbars one by one. For the Document section which contains the save button you can decide even on item level (but you can’t hide the save button ;-). Let’s put false on every item except for Editing and see what we get.

 

comment8.png

     Fig 3 Reduced editor toolbar view


If you need more fine grained customization you will need to get back to me or adjust the coding on the SDK component yourself. Now let’s jump to the fun part.

 

On Saving and Loading

At first I am going to tell you about the frontend part which is covered by the EasyComment component and how to model a data structure to store our DesignStudio comments before actually moving over to the backend part to show you possible starting points to implement your individual solution.

 

To be able to actually persist and successfully load a comment for a specific DesignStudio object you need to identify the object itself and maybe its filter state. For static content this very easy and straightforward. We could just take the technical name of the targeted object as key and save our HTML-string along with it on a table on our backend. For dynamic content like charts with arbitrary complex filter possibilities this can be a very complicated task.

 

Some of the commercial DesignStudio commentary components approach this topic on the SAP backend by evaluating for example BEx query state and learn the object state from there. That way they can identify the right comment to load or with what key to store it. To get this done for all of the possible DesignStudio data sources like BEx queries, BW cubes, Universes, Custom SDK data sources, CSV files and HANA views is quite a lengthy task for an ABAP developer.

 

Don’t make this harder as it needs to be!

My approach is not going to cover all kinds of complex scenarios but it will be as easy as it gets and get the job done for many cases. At first I make the assumption that it is sufficient to store only a limited number of characteristics values to successfully identify the breakdown of a value on a component like a DesignStudio chart, crosstab, KPI-View or Scorecard. Let’s differentiate two cases:

 

  • Static only content like DesignStudio texts or objects themselves and
  • dynamic content like data breakdowns and key figures on Crosstabs or Charts.

 

All of the static content can be covered by its technical object name and the dashboard they are on for example:

 

Key Fields

HTML Content

DashboardID

Object Technical Name

MYDASH_1

Demo_dashboard

<h1>This a comment for a dashboard itself</h1>

MYDASH_1

SOME_QUERY

<i>This is a general comment on a query</i>

MYDASH_2

TEXT_TITLE

<h2><b>This is a comment for a standard text</b></h2>

     Table 1 Static objects comment saving


Now on the dynamic stuff. From my experience many cases that need comments for key figure release processes for example, there is only a limited number of filter values involved. Often you can get away with an accounting basis, an accounting entity and a key date (single date, date ranges and etc.).

 

 

Key Fields

HTML Content

DashboardID

Obj tech. Name

Acc. Basis


Acc. Entity

Key date

MYDASH_1

QUERY1

GAAP

COMP1

10.03.2016

<p>some html content</p>

MYDASH_1

HANA_CALC_VIEW

GAAP

COMP1

01.01.2016

<p>year end forecasts are looking good</p>

MYDASH_1

CHART_1

 

COMP2

10.03.2016

<p> Please check the spike! </p>

     Table 2 Dynamic objects comment saving


How do you provide this data to the WebService?

DesignStudio offers lots of scripting methods that already provide what we need:

 

  • DashboardID: Accessible through APPLICATION.getInfo().name


  • Object technical Name: All SAP data sources (except SDK data sources) provide the method getInfo() which gives you access to the underlying meta data. The technical name is part of it.

 

  • Accounting Basis, Accounting Entity and Key date: Data sources offer methods to retrieve key-value pairs for given dimensions and DesignStudio components like the Dimension Filter give the user the ability to filter certain values on demand. When working with filter variables you can for example use the following script to learn their current setting influenced by the user input during runtime:

    

     var vars = DS_1.getVariables();

 

     vars.forEach(function(element, index) {

       if(element.inputEnabled){

         DS_1.getVariableValueExt(element.name);

    }

});


You could save the values for later usage with the ConVista EasyComment using the SCN community SDK component ARRAY.

 

 

Now that we learned how to retrieve keys to identify our data sets, we are ready to send some HTML-strings to the backend. Exciting, isn’t it!? Let me give you a simplified example.

 

As I already told you before, there is an event provided by the EasyComment component which gets triggered when you click the save button on the editor. Here is a script from a demo application:

 

             //cache busting

var ccid = APPLICATION.getTickCount();

//retrieve an accounting entity

var bukrs = DROPDOWN_1.getSelectedValue();

//set http request method

      me.setHttpMethod("POST");

      me.setServerUrl(

     "http://<sap backend>:<port>/sap/bc/<WebService Endpoint>?bukrs="+bukrs+"&ccid="+ccid

);

//Actually Trigger the save

      me.saveHTMLOnServer();


This DesignStudio script sets up the HTTP parameters and sends a POST request to the server. The method saveHTMLOnServer internally retrieves the current HTML-string from the editor on execution. If everything on the backend went good, you just saved your first comment!

 

To retrieve it again you need some more scripting and an approach how to expose that functionality. Usually people go for selection events in some sort of way. Let’s check out an example with a Dropdown.

 

comment2.png

     Fig 4 Editor full cycle interaction


Once the user selects an entity from the dropdown, the components On Select method fires. In there I put the following scripting:

 

            //Get the currently selected entity

var bukrs = me.getSelectedValue();

//Cache busting

var ccid = APPLICATION.getTickCount();

COMMENT_1.setServerUrl(

     "http://<sap backend>:<port>/sap/bc/<WebService Endpoint>?bukrs="+bukrs+"&ccid="+ccid

);

//Set HTTP request method

COMMENT_1.setHttpMethod("GET");

//Actually trigger the load

COMMENT_1.loadHTMLFromServer();

 

The above script loads the saved comment into the editor according to the selection on the dropdown. If you need to more than just an accounting entity to select your comment, like in my example, you will have to enrich this scripting slightly (e.g. put some more URL parameters etc.).

 

In light of above you can easily imagine how to extend this approach to serve your specific needs without aiming for a general solution for every possible scenario and putting hundreds of hours. Now let’s have a look at a possible SAP backend WebService class implementation to take care of the saving and loading of our precious HTML-strings.

 

Integration of the SDK component with a server

In order to be able to save the HTML content you add to the editor, I implemented the DesignStudio SDK component to be ready to integrate with a RESTful Web Service. I am using the standard JavaScript object XMLHttpRequest to manage the communication from the browser to the backend. Of course Cross-Origin Resource Sharing (CORS) problems might apply at this point if you are hosting you dashboard on a different server than the backend. To overcome that browser security problem you have to setup your backend code to supply two HTTP headers on the HTTP response:

 

Access-Control-Allow-Origin: true

Access-Control-Allow-Credentials: true

 

I will show an easy ABAP example below. At first you have to provide an ABAP class which will serve as the handler for the WebService communication.

 

  • ABAP class setup

Create a standard class and put it on your local objects or a development package.

 

     comment3.png

     Put the following two interfaces to provide your custom implementation for the SAP standard HTTP interfaces.

 

     comment4.png

     Once you save, the class structure will immediately be generated and look something like this:

 

     comment5png.png

    In order to put your custom WebService behavior you will have to implement the method HANDLE_REQUEST. Before that there is one more step. We      need to register this class with an ICF node. To do so, call transaction SICF and create a new node under default_host > sap > bc.

   

     comment6png.png

 

Put your class under the handler list and save. Go back and activate the ICF node. Hit test to learn your WebService endpoint URL and check if the registration worked. You will need that URL for the DesignStudio scripting and also for easy testing purposes with your browser.

 

Note that every URL call is basically an HTTP GET request.

 

  • HTTP CORS setup and HANDLE_REQUEST implementation

Now I am going to show you the essential ABAP code to get started. You need to be able to retrieve URL parameters from the HTTP requests, put CORS headers on your response and send the response to the client. This is done using SAP standard interface methods:

 

constants:
lc_header_mimetype_name      
type string value 'Content-Type',
lc_header_mimetype_value_html
type string value 'text/HTML; charset=utf-8',
lc_header_aca_origin         
type string value 'Access-Control-Allow-Origin',
lc_header_aca_credentials    
type string value 'Access-Control-Allow-Credentials',

lc_true                      
type string value 'true'.

 

data: _request_method    type string,
lt_inputparams       
type tihttpnvp,
ls_inputparams       
like line of lt_inputparams,
ld_bukrs             
type i,
ld_html_string       
type string,
ld_cors_callee       
type string,
ld_request_payload   
type string.

 

  "Get passed parameters
call method server->request->get_form_fields
changing
fields = lt_inputparams.
"Get passed payload, HTML data
call method server->request->get_cdata
receiving
data = ld_request_payload.
“ CORS setup
ld_cors_callee
= 'http://<server hosting DesignStudio>:<port>'.

  "Translate Input Parameters to Uppercase
loop at lt_inputparams assigning <ls_inputparams>.

translate: <ls_inputparams>-name  to upper case.
case <ls_inputparams>-name.
when 'BUKRS'.
ld_bukrs
= <ls_inputparams>-value.
endcase.
endloop.

_request_method
= server->request->get_header_field( name = '~request_method' ).
"Determine if method is get or post.
if _request_method = 'GET'.
"set the response mimetype to HTML
server
->response->set_header_field
( name  = lc_header_mimetype_name
value = lc_header_mimetype_value_html ).
"Set CORS access control to avoid browser policy restrictions
server
->response->set_header_field
( name = lc_header_aca_origin
value = ld_cors_callee ).
server
->response->set_header_field
( name = lc_header_aca_credentials
value = lc_true ).


“Do your table loading implementation here and assign to ld_html_string


"set the cdata response to the text
server
->response->set_cdata( data = ld_html_string ).

elseif _request_method = 'POST' .

"set the response mimetype to HTML
server
->response->set_header_field
( name  = lc_header_mimetype_name
value = lc_header_mimetype_value_html ).

"Set CORS access control to avoid browser policy restrictions
server
->response->set_header_field( name = lc_header_aca_origin
value = ld_cors_callee).
server
->response->set_header_field
( name = lc_header_aca_credentials
value = lc_true ).
“Do your table saving implementation here and send given html back to have a graceful answer since the SDK component is “assigning back the data coming from the server to the editor “right away
"set the cdata response to the text
server
->response->set_cdata( data = ld_request_payload ).

endif.

 

 

    Make sure you send the send HTML-string back on POST requests because the EasyComment component relies on setting the HTML response to the      editor as assurance that the saving worked. You could write a message here if something is wrong too. Further error handling is not implemented yet.

 

  • Tables

To get you started have a look at the table examples in the previous section. Put the table coding at the sections highlighted in red above on the ABAP code.

 

Once all of that is done, put an example value on your table and make a browser GET request using the URL we remembered before. If that works, your WebService is ready to serve and you can start integrating with EasyComment. Now start saving some comments even with images attached!

 

comment9.png

     Fig 5 EasyComponent editor with image on comment


Commentary Lifecycle (Commentary Solution Architecture)

To sum up the technical part I would like to provide a high level view on what I showed you in detail before.

 

EasyComment-Architecture.jpg

     Fig 6 Commentary Lifecycle Deployment View


In DesignStudio you need to put some logic to trigger the RESTful WebService and think about how to make that accessible to the user during runtime. On the backend you need to provide the communication endpoint for the RESTful WebService to deal with the HTTP requests. In my case that was SAP BW but the implementation is by no means limited to that. You could call any other system.

 

EasyComment-Sequence.jpg

     Fig 7 Commentary Lifecycle Implementation View

 

This sequence diagram visualizes the function calls on the involved software instances. DesignStudio scripting and events trigger internal methods on the EasyComment SDK component. As a result the component communicates with the backend to actually save and load HTML content. The callbacks deliver the content to the frontend.

 

What’s next?

As a next step I want to implement, what I call “Live-Commentary”. This means you no longer need to save your html content actively by hitting the save button but just start typing and save immediately. This will be achieved using WebSockets which enable full-duplex communication. User-Authorization at a side, this will allow users to edit comments even in parallel, seeing what their colleague does right away. Some of you might be familiar with that behavior from google docs or similar applications. I will keep you posted as development progresses.

 

Final Words

You are now able to enrich your DesignStudio dashboards with shiny comments up to a complexity that suits your needs. The frontend technology to get you started is already setup and implemented. The only open task is to decide how to store your HTML content. I have shown you a possible starting point to get this done quick and easy. Now find yourself an ABAP developer or roll up your own sleeves and have fun commenting.

 

You can get the component by installing the ConVista SDK components package which is available on GitHub:

https://github.com/MartinPankraz/ConVista-DS-SDK-Visualizations

 

As always feel free to leave comments and ask lots of follow up questions.

 

Yours

Martin

Your First Extension: Part 10b - Transitions in D3

$
0
0

This is part of a tutorial series on creating extension components for Design Studio.

 

Last time, we ensured that we were binding data to our shapes.  Now were going to get down to animating things.  Animation in D3 is gone through transitions.  In short, a transition in D3 changes an attribute on an existing component over time.  If that attribute is part of a path, you can alter the position or shape over time.  If it is a style element, you can slide from one style property to another.  The possibilities are limitless.  Furthermore, if what you are doing is simple, D3 can take care of it for you, black box style.  If it is more complex, you can take manual control.

 

10,000 Foot View of Transitions

 

Let's take a very simple example.  In the html code below, we use D3 to draw a small, red, semi-transparent circle.

<!DOCTYPE html>

<html>

  <head>

  <title>Simple D3 Transition</title>

  <div id='content'></div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>

    </head>

  <body class='sapUiBody'>

  <script>

  var vis = d3.select("#content").append("svg:svg")

  var circle = vis.append("circle")

  .attr("cx", 50)        

  .attr("cy", 50)       

  .attr("r", 20)

  .attr("opacity", 0.2)

  .style("fill", "red");

  </script>

  </body>

</html>

 

Part10b.1.png

 

D3 transitions have a fairly straightforward lifecycle.

  1. It is scheduled
  2. It starts
  3. It runs
  4. It Ends

 

The scheduling might be right away (the default) or it might be delayed.  Scheduling a transition is automatically triggered by selecting what we want to transition and calling it's transition() function; in the case above, it would be:

circle.transition();

 

 

The line of code above would not do anything visually, but it would trigger the full transition lifecycle.  Start and End are proper events and we could attach callbacks to them and do whatever we want on those events.  We could, for example, trigger browser alerts, telling the user that we're starting and ending the transition:

circle.transition()

  .each("start", function() { alert("start");})

  .each("end", function() { alert("end");});

 

 

This would trigger the two popups as soon as the page is refreshed.  We could also schedule a delay into the start of the transition by a couple of seconds (2000miliseconds = two seconds:

circle.transition()

  .delay(2000)

  .each("start", function() { alert("start");})

  .each("end", function() { alert("end");});

 

 

We can also define how long the transition lasts.  So in the example below, it is scheduled to start two seconds after refresh (when the start alert appears), with a duration of 5 seconds.  So the end alert comes seven seconds after page refresh.

circle.transition()

  .delay(2000)

  .duration(5000)

  .each("start", function() { alert("start");})

  .each("end", function() { alert("end");});

 

 

We've covered the scheduling, start and end.  Now let's have a look at the running.

 

 

 

Keyframes and Tweening

 

In the days of hand drawn animation, Disney's more experienced artists would not draw all 24 frames per second.  Instead, they would draw points in an animation; usually points with relatively simple movement in between.  These were called key frames.  Younger, less experienced (and less expensive) artists would fill in the frames in between the keyframes; this process was called inbetweening, or tweening for short.  This process is also used in computer animation, both of the 2D and 3D sort.  When preparing animations for a computer game for instance, a 3D artist will define the keyframes of an actor's motion.  At runtime, the graphics engine will perform the tweening computationally; providing smooth motion between the keyframes.

 

Transitions in D3 are also keyframe based.  There are always two keyframes; a start and an end keyframe.  D3 uses a built in tweening function to orchestrate the timing of frames and the update of properties.  In turn, it uses an interpolator function to determing the transient values the in between timeslice frames of an animation. The interpolation function is triggered once per frameand terurns a calculated value for the  attribute or style in question.  D3 contains a number of built in interpolator functions and will try to use one of these, depending on the data type being transitioned.

 

D3 has built in interpolators for handling cases such as:

  • numbers
  • colors
  • geometric transforms, such as scale, rotation and transformation
  • certain kinds of strings

 

If you need a custom interpolator, you can override the standard attrTween or styleTween and implement your own, along with the custom interpolator.

 

 

Using Standard attrWeen()

 

 

Our gauge rotates about its origin point and lends itself to a straightforward animation, using D3's built in rotation interpolator.  We simple add an attribute update to the transition() function and ask it to perform a transformation for rotation, with a specified end angle:

//Arcs are in radians, but rotation transformations are in degrees.  Kudos to D3 for consistency

needle.transition()

  .attr("transform", "rotate(" + endAngleDeg + ")")

  .duration(durationArc)

  .delay(delayArc)

  .ease(easeArc);

 

Opacity , being defined by a number between zero and one, is another thing that can be handled by a built in D3 attribute interpolator.  Here, we chain two transitions together.  The first instantaneously sets the opacity of the gauge's outer ring to 0 (fully transparent).  The second schedules a fade in that brings the "fill-opacity" back to 1; making the outer ring fully opaque.

ringArc.transition()

  .attr( "fill-opacity", 0 )

  .transition()

  .delay( delayArc )

  .duration(durationArc)

           .attr( "fill-opacity", 1 );

 

 

 

A custom arcTween()

 

As D3 has no built in radial interpolator for arcs the standard attrTween() function won't know how to handle it.  Therefore, we'll need to override the standard attrTween() function.  We don't need to override the standard interpolate() function, as we'll use the angles as let it operate as a standard linear interpolator.  The attrTween() function will take the interpolated  angle at each frame and update arc, arcDef.

guageArc.transition()

  .duration(durationArc)

      .attrTween("d", function(d) {

     var interpolate = d3.interpolate(d.endAngle, endAngleDeg * (pi/180));

     return function(t) {

  d.endAngle = interpolate(t);

  return arcDef(d);

  };

  });

 

 

The Complete Sandbox Webpage

 

<!DOCTYPE html>

<html>

  <head>

  <meta http-equiv='X-UA-Compatible' content='IE=edge' />

  <title>Part 6</title>

 

  <div id='content'></div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>

  <!-- <script src="file://d3/d3.js" charset="utf-8"></script>-->

  <script>

  var vis = d3.select("#content").append("svg:svg").attr("width", "100%").attr("height", "100%");

 

  var pi = Math.PI;

 

  //Viz definitiions

  var innerRad = 0;

  //var outerRad = 70;

  var width = 200;

  var height = 200;

  var startAngleDeg = -45;

  var endAngleDeg = 45;

  var colorCode = "red";

 

 

  //Outer Dimensions & Positioning

  var paddingTop = 10;

  var paddingBottom = 10;

  var paddingLeft = 10;

  var paddingRight = 10;

 

  //The total size of the component is calculated from its parts

 

  // Find the larger left/right padding

  var lrPadding = paddingLeft + paddingRight;

  var tbPadding = paddingTop + paddingBottom;

  var maxPadding = lrPadding;

  if (maxPadding < tbPadding){

  maxPadding = tbPadding

  }

 

  var outerRad = (width - 2*(maxPadding))/2;

  //var width = (outerRad * 2) + paddingLeft + paddingRight;

  //var height = (outerRad * 2) + paddingTop + paddingBottom;

 

  //The offset will determine where the center of the arc shall be

  var offsetLeft = outerRad + paddingLeft;

  var offsetDown = outerRad + paddingTop;

 

  //Don't let the arc have a negative length

  if (endAngleDeg < startAngleDeg){

  endAngleDeg = startAngleDeg;

  alert("End angle may not be less than start angle!");

  }

 

 

  var arcDef = d3.svg.arc()

  .innerRadius(innerRad)

  .outerRadius(outerRad);

 

  // Add the foreground arc in orange, currently showing 12.7%.

  var guageArc = vis.append("path")

     .datum({endAngle: startAngleDeg * (pi/180), startAngle: startAngleDeg * (pi/180)})

     .style("fill", "orange")

     .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")")

     .attr("d", arcDef);

 

 

 

 

 

  ///////////////////////////////////////////

  //Lets build a border ring around the gauge

  ///////////////////////////////////////////

  //var visRing = d3.select("#content").append("svg:svg").attr("width", "100%").attr("height", "100%");

  var ringThickness = 2;

  var ringOuterRad = outerRad + ringThickness;  //Outer ring starts at the outer radius of the inner arc

  var ringColorCode = "black";

  var ringStartAngleDeg = 0;

  var ringEndAngleDeg = 360;

 

  //Don't let the arc have a negative length

  if (ringEndAngleDeg < ringStartAngleDeg){

  ringEndAngleDeg = ringStartAngleDeg;

  alert("End angle of outer ring may not be less than start angle!");

  }

  var ringArcDefinition = d3.svg.arc()

  .innerRadius(outerRad)

  .outerRadius(ringOuterRad);

 

  var ringArc = vis.append("path")

  .datum({endAngle: ringEndAngleDeg * (pi/180), startAngle: ringStartAngleDeg * (pi/180), opacity: 0.0001})

  .attr("d", ringArcDefinition)

  .attr("fill", ringColorCode)

  .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")");

 

 

 

  ///////////////////////////////////////////

  //Lets build a the start and end lines

  ///////////////////////////////////////////

  var bracketThickness = 2;

  var lineData = [endPoints (outerRad, startAngleDeg), {x:offsetLeft, y:offsetDown}, endPoints (outerRad, endAngleDeg)];

  var visStartBracket = d3.select("#content").append("svg:svg").attr("width", "100%").attr("height", "100%");

  var lineFunction = d3.svg.line()

  .x(function(d) { return d.x; })

  .y(function(d) { return d.y; })

  .interpolate("linear");

 

  var borderLines = vis

  .attr("width", width).attr("height", height) // Added height and width so line is visible

  .append("path")

  .attr("stroke", ringColorCode)

  .attr("stroke-width", bracketThickness)

  .attr("fill", "none");

 

  //Helper function

  function endPoints (lineLength, lineAngle){

  var endX = offsetLeft - (lineLength * Math.sin(lineAngle * (pi/180)));

  var endY = offsetDown - (lineLength * Math.cos(lineAngle * (pi/180)));

  return {x:endX, y:endY}

  }

 

  ///////////////////////////////////////////

  //Lets add the indicator needle

  ///////////////////////////////////////////

 

  //needleWaypoints is defined with positive y axis being up

  var needleWaypoints = [{x: 0,y: 100}, {x: 10,y: 0}, {x: 0,y: -10}, {x: -10,y: 0}, {x: 0,y: 100}]

 

  //we need to invert the y-axis and scale the indicator to the gauge.

  //  If Y = 100, then that is 100% of outer radius.  So of Y = 100 and outerRad = 70, then the scaled Y will be 70.

  var needleFunction = d3.svg.line()

  .x(function(d) { return (d.x)*(outerRad/100); })

  .y(function(d) { return -1*(d.y)*(outerRad/100); })

  .interpolate("linear");

 

  var needle = vis

  .append("g")

      .attr("transform", "translate(" + offsetLeft + "," + offsetDown + ")")

  .append("path")

  .data(needleWaypoints)

      .attr("d", needleFunction(needleWaypoints))

  .attr("stroke", ringColorCode)

  .attr("stroke-width", bracketThickness)

  .attr("fill", ringColorCode)

  .attr("transform", "rotate(" + startAngleDeg + ")");

 

 

 

 

 

  ///////////////////////////////////////////

  //Lets add animations

  ///////////////////////////////////////////

 

  var delayArc = 500;

  var durationArc = 5000;

  var easeArc= "linear"; //https://github.com/mbostock/d3/wiki/Transitions#d3_ease

 

 

  //Arcs are in radians, but rotation transformations are in degrees.  Kudos to D3 for consistency

  needle.transition()

  .attr("transform", "rotate(" + endAngleDeg + ")")

  .duration(durationArc)

  .delay(delayArc)

  .ease(easeArc);

 

 

  //This blog post explains using attrTween for arcs: http://bl.ocks.org/mbostock/5100636

  // Function adapted from this example

  // Creates a tween on the specified transition's "d" attribute, transitioning

  // any selected arcs from their current angle to the specified new angle.

  guageArc.transition()

  .duration(durationArc)

        .attrTween("d", function(d) {

     var interpolate = d3.interpolate(d.endAngle, endAngleDeg * (pi/180));

     return function(t) {

  d.endAngle = interpolate(t);

  return arcDef(d);

  };

  });

 

  ringArc.transition()

  .attr( "fill-opacity", 0 )

  .transition()

  .delay( delayArc )

  .duration(durationArc)

            .attr( "fill-opacity", 1 );

 

 

  </script>

    </head>

  <body class='sapUiBody'>

  <div id='content'></div>

  </body>

</html>

 

This video shows the animations (with the exception of the ring fade) in action:

 

 

 

Next time, we'll bring the animations into the component.

Split your applications using external parameters

$
0
0

In this blog we will look at external parameters and their usage to enable you to split applications. We will look at the reasons why you want to split first and subsequently look at the way you can make it happen. For the latter we will first look at the basics and then continue to look at the architectural part, how to link to other applications in the same window and finally to be able to go back to the original application.


Why Split

There are a couple of reasons why you want to split applications into smaller applications that each perform a task.

  • Performance
    When you look at performance you will see that the best way to optimize is to show few components and load as few datasources as possible. This is hard to do when you’re application reaches across multiple levels and has numerous click-through possibilities.
  • Complexity
    Each component that you add increases the possible number of interconnected components. You can address each component from each component with script. When your application contains hundreds of components you have to be careful to keep them under control.
  • Flexibility
    When you work with multiple applications you can have multiple people working on them at the same time. Each application can also be independently called from any other application.

 

The basics

Before we go into the extras, lets revisit the basics. If you want to open a new application you use the method APPLICATION.openNewWindow(Url);

The Url in the parameter Is the address of the application you want to go to. A very basic script of how this would work is this :

 

var servername = "http://localhost:57821/aad/zen?APPLICATION=";
var application = "STORE_SALES";
var parameters = "&store=29938&period=20160401";
var newUrl = servername + application + parameters;
APPLICATION.openNewWindow(newUrl);

In this example a new application STORE_SALES is opened and two parameters are passed. Store and period.

In the application STORE_SALES you need to define variables to accept these parameters.

 

In the start script you can work with these Global Script Variables.

Clipboard01.jpg

 

 

Agree on architectural level on the names of the parameters

If you create multiple applications it is a good idea to agree on the names of the variables and  require each application to be able to handle them. When you have this in place the advantage is that you can blindly pass a set of parameters to another application knowing that that other application should understand what you mean.

So in our example. If someone else developed STORE_SALES it doesn’t matter as long there is agreement that Xstore and Xperiod are generally accepted parameters. It basically enables you to call any application and tell the other application what’s going on. Based on that the other application picks up and moves on.

 

Move to other application in frame

If you want a more seamless experience for your users you may want to have all the applications open in the same window. For that purpose you can use the Open url inplace component that was created by Karol Kalisz. Design Studio SDK: Open Url Inplace Component. With that component you use  code like

 

OPENURLINPLACE_1.removeAllParameters(); 
OPENURLINPLACE_1.addParameter("P1", "V1"); 
OPENURLINPLACE_1.addParameter("P2", "V2"); 
OPENWINDOWPOST_1.triggerExecution(); 
Instead of the APPLICATION.openNewWindow() method.

 

Callback to the referring application

Finally if you want to let the applications work together you have to find a way to go back to the previous applications in such a way that it is shown as it was when you left it. For that you can use two parameters Xreferapp and Xreferpar.

Xreferapp holds the application where you came from and the Xreferpar holds all the parameters you need to inform the application where you were when you left that application.

For example if you were in level 2 of the dashboard application and looking at productgroup non-food your parameter value of Xreferpar could hold

“&level=2&productgrup=non-food”

When you press a back button the application then opens the url in Xreferapp with the parameters in Xreferpar added. The original application should know how to use these values to recreate the previous state of the application.

Design Studio SDK Extension - Motion Chart Use Case

$
0
0

Idea Behind the Use Case:


SAP BusinessObjects Design Studio is an analysis tool which serves the purpose to make intuitive design based on analytical content and other OLAP applications. So, while working on the charting components of Design Studio, I found a motion chart online built in D3.js (source: https://bost.ocks.org/mike/nations/) which helps to analyze the data with three dimension (X-Axis, Y-Axis, Bubble Radius) over the years. Therefore, some research was done on how to include or develop such component in Design Studio. Hence, as a part of Design Studio Extension development, use case of Motion Chart has been recreated using SAP Design Studio SDK 1.6.

 

 

 

What is Motion Chart?

 

Motion Chart is a dynamic bubble chart which allows efficient and interactive exploration and visualization of longitudinal multivariable data. They provide mechanisms for mapping ordinal, nominal and quantitative variables onto time, 2D coordinate axes, size, colors, glyphs and appearance characteristics, which facilitate  the interactive display of multidimensional and temporal data.

 

motionchart.png

 

 

Technology Used:


Using Design Studio SDK in Eclipse IDE, the Motion Chart has been coded by implementing basics of JavaScript and its libraries, D3.js and jQuery.

 

  • D3.js plays an important role in this use case for the rendering of chart, the axis and the movement of bubbles over the graph etc.
  • Knowledge and concepts of HTML, DOM and CSS
  • know how of SVG and canvas

 

 

Final Steps:


After Motion Chart was developed and tested, it was deployed as SDK Extension Feature, packed into archive file which is readily available for installation in SAP Design Studio as Custom Component.

 


Github Link to the Motion Chart Component:


https://github.com/AntarjotSingh/SAP-Design-Studio-SDK/tree/master/com.sap.motionchart


Viewing all 662 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>