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 tuile | Description | Source de données |
|---|---|---|
| Static Tile | Titre et icône fixes | Aucune |
| Dynamic Tile | Indicateur en direct avec tendance | Service OData |
| News Tile | Fil d’actualités avec images | Service OData |
| Custom Tile | Implémentation UI5 libre | Au choix |
| KPI Tile | KPI Smart Business | Framework 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 : TravelAction : manageTuile : - Titre : Gérer les voyages - Sous-titre : Travel Management - Icône : sap-icon://flight - Info : TransactionnelNavigation entrante dans l’application
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 ouvertesgroup by statusVersion 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 : TaskAction : manageConfiguration 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 : InfoChamps de tuile dynamique
| Champ | Description | Exemple |
|---|---|---|
Number | Indicateur principal | 42 |
NumberUnit | Unité | ”EUR”, “Tâches” |
NumberFactor | Échelle | ”k”, “M”, “B” |
NumberDigits | Décimales | 0, 1, 2 |
NumberState | Couleur | ”Good”, “Critical”, “Neutral” |
StateArrow | Flèche de tendance | 1=up, 0=none, -1=down |
Info | Info supplémentaire | ”+5% vs. année préc.” |
InfoState | Couleur 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_dateorder by published_at descendingConfiguration 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 :
- Créer des Apps (lier le Service Binding)
- Créer des Catalogs (grouper les applications)
- Définir des Groups (groupes visibles dans le Launchpad)
- 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_EXTENSIBLEdefine 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 :
- Clic droit sur Service Definition → New Service Binding
- Binding Type : OData V4 - UI
- Activer et tester l’URL
Étape 6 : Configuration Launchpad
Configurer la tuile dans le Launchpad Content Manager :
| Paramètre | Valeur |
|---|---|
| Type de tuile | Dynamic |
| URL de service | /sap/opu/odata4/sap/zsb_po_kpi/srvd/sap/zsb_po_kpi/0001/ |
| Entity Set | ZC_OpenPurchaseOrdersKPI |
| Number Property | Number |
| Number Unit | NumberUnit |
| Number State | NumberState |
| State Arrow | StateArrow |
| Info | Info |
| Intervalle d’actualisation | 30 (secondes) |
Intervalle d’actualisation et performances
Recommandations
| Cas d’usage | Intervalle d’actualisation |
|---|---|
| Indicateurs temps réel | 10-30 secondes |
| KPI standards | 60-300 secondes |
| Valeurs quotidiennes | 900+ secondes |
| Données statiques | Manuel |
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 : PurchaseOrderActions : - manage → Application principale - display → Affichage uniquement - create → Saisie rapide - approve → Application d'approbation - kpi → Tableau de bord2. Choisir correctement les types de tuiles
| Scénario | Type de tuile |
|---|---|
| Application sans données en direct | Static |
| Indicateur unique avec tendance | Dynamic |
| Fil d’actualités | News |
| Visualisation complexe | Custom (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
| NumberState | Signification | Couleur |
|---|---|---|
| Good | Positif | Vert |
| Neutral | Normal | Gris |
| Critical | Attention | Rouge |
| Error | Erreur | Rouge (foncé) |
Erreurs fréquentes
| Problème | Cause | Solution |
|---|---|---|
| Tuile vide | Service non accessible | Activer le Service Binding |
| ”No data” | Mauvais Entity Set | Vérifier l’Entity Set dans Target Mapping |
| Pas d’actualisation | Intervalle = 0 | Définir l’intervalle d’actualisation |
| Tuile non visible | Pas d’autorisation | Attribuer le catalogue Business |
| Mauvais indicateur | Mapping de propriété incorrect | Vérifier les noms de champs dans la configuration |
Sujets connexes
- Services OData - Service Binding et bases OData
- Catalogues IAM Business - Gestion des autorisations pour tuiles
- SAP Fiori Elements - Génération UI avec annotations
- Fiori Overview Page (OVP) - Tableaux de bord basés sur des cartes
Résumé
Les tuiles Fiori Launchpad offrent différentes possibilités de navigation vers les applications :
| Aspect | Tuile statique | Tuile dynamique |
|---|---|---|
| Données en direct | Non | Oui |
| Service OData | Pas nécessaire | Requis |
| Complexité | Faible | Moyenne |
| Cas d’usage | Navigation simple | KPI, indicateurs |
Implémentation de base :
- Vue CDS ou entité personnalisée pour données KPI
- Service Definition et Service Binding (OData V4)
- Target Mapping dans le Launchpad Content Manager
- 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.