Tuiles personnalisées Fiori Launchpad : Créer ses propres tuiles avec données en direct

Catégorie
Fiori
Publié
Auteur
Johannes

Les tuiles Fiori Launchpad sont le point d’entrée de vos applications. En plus des tuiles statiques simples, vous pouvez créer des tuiles dynamiques avec données en direct qui affichent des indicateurs directement sur le Launchpad. Cet article présente tous les types de tuiles et leur implémentation dans ABAP Cloud.

Vue d’ensemble des types de tuiles

Le Fiori Launchpad prend en charge différents types de tuiles :

Type de tuileDescriptionSource de données
Static TileTitre et icône fixesAucune
Dynamic TileIndicateur en direct avec tendanceService OData
News TileFil d’actualités avec imagesService OData
Custom TileImplémentation UI5 libreAu choix
KPI TileKPI Smart BusinessFramework KPI

Tuiles statiques

Les tuiles statiques sont la forme la plus simple - une icône, un titre et un sous-titre optionnel.

Quand utiliser ?

  • Navigation simple vers une application sans données en direct
  • Applications de configuration
  • Documentation et liens d’aide

Configuration Target Mapping

La configuration de la tuile s’effectue via le Target Mapping dans le Fiori Launchpad Designer ou via le SAP Fiori Launchpad Content Manager.

Objet sémantique : Travel
Action : manage
Tuile :
- Titre : Gérer les voyages
- Sous-titre : Travel Management
- Icône : sap-icon://flight
- Info : Transactionnel

Dans l’application UI5 (manifest.json), vous définissez l’inbound :

{
"sap.app": {
"id": "ztravel.manage",
"crossNavigation": {
"inbounds": {
"Travel-manage": {
"semanticObject": "Travel",
"action": "manage",
"title": "{{appTitle}}",
"subTitle": "{{appSubTitle}}",
"icon": "sap-icon://flight",
"signature": {
"parameters": {},
"additionalParameters": "allowed"
}
}
}
}
}
}

Tuiles dynamiques - Afficher des données en direct

Les tuiles dynamiques affichent des indicateurs actuels directement sur le Launchpad. Les données sont chargées via un service OData.

Architecture

┌─────────────────────────────────────────────────────────────────────┐
│ Fiori Launchpad │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Tuile dynamique │ │ Tuile dynamique │ │ Tuile statique │ │
│ │ │ │ │ │ │ │
│ │ 42 │ │ € 125k │ │ ┌────────┐ │ │
│ │ Tâches ouvertes│ │ Ventes T1 │ │ │ Icône │ │ │
│ │ ↑ +5 │ │ ↓ -3% │ │ └────────┘ │ │
│ └────────┬─────────┘ └────────┬─────────┘ └──────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ Requête OData Requête OData │
│ │ │ │
└───────────┼─────────────────────┼────────────────────────────────────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Vue CDS │ │ Vue CDS │
│ ZI_TaskKPI │ │ ZI_SalesKPI │
└─────────────┘ └─────────────┘

Vue CDS pour tuile dynamique

La base est une vue CDS avec une seule entité qui fournit les données de la tuile :

@EndUserText.label: 'KPI tâches ouvertes pour tuile"
@ObjectModel.representativeKey: 'TileId"
@ObjectModel.semanticKey: ['TileId']
define view entity ZI_OpenTasksKPI
as select from ztasks
{
-- Clé factice (un seul enregistrement)
key 1 as TileId,
-- Nombre de tâches ouvertes
@EndUserText.label: 'Tâches ouvertes"
cast( count(*) as abap.int4 ) as Number,
-- Unité (optionnel)
@EndUserText.label: 'Unité"
cast( 'Tâches' as abap.char(10) ) as NumberUnit,
-- Info de statut
@EndUserText.label: 'Info"
cast( 'Actuel' as abap.char(20) ) as Info,
-- Tendance : Comparaison avec hier
@EndUserText.label: 'Tendance"
case
when count(*) > (
select count(*) from ztasks as t2
where t2.created_at < @( cl_abap_context_info=>get_system_date( ) )
and t2.status = 'O"
)
then cast( 'Up' as abap.char(10) )
else cast( 'Down' as abap.char(10) )
end as NumberTrend,
-- Flèche de tendance (1=up, 0=none, -1=down)
@EndUserText.label: 'Flèche d''état"
case
when count(*) > (
select count(*) from ztasks as t2
where t2.created_at < @( cl_abap_context_info=>get_system_date( ) )
and t2.status = 'O"
)
then 1
else -1
end as StateArrow
}
where
status = 'O' -- Uniquement tâches ouvertes
group by
status

Version simplifiée avec entité personnalisée

Pour des calculs plus complexes, utilisez une entité personnalisée :

@EndUserText.label: 'KPI ventes pour tuile dynamique"
@ObjectModel.query.implementedBy: 'ABAP:ZCL_SALES_KPI_QUERY"
define custom entity ZC_SalesKPI
{
key TileId : abap.int4;
Number : abap.dec(15,2);
NumberUnit : abap.char(10);
NumberFactor : abap.char(10);
NumberDigits : abap.int4;
NumberState : abap.char(20);
StateArrow : abap.int1;
Info : abap.char(30);
InfoState : abap.char(20);
TargetNumber : abap.dec(15,2);
Subtitle : abap.char(50);
}

Implémentation de requête

CLASS zcl_sales_kpi_query DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_rap_query_provider.
ENDCLASS.
CLASS zcl_sales_kpi_query IMPLEMENTATION.
METHOD if_rap_query_provider~select.
" Calculer le chiffre d'affaires
SELECT SUM( amount ) AS total_sales
FROM zsales
WHERE fiscal_year = @( substring( cl_abap_context_info=>get_system_date( ), 1, 4 ) )
INTO @DATA(lv_current_sales).
" Chiffre d'affaires année précédente
SELECT SUM( amount ) AS total_sales
FROM zsales
WHERE fiscal_year = @( substring( cl_abap_context_info=>get_system_date( ), 1, 4 ) - 1 )
INTO @DATA(lv_last_year_sales).
" Calculer la tendance
DATA(lv_trend) = COND i(
WHEN lv_current_sales > lv_last_year_sales THEN 1
WHEN lv_current_sales < lv_last_year_sales THEN -1
ELSE 0 ).
" Changement en pourcentage
DATA(lv_change_pct) = COND decfloat34(
WHEN lv_last_year_sales > 0
THEN ( lv_current_sales - lv_last_year_sales ) / lv_last_year_sales * 100
ELSE 0 ).
" Déterminer le statut
DATA(lv_state) = COND string(
WHEN lv_change_pct >= 5 THEN 'Good"
WHEN lv_change_pct >= 0 THEN 'Neutral"
ELSE 'Critical' ).
" Préparer le résultat
DATA(lt_result) = VALUE ztt_sales_kpi(
( TileId = 1
Number = lv_current_sales / 1000 " En milliers
NumberUnit = 'EUR"
NumberFactor = 'k"
NumberDigits = 1
NumberState = lv_state
StateArrow = lv_trend
Info = |{ lv_change_pct DECIMALS = 1 }% vs. année préc.|
InfoState = lv_state
TargetNumber = lv_last_year_sales * '1.05"
Subtitle = |État: { cl_abap_context_info=>get_system_date( ) DATE = USER }| )
).
io_response->set_data( lt_result ).
io_response->set_total_number_of_records( 1 ).
ENDMETHOD.
ENDCLASS.

Service Binding pour tuile dynamique

@EndUserText.label: 'Service de tuiles KPI"
define service ZSB_KPI_TILES {
expose ZI_OpenTasksKPI;
expose ZC_SalesKPI;
}

Target Mapping avec tuile dynamique

Dans le Launchpad Content Manager ou Designer :

Objet sémantique : Task
Action : manage
Configuration de la tuile :
- Type de tuile : Dynamic
- Titre : Tâches ouvertes
- Sous-titre : Task Management
- Icône : sap-icon://task
- URL de service : /sap/opu/odata4/sap/zsb_kpi_tiles/srvd/sap/zsb_kpi_tiles/0001/
- Entity Set : ZI_OpenTasksKPI
- Number : Number
- Number Unit : NumberUnit
- Number State : NumberState
- State Arrow : StateArrow
- Info : Info

Champs de tuile dynamique

ChampDescriptionExemple
NumberIndicateur principal42
NumberUnitUnité”EUR”, “Tâches”
NumberFactorÉchelle”k”, “M”, “B”
NumberDigitsDécimales0, 1, 2
NumberStateCouleur”Good”, “Critical”, “Neutral”
StateArrowFlèche de tendance1=up, 0=none, -1=down
InfoInfo supplémentaire”+5% vs. année préc.”
InfoStateCouleur de l’info”Good”, “Critical”

Tuiles d’actualités

Les tuiles d’actualités affichent un fil avec des images et des descriptions.

Vue CDS pour tuile d’actualités

@EndUserText.label: 'Actualités de l''entreprise pour tuile"
@ObjectModel.semanticKey: ['NewsId']
define view entity ZI_CompanyNews
as select from znews
{
key news_id as NewsId,
@EndUserText.label: 'Titre"
title as Title,
@EndUserText.label: 'Description"
description as Description,
@EndUserText.label: 'URL image"
image_url as ImageUrl,
@EndUserText.label: 'Lien"
link_url as LinkUrl,
@EndUserText.label: 'Date"
published_at as PublishedAt
}
where
published_at <= $session.system_date
order by
published_at descending

Configuration du fil d’actualités

{
"tileType": "sap.ushell.ui.tile.DynamicTile",
"tileConfiguration": {
"semantic_object": "News",
"semantic_action": "display",
"service_url": "/sap/opu/odata4/sap/zsb_news/srvd/sap/zsb_news/0001/",
"service_refresh_interval": 300,
"collection": "ZI_CompanyNews",
"title": "{Title}",
"subtitle": "{Description}",
"imageUrl": "{ImageUrl}",
"targetURL": "{LinkUrl}"
}
}

Target Mapping - Configurer la navigation

Le Target Mapping relie la tuile à l’application cible.

Concept

┌─────────────────────────────────────────────────────────────────────┐
│ Target Mapping │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Objet sémantique : "SalesOrder" │
│ Action : "manage" │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Tuile (Ce que l'utilisateur voit) │ │
│ │ - Titre : "Gérer les commandes" │ │
│ │ - Icône : sap-icon://sales-order │ │
│ │ - Données dynamiques : Service OData │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Cible (Où la navigation mène) │ │
│ │ - Type d'application : SAPUI5 Fiori App │ │
│ │ - URL : /sap/bc/ui5_ui5/sap/zsalesorder_app │ │
│ │ - Paramètres : SalesOrg=1000 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

Launchpad Content Manager

Dans ABAP Cloud, la configuration s’effectue via le SAP Fiori Launchpad Content Manager :

  1. Créer des Apps (lier le Service Binding)
  2. Créer des Catalogs (grouper les applications)
  3. Définir des Groups (groupes visibles dans le Launchpad)
  4. Attribuer des Roles (qui voit quoi)

Configuration programmatique

Pour un déploiement automatisé, vous pouvez exporter la configuration en JSON :

{
"apps": [
{
"id": "ztravel_manage",
"vizId": "Travel-manage",
"vizType": "sap.ushell.StaticAppLauncher",
"title": "Gérer les voyages",
"subTitle": "Travel Management",
"icon": "sap-icon://flight",
"info": "Travel",
"target": {
"type": "URL",
"url": "/sap/bc/ui5_ui5/sap/ztravel_manage/index.html"
}
}
],
"catalogs": [
{
"id": "ZTRAVEL_CATALOG",
"title": "Travel Management",
"apps": ["ztravel_manage", "ztravel_approve"]
}
],
"groups": [
{
"id": "ZTRAVEL_GROUP",
"title": "Gestion des voyages",
"apps": ["ztravel_manage"]
}
]
}

Tuile dynamique avec données en direct - Exemple complet

Étape 1 : Table de base de données

@EndUserText.label: 'Commandes d''achat"
@AbapCatalog.enhancement.category: #NOT_EXTENSIBLE
define table zpurchase_orders {
key client : abap.clnt;
key po_id : abap.numc(10);
vendor_id : abap.numc(10);
amount : abap.curr(15,2);
currency : abap.cuky;
status : abap.char(1); -- O=Open, A=Approved, R=Rejected
created_at : timestampl;
created_by : abap.uname;
}

Étape 2 : Vue CDS KPI

@EndUserText.label: 'KPI commandes ouvertes pour tuile dynamique"
@ObjectModel.query.implementedBy: 'ABAP:ZCL_OPEN_PO_KPI"
define custom entity ZC_OpenPurchaseOrdersKPI
{
key TileId : abap.int4;
Number : abap.int4;
NumberUnit : abap.char(10);
NumberState : abap.char(20);
StateArrow : abap.int1;
Info : abap.char(50);
InfoState : abap.char(20);
Subtitle : abap.char(50);
}

Étape 3 : Implémentation de requête

CLASS zcl_open_po_kpi DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_rap_query_provider.
ENDCLASS.
CLASS zcl_open_po_kpi IMPLEMENTATION.
METHOD if_rap_query_provider~select.
DATA: lv_today TYPE d,
lv_yesterday TYPE d.
lv_today = cl_abap_context_info=>get_system_date( ).
lv_yesterday = lv_today - 1.
" Commandes ouvertes aujourd'hui
SELECT COUNT(*) FROM zpurchase_orders
WHERE status = 'O"
INTO @DATA(lv_open_today).
" Commandes ouvertes hier (instantané)
SELECT COUNT(*) FROM zpurchase_orders
WHERE status = 'O"
AND created_at < @( CONV timestampl( lv_today ) )
INTO @DATA(lv_open_yesterday).
" Différence
DATA(lv_diff) = lv_open_today - lv_open_yesterday.
" Déterminer la tendance
DATA(lv_arrow) = COND i(
WHEN lv_diff > 0 THEN 1 " Plus de commandes ouvertes = mauvais
WHEN lv_diff < 0 THEN -1 " Moins = bon
ELSE 0 ).
" Statut (logique inversée : moins ouvert = bon)
DATA(lv_state) = COND string(
WHEN lv_diff <= 0 THEN 'Good"
WHEN lv_diff <= 5 THEN 'Neutral"
ELSE 'Critical' ).
" Texte d'info
DATA(lv_info) = COND string(
WHEN lv_diff > 0 THEN |+{ lv_diff } depuis hier|
WHEN lv_diff < 0 THEN |{ lv_diff } depuis hier|
ELSE |Inchangé| ).
" Résultat
DATA(lt_result) = VALUE ztt_open_po_kpi(
( TileId = 1
Number = lv_open_today
NumberUnit = 'Cmds"
NumberState = lv_state
StateArrow = lv_arrow
Info = lv_info
InfoState = lv_state
Subtitle = |Commandes ouvertes| )
).
io_response->set_data( lt_result ).
io_response->set_total_number_of_records( 1 ).
ENDMETHOD.
ENDCLASS.

Étape 4 : Définition de service

@EndUserText.label: 'Service KPI commandes d''achat"
define service ZSB_PO_KPI {
expose ZC_OpenPurchaseOrdersKPI;
}

Étape 5 : Créer le Service Binding

Dans ADT :

  1. Clic droit sur Service Definition → New Service Binding
  2. Binding Type : OData V4 - UI
  3. Activer et tester l’URL

Étape 6 : Configuration Launchpad

Configurer la tuile dans le Launchpad Content Manager :

ParamètreValeur
Type de tuileDynamic
URL de service/sap/opu/odata4/sap/zsb_po_kpi/srvd/sap/zsb_po_kpi/0001/
Entity SetZC_OpenPurchaseOrdersKPI
Number PropertyNumber
Number UnitNumberUnit
Number StateNumberState
State ArrowStateArrow
InfoInfo
Intervalle d’actualisation30 (secondes)

Intervalle d’actualisation et performances

Recommandations

Cas d’usageIntervalle d’actualisation
Indicateurs temps réel10-30 secondes
KPI standards60-300 secondes
Valeurs quotidiennes900+ secondes
Données statiquesManuel

Optimisation des performances

METHOD if_rap_query_provider~select.
" Cache pour calculs coûteux
DATA: lv_cache_key TYPE string,
ls_cached TYPE zs_kpi_cache.
lv_cache_key = |PO_KPI_{ sy-datum }|.
" Vérifier le cache (par ex. Shared Memory ou Application Buffer)
IF cache_is_valid( lv_cache_key ).
ls_cached = get_from_cache( lv_cache_key ).
ELSE.
" Effectuer le calcul
ls_cached = calculate_kpi( ).
put_to_cache( lv_cache_key, ls_cached ).
ENDIF.
io_response->set_data( VALUE #( ( ls_cached ) ) ).
ENDMETHOD.

IAM et autorisations

La visibilité des tuiles est contrôlée via les catalogues IAM Business :

Catalogue IAM Business : ZPO_BC_BUYER
├── Application IAM : ZPO_MANAGE (Gérer les commandes)
├── Application IAM : ZPO_KPI (Service de tuile KPI)
└── Type de restriction : ZPO_RT (Unités organisationnelles)

Sans attribution du catalogue Business au rôle Business, la tuile n’est pas visible.

Catalogue pour services KPI

<?xml version="1.0" encoding="utf-8"?>
<iam:catalog
xmlns:iam="http://www.sap.com/iam"
catalogId="ZPO_BC_KPI">
<catalogDescription>Tuiles KPI commandes d'achat</catalogDescription>
<catalogApps>
<iamApp>ZPO_KPI_TILES</iamApp>
</catalogApps>
</iam:catalog>

Bonnes pratiques

1. Nommer les objets sémantiques de manière cohérente

Objet sémantique : PurchaseOrder
Actions :
- manage → Application principale
- display → Affichage uniquement
- create → Saisie rapide
- approve → Application d'approbation
- kpi → Tableau de bord

2. Choisir correctement les types de tuiles

ScénarioType de tuile
Application sans données en directStatic
Indicateur unique avec tendanceDynamic
Fil d’actualitésNews
Visualisation complexeCustom (UI5)

3. Tenir compte des performances

  • Garder les requêtes KPI sous 200ms
  • Effectuer les agrégations au niveau DB
  • Cache pour calculs coûteux

4. Coloration cohérente

NumberStateSignificationCouleur
GoodPositifVert
NeutralNormalGris
CriticalAttentionRouge
ErrorErreurRouge (foncé)

Erreurs fréquentes

ProblèmeCauseSolution
Tuile videService non accessibleActiver le Service Binding
”No data”Mauvais Entity SetVérifier l’Entity Set dans Target Mapping
Pas d’actualisationIntervalle = 0Définir l’intervalle d’actualisation
Tuile non visiblePas d’autorisationAttribuer le catalogue Business
Mauvais indicateurMapping de propriété incorrectVérifier les noms de champs dans la configuration

Sujets connexes


Résumé

Les tuiles Fiori Launchpad offrent différentes possibilités de navigation vers les applications :

AspectTuile statiqueTuile dynamique
Données en directNonOui
Service ODataPas nécessaireRequis
ComplexitéFaibleMoyenne
Cas d’usageNavigation simpleKPI, indicateurs

Implémentation de base :

  1. Vue CDS ou entité personnalisée pour données KPI
  2. Service Definition et Service Binding (OData V4)
  3. Target Mapping dans le Launchpad Content Manager
  4. Catalogue IAM Business pour autorisations

Avec les tuiles dynamiques, vous affichez des indicateurs pertinents directement sur le Launchpad et permettez aux utilisateurs d’obtenir un aperçu rapide des données métier importantes.