
BTP - Dynamic Tile Service
Wie kannst du dein Dynamic Tile mit weiteren Informationen anreichern und auch nicht übersetzbare Bestandteile trotzdem übersetzen? Gehen wir mit einem Beispiel in die Analyse und wie du mehr daraus machen kannst.
Inhaltsverzeichnis
In diesem Artikel schauen wir uns die Konfiguration des Dynamic Tiles an und wie du zur Laufzeit noch weitere Eigenschaften anpassen kannst.
Einleitung
Vor einer Weile hatten wir uns verschiedene Kacheln angeschaut und wie du sie mit dem App Descriptor Item im System konfigurieren kannst. In diesem Artikel schauen wir uns an, wie du mit einer zusätzlichen Lösung die Kachel weiter dynamisch gestalten kannst und noch einige Texte zusätzlich für den User übersetzen kannst.
Herausforderung
Im Moment haben wir eine zusätzliche Kachel angelegt, die sich aus dem Launchpad App Descriptor Item bedient und die Anzahl der Partner im System anzeigt. Dabei haben wir auch eine Einheit hinterlegt. Leider wirst du die Einheit nicht unter den übersetzbaren Elementen des Systems finden, wenn du in die "Maintain Translations" App schaust. Daher würde die Einheit in jeder Sprache erst einmal gleich aussehen.
Lösung
Daher schauen wir uns in diesem Kapitel einmal eine mögliche Lösung an und versuchen sie möglichst wiederverwendbar zu gestalten. Dabei machen wir uns zu Nutzen, dass das Dynamic Tile nicht nur auf die Zahl reagiert, die wir über den Service zurückgeben, sondern auch auf eine mögliche JSON Payload.
Konfiguration
Daher verwenden wir einen Service Endpunkt, der ein JSON zurückgibt, womit wir eine bessere und dynamische Konfiguration erreichen können. Weitere Informationen zum Aufbau der Payload findest du unten in der SAP Help Dokumentation, auch zu den möglichen Werten.
HTTP Service
Damit wir einen möglichst frei konfigurierbaren Endpunkt haben, verwenden wir einen HTTP Service im System. Darüber können wir flexibel steuern, welche Struktur und welche Informationen wir zurückgeben möchten. Der Endpunkt erzeugt eine URL im System, wovon wir nur den ersten Teil benötigen, wie im Screenshot markiert.
Weiterhin passen wir die Kachel Konfiguration an und ändern die "Service URL" auf unseren Endpunkt. Wie du im Bild sehen kannst, haben wir hinter dem Endpunkt noch den Pfad ergänzt, diesen wollen wir verwenden, um die eigentliche Kachel im Coding auszusteuern und so den Service wiederzuverwenden.
Implementierung
Im Grunde wollen wir nun über den Endpunkt das JSON erzeugen und es dem Aufrufer zurückgeben, damit wir die Kachel dynamisch anpassen und überschreiben können. Da wir den Service aber wiederverwendbar machen wollen, müssen wir etwas mehr Logik implementieren. Dazu übernehmen wir im ersten Schritt den Pfad aus dem Header.
request->get_header_field( `~path` )
Danach können wir den Pfad zerlegen, um an das letzte Element zu kommen. Dieses wollen wir dann für die Klassifizierung der Kachel nutzen. Dazu verwenden wir die XCO Bibliotheken, sodass wir am Ende die Konfiguration in Großbuchstaben haben.
DATA(parts) = xco_cp=>string( path )->split( `/` )->value.
DATA(last_part) = parts[ lines( parts ) ].
DATA(endpoint) = to_upper( last_part ).
Zur Sicherheit sollten wir natürlich validieren, ob der Teil zum Beispiel nur aus erlaubten Zeichen besteht. Hierzu prüfen wir den Endpunkt auf alle lateinischen Großbuchstaben, Zahlen und Unterstriche, die in ABAP Objekten erlaubt sind.
DATA(regex) = `^[A-Z0-9_]+$`.
RETURN xco_cp=>regular_expression( iv_value = regex
io_engine = xco_cp_regular_expression=>engine->pcre( )
)->matches( endpoint ).
Um die Arbeit etwas leichter zu machen, definieren wir ein Interface, dass jede Konfiguration erhalten soll. In dem Interface definieren die mögliche Konfiguration, unser Ziel-JSON und eine Hilfskonstanten für die Formatierung einiger Werte im Service.
INTERFACE zif_bs_demo_tilec
PUBLIC.
TYPES:
BEGIN OF configuration,
title TYPE string,
subtitle TYPE string,
icon TYPE string,
info TYPE string,
info_state TYPE string,
number TYPE p LENGTH 15 DECIMALS 4,
number_digits TYPE i,
number_factor TYPE string,
number_state TYPE string,
number_unit TYPE string,
state_arrow TYPE string,
END OF configuration.
CONSTANTS:
BEGIN OF info_state,
negative TYPE string VALUE `Negative`,
neutral TYPE string VALUE `Neutral`,
positive TYPE string VALUE `Positive`,
critical TYPE string VALUE `Critical`,
END OF info_state.
CONSTANTS:
BEGIN OF number_state,
none TYPE string VALUE `None`,
error TYPE string VALUE `Error`,
neutral TYPE string VALUE `Neutral`,
good TYPE string VALUE `Good`,
critical TYPE string VALUE `Critical`,
END OF number_state.
CONSTANTS:
BEGIN OF arrow_state,
none TYPE string VALUE `None`,
up TYPE string VALUE `Up`,
down TYPE string VALUE `Down`,
END OF arrow_state.
METHODS get_configuration
RETURNING VALUE(result) TYPE configuration.
ENDINTERFACE.
Im nächsten Schritt versuchen wir dann für den Endpunkt die passende Klasse zu laden. Dazu bedienen wir uns einer generischen Implementierung über das Interface. Dazu setzen wir den Namen der Klasse zusammen und versuchen dann ein Objekt zu erzeugen, um die Methode GET_CONFIGURATION zu rufen. Sollte das fehlschlagen, geben wir eine leere Konfiguration zurück, damit bleibt die Kachel bis auf die Anzahl im Standard.
DATA config_handler TYPE REF TO zif_bs_demo_tilec.
DATA(class_name) = |ZCL_BS_DEMO_TILEC_{ endpoint }|.
TRY.
CREATE OBJECT config_handler TYPE (class_name).
RETURN config_handler->get_configuration( ).
CATCH cx_root.
RETURN.
ENDTRY.
In der Implementierung müssen wir dann noch die Anzahl ermitteln, dies machen wir am besten über den gleichen Core Data Service wie bisher. Da wir über unseren User angemeldet sind, ziehen auch die gleichen Berechtigungen und die Anfrage sollte uns die gleichen Ergebnisse liefern. Dann können wir die weiteren Attribute in der Konfiguration setzen, wie zum Beispiel den Titel, Untertitel und ein neues Icon. Grundsätzlich können wir auch verschiedene Farben auf der Kachel setzen, zum Beispiel für die Nummer, die Info oder hinter der Zahl einen Pfeil ergänzen.
SELECT FROM ZBS_C_RAPPartner
FIELDS COUNT( * ) AS number
INTO @DATA(total_partner_number).
RETURN VALUE #( title = 'Partner'
subtitle = 'Dynamically loaded ...'
icon = 'sap-icon://general-leave-request'
info = ''
info_state = zif_bs_demo_tilec=>info_state-neutral
number = total_partner_number
number_digits = 0
number_factor = ''
number_state = zif_bs_demo_tilec=>number_state-good
number_unit = 'Custom Unit'
state_arrow = zif_bs_demo_tilec=>arrow_state-up ).
Zum Abschluss konvertieren wir die Struktur dann nach JSON, dazu verwenden wir wieder eine XCO Klasse und die camelCase Konvertierung. Damit gibt der HTTP Service ein JSON zurück. Nicht vergessen auch den Content-Type für die Rückgabe zu setzen, damit der Aufrufer weiß, was er von dir erhält.
RETURN xco_cp_json=>data->from_abap( configuration )->apply(
VALUE #( ( xco_cp_json=>transformation->underscore_to_camel_case ) )
)->to_string( ).
Aktualisieren wir die Kachel und schauen uns das Ergebnis im Launchpad an, dann wurden die Elemente entsprechend ausgetauscht durch unsere neuen Werte. Damit haben wir die volle Kontrolle über die Anzeige auf der Kachel. Allerdings solltest du deinen Anwender nicht all zu sehr verwirren, wenn die Konfiguration die komplette Kachel verändert und die korrekte Anwendung nicht mehr auffindbar ist. Bei dieser Methode geht es um das Überschreiben von Informationen, lässt du also ein Feld leer, dann wird der Standard der Kachel Konfiguration verwendet.
Die Texte kannst du nun Text-Symbolen zuweisen und normal in ABAP übersetzen, um so alle Bestandteile der Kachel in deiner Sprache zu haben. Neben normalem Text kannst du nun auch die Emoji-Apokalypse über dein Launchpad bringen, solltest du aber aus Best-Practice Gesichtspunkten nicht machen.
Sicherheit
Bei dieser Methode stellen wir einen Service zur Verfügung, der generisch ist und von allen berechtigten Usern verwendet werden kann. Daher solltest du einige Dinge in Richtung Sicherheit bedenken:
- HTTP Service - Grundsätzlich sollteste du alle Inputs prüfen, bevor du sie in der Verarbeitung verwendest. Ein Angreifer kann über die verschiedenen Methoden und Parameter dir alles ins Backend schicken.
- Daten - Verwende für die Zahlen und Summen nur Informationen, wo du vorher eine Berechtigungsprüfung auf Ebene des Users gemacht hast und sich dieser auch authentifiziert hat.
Wieso verwenden wir eigentlich einen HTTP Service? Wir hatten es vorher mit einer Custom Entity probiert, die im gleichen Service war. Allerdings funktionierte hier schon nicht die Benennung eines Feldes mit "number" und die Erzeugung der Struktur wie sie der Endpunkt benötigt. Daher haben wir uns für eine flexiblere Art entschieden.
Vollständiges Beispiel
Das komplette Beispiel findest du dabei bei uns im GitHub Repository und kannst zusätzlich über diesen Commit die Änderungen nachvollziehen.
Fazit
Mit der heute gezeigten Methode kannst du noch mehr Informationen aus deiner dynamischen Kachel im ABAP Environment holen. Neben der Übersetzbarkeit können wir so auch mit den Zahlen, Farben und Texten spielen. Damit sollte die maximale Flexibilität zur Laufzeit möglich sein.




