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

Visual BI Extensions - Providing a true hierarchical filter experience

$
0
0

Assuming you are using SAP BusinessObjects Design Studio, then chances are high that you are using SAP BW or SAP HANA as a data source for your dashboarding and then you most likely will have to deal with hierarchies as part of your dashboard as well.

 

At one point your business users will most likely bring up the requirement to be able to filter based on a hierarchy definition the data in the dashboard, and that is when you will notice that Design Studio before release 1.6 does not really provide any hierarchical filtering options and that even with the Tree component in release 1.6 the hierarchical filtering options basic.

 

As part of the Visual BI Extensions we provide a Hierarchical Filter component since Design Studio release 1.4 already and I would like to give a short overview on the capabilities.

 

DS_BLOG_APRIL_01_002.jpg

 

Above you can see a very simple hierarchy being displayed in our Hierarchical Filter component and you will notice a few items right away. The hierarchical filter component does provide the option to either choose specific members, or you can use the option to filter the hierarchy based on the selected levels or the leaf only. In addition you will notice the numbers in the brackets behind the node text, which indicate how many child nodes and how many child leafs are available - this can easily be switch on of off.

 

DS_BLOG_APRIL_01_003.jpg

 

Above you can see the display for the tab Level for our sample hierarchy and you can see the user then has the choice to either select the actual members - nodes or leafs from the hierarchy, or the user can create a selection based on levels or even select the item Leaf and then the lowest levels in the hierarchy will be selected - regardless where in the hierarchy ( >> unbalanced hierarchy).

 

DS_BLOG_APRIL_01_004.jpg

 

When selecting elements in the hierarchy, the filter dialog behaves like a typical hierarchical filter - meaning that when the user selects for example the entries US and Canada, then the parent node North America is automatically being selected as well.

 

DS_BLOG_APRIL_01_005.jpg

 

Above is an example of our simple hierarchy, where the user used the "Leaf only" option, which then selects the lowest members in the hierarchy across the complete hierarchy.

 

In addition to the functionality above, the real "power" of the component is in the scripting options. The hierarchical filter provides scripting to

 

  • retrieve the selected member with the internal / external key or text values
  • retrieve the children based on the selected member with the internal / external key or text values
  • retrieve the descendants based on the selected member with the internal / external key or text values
  • retrieve the parents based on the selected member with the internal / external key or text values
  • set the selected member using script
  • set the hierarchy that is being used using script

 

 

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


Lessons learned on more than 1 year SCN SDK community

$
0
0

This will be non-technical blog.

 

I want to write on my lessons learned of more than one year working together with many members of the SCN SDK community in great collaboration and bringing value for other users / partners and customers. The reason I want to write it is to show and convince others that also in small scope collaboration is helping to speed up, learn, know each other and increase the value from common efforts.

 

I have used some time in last month to review what we have done, how it came and what outputs have been produced. I have looked at the old times, old components we created separately and together. Here my personal view on the procedure.

 

My initial work.

A short overview on the historical data, I have been more active on SCN around August 2014 - this was the time when Design Studio 1.3 SP1 has been released. With this release SDK development has got some important method (for me) - afterDesignStudioUpdate() - which has allowed creation of UI5 components with easy synchronization of updating properties. This was a point for me when I started to look at any options to create show cases for SDK components. My focus was always to fill-in areas where at that time some components were missing.

 

The first component - Design Studio SDK: NotificationBar Component - was a tryout. And this worked! I could get it done - simply covering already existing component from the UI5 library and making it work in DEsign Studio. Then, with Design Studio SDK: Simple Date Object Component I have learned how to use the capabilities of ZTL language and provide some functions in the scripting language. Some more components have followed up, until around September 2014. All those components were in the GIHUB repository GitHub - KarolKalisz/DesignStudioSdkPack: Design Studio SDK.

 

My view on MIke's initial work.

I must say that at the time Mike has provided already a repository with many components - Design Studio 1.2/1.3 SDK - Design Studio Utility Pack. Those were collecting many components written already since November 2013, bounded in the utility pack (May 2014, after RTC of 1.3 release). Mike has started the "open source" idea, which was quite new at this point of time - especially for SAP software.

I have followed similar procedure in the beginning - as in the beginning it looked like every component is "self-contained", so it does not matter how it will be downloaded and installed. But this has changed as I have seen that my components are quite primitive, basically I could not write any APS at this time - I tried once, but it was very basic.

 

Community Idea

In many discussions over SCN (great platform to exchange ideas on SAP content) at some point of of time we got together and started to cooperate on ideas, code content and other functions, MIke's blog on Design Studio SDK - BIAL for...next loop (and my first GitHub co-author attempt). For me, the start was actually 2 versions for Accordion component, one from Mike - one from me.

 

We started to discuss also an option to make a github repository which is really public, this is how the community work started - the goal was to be ready for New Year 2014/2015 (which matches the release of Design Studio 1.4). On the way, we could "deprecate" the old repositories, make a structure which is helping us to work together (avoiding too many rebases and merges) and offer semi-automatic production capabilities for release of the content.

 

Milestone

The community has been created - SCN Design Studio SDK Development Community. The next steps are quite public in the scn blogs, so now it is time to collect lessons learned.

 

At some point of time we managed to get the technical help content at Component List 3.0 - SCN Design Studio Community where all components are listed with its functions. Those content is also generated, so it gets updated when we change the components.

 

Lessons Learned

 

1. It is good to have a good technical infrastructure

We have found the infrastructure in GITHUB - this is how we started and this is how it currently works. It offers easy collaboration on code, we have increased the collaboration by some "procedures" how to avoid conflicts in merges - my blog SDK Development Community Git Repository (list & documentation). There is one more point, the infrastructure needs to be in "common sense" and "as primitive as possible" to not get into lengthy discussions. We managed to find it quite quickly, but there is always a risk.

 

2. Work on same content can be a nightmare (merge conflicts)

This learning is my personal - especially as I was not experienced in GIT procedures at all, and even now I can say - I can use it until I get into troubles. Then I make a copy, reset and overwrite ;-). But in my searches on fixing issues, I found a lot of blogs suggesting the same in troubles... This is the reason why we splitted technically the content into more repositories, one for code, one for binary files, one for help files...

 

3. You do not need to understand everything

When working together, I often had to say "WOW".. when something new got pulled from the repository. Especially when I remember the Mike's work on APS code to process parameters - this was and is Mike's area of expertise. I have tried to get the idea and understand how I can use it in my components. First after few weeks or even months I have debugged into the code as I wanted to change some places. But in general, the understanding is required first when you need to make something with the code - important is to get the "external API" first.

 

4. Community has to define very flexible rules

One of my findings is, common rules help and a baseline must be common. In other case the scripts which have to be used would not work in our repository. But the ways how to get to the common rules and structures is open - this can be seen in the repository on the example how we create components. I have my way, Mike has own way. But we are happy as both are leading to the same output and structure.

 

5. Everyone is welcome (you do not need to code)

It is good to have more than 2 members, and this is something we achieved. Not everyone is coding, but there is a big value also when someone is using the components, providing feedback, reporting issues. My hope is that more people will join in the future.

 

6. Common reused code is helping to make bigger value from effort

For me, there were 2 big "steps forward"

- the generic APS, which allows also component generation and ZTL script generation used in my components and

- common methods for flattening of data, which allows to convert the multidimensional data model (hard to understand) into something which is easy to use.

The reuse of such code in many components was really reducing the effort of component creation. Honestly, small idea - and new component can be created in 2-3 hours as only the rendering part counts. The other parts are generated based on specification. This is allowing us to contribute with very small time effort.

 

7. Everyone is bringing his knowledge area

In a community it is important to find and use the expertise from every member. This is how the work gets shared better. As Mike was bringing a lot of big components, I have concentrated myself on covering the SAPUI5 components. I have looked again on many of the components blogs - and such as the Design Studio SDK (1.3/1.4) - Opensource SCN Maps (Part 1) or Design Studio SDK - Hexagonal Binning are requiring a lot of time to be coded (at least in my view), and this is the point - do what is cheap for you (as you know how to make it) and leave those parts you have troubles in.

 

8. Using published code from someone else (or yourself) is a nice experience

Not the technical part counts. What counts is the outcome. This means, it is not necessary to invent the same code again and again. I have used some code from Mike and also from other components I have written. In addition, at some point you will know where is the solution to your current issue - and then go, copy and use. very nice.

 

9. Freedom of expressions and development directions is a personal value

We have very less synchronization on any direction. Everyone has freedom to contribute what he want - and this is how the repository grows. There were some synchronized actions like the 3.0 conversion due to changes in design studio 1.6 SDK api (or extensions actually), but this was a technical change which had to be made. On use cases and ideas, it is just nice to see others commits and direction of work when it is available.

 

10. Building modular software with common functions helps

Again the point with collaboration and merge issues. the repository is quite modular. It means the code is existing only once and in case the function needs to be changed it can be changed only once.

 

and also..

 

11. It is really hard to get feedback

A bit challenging topic is - why we do it? Is someone getting value out of the work? This is really hard to answer. But after the year I can say - yes. Some are just influenced and perhaps build own components based on the ideas, some are really using the content. Perhaps this topic is so difficult as the content is open sourced and free accessible. But on other hand, if something will break there is quick feedback. And looking at the Issues page there are already more and more reported topics for issues or extensions. Also here I hope this channel will increase.

 

12. You have to risk when changing (and avoid changing to reduce risk)

I still remember the last conversion to 3.0 repository version. We changed a lot.. and we tried to make everything working again. It is so good that we have a lot of common code, many components are generated. But at the end, it is open source content and not a full time paid job, so the time is restricted. It means also some activities must be made manually when changing parts of the code. This means, we now do not touch too much - if the component is working as expected, every change can break it. Something like big refactoring is not planned (good that there is no reason currently for it..)

 

13. community is growing not too fast

Finding others for participation and setting some procedures (like creation of issues on Issues instead asking in SCN which is quite easy to miss) takes time. You have to accept that there is much time required to establish such communities. Also some effort in the preparation and setup and documentation. This pays out at some point of time.

 

and my last one..

 

14. Community work never ends

The special point is - the work does not end. In my journey over old documents, blogs - especially from Mike and myself - shows that some nice components which were available in the old repository are not available in the new one. It is hard to say what does it mean (point 11) and we do not know if someone would like to have it, but as it is not available is using also the old packages? Second topic is, the components we have created were our own idea - "what do I miss in my project?", "what could be made better?". But I think that also others can bring ideas what could be build - as extensions in the Issues list.

 

Closing Words

I hope that not only the contributors, but also other developers could learn in the time since the community has been started. I hope also that those of you who use the components in the installable version will have fun with it for long time. All code is open and in any case which will require it changed, corrected by anyone (not necessary the initial author).

 

As of today, you can also find all existing components in the great summary by Mike SCN Design Studio 1.6 SDK Components (ver 3.0). or the community story SCN Design Studio SDK Development Community.


Any feedback including issues, enhancements or some others feel free to place on the Issuesarea in github.


Many thanks to...

Michael Howles, Franck Blais , Manfred Schwarz ,Martin Pankraz , James Rapp , Mustafa Bensan , Jeroen van der A , Donnie Burhan

for the awesome collaboration, learning from you and bringing value by work in one direction!


I hope you have enjoyed the time as well and we can still stay together helping others with the community content. For me it was a great time with a lot of learning! Every component I have created was a small step in the learning curve!

ASUG Design Studio Highlights and Updates

$
0
0

asug.png

 

ASUG Annual Conference is getting closer each day (May 17-19). With so many sessions to choose from, your ASUG Volunteers have selected these sessions, highlighting SAP BusinessObjects Design Studio and related topics.  The links below take you to the agenda builder.

 

Session ID

Title

A3744

Interactive ASUG Influence: Design Studio

A3747

Tetrapak BI Reporting Strategy and Business Empowerment with SAP BusinessObjects Design Studio

A3756

Road Map: SAP BusinessObjects Design Studio: The Road Ahead

A3757

On-Premise BI Versus SAP Cloud for Analytics: What’s In It for SAP Business Warehouse Customers?

A4061

Self-Service Dashboards: SAP BusinessObjects Design Studio and SAP Lumira

A4063

Are You Ready to Migrate from SAP BusinessObjects Dashboards to SAP BusinessObjects Design Studio?

A4108

Unlocking the Value of SAP BusinessObjects Design Studio with Callaway Golf

A5478

All About That Base: Precision Drilling Built Scalable Analytics with SAP BusinessObjects Software

A5821

ASUG Business Intelligence Community Meet-Up

A5840

SAP BusinessObjects Design Studio Deep Dive (Advanced Topics)

 

ASUG Annual Conference is once again co-located with SAPPHIRE® NOW, May 17-19th in Orlando, Florida, at the Orange County Convention Center.  Browse the ASUG Business Intelligence Community Brochure

 

ASUG BI volunteers will host an Annual Conference “sneak preview” webcast on May 5th - register today.

 

ASUG Annual Conference Pre-Conference, May 16

Kick off your conference on May 16 for hands-on SAP Design Studio at ASUG Annual Conference - see Jump Start ASUG Annual Conference with a SAP Design Studio Deep-Dive Pre-conference;

For a preview of this pre-conference, register for this preview webcast on April 12th.

 

ASUG Call for Speakers at SAP TechEd Las Vegas

te.png

The call for speakers is open for ASUG sessions at SAP TechEd Las Vegas (September 19-23) – for more information, click here.

 

You are invited to present for ASUG at SAP TechEd Las Vegas (September 19-23). ASUG and SAP are working together again in education this year, offering customer-led education sessions and influence opportunities.

Here are the details:

  1. Call for submissions is open.
  2. The deadline to submit proposals is April 22nd.
  3. ASUG Customer sessions are one-hour lecture sessions.
  4. For non-SAP Speakers only.

 

This special call for proposals is open to SAP customers and partners who are members of Americas' SAP Users' Group (ASUG). SAP employees are not eligible to participate. Session proposals are subject to a final review by the ASUG Design Team. You will receive notification regarding the status of your proposal by late May.

 

Approved speakers receive (source: SAP site):

  • Complimentary lecture-only conference registration
  • SCN Contribution points

 

ASUG/SAP TechEd does not reimburse for speaker's time, travel or hotel.

Make sure to look through the site and reach out to saptechedspeaker.info@sap.com with any questions.

 

What do you get out of presenting?  See what SCN member Mustafa Bensan says:

 

"As an active member of the SCN and first time presenter at SAP TechEd 2015, I really enjoyed the full learning experience in terms of pre-presentation research, engaging with a live audience and post-presentation feedback, all of which I found invaluable from a personal and professional development perspective.  It’s fun to attend TechEd as a regular attendee but participating as a presenter was a new and very worthwhile opportunity."

 

Submit your session abstract today.

 

Upcoming Design Studio / Dashboarding Webcasts

 

See you in person or online

Visual BI Extensions - Hierarchical Navigation for Charts

$
0
0

In my previous blog post I outlined the hierarchical filter component and the detailed capabilities that can offer your users a true hierarchical filtering experience, including the option to filter on the lowest level on an unbalanced hierarchy with a simple click.

 

This time I would like to share a true hierarchical experience for charts. You most likely noticed that the standard charts (including the new InfoCharts in DS 1.6) right now do not offer any drill down functionality nor are they offering any options to visually outline a hierarchy that is used in a chart. The charts are able to show the hierarchy, but the user does not receive any visual indication on a hierarchy level or of the item is a hierarchy node or leaf.

 

We added several hierarchy specific functionality into our charts as part of the Visual BI Extensions for SAP BusinessObjects Design Studio - especially for those topics mentioned above.

 

So lets assume we have a data source similar to the data source shown below with a handful of measures and an activated hierarchy in the rows.

 

VBX_BLOG_HIERARCHIES_001.jpg

 

When we assign the data source to the chart, we will notice that the root level nodes from the hierarchy are not shown by default. This is a property the user can decide to activate or to disable and by default it is disabled.

VBX_BLOG_HIERARCHIES_002.jpg

 

Opening up the Additional Properties we can now see all the detailed optioned for the chart.

 

VBX_BLOG_HIERARCHIES_003.jpg

 

 

  • We can activate the hierarchical drill down, allowing the user to drill from the hierarchy nodes to the leafs. There is no limit on number of hierarchy levels.
  • We can decide to include the Root Level nodes from the hierarchy - depending on our hierarchy setup.
  • We can decide if we would like to include the parent node on the actual drill down page.
  • We can decide to show all measures or only the measure that was used for the actual drill.
  • We can activate the hierarchical label - will be shown later on in this blog.
  • We can also set a maximum number of hierarchical levels in case we want to limit the drill down options.

 

.. and we can configure on which "event' we want to perform which type of action. We have a Select, a true drill down, and the option to do an inplace expand / collapse.

 

The easiest way to explain the behavior is to simply show a short video that shows the Expand / Collapse as well as the actual drill down in the chart.

 

 

 

 

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

Visual BI Extensions - Multi - Axis Charts

$
0
0

Somtimes you will need a chart that shows more than a single measure and sometimes these measures can be off very different scale. There might even be a situation where you will need more than two measure in the chart with very different scales.

 

In core Design Studio you will notice that there is a Combination chart but there are only limited dual axis charts and if you would like to go beyond two axis - there is nothing available to you.

 

This is where the Multi-Axis Chart as part of the Visual BI Extensions can help.

 

blog_004.jpg

 

Lets say we have these three measures and we do need them in a single chart but based on their scale with up to three different axis.

 

blog_005.jpg

 

 

By default our charts will show these measure, but because we have chosen the Multi-Axis chart we can configure the type of visualization......

 

blog_006.jpg

 

... as well as on which axis we would like to plot the information.

 

blog_008.jpg

 

.. resulting in a Multi-Axis Chart showing three measures on three separate axis.

blog_007.jpg

 

and in that way create a multi - axis chart


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

ASUG BI Webinars - Upcoming Customer Stories

$
0
0

It is always great to hear from other customers on how they approach a certain topic or how they did overcome a specific issue, so here is your opportunity to listen to several customers in the BI area and to hear directly from them how they approach the topic of BI.


For all webinars :

 

  • Start Time : 11:00 AM (CT), 12:00 PM (ET), 10:00 AM (MT), 9:00 AM (PT)
  • Duration : 1 hour

 

 

June 1 -  Case Study: Lessons for Deploying and Optimizing SAP Predictive Analytics

 

Attend this session for insight into how you can enhance your BI strategy to include predictive analytics capabilities. Come away with lessons to help you determine the business scenarios in which predictive analytics might provide the greatest value to your organization, and get lessons on:

- Key questions to ask and factors to consider in choosing the right project to start your predictive analytics journey

- Available algorithms and functions available in the Predictive Analytics Library, and a decision tree process for algorithm selection

- Required skill sets associated with SAP Predictive Analytics, the role of data scientist, and ethical issues to consider

 

 

June 6: Rockwell Collins Enterprise Metrics Hub

 

Rockwell Collins will present the Enterprise Metrics Hub (‘The Hub’) through their BI Portal. This solution is designed as a set of dashboards and analytical tools to provide visibility of a series of KPIs and to support their strategy for growth and consistency to measure quality performance. The opportunity for this project came through the need for rapid improvement in Customer Quality to support our market share in the Aerospace and Defense industry. The Hub gathers data from various sources and presents a standard view of KPIs. It provides enterprise-wide visibility to data so users can evaluate process variation and predict business performance.

 

 

June 22: Reporting in Color at Benjamin Moore

 

How Benjamin Moore, a 100+ year old company rooted in tradition, embarked on one of the fastest and most successful SAP BW implementations to support a corporate wide business transformation. As a result, the organization is now armed with the relevant data and analysis for more effective business decisions. This reporting solution offers SAP technology, specifically ECC, SAP BW, BW-on-Hana, and BI Web Intelligence. This solution provides a combination of real-time data access through standard reporting, pre-built reports for distribution to users and improved self-service capabilities for power users. It has enabled continued data-driven decision making with the transition to a new SAP ERP system.

 

 

July 7: Evolving BI to Have Your Business Begging for More – CSA Group

 

The demand for the right analytics to assist in making the right decisions has been a growing trend for many businesses. This interactive session will discuss CSA’s recent re-implementation of BI targeting standardization and visualization. We will also evaluate the benefits of standardizing reporting and re-engineering your current BI/BW strategy to make a lasting impression.

 

 

July 12: Tetrapak BI Reporting Strategy and Business Empowerment with SAP BusinessObjects Design Studio

 

Learn how Tetrapak is synergizing IT and business to drive agile business intelligence (BI) strategy using standardized, repeatable, and clearly understood processes across the organization. This session will present the key driving principles for deploying BI strategy within Tetrapak, where Performance = People+Process+Tools.

 

 

July 13: SAP Runs SAP: Information Design at SAP – Framework on Reporting Principles

 

The International Business Communication Standards (IBCS) are proposals for the conceptual, perceptual, and semantic design of comprehensible business reports and presentations. The session will cover the selected approach to standardize reporting in the controlling department at SAP and the technical implementation in various SAP reporting tools.

 

 

July 26: Learn How IDEXX Migrated SAP Business Warehouse powered by SAP HANA in Five Weeks

 

Learn how IDEXX Laboratories Inc. successfully migrated the SAP Business Warehouse application powered by SAP HANA from an Oracle database within five weeks.

Your First Extension: Part 11a - D3 and the SVG Text element

$
0
0

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

 

The next feature that we want to add to our gauge is text callouts.  While it is certainly possible to position text labels where you want them and bind them to the data that you want to display, the approach that we will take in this installment has the advantage of being dynamic.  If the gauge guide line angles change, or if the display angle changes, we can dynamically reposition our callouts.  We want to be able to display the value of the measure, as well as the minimum and maximum values.

 

Before we begin adding our callouts to the sandbox file's gauge prototype, we'll create a second, simpler sandbox in order to explore the text element.  The initial version uses D3's line drawing capacity (first examined in Part 8a) to create a 200x200px svg element and then draw a par of centered crosshairs.  That starter file is laid out here:

 

<!DOCTYPE html>

<html>

  <head>

  <title>Text with D3</title>

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

    </head>

  <body>

  <script>

  var vis = d3.select("body").append("svg:svg").attr("width", 200).attr("height", 200);

 

  //Crosshairs

  var horizLineData = [{x:0, y:100}, {x:200, y:100}];

  var vertLineData = [{x:100, y:0}, {x:100, y:200}];

 

 

  var lineFunction = d3.svg.line()

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

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

  .interpolate("linear");

 

  var xAxis = vis

  .append("path")

  .attr("d", lineFunction(horizLineData))

  .attr("stroke", "black")

  .attr("stroke-width", 1)

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

 

  var yAxis = vis

  .append("path")

  .attr("d", lineFunction(vertLineData))

  .attr("stroke", "black")

  .attr("stroke-width", 1)

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

  </script>

  </body>

</html>

 

 

It has a very simple result:

Part11a.1.png

 

Adding our first text element is very simple.  Anywhere in the script, where vis has already been declared (e.g. at the end), simply as the following:

//Text

var textElementMeasure = vis.append("text")

  .attr("transform", "translate(" + 100 + "," + 100 + ")")

  .text("Hello World");

 

Part11a.2.png

 

 

So we now have drawn our first text element in D3.  There are a couple of things to note here.  Firstly, unless you have modified your browser's default font, "Hello World" is probably written in some member of the Times family (e.g. Times New Roman, Times-Roman, etc., depending on the browser and OS) at at a size of 16px.  This is because there are default style attributes to the fonts, assigned by the browser.  Secondly, while using a horizontal and vertical transformation of 100x each puts our position at the center of the crosshair, that is the lower left position of the text.  There are also default font attributes for governing horizontal and vertical positioning of the text.

 

 

A Side Digression: CSS

 

So far in this tutorial series, we've manipulated element attributes via raw JavaScript.  .attr() has become an old friend.    Many of these attributes (e.g. color, opacity, stroke) are also editable via CSS.  Virtually every aspect of text is editable in CSS, such as the font, font size, horizontal and vertical position.  Strictly speaking, it is considered a web design best practice to do everything possible in CSS.  This is the much more modern and professional way of building websites, as it allows a reskinning of the app by swapping out stylesheets.  We are not designing for professional web designers however.   The BI app designer persona is not presumed to be skilled with CSS and asking them to edit the application's visuals with CSS is asking a lot.   We'll leave two aspects of the text callouts - the font and font size - as the exercise for CSS in part 12.  Since we'll need fairly complex algorithms to determine when to use which settings for horizontal and vertical alignment, we'll handle those attributes in JavaScript.

 

 

 

Horizontal Positioning of Text

 

 

The attribute that governs the horizontal justification of text is text-anchortext-anchor has three possible values:

  • start - left justifies the text, so that it starts at the xy position of the text element.
  • end - right justifies the text, so that it ends at the xy position of the text element.
  • middle - centers the text horizontally at the xy position.

 

 

The table below shows these text-anchor values in action:

 

.attr("text-anchor", "start").attr("text-anchor", "middle").attr("text-anchor", "end")
Part11a.2.pngPart11a.4.pngPart11a.3.png

 

 

 

 

Vertical Positioning of Text

 

 

There are two  attributes that govern vertical position of text in an SVG element:

  • dominant-baseline -  This is an SVG only attribute that can greatly simplify the vertical justification of text.  Unfortunately, it is not supported by all browsers.  Specifically, Mobile Safari and Microsoft browsers don't support dominant-baseline.  This becomes a potential problem as the Design Studio designer is an eclipse based application and browser windows in eclipse can only use the platform's default browser.  In practice, this means that the canvas in the DS designer is always internet explorer or edge.  So if the users were using Chrome, the designer would see the text callouts displayed differently than the users at runtime.  If the app was being run on an Apple mobile device, then there would be no dominant-baseline.
  • dy - this is not only an SVG property, but a general html property.  It may be defined in terms of "em", where 1em = the current vertical font size.  If the em value is negative, then the text is moved upward and if it is positive, then it is moved downward.  We will use dy vertically position our text.

 

 

The table below shows the corresponding dominant-baseline and dy values in action.

dominant-baselinedy
Part11a.5.-.2em.png

  .attr("dominant-baseline", "ideographic");

  .attr("dy", "-.2em");

Part11a.5.0em.png

 

  .attr("dy", "0em");

Part11a.5.1em.png

  .attr("dominant-baseline", "hanging");

  .attr("dy", "0.8em");

SPart11a.5.0.8em.png

.attr("dominant-baseline", "text-after-edge");

.attr("dy", "1em");

 

 

 

Next time, we are going to pout these attributes to use and create the algorithms to dynamically set text-anchor and dy when we reposition our callouts.

Your First Extension: Part 11b - D3 Text Dynamic Positioning Algorithms

$
0
0

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

 

Last time, we took out first look at text elements in D3 and the attributes that we need to position our text.  Now we'll work out how the positioning of our callouts.  In general, we are going to have to types of callouts available to designers; measure value callouts and guide line value callouts.

 

  • Measure Callout - This callout tracks the value of the measureVal property, or the  endAngleDeg property if useMeasures has been disabled.
  • Guide Line Callout - This callout pair tracks the measureMin and measureMax properties, or the startAngleDeg and endAngleDegMax if useMeasures has been disabled.

 

In the end, out sandbox html file will produce something like this:

Part11b.1.png

 

 

 

Measure Callout Positioning

 

 

When the designer elects to enable measure callouts on the gauge, we want to have a couple of options as to placing the callouts.

  • The designer can select from a fixed number of vertical positions, along the horizontal centerline of the gauge.
  • The designer can elect to have the endpoint of the indicator needle, (or where it would be if the indicator is not enabled) anchored to the endpoint, or along the middle of the guide.  When anchored to the "endpoint", the callout shall be either right to left justified, as needed.

MeasureTextPositioning.png

 

 

The positioning of the measure text callout is fairly straightforward.

Unless we are positioning on the endpoint, we are on the vertical center axis.  The Y axis translation offset of the text element is always the same Y axis translation as the main arc; offsetLeft.  We'll calculate the vertical position, based on a set of arbitrary vertical axis translation values. (see image, above).  If we are positioning at the endpoint, then we'll calculate the endpoint position with basic trigonometry.  The function to do this calculation is very simple:

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}

}

 

 

 

The flow chart below, lays out the X and Y axis offset translations, as well as the final vertical anchoring of the text, presuming the use of the SVG dominant baseline property.  Since we're using the dy attribute instead, this will translate as follows:

dominant-baseline: text-before-edge   =>   dy: 0em

dominant-baseline: text-after-edge      =>   dy: 1em

MeasurePositioning.png

 

 

This translates into the following JavaScript:

if (measureTextPositionType == "endpoint"){

  measurePosition = endPoints (outerRad, endAngleDeg);

  measureTextPosition = ["start", "1em"];

  if ((measurePosition.x - offsetLeft) < 0){

  measureTextPosition[0] = "end";

  }

  if ((measurePosition.y - offsetDown) < 0){

  measureTextPosition[1] = "0em";

  }

}

else{

  if (measureTextPositionType == "top"){

  measurePosition = endPoints (outerRad, 0);

  measureTextPosition = ["middle", "-.15em"];

  //measureTextPosition = ["middle", "text-before-edge"];

  }

  else if (measureTextPositionType == "upperCentral"){

  measurePosition = endPoints (outerRad/2, 0);

  measureTextPosition = ["middle", "-.15em"];

  //measureTextPosition = ["middle", "text-before-edge"];

  }

  else if (measureTextPositionType == "upperIdeographic"){

  measurePosition = endPoints (1, 0);

  measureTextPosition = ["middle", "-.15em"];

  //measureTextPosition = ["middle", "text-before-edge"];

  }

  else if (measureTextPositionType == "lowerIdeographic"){

  measurePosition = endPoints (1, 180);

  measureTextPosition = ["middle", "1.1em"];

  //measureTextPosition = ["middle", "text-after-edge"];

  }

  else if (measureTextPositionType == "lowerCentral"){

  measurePosition = endPoints (outerRad/2, 180);

  measureTextPosition = ["middle", "1.1em"];

  //measureTextPosition = ["middle", "text-after-edge"];

  }

  else if (measureTextPositionType == "bottom"){

  measurePosition = endPoints (outerRad, 180);

  measureTextPosition = ["middle", "1.1em"];

  //measureTextPosition = ["middle", "text-after-edge"];

  }

}

 

 

 

 

Guide Line Positioning

 

If guide line callouts are enabled, we will create a pair of text callouts; one for start angle and one for end angle.  We want to be able to position these guide line callouts at either the endpoint of the guide line, or along the midpoint.  In both cases, we use the endpoint() function, above and simply use lineLength = outerRadius; or lineLength = outerRadius/2. 

 

In general, we want to follow two basic rules:

 

  • The text-anchor property is set o that the text stays outside the gauge arc.  The gauge is always presumed to run clockwise.  This means that start angle value should be positioned to come "before" the start guide line angle.   And the end angle value should come "after" the end angle value.
  • The dy value (either 0em or .8em) is set so that the text should be inside the gauge ring. 

 

 

The two images below show the positioning rules for start angle callouts and end angle callouts:

 

 

Start

GuideLinePositioningStart.png

 



End

GuideLinePositioningEnd.png

 

The flowchart for the guide positioning algorithm needed for the above pictures looks like the following:

GuidePositioning.png

 

 

 

This flow translates into the following JavaScript function:

function textPositioning (x, y, isStart){

  var relativeOffsetX = x - offsetLeft;

  var relativeOffsetY = y - offsetDown;

 

 

  if (isStart == undefined){

  isStart = false;

  }

  var dominantBaseline = null;

  var textAnchor = null;

  if ((relativeOffsetX >= 0) && (relativeOffsetY >= 0)){

  //Lower Right Quadrant

  // Both middle and enf have a negative dominant baseline

  if (isStart == true){

  textAnchor = "start";

  dominantBaseline = "0em";

  } else {

  textAnchor = "end";

  dominantBaseline = ".8em";

  }

 

  } else if ((relativeOffsetX >= 0) && (relativeOffsetY < 0)){

  //Upper Right Quadrant

  if (isStart == true){

  textAnchor = "end";

  dominantBaseline = "0em";

  } else {

  textAnchor = "start";

  dominantBaseline = ".8em";

  }

  }

  else if ((relativeOffsetX < 0) && (relativeOffsetY < 0)){

  //Upper Left Quadrant

  if (isStart == true){

  textAnchor = "end";

  dominantBaseline = ".8em";

  } else {

  textAnchor = "start";

  dominantBaseline = "0em";

  }

  } else {

  //Lower Left Quadrant

  if (isStart == true){

  textAnchor = "start";

  dominantBaseline = ".8em";

  } else {

  textAnchor = "end";

  dominantBaseline = "0em";

  }

  }

 

 

  return [textAnchor, dominantBaseline]

}

 

 

Putting it all together, into our sandbox html file, we get the following code, which displays this blog post.  Next time, we'll migrate this new code into our component. You can experiment with different measure text positions, by altering the value of measureTextPositionType, on line 205.

 

 

<!DOCTYPE html>

<html>

  <head>

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

  <title>Part 7</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 = 400;

  var height = 400;

  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);

 

  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)

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

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

 

  var ringArc = vis

  .append("path")

  .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")

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

  .attr("stroke", ringColorCode)

  .attr("stroke-width", bracketThickness)

  .attr("fill", ringColorCode)

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

 

 

 

 

 

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

  //Lets add animations

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

 

  var delayNeedle = 500;

  var durationNeedle = 10000;

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

 

  var delayBorderLines = 500;

  var durationBorderLines = 1000;

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

 

  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(durationNeedle)

  .delay(delayNeedle)

  .ease(easeNeedle);

 

  borderLines.transition()

  .attr("d", lineFunction(lineData))

  .duration(durationBorderLines)

  .delay(delayBorderLines)

  .ease(easeBorderLines);

 

 

  var arcStepDef = d3.svg.arc()

  .innerRadius(innerRad)

  .outerRadius(outerRad);

 

 

  guageArc.transition()

  .duration(durationArc)

        .call(arcTween, endAngleDeg * (pi/180));

 

 

  //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.

  function arcTween(transition, newAngle) {

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

     var interpolate = d3.interpolate(d.endAngle, newAngle);

     return function(t) {

  d.endAngle = interpolate(t);

  return arcDef(d);

  };

  });

  }

 

 

 

 

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

  //Lets add a legend

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

 

  //https://developer.mozilla.org/en/docs/Web/SVG/Attribute/text-anchor

 

  var guidePositioning = "end";  //"end" and "midpoint"

  var measureTextPositionType = "upperCentral";

  var drawGuideText = true;

  var drawMeasureText = true;

 

  //Measure Text Positioning

  if (drawMeasureText == true){

  var measurePosition = {};

  var measureTextPosition = {};

  if (measureTextPositionType == "endpoint"){

  measurePosition = endPoints (outerRad, endAngleDeg);

  measureTextPosition = ["start", "1em"];

  if ((measurePosition.x - offsetLeft) < 0){

  measureTextPosition[0] = "end";

  }

  if ((measurePosition.y - offsetDown) < 0){

  measureTextPosition[1] = "0em";

  }

  }

  else{

  // Hack Alert!

  //As of now, MS browsers don"t support the dominant baseline SVG property. 

  //  Using the dy property with a Xem offset is the hackish workaround

  // https://msdn.microsoft.com/en-us/library/gg558060(v=vs.85).aspx

  if (measureTextPositionType == "top"){

  measurePosition = endPoints (outerRad, 0);

  measureTextPosition = ["middle", "-.15em"];

  //measureTextPosition = ["middle", "text-before-edge"];

  }

  else if (measureTextPositionType == "upperCentral"){

  measurePosition = endPoints (outerRad/2, 0);

  measureTextPosition = ["middle", "-.15em"];

  //measureTextPosition = ["middle", "text-before-edge"];

  }

  else if (measureTextPositionType == "upperIdeographic"){

  measurePosition = endPoints (1, 0);

  measureTextPosition = ["middle", "-.15em"];

  //measureTextPosition = ["middle", "text-before-edge"];

  }

  else if (measureTextPositionType == "lowerIdeographic"){

  measurePosition = endPoints (1, 180);

  measureTextPosition = ["middle", "1.1em"];

  //measureTextPosition = ["middle", "text-after-edge"];

  }

  else if (measureTextPositionType == "lowerCentral"){

  measurePosition = endPoints (outerRad/2, 180);

  measureTextPosition = ["middle", "1.1em"];

  //measureTextPosition = ["middle", "text-after-edge"];

  }

  else if (measureTextPositionType == "bottom"){

  measurePosition = endPoints (outerRad, 180);

  measureTextPosition = ["middle", "1.1em"];

  //measureTextPosition = ["middle", "text-after-edge"];

  }

  }

 

 

  vis.append("text")

  .attr("transform", "translate(" + measurePosition.x+ "," + measurePosition.y+ ")")

  .text("measureText")

  .attr("text-anchor", measureTextPosition[0])

  //.attr("dominant-baseline", measureTextPosition[1]);

  .attr("dy", measureTextPosition[1]);

  }

 

  //Guide Positioning

  if (drawGuideText == true){

  var guidePositionStart = {};

  var guidePositionEnd = {};

  var isMiddleCO = false;

  if (guidePositioning == "end"){

  guidePositionStart = endPoints (outerRad, startAngleDeg);

  guidePositionEnd = endPoints (outerRad, endAngleDeg);

  }

  else {

  guidePositionStart = endPoints (outerRad/2, startAngleDeg);

  guidePositionEnd = endPoints (outerRad/2, endAngleDeg);

  }

  var guideTextPositionStart = textPositioning (guidePositionStart.x, guidePositionStart.y, true);

  var guideTextPositionEnd= textPositioning (guidePositionEnd.x, guidePositionEnd.y);

 

 

  //Start Text

  vis.append("text")

  .attr("transform", "translate(" + guidePositionStart.x + "," + guidePositionStart.y + ")")

  .text("startText")

  .attr("text-anchor", guideTextPositionStart[0])

  //.attr("dominant-baseline", guideTextPositionStart[1]);

  .attr("dy", guideTextPositionStart[1]);

 

 

  //End Text

  vis.append("text")

  .attr("transform", "translate(" + guidePositionEnd.x + "," + guidePositionEnd.y + ")")

  .text("endText")

  //.attr("text-anchor", "start")

  .attr("text-anchor", guideTextPositionEnd[0])

  //.attr("dominant-baseline", guideTextPositionEnd[1]);

  .attr("dy", guideTextPositionEnd[1]);

  }

 

 

 

 

 

 

  // Helper function to determine the vertical alignment (called 'dominant-baseline') and horizontal alignment (called ' text-anchor')

  // In essence, this function tries to find a readable position for the text, so that it lies ourside the main arc, no matter the current

  // start and end points:

  // If x is to the left of the gauge's centerline, then the text should be anchored to the left of x.  Otherwise to the right

  // If y id below the centerline, then the text should be below y.  Otherwise above

  // dominant-baseline: http://bl.ocks.org/eweitnauer/7325338

  // text-anchor: https://developer.mozilla.org/en/docs/Web/SVG/Attribute/text-anchor

  function textPositioning (x, y, isStart){

  var relativeOffsetX = x - offsetLeft;

  var relativeOffsetY = y - offsetDown;

 

 

  if (isStart == undefined){

  isStart = false;

  }

 

 

  var dominantBaseline = null;

  var textAnchor = null;

  if ((relativeOffsetX >= 0) && (relativeOffsetY >= 0)){

  //Lower Right Quadrant

  // Both middle and enf have a negative dominant baseline

  if (isStart == true){

  textAnchor = "start";

  dominantBaseline = "0em";

  } else {

  textAnchor = "end";

  dominantBaseline = ".8em";

  }

 

  } else if ((relativeOffsetX >= 0) && (relativeOffsetY < 0)){

  //Upper Right Quadrant

  if (isStart == true){

  textAnchor = "end";

  dominantBaseline = "0em";

  } else {

  textAnchor = "start";

  dominantBaseline = ".8em";

  }

  }

  else if ((relativeOffsetX < 0) && (relativeOffsetY < 0)){

  //Upper Left Quadrant

  if (isStart == true){

  textAnchor = "end";

  dominantBaseline = ".8em";

  } else {

  textAnchor = "start";

  dominantBaseline = "0em";

  }

  } else {

  //Lower Left Quadrant

  if (isStart == true){

  textAnchor = "start";

  dominantBaseline = ".8em";

  } else {

  textAnchor = "end";

  dominantBaseline = "0em";

  }

  }

 

  return [textAnchor, dominantBaseline]

  }

 

 

 

  </script>

    </head>

  <body class='sapUiBody'>

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

  </body>

</html>


Design Studio SDK: Float Button for Quick Member Selection

$
0
0

After the question by Jean-François Drouet in Design Studio SDK: Calendar Selector Component blog about a possibility of month selection I have taken into consideration 3 options for making this scenario happen.


1. build your own button area by placing many buttons (this is always possible)

2. using existing controls (like SCN Design Studio SDK: Segmented Button Component)

3. any other easy way to make it.


Scenario


Selecting of months is one scenario where a quick access can be beneficial, but selection of any members would be also nice to have. Some scenarios can be already covered by Segmented Button, but it has one part which is not helping in this scenario - it is basically only horizontal and does not react on overflow.

 

So, this is how the "Float Button" was created.

 

Technical Background

Technically, it is a array of buttons (simple or toggle) which is floating over the reserved space. It means, as soon the width is not enough, next button is places below the row and opening next row. Like those examples (list of cities):

 

Effect

each city represents one button, the width is set to "-1", so the button adjusts to word width.

fb2.PNG

Code

to make a simple example, I use the bing your own data source and data iterator. of course, you can also use "getMembers()" method to fill in the content. (this is also the reason for the key replacement, as there is no real key in this data set)

 

var rows = DATAITERATOR_1.getRows();
var allKeys = ";";
rows.forEach(function(element, index) {    var key = element.getDimensionValueKey("City");    key = Convert.replaceAll(key, " ", "_");    var text = element.getDimensionValueText("City");        if(allKeys.indexOf(key + ";") == -1) {    allKeys = allKeys + key + ";";    FLOATBUTTON_3.addButton(key, text, "", -1, false);    }
});

 

In addition, for better layout you can put also hard coded width on each button to create it in strict rows and columns (like the requested months + years):

 

Effect

I use array and realdate object to dynamically fill in the control on startup script. The buttons have fixed width, therefore the layout looks nice.

fb1.PNG

 

Script

 

REALDATE_1.initializeWithInternalDate(APPLICATION.getInfo().dateNowInternalFormat);
var year = 9999;
ARRAY_1.eaches(1, 12, 1).forEach(function(element, index) {   var month = REALDATE_1.getMonthName();   var monthNum = REALDATE_1.getMonth();      REALDATE_1.rollMonths(1);   APPLICATION.log("Month: " + month);   if(index == 0) {     year = REALDATE_1.getYear();      FLOATBUTTON_1.addButton("M"+monthNum, month, "", 80, true);   } else {      FLOATBUTTON_1.addButton("M"+monthNum, month, "", 80, false);   }
});
FLOATBUTTON_2.addButton("Y"+(year-2), ""+(year-2), "", 60, false);
FLOATBUTTON_2.addButton("Y"+(year-1), ""+(year-1), "", 60, false);
FLOATBUTTON_2.addButton("Y"+(year-0), ""+(year-0), "", 60, true);
FLOATBUTTON_2.addButton("Y"+(year+1), ""+(year+1), "", 60, false);

 

Usage

With this specification, you can simply create easy to use quick filters in given space.

 

Events & Spec

The button has selection event, press event and in the specification you can also use multi select. If you use single select, you can use toggle mechanism (pressed button is marked) or just a button w/o marking selection.

 

Help / API Specification

Go directly to the help site and find the component: http://org-scn-design-studio-community.github.io/sdkinstall/web/components/index.html

 

Download & Use

This component is available on the community package, as in SCN Design Studio SDK Development Community

 

Example as BIAPP:

NAME: SDK_FLOATBUTTON

org-scn-design-studio-community/applications · GitHub

 

Any thoughts?

feel free to add as usual...

 

Enhancements Ideas?

in this case it is just a start of development...

if you have good ideas (to those who would like to contribute but cannot code...) - place an "issue" with tag "enhancement" under Issues · org-scn-design-studio-community/sdkpackage · GitHub

Your Opportunity to Influence Design Studio and Lumira - Deadline Approaching

$
0
0

SAP offers the opportunity influence innovations for next releases through the influence program Customer Engagement Initiative (CEI).  This is the first CEI cycle in 2015.

 

What innovations are there?

 

There are several projects for which you can register. The following projects are relevant for the SAP Design Studio Community Members:

1fig.png

Source: SAP

2fig.png

Source: SAP

 

These projects can be found here under the “Analytics” heading.  If you find a project that may be of interest to a co-worker, SAP asks that you to forward the project using the “Send an Email” link on the project page.

 

Other interesting projects:

SAP IT Operations Analytics

Fiori Based Mobile BI Monitoring

KPI and Report Gallery for End Users

SAP BusinessObjects Mobile (MOBI)

 

How can I sign up?

 

Go to the SAP website to register.

 

Complete list of projects is here

 

Follow-up after registration

 

When you register, you will be sent a confirmation from.  When you register for a project, you will be invited to an introductory call SAP; at this point further participation is optional. Typically signing a Feedback Agreement with SAP will be part of the procedure.

 

The deadline for this first cycle is on Friday, April 15th (tax day here in the US)

Reference:

 

How do I register on the Customer Influence website?

The process of registration is here online.

SAP Improvement Finder
You can download the latest improvements developed from the various influencing programs http://www.sapimprovementfinder.com

 

About the Customer Engagement Initiative
SAP wants customer’s early involvement in the development process. Many topics will be opened only for SAP customers, but there are also topics for which the contribution of partners is requested.

 

Note: The above information was pulled together from various sources: SAP, ASUG and VNSG with some edits by me

 

ASUG Annual Conference ASUG Pre-Conference – May 16

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, find more details here

Your First Extension: Part 11c - Packaging Dynamic Text Callouts into the Component

$
0
0

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

 

Last time, we brought our dynamic text callouts into the sandbox html file.  In this installment, we're going to bring them to the gauge component.  We'll spare ourselves the need to expose any properties to the script API, as - like with animations - callouts are likely something that the designer will strictly want to control.  (though an argument could also be made for user control and this could be a feature added later)  This leaves us with integrating the new code from kast time into component.js and adding the required properties.

 

 

New Properties

 

To review, when we added the callout JavaScript code to our  sandbox html file, we started off by declaring four variables that we later used for controlling the callouts:

var guidePositioning = "end";  //"end" and "midpoint"

var measureTextPositionType = "upperCentral";

var drawGuideText = true;

var drawMeasureText = true;

 

We'll add these four as properties.  The two draw… properties will be booleans, while the other two will be enumerated strings.  In addition, the callouts were hardcoded in the sandbox version.  In the component, we'll either want to use the relevant measure values, or (much less likely) the angle values.  In practice, this means that:

  • The measure callout is tied to measureVal or endAngleDeg
  • The start guide callout is tied to either measureMin or startAngelDeg
  • The end guide callout is tied to either measureMax or endAngleDegMax

 

None of these will require their own binding.  Instead, we'll refer back to the useMeasures property, that we introduced all the way back in Part 6a.  If the designer has decided to use measure values to define the gauge angles, then it makes no sense to display the angle values; and vice versa. 

 

So our part 11 property declarations look like the following:

<!-- Part 11 -->

<property id="drawMeasureText"

  title="Enable Measure Text"

  type="boolean"

  tooltip="Enable in-component measure value display?"

  group="SCNGaugeTextCallouts"/>

<property id="measureTextPositionType"

  title="Measure Text Position Type"

  type="String"

  tooltip="Position of the measure text value"

  group="SCNGaugeTextCallouts">

  <possibleValue>endpoint</possibleValue>

  <possibleValue>upperCentral</possibleValue>

  <possibleValue>upperIdeographic</possibleValue>

  <possibleValue>lowerIdeographic</possibleValue>

  <possibleValue>lowerCentral</possibleValue>

  <possibleValue>bottom</possibleValue>

</property>

<property id="drawGuideText"

  title="Enable Guide Text"

  type="boolean"

  tooltip="Enable in-component guide line value display (guide lines don't need to be enabled to show the text)?"

  group="SCNGaugeTextCallouts"/>

<property id="guidePositioning"

  title="Guide Text Position Type"

  type="String"

  tooltip="Position of the guide text value, along the guide axis (middle or end)"

  group="SCNGaugeTextCallouts">

  <possibleValue>end</possibleValue>

  <possibleValue>middle</possibleValue>

</property>

 

In keeping with the good parctice of using sensible defaults, we'll set the following default values in the Initialization element (we do not default to displaying callouts):

<initialization>

  ...

  <defaultValue property="drawMeasureText">false</defaultValue>

  <defaultValue property="measureTextPositionType">upperCentral</defaultValue>

  <defaultValue property="drawGuideText">false</defaultValue>

  <defaultValue property="guidePositioning">end</defaultValue>

</initialization>

 

 

Component.js

 

We'll start with the textPositioning() function, introduced last time.  It will require only minimal changes when being copied over as a new function within component.js  the offsetXXX variables will need to move into the me._ namespace. 

//New with Part 11

// Helper function to determine the vertical alignment (called 'dominant-baseline') and horizontal alignment (called ' text-anchor')

// In essence, this function tries to find a readable position for the text, so that it lies ourside the main arc, no matter the current

//  x and y are the absolute positions of the callout, within the component

//  isMiddleCallout determines whether this is anchored on the middle of a guide line

//  isStart determines whether or not this the start callout.  this function will try to position the callouts anchoren on the middle

// guide line outside of the gauge arc.

// text-anchor: https://developer.mozilla.org/en/docs/Web/SVG/Attribute/text-anchor

function textPositioning (x, y, isStart){

  var relativeOffsetX = x - me._offsetLeft;

  var relativeOffsetY = y - me._offsetDown;

 

 

  if (isStart == undefined){

  isStart = false;

  }

 

 

  var dominantBaseline = null;

  var textAnchor = null;

  if ((relativeOffsetX >= 0) && (relativeOffsetY >= 0)){

  //Lower Right Quadrant

  // Both middle and enf have a negative dominant baseline

  if (isStart == true){

  textAnchor = "start";

  dominantBaseline = "0em";

  } else {

  textAnchor = "end";

  dominantBaseline = ".8em";

  }

 

  } else if ((relativeOffsetX >= 0) && (relativeOffsetY < 0)){

  //Upper Right Quadrant

  if (isStart == true){

  textAnchor = "end";

  dominantBaseline = "0em";

  } else {

  textAnchor = "start";

  dominantBaseline = ".8em";

  }

  }

  else if ((relativeOffsetX < 0) && (relativeOffsetY < 0)){

  //Upper Left Quadrant

  if (isStart == true){

  textAnchor = "end";

  dominantBaseline = ".8em";

  } else {

  textAnchor = "start";

  dominantBaseline = "0em";

  }

  } else {

  //Lower Left Quadrant

  if (isStart == true){

  textAnchor = "start";

  dominantBaseline = ".8em";

  } else {

  textAnchor = "end";

  dominantBaseline = "0em";

  }

  }

 

  return [textAnchor, dominantBaseline]

}

 

The properties are also straightforward to bring into copmponent.js:

//Part 11 - Callouts

me._drawMeasureText = false;

me._measureTextPositionType = "upperCentral";

me._drawGuideText = false;

me._guidePositioning = "end";

 

And let's not forget our getter/setters:

//Part 11 Properties

me.drawMeasureText = function(value) {

  if (value === undefined) {

  return me._drawMeasureText;

  } else {

  me._drawMeasureText = value;

  return me;

  }

};

me.measureTextPositionType = function(value) {

  if (value === undefined) {

  return me._measureTextPositionType;

  } else {

  me._measureTextPositionType = value;

  return me;

  }

};

me.drawGuideText = function(value) {

  if (value === undefined) {

  return me._drawGuideText;

  } else {

  me._drawGuideText = value;

  return me;

  }

};

me.guidePositioning = function(value) {

  if (value === undefined) {

  return me._guidePositioning;

  } else {

  me._guidePositioning = value;

  return me;

  }

};

//End Part 11 Properties

 

And the 33 lines "Guide Positioning " code go to the end of the me.redraw() function.  Don't forget to refactor it.  The outerRad and xxxAnglexxx variables need a me._ prefix:

//Guide Positioning

if (me._drawGuideText == true){

  var guidePositionStart = {};

  var guidePositionEnd = {};

  var isMiddleCO = false;

  if (me._guidePositioning == "end"){

  guidePositionStart = endPoints (me._outerRad, me._startAngleDeg);

  guidePositionEnd = endPoints (me._outerRad, me._endAngleDegMax);

  }

  else {

  guidePositionStart = endPoints (me._outerRad/2, me._startAngleDeg);

  guidePositionEnd = endPoints (me._outerRad/2, me._endAngleDegMax);

  }

  var guideTextPositionStart = textPositioning (guidePositionStart.x, guidePositionStart.y, true);

  var guideTextPositionEnd= textPositioning (guidePositionEnd.x, guidePositionEnd.y);

 

 

  //Start Text

  vis.append("text")

  .attr("transform", "translate(" + guidePositionStart.x + "," + guidePositionStart.y + ")")

  .text(calloutTextStart)

  .attr("text-anchor", guideTextPositionStart[0])

  //.attr("dominant-baseline", guideTextPositionStart[1]);

  .attr("dy", guideTextPositionStart[1]);

 

 

  //End Text

  vis.append("text")

  .attr("transform", "translate(" + guidePositionEnd.x + "," + guidePositionEnd.y + ")")

  .text(calloutTextEnd)

  //.attr("text-anchor", "start")

  .attr("text-anchor", guideTextPositionEnd[0])

  //.attr("dominant-baseline", guideTextPositionEnd[1]);

  .attr("dy", guideTextPositionEnd[1]);

}

 

Here is a short demonstration video of it all coming together:

 

 

As usual, the current state of the project and the test app are in a public repository on Github.  Next time, we'll have a look at styling the fonts in the callouts via SCC.

SAP BusinessObjects Design Studio Deep Dive - Preview of ASUG Pre-Conference

$
0
0

Today Ingo Hilgefort and ASUG's Danny Pancratz held a webcast preview of the ASUG Annual Conference pre-conference May 16.  Learn more at Agenda for 2016 SAPPHIRE NOW + ASUG Annual Conference | SAP and ASUG

 

If you are an ASUG member you can watch the recording at https://www.asug.com/discussions/docs/DOC-43934 (logon to ASUG first)

 

This year we wanted to go beyond the beginner topics; feedback from previous attendees was to go beyond beginner topic.

1fig.png

Figure 1 Source: ASUG

 

We start a day early before the conference.

 

It goes a full day

 

You need to bring your own laptop

 

This is a pure hands-on session

 

You will spend most of the time working on Design Studio; each person has their own environment; you are not sharing an environment

 

Target audience – this is not a beginner class.  The feedback has been that customers want to learn more about advanced topics.  You should have prior knowledge of Design Studio

 

The first exercise is you build a KPI dashboard

2fig.png

Figure 2 Source: ASUG

 

Figure 2 covers the topics

 

What is the BI portfolio, and where does SAP go

 

What role does Design Studio in your landscape?  What role does IT play?  What about self-service?  What about migration from XCelsius to Design Studio?

 

How will evolve over time?

 

We will look at deployment options, and what are the differences

3fig.png

Figure 3 Source: ASUG

 

We will cover filtering data inside your dashboard – variable in BW, prompts in Universe, data selection, differences in approaches, what is possible

 

You will do exercises using personalization and bookmarking and differences between, what are the options of bookmarks itself

 

Online composition – create an environment where the user can switch between data sources, charts, filter the information and create a gallery of charts so the user can create his own dashboard from previous parts

4fig.png

Figure 4 Source: ASUG

 

Then more data related topics – how load in parallel, how configure your dashboard, impact on your backend, sizing, background processing

 

How Design Studio processes information until the components have been rendered

 

You will learn how to load the data on demand and so it is not loaded more than once

 

Look at maps, what is possible, how create maps, visualization options you have and limitations you have

 

Scripting – use global scripts, how you can create global scripting functions, what the advantage, and how replace common scripts, repeat the code over and over again

5fig.png

Figure 5: Source: ASUG

 

Lastly, look at the Scorecard component, how create a custom table layout, how leverage this, and spend time on understanding the profiling and tracing of a dashboard.  It is helpful if you created a dashboard that runs in 10 seconds and squeeze out seconds, identify where the time is spent and where you have a performance issue overall so you can tune your dashboard.

 

Question and Answer

Q: Which version of Design Studio is used?

A: Using Design Studio 1.6 - version that is out since November

 

Q: Will you cover best practices for using Design Studio with universes?

A: We'll talk about Design Studio and universes and limitations

 

Q: Which version of design studio would we be using in the conference?

A: 1.6

 

Q: Will Design Studio best practices for Mobile be covered? CSS best practices?

A: Stylesheets - basic skill set - mobile - clarify? Design for mobile device - no

 

Q: When to use Lumira vs. Design Studio? If covering self-service should our business users attend?

A: Will cover the positioning of product

 

Q: Will you get into connecting to HANA?

A: All exercises are designed in the way such that it doesn't matter which data source is uses; concepts of using scorecard, online composition, background composition - doesn't matter if talk HANA universes- main source will be BW box

 

Q: How do you know when to go with an SDK or not?

A: Not going on SDK level in session - simple question - if standard components not cover, then use an extension

 

Q: If my organization has certain UI layout guidelines, like color palettes, .css files etc. Will you cover how to incorporate my org's look and feel into DS applicatons we build ?

A: not covered in this session;

 

Q: To confirm - I won't have to share my laptop with another attendee?

A: BYOD hands-on - no sharing of devices

 

Q: We use WAD to display reports in i-views on our corporate intranet. Will you get into how to get a Design Studio published and displayed in an iview?

A: Not covering that; reason for not covering as putting Design Studio an in iView is easy - documented as part of installation guide

 

Q: Are the exercises such that I can use them back at my office?

A: All the exercises are based on common models - the data model is in every BW system. All the exercises are done in a way if you have a BW system you can repeat them at home

 

Q: thank you for the session

A: Thank you for attending - hope to see you in person May 16 at this session!

 

Register for this Pre-Conference Seminar

 

For more information regarding ASUG Annual Conference in May seeASUG BI Community Annual Conference Brochure | ASUG

Your First Extension: Part 12 - Cascading Stylesheets in Custom Components

$
0
0

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

 

Last time, we added our text to the component.  We covered the dynamic positioning of the SVG text elements very thoroughly, but we deliberately left the styling aside, as we'd promised back in Part 11a to use the styling of the text elements to examine custom component CSS styling.  In principle, we can control many, many more of the properties via CSS than we previously have, but rather then refactoring our entire gauge (and making it less user friendly to anyone who is not a skilled CSS aficionado), we will focus on the text callouts to demonstrate CSS in custom components. 

 

 

Different kinds of Styling

 

 

As a general rule, every component in Design Studio can have a custom CSS class assigned, whether that component is custom or standard.  The developer of the component does not need to do anything special.  The designer simply assigns the class to the component in the properties pane.  As long as the class has been defined in either the theme, or in the application's stylesheet, it will be applied to the component:

Part12a.1.png

 

Any class from the theme is fair game.  E.g. the default Blue Crystal theme contains a UI5 header text css class called sapMH1Style.  Copying that css class name into the application CSS Class field changes the font size from the default 16px to 1.75rem.  Adding an application stylesheet is quite easy.  For those who have never done it before, rather then go into a long side quest here, I will link to Xavier Hacking's excellent blog post on the subject.

 

In addition to the classes in the theme, or custom classes in the application stylesheet, a custom extension can also access its own custom stylesheets.  This can be a handy way of defining default theming for a component, especially when its properties are not already covered in a standard theme.  Since our gauge is drawn using SVG and SVG's CSS attributes don't match up completely with HTML's CSS attributes, and custom components drawn with SVG are good candidates for such custom stylesheets.

 

 

 

Custom Extension Stylesheets

 

 

If we want to include custom CSS classes in our extension, we have to do two things:

  1. Define a file where we'll keep our CSS styles.  We actually already have one.  You may recall from way back in Part 1, that we created our project by forking a copy from the colored box SDK sample.  It already had a css file named component.css, located at ..//res/css/component.css. 
  2. We need to include a reference to it in contribution.xml.  In versions prior to 1.6, this was always done with the cssInclude element.  That element is now deprecated with 1.6 in favor of the new  requireJS element, introduced in 1.6.  For now, we'll stick to the old way of doing things and continue to use cssInclude.  It still works and again, we inherited a such an element when we forked the colored box.

...

<stdInclude kind="d3"/>

<jsInclude>res/js/component.js</jsInclude>

<cssInclude>res/css/component.css</cssInclude>

...

 

 

Let's delete the coloredBox class from component.css and add two classes to its place.  The two classes, measure and guide, will later be used for the measure and guide texts:

 

Black, boldface Helvetica font in a 1.5em font size:

.measure {

  fill: black;

  font-weight: bold;

  font-family: Helvetica;

  font-size: 1.5em;

}

 

 

Grey, Helvetica font in the 1em size:

.guide {

  fill: #808080;

  font-weight: bold;

  font-family: Helvetica;

  font-size: 1em;

}

 

 

Take Note!  We are not defining the color by a color attribute, as is normal for html and what you might expect.  Since these are SVG text elements, we have to style SVG attributes.  If you use the color attribute, nothing will happen!  Since SVG separates the border line properties from the fill, you must define them separately.  We use the fill attribute to color the fonts.  Jacob Jenkov has a good overview of the CSS style attributes of an SVG text element.

 

 

You can now start Design Studio in the debugger and try them out by entering the class names into the CSS Class field:

 

guidemeasure
Part12a.3.pngPart12a.4.png

 

 

 

 

Text Element Specific CSS Styling

 

 

What we'd really like is to ve able to assign different styles to the callouts for the guides and measure.  This is actually very simple.  We're going to introduce a new text property for each callout type.  When the SVG text elements are drawn, we will apply the text property as a class attribute. 

 

 

The New Properties in contribution.xml

 

We'll call our new properties measureTextCSSClass and guideTextCSSClass.

<property id="measureTextCSSClass"

  title="Measure Text Class"

  type="String"

  tooltip="CSS class of the measure text (overrides component CSS class.  Default value is 'measure')"

  group="SCNGaugeTextCallouts">

</property>

 

 

<property id="guideTextCSSClass"

  title="Guide Text Class"

  type="String"

  tooltip="CSS class of the guide text (overrides component CSS class.  Default value is 'guide')"

  group="SCNGaugeTextCallouts">

</property>

 

 

We'll give them default values.  We want the measure callout to default to using the new measure class and the guide callouts to default to the new guide class.  So we'll give them corresponding defaultValue  values.

<initialization>

  ... 

  <defaultValue property="measureTextCSSClass">measure</defaultValue>

  <defaultValue property="guideTextCSSClass">guide</defaultValue>

</initialization>

 

 

 

Component.js Changes

 

As with any property that gets used in component.js, we define a delegate variable for each property:

//Part 12 CSS

me._measureTextCSSClass = 'measure';

me._guideTextCSSClass = 'guide';

 

 

And the Getter/Setters:

//Part 12 Properties

me.measureTextCSSClass = function(value) {

  if (value === undefined) {

  return me._measureTextCSSClass;

  } else {

  me._measureTextCSSClass = value;

  return me;

  }

};

me.guideTextCSSClass = function(value) {

  if (value === undefined) {

  return me._guideTextCSSClass;

  } else {

  me._guideTextCSSClass = value;

  return me;

  }

};

//End Part 12 Properties

 

 

 

New we need to update text elements to include the CSS class.  If there is no element specific CSS class defined, then we'll skip adding a class attribute.  In the case of the measure callout, we'll wrap the element creation in an if/else statement, checking for me._measureTextCSSClass property.  In the case of the guide callouts, we'll do the same with the  me._guideTextCSSClass property.

 

For the measure:

if (me._measureTextCSSClass == ""){

  //No CSS class applied

  vis.append("text")

  .attr("transform", "translate(" + measurePosition.x+ "," + measurePosition.y+ ")")

  .text(calloutTextMeasure)

  .attr("text-anchor", measureTextPosition[0])

  .attr("dy", measureTextPosition[1]);

}

else{

  //me._measureTextCSSClass has a CSS class

  vis.append("text")

  .attr("transform", "translate(" + measurePosition.x+ "," + measurePosition.y+ ")")

  .text(calloutTextMeasure)

  .attr("text-anchor", measureTextPosition[0])

  .attr("class", me._measureTextCSSClass)

  .attr("dy", measureTextPosition[1]);

}

 

 

For the guides:

if (me._guideTextCSSClass == ""){

  //Empty CSS Class version

  //Start Text

  vis.append("text")

  .attr("transform", "translate(" + guidePositionStart.x + "," + guidePositionStart.y + ")")

  .text(calloutTextStart)

  .attr("text-anchor", guideTextPositionStart[0])

  //.attr("dominant-baseline", guideTextPositionStart[1]);

  .attr("dy", guideTextPositionStart[1]);

  //End Text

  vis.append("text")

  .attr("transform", "translate(" + guidePositionEnd.x + "," + guidePositionEnd.y + ")")

  .text(calloutTextEnd)

  .attr("text-anchor", guideTextPositionEnd[0])

  //.attr("dominant-baseline", guideTextPositionEnd[1]);

  .attr("dy", guideTextPositionEnd[1]);

}

else{

  //Start Text

  vis.append("text")

  .attr("transform", "translate(" + guidePositionStart.x + "," + guidePositionStart.y + ")")

  .text(calloutTextStart)

  .attr("text-anchor", guideTextPositionStart[0])

  .attr("class", me._guideTextCSSClass)

  .attr("dy", guideTextPositionStart[1]);

  //End Text

  vis.append("text")

  .attr("transform", "translate(" + guidePositionEnd.x + "," + guidePositionEnd.y + ")")

  .text(calloutTextEnd)

  .attr("text-anchor", guideTextPositionEnd[0])

  .attr("class", me._guideTextCSSClass)

  .attr("dy", guideTextPositionEnd[1]);

}

 

 

 

If you now start Design Studio in debug mode, you should have the options to set the individual CSS classes of the measure and guide callouts.  Your order of appearance within the Text callout group might be different.  Order of appearance within a group is determined by the order of appearance within the component.xml file.  In my example, I'd inserted the measure callout class after the other measure properties, but before the guide ones. 

Part12a.2.png

 

 

 

The Witches Brew: AKA the CSS Attribute Order of Precedence

 

 

At this point, there are several CSS classes that can affect both the component as a whole and the callouts.  Some are in by default and others must be chosen by the designer.  Let's take a tour of them:

 

sapUiBody - This class is assigned at the application level and inherited by all child elements.  As you can see below, it is quite simple, setting a black, 16px font, defaulting to one of the common serif fonts and falling back to sans-serif if Aral and Helvetica are not available in the browser.

.sapUiBody{

  background-color:#f2f2f2;

  color:#000000;

  font-family:Arial,Helvetica,sans-serif;

  font-size:16px;

  -webkit-tap-highlight-color:transparent

}

 

zenControl - This class is assigned to the component's container div when created.  It does not actually do anything and is used by Design Studio for housekeeping.  CSS classes make a handy tag for selecting elements.  Note that this class assigns a color attribute, which is ignored by SVG.  So the gauge and all of its elements will ignore the slate gray color setting and default to black if no fill attributes are assigned.

 

Designer defined Component CSS class - If the designer assigns a component level CSS class, that is also assigned at the container div level.

 

Designer defined  SVG Text Clement CSS class - If the designer assigns a text element level css class - using the properties that we just added - then that class is assigned to the SVG text element.

 

 

Always keep in mind that the attributes of the most specific class always override those of  less specific ones.  So if I apply a font size of 40px  and the fill attribute to green in the component level class, but leave the font-family setting the same, I'll get a green, 40px Aral font when displayed. If I then set the fill to red in the SVG text element CSS class - while leaving the other settings untouched - will result in a red, 40px Aral font.

Part12a.5.png

 

 

 

As usual, there is a public project on Github, with the eclipse project and the test application (in exported zip form).  Below is a short demo video of the results.

 

 

Your First Extension: Part 13 - IncludeJS

$
0
0

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

 

When I first started writing this tutorial, the current generally available (GA) version of Design Studio was 1.5.   When we released 1.6, we added a few major features to the extensions SDK.  I've already touched on one of the major new features in Part 6a and Part 6b, data binding.  There is another that I've wanted to touch on for months now, but have been waiting until the tutorial gauge had reached feature completion; RequireJS.

 

 

What is RequireJS and what is it used for?

 

JavaScript is not like most programming languages.  In most other languages, if you want to use a library, you can use some sort of import statement; usually using one of the keywords "import", "include" or "using", which are all synonymous with regard to what they actually do.  The syntax varies from language to language, but the usual pattern is that you'll declare which external libraries that you want to access and then you've got a handle to them within your current code.  JavaScript ticks differently and has no notion of import.  In its traditional domain of being embedded within <script> tags in html, this is not really a problem.  Anything that you want to be accessible outside the current script of .js file, you simply make a global variable.  This can be annoying in the browser, but usually worked around.  It becomes a major problem in a server side environment, such as Node.js or Rhino.  (Trivia: Design Studio scripts are actually executed as JavaScript in Rhino)

 

  • But what if the global variable trick is not an option?  This works in html, but files imported via jsInclude don't share a variable scope, so this won't work.
  • What if load order matters?  If A is dependent on B, it does not do to have A load first.  B must be loaded first! 

 

Suppose I wanted to use Jason Davies' word cloud extensions to D3.  It is an actual extension to D3 and adds a wordcloud() function.  If simply add d3.layout.cloud.js  to your extension's res/js folder and add a <jsInclude> element contribution.xml, the component won't load.  Those of you who attended the advanced Design Studio session at TechEd in 2015 may recall the geo heatmap component.  That uses leaflet and would not have worked either, if I'd simply have used multiple jsIncludes.  In order to get leaflet to work in that component, I integrated the entire leaflet library into component.js;  giving me a single file.  

 

In a nutshell, RequireJS is a framework that lets JavaScript import libraries.  It allows you to make use of libraries without any single file integration voodoo!

 

 

 

RequireJS and Design Studio

 

There has been limited support for RequireJS since Design Studio 1.4, but with 1.6, we made it the core way of handling includes.  In fact, the old way of creating includes is deprecated.  It still works if you want to use it, but we recommend using the new RequireJS way.  Just to be clear, the following elements are all depricated:

  • cssInclude
  • stdInclude
  • jsInclude

 

They have all been replaced by a single requireJS element.  In fact, you no longer need to explicitly declare the standard JavaScript and CSS libraries used in your component.  You'll refer to them directly from your component.js file.  

 

 

So let's get started in updating our gauge so that it uses RequireJS!

 

 

 

Contribution.xml

 

The old xxInclude statements need to go.  So either comment out, or delete the following three lines:

<stdInclude kind="d3"/>

<jsInclude>res/js/component.js</jsInclude>

<cssInclude>res/css/component.css</cssInclude>

 

We'll replace it with a single requireJS element:

<requireJs modes="commons m">res/js/component</requireJs>

 

Note the modes attribute!  This let's you decide which UI5 mode (the radio button choice between commons and m, made by the designer at project creation) is supported by which component JavaScript files.  If you are not using UI5 libraries in your component, you don't have to choose and can run in both.  If you are using UI5 the implementations will be different and you can use the classic (commons) UI5 library for designers running in commons and the Fiori (m) library for designers choosing that mode.   Even if you are not using UI5, you may still want to differentiate between the modes if you are using different CSS styling.  Our gauge is not using UI5 and is not differentiating its's CSS styling based on the mode, so we set it for both.

 

 

Also note that we no longer add the .js extension when declaring the file path!

 

JavaScript file is used in...modes attribute says
M onlymodes="m"
Commons onlymodes="commons"
Both Commons and Mmodes="commons m"

 

 

 

Explaining the Component.js Changes

 

The second time you migrate a component.js file over to using requireJS, it will take you about 30 seconds.  For this first time, we'll do a slow and comprehensive walkthrough.  First, we'll show the structure of the old component.js file, and the new requireJS friendly component.js file.  Then we'll walk through its features how we go from onw to the other.

 

 

The old one:

Step13.1.png

 

 

The new one:

Step13.2.png

 

Our new RequireJS based component.js file starts with a define() function containing two parameters, a list of includes and then an anonymous function, which contains our component subclass.  This results, broadly speaking, in three major "zones" .  They are shown in the diagram, below:

 

  • The list of includes.  It always includes the component itself and then any standard, external and css libraries.

 

  • The parameters of the anonymous function, which act as aliases for the included files.  Every include in the above list must have a corresponding parameter in the anonymous function.

 

  • The body of the anonymous function, which is the component subclass body itself.

Step13.3.png

 

 

 

The define() function include list

 

  • The first include in the include list is always the same: a boilerplate reference to the SDK component. 

 

  • Next comes and standard includes and external libraries, in the order that we want them loaded.  Since d3 is still a standard library in the Design Studio SDK, we don't need to refer to any hosted versions, but can simply say "d3"; using the same name as we did in the old stdInclude element..  We are not including any other libraries, but if we were, they'd come after d3.  

 

  • Lastly, we include our CSS stylesheet.   For our gauge, we previously had one stdInclude and one cssIncludeThis means  including the component itself, any standard includes and finally the CSS includes.  Note the syntax!  It starts with "css!".  This is a parser aid that signals the use of a css stylesheet.  This is followed by a relative path, from the component.js file to the CSS stylesheet file. 
css!<relativepath>

In our case, the relative path is up one directory level, over to the css sibling and down to the component.css file.

Step13.4.png

 

 

The anonymous function parameters

 

  • The first parameter is Component.  This is boilerplate.  As our first include is a reference to the component, we need it to be the first parameter here.  It needs to be "Component", with a capital C, as that is what we are extending.

 

  • As the standard include d3 was the second include in the list, it needs to be the second parameter.  We'll call it d3 here, in line with what it was called in the old, stdInclude system.  We are actually free to call it anything we want, but rather than refactoring 1000 lines of code to change references from "d3" to "potato, we"ll leave it.  Tthe important thing is that we know we could if we wanted to!

 

  • The third item in the list was the CSSinclude.  We don't actually reference that in code, so we'll just add a placeholder parameter.  We'll call it unusedDummy, because it is a dummy parameter that we never use. 

Step13.5.png

 

 

Component.subclass() changes

 

  • Taking the pre-existing contents of the component.js, we remove "sap.designstudio.sdk" from the start of the Component subclass declaration.  Then we copy+paste the entire contents into the new define() anonymous function.

Step13.6.png

 

 

 

That's it!  As usual,  current state of the project is available in a public github repository.  Next time, we'll create an installable archive for your extension. 

ASUG BI Webinars - Upcoming Customer Stories

$
0
0

It is always great to hear from other customers on how they approach a certain topic or how they did overcome a specific issue, so here is your opportunity to listen to several customers in the BI area and to hear directly from them how they approach the topic of BI.


For all webinars :

 

  • Start Time : 11:00 AM (CT), 12:00 PM (ET), 10:00 AM (MT), 9:00 AM (PT)
  • Duration : 1 hour

 

 

June 1 -  Case Study: Lessons for Deploying and Optimizing SAP Predictive Analytics

 

Attend this session for insight into how you can enhance your BI strategy to include predictive analytics capabilities. Come away with lessons to help you determine the business scenarios in which predictive analytics might provide the greatest value to your organization, and get lessons on:

- Key questions to ask and factors to consider in choosing the right project to start your predictive analytics journey

- Available algorithms and functions available in the Predictive Analytics Library, and a decision tree process for algorithm selection

- Required skill sets associated with SAP Predictive Analytics, the role of data scientist, and ethical issues to consider

 

 

June 6: Rockwell Collins Enterprise Metrics Hub

 

Rockwell Collins will present the Enterprise Metrics Hub (‘The Hub’) through their BI Portal. This solution is designed as a set of dashboards and analytical tools to provide visibility of a series of KPIs and to support their strategy for growth and consistency to measure quality performance. The opportunity for this project came through the need for rapid improvement in Customer Quality to support our market share in the Aerospace and Defense industry. The Hub gathers data from various sources and presents a standard view of KPIs. It provides enterprise-wide visibility to data so users can evaluate process variation and predict business performance.

 

 

June 22: Reporting in Color at Benjamin Moore

 

How Benjamin Moore, a 100+ year old company rooted in tradition, embarked on one of the fastest and most successful SAP BW implementations to support a corporate wide business transformation. As a result, the organization is now armed with the relevant data and analysis for more effective business decisions. This reporting solution offers SAP technology, specifically ECC, SAP BW, BW-on-Hana, and BI Web Intelligence. This solution provides a combination of real-time data access through standard reporting, pre-built reports for distribution to users and improved self-service capabilities for power users. It has enabled continued data-driven decision making with the transition to a new SAP ERP system.

 

 

July 7: Evolving BI to Have Your Business Begging for More – CSA Group

 

The demand for the right analytics to assist in making the right decisions has been a growing trend for many businesses. This interactive session will discuss CSA’s recent re-implementation of BI targeting standardization and visualization. We will also evaluate the benefits of standardizing reporting and re-engineering your current BI/BW strategy to make a lasting impression.

 

 

July 12: Tetrapak BI Reporting Strategy and Business Empowerment with SAP BusinessObjects Design Studio

 

Learn how Tetrapak is synergizing IT and business to drive agile business intelligence (BI) strategy using standardized, repeatable, and clearly understood processes across the organization. This session will present the key driving principles for deploying BI strategy within Tetrapak, where Performance = People+Process+Tools.

 

 

July 13: SAP Runs SAP: Information Design at SAP – Framework on Reporting Principles

 

The International Business Communication Standards (IBCS) are proposals for the conceptual, perceptual, and semantic design of comprehensible business reports and presentations. The session will cover the selected approach to standardize reporting in the controlling department at SAP and the technical implementation in various SAP reporting tools.

 

 

July 26: Learn How IDEXX Migrated SAP Business Warehouse powered by SAP HANA in Five Weeks

 

Learn how IDEXX Laboratories Inc. successfully migrated the SAP Business Warehouse application powered by SAP HANA from an Oracle database within five weeks.


Integrated CSS Editor - minor issue

$
0
0

This blog is just to make people aware of a small issue (I would call it a small issue) with the integrated CSS Editor in Design Studio 1.6.

 

Lets assume you are starting a new application in Design Studio and you navigate to the Custom CSS property for the application.

 

CSSEditor_001.jpg

 

You then start the integrated CSS editor

 

CSSEditor_002.jpg

 

.. and you might notice that the file extension is missing already

 

CSSEditor_003.jpg

 

... and when you save the CSS, the extension is also missing in the property.

 

Basically - unless you add the CSS Extension manually to the file - it seems that the integrated CSS editor is not adding the file extension automatically, which means that your CSS is not working.

Scorecard: Step by Step to Nice Visualization (Conditional Format)

$
0
0

Step-by-Step to define a Scorecard with Conditional Format visualization.

 

Screcard can visualize conditional formats, but scorecard does not have special calculation engine (see DS 1.6 Scorecard - Conditional Formatting | SCN). This means in the practice, you need to assure conditional formats are defined in the data source.

 

- following example is showing technical aspects, the values are really random -

 

How to assure Conditional Formats in data source?

You have basically 2 options, based on your source system.

 

Option 1: Bex Exception in Query Definition (BW)

Option 2: Conditional Formats definition in Analysis Office (BW, HANA)

 

Here I show you the option 2.

 

1. Open your data source in Analysis Office

y1.PNG

2. Define your drilldown

y2.PNG

3. Define your Conditional Formats

( in this example it is defined on second measure with T15 in key, sorry, this test data source does not have texts)

y24.PNG

4. In addition I have created second Conditional Format "for Results" to have also the option for the result values.

y23.PNG

 

5. When you finished, use "Smart Copy" and go to Design Studio.

y4.PNG

 

6. There, use Smart Paste on Data Sources

y5.PNG

 

Now, your data source is transferred also with the definitions for conditional formats.

 

In Design Studio, I want to create simple Scorecard with Bullet Chart column.

 

7. insert Scorecard and assign Data Source

y6.PNG

8. Then, in additional properties you will see

y7.PNG

9. and this is also the sequence you always need to define scorecard

  First, assure your Dimension selected for Row Scope is correct (see the blog for more on this topic Design Studio 1.6 - View on Scorecard Component)

  Second, use always "Generate Initial Scorecard" button

 

y8.PNG

By default, you get the initial scorecard - now you can change what you want (here I concentrate only on the last column)

 

10. Let us change the type to "Bullet Chart" on column 4. I delete also column 2 and 3.

y26.PNG

11. Now, let us check again what is currently selected to display:

 

y27.PNG

 

Actual Value is the measure 1 (34950 in row 1)

y28.PNG

Target Value is measure 2 (957 in row 1)

y30.PNG

12. The problem is, somehow all rows loot similar (the visual comparison is not possible).

Explanation: the setting "Auto Value Axis" is ON. This means, scorecard is adjusting the chart axis per row. And for this reason all rows are looking similar.

y31.PNG

13. Deselect this property and adjust the values to the lowest and highest value across ALL ROWS!

 

y32.PNG

14. Effect is now a bit better:

y33.PNG

15. Now, we want to use Conditional Formatting.

I use the property "Actual Color" and select the result cell to read the conditional format from.

y41.PNG

y42.PNG

Important: Binding Type is "Conditional Format Value"

 

16. This is not yet enough, now I know that I will get the values of the conditional format, maximum is 1 to 9 (numbers) and can apply conditional display in scorecard.

 

(now scroll up to see what was defined for Results - only "1" is set to value > 1000)

I add the conditional display and define only the value "1" to "Good".

y51.PNG

y52.PNG

17. and the effect is, FAX is GREEN

 

I hope this helps some of you to understand how to use conditional formats in Scorecard.

All steps are numbered, so if something is unclear, ask placing the step number.

 

Example

I have exported the data source to CSV and the example is available here.

applications/SCN_SCORECARD_CONDITIONS-20160418202440.zip

 

You can find in it 2 Scorecards and 2 data sources. The first one will not work offline, the second will display data, but w/o conditions.

Scorecard: Step by Step to Nice Visualization (Delta Bar Chart)

$
0
0

Step-by-Step to define a Scorecard with Comparison Chart visualization.

 

 

 

This time, the example can be made offline as I will use the Bring your own Data Source from Mike (included in SCN Design Studio SDK Development Community).

 

1. We start with data source and empty scorecard:

d1.PNG

d2.PNG

 

2. After assigning to scorecard and generating initial scorecard.

d3.PNG

 

3. Initial scorecard is very basic, only the dimension and first measure is displayed.

the goal is to create a visualization which compares year 1960 and 2010.

 

4. we will insert a column with comparison chart manually

d5.PNG

What is changed?

- add new column

- change template to "Comparison Chart, Delta Bar"

- change Column Size to make it bigger

- set some header text

 

5. Define the "Actual Value" and "Benchmark Value"

d4.PNG

 

d7.PNG

 

6. the effect is...

d11.PNG

7. now, only adjustments in maximum and minimum are required

d12.PNG

8.  and the chart will change

d13.PNG

9. of course, the scale is too small for some values which are bigger than max value.


10. you can also add suffix for value, e.g.

d14.PNG

11. and also remove decimal places

d16.PNG


Example

I have exported the data source to CSV and the example is available here.

applications/SCN_SCORECARD_STEP_1-20160418205436.zip

 

You can find the scorecard definition together with used data source.

Your First Extension: Part 14 - Zipit 'n Shipit (aka Creating an Installer)

$
0
0

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

 

Our gauge is effectively done.  There are lot's of small features that we could still pack into it, but there are no real new concepts that we can use the gauge as a credible vehicle to explore and the component.js already weighs in at 1300 lines.  It is also already very capable and flexible and could be a powerful tool in the hands of any good designer.  So it is time to stop tinkering and finally create an installer that will allow anyone to add the gauge to their Design Studio via the Tools menu.

 

There are three major steps to creating a Tools menu friendly installer:

  1. Create a Feature Project (as a project in Eclipse)
  2. Add a Category to your Feature Project
  3. Create a Deployable Feature

 

 

Creating a Feature Project

 

Use the following steps to create a new feature project in Eclipse. 

 

  1 - From the File Menu, select New -> Feature Project if it is in the recents list and skip to step 3.  If Feature Project is not listed in the recents list, select New - Other.

Part14.01.png

 

  2 - In the wizard selector dialog's search bar, start tying in "Feature Project", until you see it in the window.  Select it.

Part14.02.png

 

  3 - Give your project a name.  We'll call ours SCN Gauge.  Click Finish.

Part14.03.png

 

  4 - A new feature project will be created in Eclipse.  Because this kind of project is associated with its own perspective, you will get the popup asking if you want to switch to that perspective.  Click yes.  This will now open the Plugin-ins and Fragments perspective.

Part14.04.png

 

  5 - In Plugin-ins and Fragments perspective, you'll see a row of tabs across the bottom.  Select the Included Plug-ins tab.

Part14.05.png

 

  6 - Find the Plug-in Details area, on the right hand side.  Uncheck Unpack the plug-in archive after the installation. 

Part14.06.png

 

  7 - Save

 

 

 

 

Add a Category

 

  1 - From the File Menu, select New -> Other.

Part14.01.png

 

  2 - In the wizard selector dialog's search bar, start tying in "Category", until you see it in the window.  Select it.

Part14.07.png

 

  3 - The Category Definition dialog will open and ask you which of the open Eclipse projects should be the parent folder.  Select the SCNGauge project folder.

Part14.08.png

 

  4 - In the Category perspective, click on the New Category button (in the top, center).  In the ID field, add "com.sap.ip.bi.zen.sdk".  This is the standard category ID for all Design Studio extensions.  In the name field, add whatever you want.

Part14.10.png

 

  5 - Click on the Add Feature button.  This will open the Feature Selection dialog.  Select the SCNGauge feature. 

Part14.11.png

Part14.12.png

 

  6 - Save

 

 

 

 

Creating the Installer File

 

  1 - Right Click on the Feature Project and select Export.

Part14.13.png

 

  2 - When the Export dialog comes up, select Deployable features.

Part14.14.png

 

  3 - Add a destination.  In this case, I’m choosing a file on my desktop.

Part14.15.png

 

  4 - In the Options tab, click on Browse and then select the category.xml file that you previously created.

Part14.17.png

 

  5 - Click on Finish. 

 

 

That's It!  I've saved the example project and install zip into a public Github repository.  You have now created a comprehensive and functional first Design Studio component.  You have touched the basics and should be prepared for building your own other components.  This is the last installment and our tutorial is now at an end. 

How to pass DIMENSIONFILTER Values from Design Studio Application to WEBI for Compounded Characteristics

$
0
0

How to pass parameters from Design Studio Application to WEBI for Compounded Characteristics

 

    It is quite often that we need to pass the sections from Design studio application to WEBI on Compound characteristics, when we use the BEX queries as the source. I am presenting the situation here what I had and what solution that I have followed.

 

I have a BEx Query to display some Plant Maintenance data. This BEx Query is used as the source for both Design studio application and WEBI. WEBI is used to show the data at detail level as the drill through from Design Studio application.

 

The BEx Query has the below set of Variables and all of them are optional entry variables. These Variables are used is WEBI (but not in Design Studio application) to receive the values form sender application. And it also allow the users to select the different selection after jumping to WEBI from DS application.

 

1.png

 

Here 0WORKCENTER and 0PMPLANGRP are compounded characteristics as shown below:

2.png

3.png

 

Even though there are compounded, the possible values that we see in the variable prompt are not compounded ones. So we need to pass uncompounded values when we pass the values to the prompts of WEBI.

Here in the below screen, we can observe that we need to pass/Enter uncompounded values for “Work Center” and “PM planner group”.

 

4.png

 

 

5.png

We can see that the same Key values are appearing more than once (it can be same description or different), since they belong to different compounding characteristics.

  For EX:


6.png

 

 

7.png

 

Even though we selected one single Value of all those repeated Keys (for ex: M for Work centers), in the WEBI/BEX report it shows all the plants where ever we have “M” Work centers.

8.png

 

 

 

But where as in Design Studio application, we see the possibility to select the Compounded characteristic with its compounding characteristics. For ex, as shown below, Work Center along with Plant is allowed to select in the DIMENSIONFILTER.


9.png


The problem statement: When we are calling the WEBI Application, by passing the values by statement, then I get the error message like this:

 

var url="/BOE/OpenDocument/opendoc/openDocument.jsp?sIDType=CUID&iDocID=AXodJcudeyFHmjL10ztpBxA"+ "&lsMWork Center="+DS_5.getFilterExt("0WORKCENTER")+  "&sRefresh=Y";



10.png


Note: I have used DIMESIONFILTER for both 0WORKCENTER and 0PMPLANGRP dimensions in the Design Studio application.

 

Solution: I need to pass the uncompounded values. So I have used the below solution in this case. Here I managed to get uncompounded values into Variables and used these variables while calling the WEBI application. 

 

Here I have taken a TEXT Component called TEXT_3 to show how the system considers the selected values from DIMENSIONFILTER on WorkCentre. Please see the value of TEXT_3 component.

 

Here I have taken TEXT_4 as the TEXT component to show us what is the final value that we need to pass to WEBI while drill through from DS Application.

 

11.png

I have used 2 different solutions for passing values of 0WORKCENTER and 0PMPLANGRP.

 

Approach 1:

In Step 3: I have taken all the possible values of “PM planner group” which are available in the Data source.

So here I get not only user selected Dimension filter values but I get all the values. But I restricted to 1000, since I know that there are not more than 1000 distinct values in the source Cube.

In step 9: I have taken the user selected values into TEXT_3 to just to show how the selected values in DIMESIONFILTER comes out of the function “GetFilterExt”.

The number of user selected values in DIMESIONFILTERS of “PM planner group” is always less than the number of records gets out of “getmembers” function.

In step 10 to 18: Since number of Values in PG1 are always greater than the number of selected user selected values in “GetFilterExt”, I have used to loop on PG1 and taking different substring every time from the result of “GetFilterExt”

 

12.png

 

Approach 2:

In step 21: I have taken the user selected values into variable PG3 by using the function “GetFilterExt”. Since I used Split function, so I am getting result as array.

In Step 24 to 32: I have used loop statements on the array result from step 21.

Here I used “if” statement to avoid concatenating “;” incase if user has selected only one value in the DIMENSION Filter of Workcenter.

 

13.png

 

How am I using it while calling open document:

 

As shown below, The values derived in approach 1 for “PM Planner Group” is passed to “url” variable by using “getText” function, since I have used TEXT Component in approach1.

The values derived in approach 2 for “Work Center” is passed to “url” variable by providing the String PG4.

14.png

 

Values selected in Design Studio:

 

 

15.png

 

Here User has selected the Work centers: 1000/E-MC; 1000/I-PL; 1000/M-EL; 1000/M-IN; 1000/M-IS

And user has selected the PM Planer Group: 1000/C01; 1000/C03; 1000/C04

 

We can see that the non-concatenated values are passed to WEBI from below screen:


16.png



Viewing all 662 articles
Browse latest View live


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