Table of Contents

ControlAddIn "Calendar V2 UTCAP"

Namespace: CapVision.Core.Controls

Met à disposition un calendrier pour la planification de tâches (vue Planning d'équipe).

Remarks

Modèle de positionnement

Le calendrier se structure en une grille de PeriodCount périodes (colonnes principales) × SubPeriodCount sous-périodes, soit PeriodCount × SubPeriodCount colonnes au total. Tâches, marqueurs et périodes fermées se placent uniquement par index de colonne (startIndex/endIndex, 0-based, bornes inclusives) — jamais par date ou heure.

La conversion est : index de colonne = indexPériode × SubPeriodCount + indexSousPériode. Le codeunit Calendar Column Math UTCAP fournit ToColumnIndex et les procédures inverses.

SetRenderer est le point d'entrée : chaque appel réinitialise le planning (ressources, tâches, marqueurs, périodes fermées et tooltips sont vidés) puis applique la nouvelle configuration.

Examples

L'exemple ci-dessous affiche un planning d'équipe sur 5 jours × 2 demi-journées (Matin / Après-midi). Pour créer une tâche, double-cliquez sur une cellule vide du calendrier. Vous pouvez déplacer et redimensionner les tâches éditables par glisser-déposer. Un clic droit sur une tâche propose de la supprimer via un menu contextuel.

namespace CapVision.Samples;

using Microsoft.Projects.Resources.Resource;
using System.Utilities;
using CapVision.Core.Controls;

page 50100 "Test Calendar UTCAP"
{
    PageType = Card;
    ApplicationArea = All;
    UsageCategory = Tasks;
    Caption = 'Test Calendar', Locked = true;
    Extensible = false;

    layout
    {
        area(Content)
        {
            usercontrol(Calendar; "Calendar V2 UTCAP")
            {
                trigger OnControlAddInReady()
                begin
                    LoadCalendar();
                end;

                trigger OnCalendarContextMenuRequested(assignedTo: Text; index: Integer)
                var
                    Helper: Codeunit "Calendar Helper V2 UTCAP";
                    ContextMenuItems: JsonArray;
                begin
                    ContextMenuItems.Add(Helper.CreateMenuItem('newTask', 'Créer une tâche', 'New'));
                    CurrPage.Calendar.OpenCalendarContextMenu(assignedTo, index, ContextMenuItems);
                end;

                trigger OnCalendarContextMenuClicked(assignedTo: Text; index: Integer; contextMenuItemId: Text)
                begin
                    if contextMenuItemId = 'newTask' then
                        CreateSampleTask(assignedTo, index);
                end;

                trigger OnCalendarDoubleClicked(assignedTo: Text; index: Integer)
                begin
                    CreateSampleTask(assignedTo, index);
                end;

                trigger OnTaskContextMenuRequested(taskId: Text)
                var
                    Helper: Codeunit "Calendar Helper V2 UTCAP";
                    ContextMenuItems: JsonArray;
                begin
                    ContextMenuItems.Add(Helper.CreateMenuItem('deleteTask', 'Supprimer cette tâche', 'Delete'));
                    CurrPage.Calendar.OpenTaskContextMenu(taskId, ContextMenuItems);
                end;

                trigger OnTaskContextMenuClicked(taskId: Text; contextMenuItemId: Text)
                begin
                    if contextMenuItemId = 'deleteTask' then
                        CurrPage.Calendar.DeleteTask(taskId);
                end;

                trigger OnTaskMoved(taskId: Text; newAssignedTo: Text; newStartIndex: Integer; newEndIndex: Integer)
                begin
                    Message('Task %1 moved to resource %2, columns %3..%4', taskId, newAssignedTo, newStartIndex, newEndIndex);
                end;

                trigger OnTaskClicked(taskId: Text)
                begin
                    Message('Task clicked: %1', taskId);
                end;

                trigger OnResourceClicked(resourceId: Text)
                begin
                    Message('Resource clicked: %1', resourceId);
                end;
            }
        }
    }

    local procedure LoadCalendar()
    var
        Resource: Record Resource;
        Helper: Codeunit "Calendar Helper V2 UTCAP";
        ResourceImage: Codeunit "Temp Blob";
        ResourceImageInStream: InStream;
        ResourceImageOutStream: OutStream;
        Renderer: JsonObject;
        Resources: JsonArray;
        Periods, SubPeriods : List of [Text];
    begin
        // 1. Configure l'affichage (réinitialise le planning).
        Periods.Add('Lundi'); Periods.Add('Mardi'); Periods.Add('Mercredi'); Periods.Add('Jeudi'); Periods.Add('Vendredi');
        SubPeriods.Add('Matin'); SubPeriods.Add('Après-midi');

        Renderer := Helper.CreateTeamPlanRenderer(5, Periods, 2, SubPeriods);
        Helper.SetHeaderColumnWidth(Renderer, 220);
        Helper.SetCollapsedHeaderMaxVisibleRows(Renderer, 2);
        Helper.SetCornerCellText(Renderer, 'Équipe');
        Helper.SetSubPeriodWidth(Renderer, '*');
        CurrPage.Calendar.SetRenderer(Renderer);

        // 2. Publie les ressources.
        if Resource.FindSet() then
            repeat
                Clear(ResourceImage);
                if Resource.Image.HasValue() then begin
                    ResourceImage.CreateOutStream(ResourceImageOutStream);
                    Resource.Image.ExportStream(ResourceImageOutStream);
                end;
                ResourceImage.CreateInStream(ResourceImageInStream);
                Resources.Add(Helper.CreateResource(Resource."No.", Resource.Name, Resource."Job Title", '', ResourceImageInStream));
            until Resource.Next() = 0;
        CurrPage.Calendar.CreateResources(Resources);
    end;

    local procedure CreateSampleTask(ResourceId: Text; ColumnIndex: Integer)
    var
        Helper: Codeunit "Calendar Helper V2 UTCAP";
    begin
        // La tâche est posée dans la seule colonne cliquée (startIndex = endIndex = ColumnIndex).
        CurrPage.Calendar.CreateTask(
            Helper.CreateTask(Format(CreateGuid()), ResourceId, ColumnIndex, ColumnIndex, 'Réunion', 'Salle 1', 'Bâtiment C', 2, true, '#21888c', '#e74c3c'));
    end;
}

Methods

SetRenderer

Définit l'affichage à utiliser. Chaque appel réinitialise le planning (ressources, tâches, marqueurs, périodes fermées et tooltips sont vidés) puis applique la configuration. C'est le point d'entrée : appelez-le en réponse à OnControlAddInReady, puis republiez vos données.

procedure SetRenderer(config: JsonObject)

Parameters

Name Type Description
config JsonObject

Configuration du renderer (voir CreateTeamPlanRenderer).

Examples

Configuration de la vue Planning d'équipe (Team) :

{
    "renderer": 2,                 // 2 = Team (obligatoire pour afficher la vue)
    "options": {
        "Locale": "fr-FR",           // Locale d'affichage, format "xx-XX"
        "PeriodCount": 5,            // Nombre de colonnes principales (fait foi)
        "Periods": ["Lundi","Mardi","Mercredi","Jeudi","Vendredi"], // Libellés par index de période
        "SubPeriodCount": 2,         // Nombre de sous-colonnes par période (fait foi ≥ 1, sert au calcul d'index)
        "SubPeriods": ["Matin","Après-midi"], // Libellés par index. Plus courte → colonnes de fin vides ; plus longue → surplus ignoré. Liste vide (ou tous vides) → colonnes conservées mais ligne des sous-périodes masquée
        "BreakSubPeriods": [1],      // (opt) Index de sous-colonnes de pause (hachurées, non-droppables)
        "SubPeriodsMode": "default", // (opt) "default" (défaut) = alignés par index, sans bouclage (consécutifs identiques fusionnés) | "repeat" = bouclés modulo pour remplir la période (["A","B"]×6 → A B A B A B) | "stretch" = espacés : chaque libellé suivi de ⌈SubPeriodCount÷nbLibellés⌉−1 vides + vides finaux éventuels (4 lbl/10 → X··X··X··X ; /12 → X··X··X··X··). Mutuellement exclusifs. Voir Helper.SetSubPeriodsMode
        "CollapsedHeaderMaxVisibleRows": 2, // (opt) Sous-lignes visibles avant repli
        "RowHeight": "50",           // (opt) Hauteur unitaire d'une ligne — échelle avatar + textes ("50" fixe, "50*" max, "*50" min, "*" remplit)
        "PeriodHeaderHeight": 40,    // (opt) Hauteur (px) de la ligne d'en-tête des périodes
        "PeriodTextOrientation": "horizontal", // (opt) "horizontal" (défaut) ou "vertical" (texte pivoté)
        "CornerCellText": "Équipe",  // (opt) Texte de la cellule du coin haut-gauche
        "HeaderColumnWidth": 220,    // (opt) Largeur de la colonne des ressources (px)
        "SubPeriodWidth": "200*"     // (opt) Largeur d'une sous-colonne ("200" fixe, "200*" max, "*200" min, "*" remplit)
    }
}

Remarks

Actuellement, seule la vue Planning d'équipe (renderer = 2, Team) est rendue. Utilisez Calendar Helper V2 UTCAP.CreateTeamPlanRenderer pour construire la configuration.

CreateTask

Ajoute (ou met à jour) une tâche dans le calendrier.

procedure CreateTask(task: JsonObject)

Parameters

Name Type Description
task JsonObject

Tâche à ajouter.

Examples

La structure d'une tâche est la suivante :

{
    "id": "t1",                    // Identifiant unique de la tâche
    "assignedTo": "r1",            // Identifiant de la ressource (ligne)
    "startIndex": 2,               // Index de colonne de début (0-based) = période × SubPeriodCount + sous-période
    "endIndex": 3,                 // Index de colonne de fin (0-based, inclusif)
    "text": "Réunion",            // (opt) Texte principal
    "secondaryText": "Salle 1",    // (opt) Texte secondaire
    "tertiaryText": "Bâtiment C",  // (opt) Texte tertiaire
    "quantity": 2,                 // (opt) Quantité, nombre OU texte (ex. "1/2") — pastille affichée UNIQUEMENT si ce champ est présent
    "isEditable": true,            // (opt) Autorise le déplacement / redimensionnement
    "startingDateTime": "2026-01-01T08:00:00", // (opt) INFORMATIF — jamais utilisé pour le placement
    "endingDateTime": "2026-01-01T10:00:00",   // (opt) INFORMATIF — idem
    "style": {
        "background": "#21888c",   // (opt) Couleur de fond
        "foreground": "#ffffff",   // (opt) Couleur du texte — imposée ; absente = calculée par contraste
        "borderLeft": "#e74c3c"    // (opt) Couleur de la bordure gauche
    }
}

CreateTasks

Ajoute (ou met à jour) un ensemble de tâches dans le calendrier.

procedure CreateTasks(tasks: JsonArray)

Parameters

Name Type Description
tasks JsonArray

Tableau de tâches à ajouter (voir CreateTask pour la structure de chaque tâche).

DeleteTask

Supprime la tâche spécifiée.

procedure DeleteTask(taskId: Text)

Parameters

Name Type Description
taskId Text

Identifiant de la tâche à supprimer.

DeleteTasks

Supprime les tâches spécifiées.

procedure DeleteTasks(tasks: JsonArray)

Parameters

Name Type Description
tasks JsonArray

Tableau des identifiants de tâches à supprimer.

CreateResource

Ajoute (ou met à jour) une ressource dans le calendrier.

procedure CreateResource(resource: JsonObject)

Parameters

Name Type Description
resource JsonObject

Ressource à ajouter.

Examples

La structure d'une ressource est la suivante :

{
    "id": "r1",                    // Identifiant unique de la ressource
    "name": "Emilie Dupont",       // Nom de la ressource
    "description": "Technicienne", // (opt) Description
    "imageColor": "#ffd574",       // (opt) Couleur de l'anneau autour de l'image
    "image": "iVBORw...",          // (opt) Image encodée en Base64 (sans le préfixe data:)
    "nameColor": "#d33",           // (opt) Couleur du nom
    "collapsed": false             // (opt) Indique si la ressource est repliée
}

Remarks

Renvoyer une ressource déjà connue (même id) met à jour ses champs ; les champs optionnels absents restent inchangés.

CreateResources

Ajoute (ou met à jour) des ressources dans le calendrier.

procedure CreateResources(resources: JsonArray)

Parameters

Name Type Description
resources JsonArray

Tableau de ressources à ajouter (voir CreateResource pour la structure de chaque ressource).

DeleteResource

Supprime la ressource spécifiée.

procedure DeleteResource(id: Text)

Parameters

Name Type Description
id Text

Identifiant de la ressource à supprimer du calendrier.

DeleteResources

Supprime les ressources spécifiées du calendrier.

procedure DeleteResources(resources: JsonArray)

Parameters

Name Type Description
resources JsonArray

Tableau des identifiants de ressources à supprimer.

CreateMarker

Créé (ou met à jour) un marqueur sur le calendrier.

procedure CreateMarker(marker: JsonObject)

Parameters

Name Type Description
marker JsonObject

Marqueur à ajouter.

Examples

La structure d'un marqueur est la suivante :

{
    "id": "mk1",                   // Identifiant unique du marqueur
    "anchorType": "cell",          // Type d'ancrage. Seul "cell" est rendu actuellement.
    "assignedTo": "r1",            // Ressource (ligne) sur laquelle poser le marqueur
    "startIndex": 3,               // Index de colonne de début (0-based)
    "endIndex": 8,                 // Index de colonne de fin (0-based, inclusif)
    "shape": "line",               // "line" (bande hachurée) ou "triangle" (repère par cellule)
    "title": "Indisponible",       // (opt) Texte affiché au survol
    "style": {
        "color1": "#f1c40f",       // (opt) Couleur principale
        "color2": "#000"           // (opt) Couleur secondaire (hachuré alterné pour "line")
    }
}

Pour shape = line, le marqueur couvre une bande contiguë sur toute la plage de colonnes (peut traverser plusieurs périodes). Pour shape = triangle, un triangle est affiché par cellule de la plage.

CreateMarkers

Créé (ou met à jour) les marqueurs sur le calendrier.

procedure CreateMarkers(markers: JsonArray)

Parameters

Name Type Description
markers JsonArray

Tableau de marqueurs à ajouter (voir CreateMarker pour la structure de chaque marqueur).

DeleteMarkers

Supprime tous les marqueurs du calendrier.

procedure DeleteMarkers()

CreateClosedPeriod

Créé (ou met à jour) une période fermée (férié, absence) : une bande hachurée et grisée, superposée à la grille sans empêcher le placement d'activités.

procedure CreateClosedPeriod(period: JsonObject)

Parameters

Name Type Description
period JsonObject

Période fermée à ajouter.

Examples

La structure d'une période fermée est la suivante :

{
    "id": "cp1",                   // Identifiant unique de la période fermée
    "startIndex": 4,               // Index de colonne de début (0-based, inclusif)
    "endIndex": 5,                 // Index de colonne de fin (0-based, inclusif)
    "assignedTo": "r4",            // (opt) Vide = toutes les ressources ; renseigné = une seule
    "text": "Férié",              // (opt) Tooltip
    "style": {
        "color1": "#e84393",       // (opt) Couleur principale du hachuré
        "color2": "#fff"           // (opt) Couleur secondaire du hachuré
    }
}

CreateClosedPeriods

Créé (ou met à jour) des périodes fermées sur le calendrier.

procedure CreateClosedPeriods(periods: JsonArray)

Parameters

Name Type Description
periods JsonArray

Tableau de périodes fermées à ajouter (voir CreateClosedPeriod pour la structure).

DeleteClosedPeriod

Supprime la période fermée spécifiée.

procedure DeleteClosedPeriod(id: Text)

Parameters

Name Type Description
id Text

Identifiant de la période fermée à supprimer.

DeleteClosedPeriods

Supprime les périodes fermées spécifiées.

procedure DeleteClosedPeriods(periods: JsonArray)

Parameters

Name Type Description
periods JsonArray

Tableau des identifiants de périodes fermées à supprimer.

SetTaskTooltip

Définit l'info-bulle pour une tâche.

procedure SetTaskTooltip(taskTooltip: JsonObject)

Parameters

Name Type Description
taskTooltip JsonObject

Info-bulle à lier à une tâche.

Examples

Structure d'une info-bulle :

{
    "id": "t1",                    // Identifiant de la tâche à laquelle lier l'info-bulle
    "content": "<b>Réunion</b>", // Contenu HTML libre de l'info-bulle
    "cssClass": ""                 // (opt) Classe CSS additionnelle
}

Remarks

Vous ne pouvez pas appeler cette méthode pour une tâche qui n'existe pas. Usage recommandé : en réponse à OnTaskTooltipRequested (chargement à la demande, au survol). Le contenu HTML est injecté tel quel (source de confiance = BC) : n'y concaténez jamais d'entrée utilisateur non échappée.

SetTasksTooltip

Définit l'info-bulle à afficher pour un ensemble de tâches.

procedure SetTasksTooltip(taskTooltips: JsonArray)

Parameters

Name Type Description
taskTooltips JsonArray

Tableau d'info-bulles (voir SetTaskTooltip pour le format d'une info-bulle).

Remarks

Vous ne pouvez pas appeler cette méthode pour des tâches qui n'existent pas.

OpenTaskContextMenu

Ouvre un menu contextuel sur une tâche. Cette méthode est généralement appelée en réaction à l'événement OnTaskContextMenuRequested.

procedure OpenTaskContextMenu(taskId: Text; items: JsonArray)

Parameters

Name Type Description
taskId Text

Identifiant de la tâche pour laquelle ouvrir le menu. Il sera réutilisé par OnTaskContextMenuClicked.

items JsonArray

Liste des entrées du menu contextuel à afficher (voir OpenCalendarContextMenu pour le format d'une entrée).

OpenTasksContextMenu

Ouvre un menu contextuel pour PLUSIEURS tâches (multi-sélection). Cette méthode est généralement appelée en réaction à l'événement OnTasksContextMenuRequested.

procedure OpenTasksContextMenu(taskIds: JsonArray; items: JsonArray)

Parameters

Name Type Description
taskIds JsonArray

Identifiants des tâches pour lesquelles ouvrir le menu. Ils seront réutilisés par OnTasksContextMenuClicked.

items JsonArray

Liste des entrées du menu contextuel à afficher (voir OpenCalendarContextMenu pour le format d'une entrée).

OpenCalendarContextMenu

Déclenche l'ouverture du menu contextuel sur une cellule. Cette méthode est généralement appelée en réaction à l'événement OnCalendarContextMenuRequested.

procedure OpenCalendarContextMenu(assignedTo: Text; index: Integer; items: JsonArray)

Parameters

Name Type Description
assignedTo Text

Ressource (ligne) pour laquelle le menu doit être ouvert.

index Integer

Index de colonne (0-based) pour lequel le menu doit être ouvert.

items JsonArray

Liste des entrées du menu contextuel à afficher.

Examples

Structure d'une entrée de menu contextuel :

{
    "id": "delete",                // Identifiant de l'entrée
    "caption": "Supprimer",        // Texte de l'entrée. Un tiret (-) affiche un séparateur.
    "image": "Delete",             // (opt) Nom de l'icône (Office UI Fabric Icons — https://uifabricicons.azurewebsites.net/)
    "shortcut": "Ctrl+Suppr",      // (opt) Raccourci affiché
    "dangerous": true,             // (opt) Style « action dangereuse » (rouge)
    "subActions": [ /* entrées de sous-menu */ ]  // (opt)
}

ExportToPDF

Demande au calendrier d'exporter le planning au format PDF (vectoriel), avec les options par défaut (une seule page dimensionnée au contenu ; ressources sans activité retirées). Le document généré est automatiquement téléchargé sur le poste de l'utilisateur.

procedure ExportToPDF()

Remarks

Le PDF est reconstruit VECTORIELLEMENT à partir du modèle (aucune rastérisation, aucune librairie) : rendu net à toute échelle, fichier léger. Export PDF uniquement.

ExportToPDF

Demande au calendrier d'exporter le planning au format PDF (vectoriel), avec options. Le document généré est automatiquement téléchargé sur le poste de l'utilisateur.

procedure ExportToPDF(fullView: Boolean; includeAll: Boolean; paged: Boolean)

Parameters

Name Type Description
fullView Boolean

Réservé : true = tout le planning, false = vue courante. Non encore exploité (le PDF reprend l'intégralité du planning courant).

includeAll Boolean

true = conserve dans le PDF les ressources sans aucune activité ; false = ces ressources sont retirées.

paged Boolean

true = pages A4 paysage découpées (en-tête répété, ressources paginées) ; false = une seule page dimensionnée au contenu.

Remarks

Le PDF est reconstruit VECTORIELLEMENT à partir du modèle (aucune rastérisation, aucune librairie) : rendu net à toute échelle, fichier léger. Export PDF uniquement.

Ping

Produit un événement Pong après le délai spécifié.

procedure Ping(Timeout: Integer)

Parameters

Name Type Description
Timeout Integer

Délai en millisecondes jusqu'à la réception de l'événement Pong.

HighlightPeriods

Met en surbrillance les périodes (colonnes principales) dont l'index (0-based) figure dans indices. Chaque appel remplace la surbrillance précédente (non cumulatif). Un tableau vide efface toute surbrillance de périodes.

procedure HighlightPeriods(indices: JsonArray)

Parameters

Name Type Description
indices JsonArray

Tableau JSON d'entiers : index (0-based) des périodes à surligner.

HighlightSubPeriods

Met en surbrillance des sous-périodes (créneaux) ciblées par un couple (période, sous-période) : une sous-période est toujours surlignée dans une période PRÉCISE (pas sur toutes). Chaque appel remplace la surbrillance précédente (non cumulatif). Un tableau vide l'efface.

procedure HighlightSubPeriods(pairs: JsonArray)

Parameters

Name Type Description
pairs JsonArray

Tableau JSON de paires [indexPériode, indexSousPériode] (0-based) — chaque paire est elle-même un tableau JSON de deux entiers. Autant de paires que souhaité.

SetQuantityScale

Définit l'échelle (multiplicateur de transform: scale) de la pastille de quantité affichée à droite d'une tâche : agrandit ou réduit le conteneur ENTIER de la pastille (cercle + texte). 1 correspond à 100 % (valeur par défaut). Aucune borne n'est appliquée (toute valeur strictement positive est acceptée).

procedure SetQuantityScale(scale: Decimal)

Parameters

Name Type Description
scale Decimal

Multiplicateur d'échelle (strictement positif ; 1 = taille normale).

Remarks

Réglage d'affichage DYNAMIQUE : il persiste entre les appels à SetRenderer (inutile de le renvoyer à chaque changement de vue / de semaine). N'a d'effet que sur les tâches portant une quantité (cf. Calendar Helper V2 UTCAP.SetTaskQuantity) ; sans pastille, aucun effet visible.

See also