Initial commit
This commit is contained in:
314
references/iframe-embedding-lumira-migration.md
Normal file
314
references/iframe-embedding-lumira-migration.md
Normal file
@@ -0,0 +1,314 @@
|
||||
# iFrame Embedding and Lumira Designer Migration
|
||||
|
||||
Reference documentation for iFrame PostMessage communication and migration guidance from Lumira Designer to SAP Analytics Cloud.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [iFrame Embedding with PostMessage](#iframe-embedding-with-postmessage)
|
||||
2. [Differences Between SAP Analytics Cloud and Lumira Designer](#differences-between-sap-analytics-cloud-and-lumira-designer)
|
||||
|
||||
---
|
||||
|
||||
## iFrame Embedding with PostMessage
|
||||
|
||||
When your analytic application is embedded in an iFrame, it can communicate bidirectionally with the host web application using JavaScript PostMessage.
|
||||
|
||||
### Application Events for Embedded Scenarios
|
||||
|
||||
SAC analytic applications have two primary application events:
|
||||
|
||||
1. **onInitialization**: Runs once when the application is instantiated by a user
|
||||
2. **onPostMessageReceived**: Triggered when the host application sends a PostMessage
|
||||
|
||||
### onPostMessageReceived Event
|
||||
|
||||
This event fires whenever the host application makes a PostMessage call into the embedded analytic application.
|
||||
|
||||
**Reference**: [https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage)
|
||||
|
||||
### Event Parameters
|
||||
|
||||
The `onPostMessageReceived` event provides two input parameters:
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `origin` | string | The domain of the host application |
|
||||
| `message` | any | The message content passed via PostMessage |
|
||||
|
||||
### origin Parameter
|
||||
|
||||
The `origin` parameter contains the domain of the host application.
|
||||
|
||||
**Important Security Notes**:
|
||||
- iFrame contents don't need to be in the same origin as the host app
|
||||
- Same-origin policies may still be in effect
|
||||
- Be careful about **clickjacking attacks** and **malicious iFrame hosts**
|
||||
- **Always validate** the `origin` parameter to ensure the iFrame host is expected
|
||||
|
||||
**Security Best Practice**:
|
||||
```javascript
|
||||
// onPostMessageReceived event
|
||||
if (origin !== "[https://trusted-domain.com](https://trusted-domain.com)") {
|
||||
console.log("Unauthorized origin: " + origin);
|
||||
return; // Reject messages from unknown origins
|
||||
}
|
||||
|
||||
// Process message from trusted origin
|
||||
processMessage(message);
|
||||
```
|
||||
|
||||
### message Parameter
|
||||
|
||||
The `message` parameter contains the standard JavaScript PostMessage content passed into SAP Analytics Cloud.
|
||||
|
||||
**Characteristics**:
|
||||
- Does **not** follow any specific format
|
||||
- Could contain almost any data type
|
||||
- Encoded using the **structured clone algorithm**
|
||||
- Some documented restrictions on what can and can't be encoded
|
||||
|
||||
### Structured Clone Algorithm
|
||||
|
||||
The structured clone algorithm has some limitations on what can be cloned:
|
||||
|
||||
**Supported**:
|
||||
- Primitive types (string, number, boolean)
|
||||
- Arrays
|
||||
- Plain objects
|
||||
- Date objects
|
||||
- Map, Set, ArrayBuffer, TypedArray
|
||||
|
||||
**Not Supported**:
|
||||
- Functions
|
||||
- DOM nodes
|
||||
- Symbols
|
||||
- Error objects
|
||||
- Property descriptors, setters, getters
|
||||
|
||||
### Example: Receiving PostMessage
|
||||
|
||||
```javascript
|
||||
// onPostMessageReceived event handler
|
||||
// Parameters: origin, message
|
||||
|
||||
// Security check
|
||||
if (origin !== "[https://my-portal.company.com](https://my-portal.company.com)") {
|
||||
console.log("Rejected message from: " + origin);
|
||||
return;
|
||||
}
|
||||
|
||||
// Log the received message
|
||||
console.log("Received message from: " + origin);
|
||||
console.log("Message content: " + JSON.stringify(message));
|
||||
|
||||
// Process message based on type
|
||||
if (message.type === "filter") {
|
||||
// Apply filter from host application
|
||||
var dimension = message.dimension;
|
||||
var value = message.value;
|
||||
|
||||
Chart_1.getDataSource().setDimensionFilter(dimension, value);
|
||||
|
||||
} else if (message.type === "refresh") {
|
||||
// Refresh data
|
||||
Chart_1.getDataSource().refreshData();
|
||||
|
||||
} else if (message.type === "navigate") {
|
||||
// Handle navigation request
|
||||
var pageId = message.pageId;
|
||||
// Navigate to page...
|
||||
}
|
||||
```
|
||||
|
||||
### Host Application Example
|
||||
|
||||
In the host web application (outside SAP Analytics Cloud):
|
||||
|
||||
```javascript
|
||||
// Get reference to the SAC iFrame
|
||||
var sacFrame = document.getElementById("sac-iframe");
|
||||
|
||||
// Send filter command to embedded SAC application
|
||||
sacFrame.contentWindow.postMessage({
|
||||
type: "filter",
|
||||
dimension: "Region",
|
||||
value: "EMEA"
|
||||
}, "[https://your-tenant.sapanalytics.cloud](https://your-tenant.sapanalytics.cloud)");
|
||||
|
||||
// Send refresh command
|
||||
sacFrame.contentWindow.postMessage({
|
||||
type: "refresh"
|
||||
}, "[https://your-tenant.sapanalytics.cloud](https://your-tenant.sapanalytics.cloud)");
|
||||
```
|
||||
|
||||
### Security Recommendations
|
||||
|
||||
1. **Always validate origin**: Check that messages come from expected domains
|
||||
2. **Use specific target origins**: Don't use `"*"` as target origin
|
||||
3. **Validate message structure**: Ensure message format matches expectations
|
||||
4. **Log suspicious activity**: Track rejected messages for security monitoring
|
||||
5. **Implement allowlist**: Maintain list of trusted origins
|
||||
|
||||
```javascript
|
||||
// Recommended: Origin allowlist pattern
|
||||
var trustedOrigins = [
|
||||
"[https://portal.company.com",](https://portal.company.com",)
|
||||
"[https://intranet.company.com"](https://intranet.company.com")
|
||||
];
|
||||
|
||||
// In onPostMessageReceived
|
||||
var isTrusted = false;
|
||||
for (var i = 0; i < trustedOrigins.length; i++) {
|
||||
if (origin === trustedOrigins[i]) {
|
||||
isTrusted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isTrusted) {
|
||||
console.log("Blocked message from untrusted origin: " + origin);
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Differences Between SAP Analytics Cloud and Lumira Designer
|
||||
|
||||
Design Studio / Lumira Designer and SAP Analytics Cloud, analytics designer have broadly similar scripting environments. Both are JavaScript-based and perform similar missions. Analytics designer's scripting framework was informed by experience with Design Studio.
|
||||
|
||||
However, there are important differences to understand when migrating.
|
||||
|
||||
### Execution Environment
|
||||
|
||||
| Aspect | Lumira Designer | Analytics Designer (SAC) |
|
||||
|--------|----------------|--------------------------|
|
||||
| **Script Execution** | Server-side | Browser-side (client) |
|
||||
| **Proximity** | Close to the data | Close to the user |
|
||||
| **JavaScript Engine** | Server JavaScript engine | Browser native JavaScript |
|
||||
|
||||
**Key Implication**: This "close-to-data vs close-to-user" philosophical difference affects how you design scripts.
|
||||
|
||||
### Copy-and-Paste Compatibility
|
||||
|
||||
**Analytics Designer is NOT copy-and-paste compatible with Lumira Designer.**
|
||||
|
||||
Scripts written for Lumira Designer will likely need modification to work in Analytics Designer. This is partially a consequence of the architectural differences.
|
||||
|
||||
### Data Source Access
|
||||
|
||||
| Feature | Lumira Designer | Analytics Designer |
|
||||
|---------|----------------|-------------------|
|
||||
| Standalone Data Sources | Available as global variables | Hidden within data-bound widgets |
|
||||
| Access Method | Direct access by name | Must use `getDataSource()` method |
|
||||
|
||||
**Lumira Designer**:
|
||||
```javascript
|
||||
// Direct access to data source
|
||||
DS_1.setFilter("Location", "USA");
|
||||
```
|
||||
|
||||
**Analytics Designer**:
|
||||
```javascript
|
||||
// Access through widget
|
||||
var ds = Chart_1.getDataSource();
|
||||
ds.setDimensionFilter("Location", "USA");
|
||||
```
|
||||
|
||||
**Note**: When standalone data sources become available in SAC, you'll be able to access them as global variables, similar to Lumira.
|
||||
|
||||
### Type System Differences
|
||||
|
||||
| Feature | Lumira Designer | Analytics Designer |
|
||||
|---------|----------------|-------------------|
|
||||
| Type Conversion | More lenient | Strict (no automatic conversion) |
|
||||
| Equality Operator | `==` works across types | `==` only valid with same types |
|
||||
| Recommended Operator | `==` or `===` | `===` (strict equality) |
|
||||
|
||||
**Lumira Designer** (allowed):
|
||||
```javascript
|
||||
var aNumber = 1;
|
||||
if (aNumber == "1") { // Works - auto type coercion
|
||||
// Executes
|
||||
}
|
||||
```
|
||||
|
||||
**Analytics Designer** (must use explicit conversion or strict equality):
|
||||
```javascript
|
||||
var aNumber = 1;
|
||||
|
||||
// Option 1: Strict equality with correct type
|
||||
if (aNumber === 1) { // Recommended
|
||||
// Executes
|
||||
}
|
||||
|
||||
// Option 2: Explicit conversion
|
||||
if (aNumber.toString() === "1") {
|
||||
// Executes
|
||||
}
|
||||
|
||||
// WRONG: Different types with ==
|
||||
// if (aNumber == "1") { } // Error in SAC!
|
||||
```
|
||||
|
||||
### API Method Names
|
||||
|
||||
Some API methods have different names between platforms:
|
||||
|
||||
| Operation | Lumira Designer | Analytics Designer |
|
||||
|-----------|----------------|-------------------|
|
||||
| Set filter | `setFilter()` | `setDimensionFilter()` |
|
||||
| Remove filter | `removeFilter()` | `removeDimensionFilter()` |
|
||||
| Get filter | `getFilter()` | `getDimensionFilters()` |
|
||||
|
||||
### Summary of Key Migration Steps
|
||||
|
||||
When migrating from Lumira Designer to SAP Analytics Cloud:
|
||||
|
||||
1. **Update data source access**: Change direct data source references to `widget.getDataSource()`
|
||||
|
||||
2. **Fix type conversions**: Add explicit `.toString()` or other conversion methods
|
||||
|
||||
3. **Update equality operators**: Change `==` to `===` for comparisons, especially with different types
|
||||
|
||||
4. **Update API method names**: Replace Lumira-specific methods with SAC equivalents
|
||||
|
||||
5. **Review script location**: Consider that scripts now run in browser, not on server
|
||||
|
||||
6. **Test thoroughly**: Behavior may differ due to execution environment changes
|
||||
|
||||
### Example Migration
|
||||
|
||||
**Original Lumira Designer Script**:
|
||||
```javascript
|
||||
// Lumira Designer
|
||||
DS_1.setFilter("Year", selectedYear);
|
||||
var members = DS_1.getMembers("Location");
|
||||
var count = members.length;
|
||||
console.log("Count: " + count); // Auto-converts count to string
|
||||
```
|
||||
|
||||
**Migrated Analytics Designer Script**:
|
||||
```javascript
|
||||
// Analytics Designer (SAC)
|
||||
var ds = Chart_1.getDataSource();
|
||||
ds.setDimensionFilter("Year", selectedYear);
|
||||
var members = ds.getMembers("Location");
|
||||
var count = members.length;
|
||||
console.log("Count: " + count.toString()); // Explicit conversion required
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- **SAP Analytics Designer Documentation**: [https://help.sap.com/docs/SAP_ANALYTICS_CLOUD](https://help.sap.com/docs/SAP_ANALYTICS_CLOUD)
|
||||
- **Lumira Designer Migration Guide**: Check SAP Help Portal for official migration documentation
|
||||
- **PostMessage API**: [https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage)
|
||||
|
||||
---
|
||||
|
||||
**Source**: SAP Analytics Designer Development Guide - Chapter 4: Scripting in Analytics Designer (Sections 4.2.3.1 and 4.10)
|
||||
**Last Updated**: 2025-11-23
|
||||
Reference in New Issue
Block a user