Technology Blog Posts by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 

Introduction 

Unlocking Custom Experiences in SAP Build Work Zone: Shell Plugin in Action
In today’s digital workplace, personalization is key. This article showcases how to enhance SAP Build Work Zone with a custom shell plugin that brings tailored notifications right to the user’s fingertips. Using a Multi-Target UI5/CAP application, we’ll demonstrate how to create, manage, and surface custom alerts—seamlessly integrated into your Work Zone experience.

 

f.drawio.png

Screenshot 2025-07-17 at 10.34.19 copy.png

 

 

 

 

 

 

 

 

To replicate this you should have a base knowledge of SAP BTP, JS, SAPUI5 and SAP CAP, I will not go deep down in to how to generate a project in BAS, or create an instance in SAP BTP. 

***GITHUB URL REMOVED BY MODERATION***

Project Architecture

shell-plugin-diagram.drawio.png

Backend/Frontend App Development:

Generate a regular SAP CAP application

Firstly I've created a primitave data structure under db/schema.cds

namespace my.Notification;

entity Notification {
    key ID : UUID;
    type: String(30);
    title: String;
    message: String;
}

 Than a service at srv/service.cds:

using { my.Notification as my } from '../db/schema';

service NotificationService {
    entity Notification as projection on my.Notification;
}

And the backend is almost done, now add an app router and a sapui5 freestyle base app to the project.

Now let's add a form to create and delete the notifications under app/<app name>/webapp/view/<view name>.view.xml:

 

Spoiler
Remember to correct the controller name if you copy the code

 

<mvc:View
    controllerName="com.sap.shellnotificationsender.controller.MyView"
    xmlns:mvc="sap.ui.core.mvc"
    xmlns="sap.m"
    xmlns:form="sap.ui.layout.form"
    xmlns:core="sap.ui.core">

    <Toolbar>
        <Title text="{i18n>title}" />
    </Toolbar>

    <Shell id="mainShell">
        <VBox class="sapUiSmallMargin">
            <form:SimpleForm
                    editable="true"
                    layout="ResponsiveGridLayout"
                    labelSpanL="1" labelSpanM="2"
                    adjustLabelSpan="false"
                    columnsL="3" columnsM="3"
                    class="sapUiSmallMarginBottom">

                    <Label text="Type" />
                    <ComboBox id="newType" selectedKey="information">
                        <core:Item key="Warning" text="Warning" />
                        <core:Item key="Success" text="Success" />
                        <core:Item key="Information" text="Information" />
                        <core:Item key="Error" text="Error" />
                        <core:Item key="Alert" text="Alert" />
                        <core:Item key="Confirm" text="Confirm" />
                    </ComboBox>

                    <Label text="Title" />
                    <Input id="newTitle" />

                    <Label text="Message" />
                    <Input id="newMessage" />

                    <Label text="" />
                    <Button text="Add Notification"
                        press="onAddNotification"
                        type="Emphasized"/>
                </form:SimpleForm>

            <!-- Table Section -->
            <Table id="shellNotificationsTable" items="{/Notification}">
                <columns>
                    <Column>
                        <Text text="Delete" />
                    </Column>
                    <Column>
                        <Text text="Type" />
                    </Column>
                    <Column>
                        <Text text="Title" />
                    </Column>
                    <Column>
                        <Text text="Message" />
                    </Column>
                </columns>

                <items>
                    <ColumnListItem>
                        <cells>
                            <Button icon="sap-icon://delete" type="Negative" press="deleteRow" />
                            <Text text="{type}" />
                            <Text text="{title}" />
                            <Text text="{message}" />
                        </cells>
                    </ColumnListItem>
                </items>
            </Table>
        </VBox>
    </Shell>
</mvc:View>

As next let's implement the controller that manages the view with all the necessary notification creation/deletion methods:

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/m/MessageBox",
	"sap/m/MessageToast"
], (Controller, MessageBox, MessageToast) => {
    "use strict";

    return Controller.extend("com.sap.shellnotificationsender.controller.MyView", {
        onInit() {

        },

        deleteRow: function (oEvent) {
			var oContext = oEvent.getSource().getBindingContext().getObject();
			console.log(oContext);
			MessageBox.confirm("Are your sure you want to delete this message?", {
				title: "Confirm",
				onClose: function (sAction) {
					if (sAction === "OK") {
						this.onDeleteSpecificRecord(oContext)
					}
				}.bind(this),
				actions: [
					MessageBox.Action.OK,
					MessageBox.Action.CANCEL
				],
				emphasizedAction: MessageBox.Action.OK
			})
		},

		onDeleteSpecificRecord: function (oRecord) {
			var oDataModel = this.getOwnerComponent().getModel();
			var oBusyDialog = new sap.m.BusyDialog({
				title: "Deleting Record",
				text: "Please Wait ..."
			})
			oBusyDialog.open();
			oDataModel.delete(`/Notification('${oRecord.ID}')`)
				.then(() => {
					console.log("Record deleted successfully");
				})
				.catch((error) => {
					console.error("Deletion failed:", error);
				})
				.finally(() => {
					this.getView().byId("shellNotificationsTable").getBinding("items").refresh();
					oBusyDialog.close();
				});
		},

		onAddNotification: function () {
			const sType = this.byId("newType").getValue();
			const sTitle = this.byId("newTitle").getValue();
			const sMessage = this.byId("newMessage").getValue();

			this.byId("shellNotificationsTable").getBinding("items").create({
				"type": sType,
				"title": sTitle,
				"message": sMessage
			}).created().then(function() {
				MessageToast.show("Created")
			})
		}
    });
});

The last thing to do is to add all the features that you need to the application, like HANA DB, xsuaa in my case, to do so just run

cds add hana
cds add xsuaa

And like this is the app ready, let's deploy it, firstly login to Cloud Foundry

cf login

then right click on the mta.yaml file -> "Build MTA Project"

then go to mta_archives/<archive name>.tar right click and "Deploy MTA Project".

BTP Steps

To connect to the app from the shell plugin you need to create a SAP BTP Destination, 

to do so go to <BTP Subaccount> -> Cloud Foundry -> <Your space> -> <Your app name>-srv and copy it's address, that's your destination URL

Screenshot 2025-07-17 at 13.09.47.png

Now you need to get the authentication data for the Destination

Go to <Your CF Space> -> Instances -> <Your app name>-auth -> <Your app name>-auth-key 

Screenshot 2025-07-17 at 13.10.05.png

Copy these:

Client ID, Client secret and url (Access Token URL)

Now go back to your Subaccount and create a new destination with your data:

  • URL:  app-srv URL
  • Authentication: OAuth2ClientCredentials
  • ClientID: ClientID
  • Client secret: Client secret
  • Token service URL type: Dedicated
  • Token Service URL: <Access token URL>/oauth/token

After this add these 2 parameters:

  • HTML5.DynamicDestination: true
  • WebIDEEnabled: true

With this step is the backend development concluded.

Shell Plugin Development:

Firstly a general explanation about shell plugins. Shell Plugins are UI5 Applications that allow to add new Elements to SAP Build Work Zone/Fiori Launchpad like Headers, Footers, menu items etc.

To create a shell plugin generate a plain UI5 Basic Freestyle application with the "Template Wizard" in Business Application Studio.

There are a couple of things to modify in the manifest.json to make a a Shell Plugin:

Inside sap.app change the type to component:

"type": "component"

In sap.app>crossNavigation hide the launcher:

"crossNavigation": {
      "inbounds": {
        "Shell-plugin": {
          "semanticObject": "Shell",
          "action": "plugin",
          "title": "{{Shell-plugin.flpTitle}}",
          "hideLauncher": true,
          "icon": "",
          "signature": {
            "parameters": {},
            "additionalParameters": "allowed"
          }
        }
      }
    },

 Add this part under after sap.cloud:

"sap.flp": {
    "type": "plugin"
  }

  This way the Shell Plugin configuration is completed, now let's add our newly created Destination

in sap.app>dataSources add this:

"NotificationService": {
        "uri": "/ShellNotifications/odata/v4/notification/",
        "type": "OData",
        "settings": {
          "odataVersion": "4.0"
        }
      }

and in sap.ui5>models: 

"Notification": {
        "dataSource": "NotificationService",
        "settings": {
          "synchronizationMode": "None",  
          "operationMode": "Server",
          "autoExpandSelect": true
        },
        "type": "sap.ui.model.odata.v4.ODataModel"
      }

and as last thing add this route to your xs-app.json file:

 

Spoiler
Remember: the order of the routes in xs-app matters, if you add it at the end it might not be resolved correctly by the app router

 

{
      "source": "^/ShellNotifications/(.*)$",
      "destination": "ShellNotifications",
      "target": "$1",
      "authenticationType": "xsuaa",
      "csrfProtection": true
    },

Now finally you can add the code that displays the notifications, to do so open the Component.js file and add the following code to the init method:

const oModel = this.getModel("Notification");

            oModel.bindList("/Notification").requestContexts().then((aContexts) => {
                const aData = aContexts.map(oContext => oContext.getObject());
                for (const el of aData) {
                    const nType = el["type"];
                    const nTitle = el["title"];
                    const nMessage = el["message"]
                    if (nType === "Information") {
                        MessageBox.information(nMessage, {
                            title: nTitle
                        });
                    } else if (nType === "Alert") {
                        MessageBox.alert(nMessage, {
                            title: nTitle
                        })
                    } else if (nType === "Confirm") {
                        MessageBox.confirm(nMessage, {
                            title: nTitle
                        })
                    } else if (nType === "Error") {
                        MessageBox.error(nMessage, {
                            title: nTitle
                        })
                    } else if (nType === "Success") {
                        MessageBox.success(nMessage, {
                            title: nTitle
                        })
                    } else if (nType === "Warning") {
                        MessageBox.warning(nMessage, {
                            title: nTitle
                        })
                    }
                }
            }).catch((err) => {
                console.error("Failed to load notifications:", err);
            });

 And like this is the development finished, the last step is to deploy it and add to WorkZone.

To build it do the same steps as with the MTA app:

  • right click on the mta.yaml file -> "Build MTA Project"
  • go to mta_archives/<archive name>.tar right click and "Deploy MTA Project".

SAP Build Work Zone Steps

Although the SAP Build Work Zone standard and advanced edition have some UI differences, the steps are the same for both of them.

All the steps performed below are done on SAP Build Work Zone advanced edition.

Start by going to the Administration Console -> External Integration -> Business Content -> Content Manager

f.drawio copy.png

 Than open the content channel and update the "HTML5 Apps"

f.drawio.png

 After that go Content Explorer and click Content Explorer (In the current UI it's a button in the header)

f.drawio copy 2.png

Select "HTML5 Apps" and add the new Shell Plugin that you just created

f.drawio copy 3.png

 To be able to see the plugin, assign it to a role, in my case it's the "Everyone" role, you can find it in the Content Manager

f.drawio copy 4.png

 After you've done that you should be able to see your new shell plugin the SAP Build Work Zone's launchpad

f.drawio copy 5.png

 If you don't see it try to open the page in an "Anonymous" Tab and check the developer console

Conclusion

What we’ve built here is just a glimpse into what’s possible with shell plugins in SAP Build Work Zone. By integrating a custom notification system, we’ve shown how easily you can extend the platform to better fit your customers’ needs. But this is only the starting point.

There’s a wide range of enhancements you can explore next—such as targeting specific users with personalized notifications, adding actionable buttons to each alert, or even integrating with external systems to trigger real-time messages. The flexibility of shell extensions offers endless opportunities to enrich the Work Zone experience and tailor it to your organization’s workflows.

So go ahead—experiment, extend, and elevate your Work Zone.

 

5 Comments
Labels in this area