![](https://static.wixstatic.com/media/15aea9_fbae00bfe5634253bd38c61fc72239a4~mv2.gif)
Hello everyone, welcome back to our blog series on transforming SAP Analytics Cloud (SAC) with custom widgets. In this blog post, we will extend our previous Gantt Chart widget by integrating it with SAC's API. This will allow us to update our project schedules directly from the widget and have the changes persist in our SAC model.
Before we dive in, make sure you've read our previous blog post on creating a Gantt Chart widget for SAC. This blog post will build upon the concepts and code introduced there.
Our previous blogs can be found here:
1. Transforming SAC with Custom Widgets (Part 1) – link
2.Transforming SAC with Custom Widgets (Part 2 – Gamify) – link
3.Building a Customizable Calculator Widget for SAC – Styling and Builder Panel – link 4. Transforming SAC with Custom Widgets (Part 4 – Custom Widgets Data Binding)– link
5.Gantt Chart Widget with Data Binding for SAP Analytics Cloud– link
By the way, we encourage you to follow us on [LinkedIn]. :)
Summary of Previous Blog:
In our previous blog, we discussed the creation of a custom Gantt Chart widget in SAP Analytics Cloud (SAC) with data binding functionality.This approach provided a robust way to visualize data in SAC, but it also meant that the data had to exist(either via import or via planning) in SAC before it could be used in the Gantt Chart widget.We are now introducing a significant enhancement to this process. With the new API, data can be directly created within the Gantt Chart widget itself and then pushed into the SAC model.
Our Goal
Our goal is to extend our Gantt Chart widget with the ability to update our SAC model directly from the widget. This means that when we add tasks in the Gantt chart via the Widget, these changes will be stored in our SAC model. This will make our widget a more powerful tool for managing project schedules.
![](https://static.wixstatic.com/media/15aea9_e0c874acad494c389ecbbc33587773f0~mv2.gif)
What is SAC's REST API?
SAP Analytics Cloud (SAC) provides a RESTful API that allows third-party applications to interact with data stored on an SAC tenant. For example, you can create, read, update, and delete data in your SAC models, manage users and teams, and interact with the Content Network.The API is designed to be flexible and powerful, allowing you to automate and customize your SAC workflows.
To use the API, you need to have a tenant URL and an SAP Analytics Cloud user. You also need to configure OAuth to work with your application before you can use the REST API.
API Endpoints
The SAC API provides several endpoints that allow you to interact with different aspects of your SAC tenant. Here are some examples:
api/v1/dataexport: Allows you to extract a list of models and metadata on your tenant, or retrieve information about a specific model.
api/v1/dataimport: Allows you to import fact and master data to SAC.
and so on.
Authentication
Before you can use the SAC REST APIs, you need to set up authentication.
To authenticate your application, you need to create an OAuth client in your SAC tenant. Your application will then be able to authenticate against the system’s OAuth service and obtain authorization to authenticate against the API.
For more information on the configuration and functionalities, see the SAP Analytics Cloud REST API or the API Developer Guide
Overview of Developed Objects: GanttChartWidgetAPI.js, GanttChartWidgetAPI.json, and SACAPI_DataImport.js
![](https://static.wixstatic.com/media/15aea9_546c1af332454a2cb7299cf1255663e3~mv2.png/v1/fill/w_937,h_291,al_c,q_85,enc_auto/15aea9_546c1af332454a2cb7299cf1255663e3~mv2.png)
In the context of SAP Analytics Cloud (SAC), the three developed objects, namely `GanttChartWidgetAPI.js`, `GanttChartWidgetAPI.json`, and `SACAPI_DataImport.js`, play crucial roles in data manipulation, visualization, and integration. These files are interconnected and work together to provide a seamless user experience. Here's a brief overview of each file and how they relate to each other:
GanttChartWidgetAPI.js and GanttChartWidgetAPI.json
`GanttChartWidgetAPI.js` is a JavaScript file that contains the logic for a custom Gantt Chart widget. `GanttChartWidgetAPI.json` is a JSON file that defines the structure and properties of the Gantt Chart widget. More on that you can read in our last blog– link
You can view the full JavaScript code [here].
SACAPI_DataImport.js
`SACAPI_DataImport.js` is the new JavaScript file that handles the import of data into the SAC tenant. It uses the SAC's Data Import API to push data into the SAC models. This could include fact data, master data, or both, depending on the requirements of the Gantt Chart widget. The `GanttChartWidgetAPI.js` file will use the functions in `SACAPI_DataImport.js` to fetch the necessary data from the SAC tenant. You can view the full JavaScript code [here].
const script = document.createElement('script');
script.src = 'https://planifyit.github.io/Gantt_Chart_SAC_API/SACAPI_DataImport.js';
document.head.appendChild(script);
This process is initiated when a new task is added to the Gantt chart, which triggers the `onAfterTaskAdd` event. The event handler function receives the `id` and `task` object of the newly added task. The `task` object contains the task's properties such as `id`, `text`, `start_date`, `end_date`, and so on.
gantt.attachEvent("onAfterTaskAdd", (id, task) => {
console.log("New task was added: ", task);
// Convert the task to CSV
const csvData = this.taskToCsv(task);
// Retrieve the tokens and then call createJob, uploadData, validateJob, and runJob
window.getAccessToken().then(() => {
window.getCsrfToken().then(() => {
window.createJob().then(() => {
window.uploadData(csvData).then(() => {
window.validateJob().then(() => {
window.runJob();
gantt.clearAll();
// Load the new data
gantt.parse({ data: this.tasks });
taskToCsv function is called within the event handler and is responsible for converting the `task` object into a CSV string. This is done by extracting the relevant properties from the `task` object, converting them into the appropriate format , and then concatenating them into a CSV string. The resulting CSV string is then returned by the function.
taskToCsv(task) { const id = task.id;
const label = task.text;
......
const csvString = `${version},${date},${id},${label},${startDate},${endDate},${open},${progress}`;
const csvData_raw = 'Version,Date,id,label,startDate,endDate,open,progress\n' + csvString;
return csvData_raw; }
Getting Started
Implementing the API Operations
In the context of SAP Analytics Cloud (SAC) and its REST API, the following constants are used to establish a connection and interact with the API:
1. `csrfTokenUrl`: This is the URL used to fetch the CSRF (Cross-Site Request Forgery) token for making secure requests .
2. `clientId` and `clientSecret`: These are the credentials for the OAuth client that was set up in SAC to authenticate the application against the SAC OAuth service and obtain an access token.
3. `tokenUrl`: This is the URL of the OAuth token service.
4. `apiEndpoint`: This is the URL of the specific SAC API endpoint that the application will interact with. In this case, the endpoint is for importing master fact data into a specific model in SAC.
Example below, please replace <SAC_Tenant> with your SAC Teanant:
const csrfTokenUrl = 'https://<SAC_Tenant>.eu10.hcs.cloud.sap/api/v1/csrf';
const clientId = 'sb-d36bd0cc-eaaf-4fa8-8897-5b0699';
const clientSecret = '7f7889df-1504-49f2-9e38-e2de480d85a2$NDPTA7KjiS3YdGl0wDjwu';
const tokenUrl = 'https://<SAC_Tenant>.authentication.eu10.hana.ondemand.com/oauth/token';
const apiEndpoint = 'https://<SAC_Tenant>.eu10.hcs.cloud.sap/api/v1/dataimport/models/Cdlg2a1kkbj139ea3kjvk8/masterFactData';
In our case we chose masterFactData, because we want to create the master data for task id dynamically. Uploading only FactData turns out to be much faster, in case no master data is necessary. it is also possible to upload masterData only.
Some of the URLs can be found in SAC under Administration.
![](https://static.wixstatic.com/media/15aea9_39f40142eec44ea7b92174cb36db2e98~mv2.png/v1/fill/w_514,h_448,al_c,q_85,enc_auto/15aea9_39f40142eec44ea7b92174cb36db2e98~mv2.png)
![](https://static.wixstatic.com/media/15aea9_50f71c31469147758e1af643bcdb6eff~mv2.png/v1/fill/w_645,h_128,al_c,q_85,enc_auto/15aea9_50f71c31469147758e1af643bcdb6eff~mv2.png)
![](https://static.wixstatic.com/media/15aea9_b7d0b14add2b44358f75b838d0ce1ce7~mv2.png/v1/fill/w_621,h_377,al_c,q_85,enc_auto/15aea9_b7d0b14add2b44358f75b838d0ce1ce7~mv2.png)
SAC import API Job Settings and Mapping
The `jobSettings` constant is an object that contains configuration settings for the data import job in SAP Analytics Cloud (SAC). In our case, it is divided into two main sections: `Mapping` and `JobSettings`.
1. `Mapping`: This section is used to map the column names in the source data to the corresponding dimension names in the target model in SAC.
2. `JobSettings`: This section contains additional settings for the data import job. In this case, the `importMethod` is set to `"Update". There are also "Append" and "CleanAndReplace" options.
const jobSettings = {
"Mapping": {
"Version___ID": "Version",
"Date___CALMONTH": "Date",
"id___ID": "id",
"label___ID": "label",
"startDate___ID": "startDate",
"endDate___ID": "endDate",
"open___ID": "open",
"progress": "progress"
},
"JobSettings": {
"importMethod": "Update"
}
};
Next, we need to implement the functions that will perform the API operations. Each function will send a request to the SAC API and handle the response.
For example, the `_getAccessToken` function will send a request to the `/oauth/token` endpoint of the SAC API to get an access token. The access token is a string that identifies the user and allows them to perform operations on the SAC model.
_getAccessToken() {
// Send a request to the /oauth/token endpoint of the SAC API
// Handle the response and store the access token
}
Similarly, the `_getCsrfToken` function will send a request to the `/csrf` endpoint of the SAC API to get a CSRF token. The CSRF token is a string that protects against cross-site request forgery attacks.
_getCsrfToken() {
// Send a request to the /csrf endpoint of the SAC API
// Handle the response and store the CSRF token
}
The `_createJob`, `_uploadData`, `_validateJob`, and `_runJob` functions will send requests to the `/jobs` endpoint of the SAC API to create a job, upload data to the job, validate the job, and run the job, respectively.
_createJob() {
// Send a request to the /jobs endpoint of the SAC API to create a job
// Handle the response and store the job URL
}
_uploadData(csvData) {
// Send a request to the job URL with the CSV data
// Handle the response
//csvData is taken from GanttChartWidgetAPI.js
}
_validateJob() {
// Send a request to the job URL to validate the job
// Handle the response
}
_runJob() {
// Send a request to the job URL to run the job
// Handle the response
// the data can be either CSV or JSON , in our case it is CSV
headers: {
'Content-Type': 'text/csv',
'Authorization': `Bearer ${accessToken}`,
'x-csrf-token': csrfToken,
'x-sap-sac-custom-auth' : 'true'
}}
Handling API Responses
Each API operation will return a response that we need to handle. The response will contain information about the result of the operation, such as whether it was successful or not, and any error messages.
We will handle the responses in the functions that perform the API operations. We will parse the response data and display it in the `messages` div of our widget.
_getAccessToken() {
// Send a request to the /oauth/token endpoint of the SAC API
// Parse the response and store the access token
// Display the response in the messages div
}
Updating the SAC Model
Finally, we need to update our SAC model with the changes made in the Gantt chart. We do this by sending a request to the `/jobs` endpoint of the SAC API with the updated data.
We will implement this in the `_uploadData` function. This function will take the updated data from the Gantt chart, convert it to CSV format, and send it to the SAC API.
_uploadData() {
// Get the updated data from the Gantt chart
// Convert the data to CSV format
// Send a request to the job URL with the CSV data
// Handle the response
}
SAC Model
Our SAC Model is rather simple and includes only the necessary dimensions
![](https://static.wixstatic.com/media/15aea9_0f5c1a8ddc504bd78791f7edc9a92c8b~mv2.png/v1/fill/w_980,h_673,al_c,q_90,usm_0.66_1.00_0.01,enc_auto/15aea9_0f5c1a8ddc504bd78791f7edc9a92c8b~mv2.png)
Debugger mode:
First, we need to add a few more elements to our widget's `GanttChartWidgetAPI.js` HTML. We will add a toggle button to activate and deactivate the debugging mode for our widget, and a set of buttons to trigger the various API operations. We will also add a `div` element to display messages from the API operations. This is just for demo purposes. In the standard case as soon as an object is created using the widget the data will be pushed to SAC automatically.
<label class="switch">
<input type="checkbox" id="debugToggle">
<span class="slider round"></span>
</label>
<p id="debugStatus">Debugging Mode Inactive</p>
![](https://static.wixstatic.com/media/15aea9_a32f7d41b2e445d8856bc3b17e92f5da~mv2.gif)
Next, we need to add event listeners for our new buttons. We do this in the `constructor` method of our widget. Each button will trigger a corresponding function when clicked.
this._shadowRoot.getElementById('debugToggle').addEventListener('change', this._toggleDebugging.bind(this));
this._shadowRoot.getElementById('getAccessToken').addEventListener('click', this._getAccessToken.bind(this));
this._shadowRoot.getElementById('getCsrfToken').addEventListener('click', this._getCsrfToken.bind(this));
//and so on ......
For debugging a fixed csvData_debugger is defined:
// Get a reference to the messages element
const messagesElement = this._shadowRoot.getElementById('messages');
// Pass the reference to the functions
const csvData_debugger = const csvData_debugger = `Version,Date,id,label,startDate,endDate,open,progress
public.Actual,202401,999,TaskDebugger,2023-02-02,2023-05-05,X,1`;
Created Task after running the job:
![](https://static.wixstatic.com/media/15aea9_16d0e45faa6d437ba79e3e01976fa6e8~mv2.png/v1/fill/w_980,h_163,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/15aea9_16d0e45faa6d437ba79e3e01976fa6e8~mv2.png)
It is obviously also possible to use the Console of the browser for debugging . For that reason we have added multiple console.log statements to track each step.
![](https://static.wixstatic.com/media/15aea9_d8e81a91c4024d87bf34b423114d8e27~mv2.png/v1/fill/w_713,h_460,al_c,q_85,enc_auto/15aea9_d8e81a91c4024d87bf34b423114d8e27~mv2.png)
API Limitations
As of July 29, 2023, the SAP Analytics Cloud (SAC) Data Import API has several limitations that users should be aware of when using it to import data into SAC:
1. Active Jobs Limit: The API imposes a limit of 100 active jobs per user and 100 active jobs per model.
2. POST Request Size Limit: POST requests must be 300MB or less in size.
3. Master Data Limitation: The API does not support individual master data for a single dimension.
4. Public Dimensions Limitation: Import to public dimensions is not supported. Only local dimensions are supported.
6. Version Dimension Limitation: Import to the Version dimension is not supported.
8. Hierarchy Import Limitation: Importing hierarchies is not supported.
Integration with SAC
The widgets will be freely accessible on our Github page [Github]. We believe in open-source development and the power of community collaboration.
Just download the JSON file and upload it in your SAC tenant under Custom Widgets as follows:
![](https://static.wixstatic.com/media/15aea9_75c72a33bb1f433ca997116668a9e7da~mv2.png/v1/fill/w_980,h_149,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/15aea9_75c72a33bb1f433ca997116668a9e7da~mv2.png)
Integrating the Gantt Chart Widget into SAC is a straightforward process. Once you have the `GanttChartWidget.json` file ready, you can upload the widget to SAC through the Custom Widgets panel. After uploading, the Gantt Chart Widget will be available for use in your dashboards. You can bind data to the widget and customize its properties to suit your needs.
![](https://static.wixstatic.com/media/15aea9_7fb7c9cc4dbd441aa36a80232e09961e~mv2.webp/v1/fill/w_740,h_81,al_c,q_80,enc_auto/15aea9_7fb7c9cc4dbd441aa36a80232e09961e~mv2.webp)
Dont forget to follow us on [LinkedIn]. :)
Comments