Dans cet article, nous allons nous intéresser à un élément clé pour le développement d’applications métier documentaires, la liste de documents. Tous les développeurs savent que s’il y a bien un composant qui peut être plein de surprises, c’est celui du tableau de résultats, où l’on s’attend à pouvoir faire tout ce qu’un tableur Desktop peut proposer en standard… mais la réalisation s’avère souvent bien plus délicate. En gestion documentaire, nous avons besoin d’un tableau pour afficher une liste de documents et permettre à un utilisateur de naviguer dans une arborescence de répertoires pour accéder aux documents.
Alfresco possède un framework pour le développement d’applications métier, l’Alfresco Development Framework (ADF) basé sur Angular qui propose un ensemble de composants et de services qui facilitent la navigation dans un entrepôt documentaire ainsi que les traitements divers de gestion documentaire.
Chez Atol CD, nous avons accueilli avec bienveillance l’arrivée d’ADF et sa présentation à la DevCon 2018 pour proposer des interfaces métier dédiées qui peuvent tirer parti d’une GED transverse. Tout en laissant le temps à ce framework de devenir mature, nous avons pris en main et validé ce nouveau mode de conception d’applications documentaires et notamment les capacités ergonomiques et d’assemblage de composants proposées tout comme les possibilités de base d’Angular et de son écosystème.
Pour rentrer dans le vif du sujet, il existe donc dans ADF un composant Document List qui permet d’afficher le contenu d’un répertoire et d’avoir un rendu spécifique des informations attendues. Celui-ci hérite du composant Data Table qui possède déjà un tutoriel sur son utilisation.
Liste de documents standard
Par défaut, le listing d’un répertoire ressemble à ceci :
Pour l’implémenter dans un projet ADF, il suffit d’écrire les balises HTML du composant dans le template de son composant parent.
1 2 3 |
<adf-document-list [currentFolderId]="'-my-'"> <!-- ou dans ce cas simple, currentFolderId="-my-" suffit --> </adf-document-list> |
L’identifiant -my- fait référence ici à l’espace personnel de l’utilisateur dans Alfresco, qui par défaut correspond à la racine de l’entrepôt pour l’utilisateur admin. Il existe également d’autres raccourcis prédéfinis dans l’entrepôt (-root- ou -shared-) et d’autres spécifiques au framework ADF (-trashcan-, -mysites-, -recent-…).
En pratique, on utilisera plutôt une méthode dans le contrôleur TypeScript pour récupérer un identifiant de répertoire à partir d’un service.
Les propriétés currentFolderId ou node servent à indiquer au composant quel répertoire ou liste d’éléments doivent être affichés. Ces deux propriétés sont exclusives. La première convient mieux lorsque l’identifiant du répertoire parent est connu, la seconde pour des résultats d’une recherche.
Dès lors que cette liste est instanciée, on peut interagir avec celle-ci par des clics ou en sélectionnant les éléments présents.
Le mode de fonctionnement standard permet déjà la navigation arborescente. Celle-ci se fait par défaut sur le double-clic, à la manière d’un explorateur de fichiers sur Desktop. Ce mode de navigation dans une application Web peut paraître déroutant mais il est facile de le reconfigurer pour que la navigation se fasse sur un clic simple :
1 2 3 4 |
<adf-document-list [currentFolderId]="..." [navigationMode]="'click'"> <!-- par défaut, 'dblclick' --> </adf-document-list> |
Paramétrage des colonnes
Il est possible de réorganiser et modifier totalement les colonnes de la liste. Cela permet de montrer plus ou moins d’informations aux utilisateurs sur les documents et dossiers qui sont affichées.
Pour cela il faut ajouter dans le corps de la balise adf-document-list
la balise data-columns
contenant pour chaque colonne une balise data-column
qui permet d’instancier un composant Data Column. L’ordre des balises dans le template défini l’ordre des colonnes dans la liste.
Des colonnes par défaut sont prédéfinies dans le composant (comme on a pu s’en rendre compte ci-dessus). Ajouter la balise data-columns
permet de réinitialiser cette liste des colonnes et d’y ajouter les colonnes souhaitées.
Il est possible de configurer pour chaque colonne le libellé (clé i18n), une info-bulle, l’activation du tri (sortable
, true par défaut), des informations de formatage (type
, format
) ou de style cssClass
et enfin l’attribut key
utilisé pour le data binding. Voici comment personnaliser la deuxième colonne pour afficher en dessous du nom une liste de tags associés :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<adf-document-list [currentFolderId]="..." ...> <data-columns> <data-column key="$thumbnail" type="image" [sortable]="false"> </data-column> <data-column key="name" title="ADF-DOCUMENT-LIST.LAYOUT.NAME" class="full-width ellipsis-cell"> <ng-template let-context="$implicit"> <span>{{ context.row.getValue('name') }}</span> <adf-tag-node-list [nodeId]="context.row.getValue('id')"></adf-tag-node-list> </ng-template> </data-column> <data-column key="content.sizeInBytes" type="fileSize" title="ADF-DOCUMENT-LIST.LAYOUT.SIZE"> </data-column> <data-column key="modifiedAt" type="date" format="short" title="ADF-DOCUMENT-LIST.LAYOUT.MODIFIED_ON" class="desktop-only"> </data-column> <data-column key="modifiedByUser.displayName" title="ADF-DOCUMENT-LIST.LAYOUT.MODIFIED_BY" class="desktop-only"> </data-column> </data-columns> </adf-document-list> |
Le rendu obtenu est le suivant :
L’affichage des en-têtes de colonnes peut également être désactivé avec la propriété showHeader
.
Les éléments sont triés par défaut sur leur nom dans l’ordre alphanumérique. Il est possible de définir la colonne et le sens du tri initial avec le paramètre sorting
. La valeur de la propriété sortingMode
doit être à client, dont c’est la valeur par défaut.
Attention, le tri permet d’effectuer un réarrangement par rapport aux données affichées dans la liste mais ne tiens pas compte d’une éventuelle pagination. En effet, le composant ne peut pas être configuré pour effectuer un tri côté serveur (la valeur server de la propriété sortingMode
ne fait que préciser que les éléments sont pré-triés côté serveur). Il ne s’effectue que sur une colonne à la fois.
Enfin, l’utilisation de Media queries CSS peut permettre de masquer certaines colonnes possédant une classe CSS spécifique pour un affichage plus concis sur mobile.
Ajout d’actions sur les éléments de la liste
Lorsque l’on développe une application de gestion documentaire, il est utile de pouvoir ajouter des actions (visualiser, télécharger, éditer, supprimer…) pour pouvoir agir sur les documents.
Ces interactions sont rendues possibles en ajoutant dans le corps de la balise adf-document-list
la balise content-actions
contenant pour chaque action une balise content-action
qui instancie un composant Content Action. L’ordre des balises dans le template défini l’ordre des actions dans la liste.
Par défaut, aucun action n’est affichée. Il y deux façons qui ne sont pas exclusives de présenter une liste d’actions dans un menu :
- à la place du menu contextuel affiché lors du clic droit, avec l’attribut
contextMenuActions
à true (false par défaut) - dans une colonne dédiée à droite, avec l’attribut
contentActions
à true (false par défaut)
Il est possible de configurer pour chaque action l’icône (Material icons), le libellé (clé i18n), s’il est inactif, masqué ou s’il dépend d’une permission pour être affiché. Enfin, l’événement execute
et l’attribut handler
permettent de spécifier l’action à lancer. Voici comment personnaliser la deuxième action pour renommer un objet :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<adf-document-list [currentFolderId]="..." [contentActions]="true" ...> <content-actions> <content-action icon="get_app" title="DOCUMENT.CONTENT_ACTION.DOWNLOAD" target="document" handler="download"> </content-action> <content-action icon="gesture" title="DOCUMENT.CONTENT_ACTION.RENAME" target="document" permission="update" (execute)="rename($event)"> </content-action> <content-action icon="delete" title="DOCUMENT.CONTENT_ACTION.DELETE" permission="delete" disableWithNoPermission="true" handler="delete" (success)="notify($event)"> </content-action> </content-actions> </adf-document-list> |
Il n’existe qu’un nombre restreint de handler
: download, lock, copy, move et delete. Pour effectuer des actions personnalisées, il faut créer une méthode dans le contrôleur TypeScript puis la renseigner dans l’événement execute
. C’est le cas ici de l’action rename. D’autres événements tels que success
ou error
peuvent être ajoutés notamment pour notifier l’utilisateur du résultat de l’action ou gérer des cas particuliers.
Voici le résultat obtenu :
Filtrage des éléments de la liste
Le composant de liste de documents permet également de filtrer les éléments affichés via l’ajout d’un paramètre rowFilter
dans la balise du composant :
1 2 3 4 5 |
<adf-document-list [currentFolderId]="..." [rowFilter]="noFolder" ...> </adf-document-list> |
noFolder doit alors être défini dans le contrôleur TypeScript associé au template. Pour masquer les répertoires par exemple, on peut mettre en place le filtre comme ceci :
1 2 3 4 |
noFolder: RowFilter = (row: ShareDataRow) => { const node = row.node.entry; return node && !node.isFolder; } |
Attention, les éléments qui ne correspondent pas au filtre seront masqués dans cette liste côté client, mais font tout de même partie des objets retournés par Alfresco et seront notamment comptabilisés dans la pagination.
Sélection des éléments de la liste
Il est également possible de sélectionner des éléments affichés dans la liste via le paramètre selectionMode
qui ne permet de choisir qu’un seul élément à la fois (valeur single par défaut), et qui peut prendre la valeur multiple pour autoriser la sélection de plusieurs éléments. Dans ce cas, comme sur Desktop, il faut utiliser la touche Ctrl du clavier Windows ou Cmd du clavier Mac pour que cela fonctionne.
Dès lors, il parait plus judicieux de rester sur un mode de navigation sur le double clic, le clic étant dans ce cas dédié à la sélection. Lorsqu’un élément est sélectionné, l’icône de celui-ci change pour afficher l’image d’un check.
En outre, il est possible d’ajouter une colonne présentant une case à cocher pour chaque élément afin d’utiliser un mode de sélection plus familier à un utilisateur Web. Pour cela, il faut passer le paramètre multiselect
à true (false par défaut).
1 2 3 4 5 6 |
<adf-document-list [currentFolderId]="..." [multiselect]="true" selectionMode="multiple" ...> </adf-document-list> |
Pour pouvoir agir sur les éléments sélectionnés, il suffit d’en récupérer la liste via l’attribut selection
de type Array<MinimalNodeEntity>
du composant.
Pagination des éléments de la liste
Naturellement, on a envie de rajouter la capacité de pagination sur des gros volumes pour pouvoir n’afficher à l’écran qu’un nombre restreint d’objets à la fois.
Ce cas est prévu par le framework avec le composant Pagination.
Il faut au préalable avoir identifié le composant de liste puis le référencer dans le composant de pagination via l’attribut target
:
1 2 3 4 5 6 7 8 9 |
<adf-document-list #documentList [currentFolderId]="..." ...> </adf-document-list> <adf-pagination [target]="documentList"> </adf-pagination> |
Il est également possible d’utiliser un composant de Pagination Infinie de manière à charger les documents suivants à l’aide d’un simple bouton tant que la liste n’est pas complète :
1 2 3 4 5 |
<adf-infinite-pagination [pageSize]="10" [target]="documentList"> {{ 'ADF-DOCUMENT-LIST.LAYOUT.LOAD_MORE' | translate }} </adf-infinite-pagination> |
En testant ce code, il s’avère que le paramètre pageSize n’est pas pris en compte ! Nous avons donc contribué une correction à ce petit désagrément qui sera disponible dans la version 3.0.0.
Conclusion
J’espère que cet article vous a donné un bon aperçu des capacités offertes nativement par le composant de liste de documents d’ADF. Lorsque l’on conçoit une application métier il est important de réfléchir à ce qui peut être réutilisé et les points d’extensions qui ont été prévus. Il faut notamment prendre en compte le design du composant, à la fois en termes de conception (cycle de vie de la donnée, paramétrage) et d’ergonomie pour pouvoir l’intégrer au mieux dans une interface dédiée.
En somme, ce composant proposé par Alfresco permet déjà de combler les besoins les plus courants et les composants de pagination viennent compléter ses capacités d’affichage selon la volumétrie. Il pourrait être amélioré en termes de fonctionnalités avec du tri côté serveur ou de filtres côté client sur lesquels l’utilisateur pourrait saisir des valeurs directement.
Laisser un commentaire