API Platform Admin 0.2 : créez une admin en 1 minute pour votre API (React Progressive Web App inside)

Retrouvez la version originale (EN) de cet article ici.

api-platform-admin

La version 0.2 du composant admin d’API Platform vient juste de sortir !

Cet outil permet de créer une interface d’administration complète, intuitive et dynamique (CRUD, paginations, relations) pour n’importe quelle API supportant le vocabulaire hypermedia Hydra, et cela sans une seule ligne de code (d’autres formats seront bientôt supportés, vous le saurez en lisant la fin de cet article ;)) !

API Platform Admin est construit avec React à partir de la bibliothèque Admin on Rest sous la forme d’une Progressive Web App. Découvrons ensemble les nouvelles fonctionnalités apportées par cette version !

Installation

En partant du principe que vous avez une API exposant une documentation Hydra, vous n’avez qu’à initialiser le composant React suivant pour obtenir votre admin :

import React from 'react';
import { HydraAdmin } from '@api-platform/admin';

export default () => <HydraAdmin entrypoint="https://api.example.com"/>;

Prenons un exemple. Créez une nouvelle application avec le package create-react-app de Facebook, remplacez le contenu de src/App.js avec l’extrait plus haut et exécutez yarn add @api-platform/admin. C’est tout ! Si vous obtenez une erreur liée aux multiples versions de React chargées, retirez les packages react et react-dom de votre package.json et exécutez à nouveau yarn install.

Si vous n’avez pas encore une API au format Hydra / JSON-LD, voici le code de celle que nous utiliserons dans les exemples suivants. Elle a été créée en suivant la distribution officielle d’API Platform :

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ApiResource
 */
class Person
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column
     * @ApiProperty(iri="http://schema.org/name")
     */
    public $name;

    /**
     * @var Greeting[]
     *
     * @ORM\OneToMany(targetEntity="Greeting", mappedBy="person", cascade={"persist"})
     */
    public $greetings;

    public function __construct()
    {
        $this->greetings = new ArrayCollection();
    }

    public function getId()
    {
        return $this->id;
    }

    public function addGreeting(Greeting $greeting)
    {
        $greeting->person = $this;
        $this->greetings->add($greeting);
    }

    public function removeGreeting(Greeting $greeting)
    {
        $greeting->person = null;
        $this->greetings->removeElement($greeting);
    }
}
<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ApiResource
 * @ORM\Entity
 */
class Greeting
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column
     * @Assert\NotBlank
     * @ApiProperty(iri="http://schema.org/name")
     */
    public $name = '';

    /**
     * @ORM\ManyToOne(targetEntity="Person", inversedBy="greetings")
     */
    public $person;

    public function getId(): ?int
    {
        return $this->id;
    }
}

Et oui, vous n’avez besoin que de ces deux petites classes en PHP pour obtenir une API hypermedia. Découvrez davantage d’informations au sujet du composant API en lisant ce guide de démarrage. N’importe quelle API avec une documentation Hydra fera le job indépendamment du langage de programmation côté serveur.

Le support natif pour les relations to-many

L'admin d’API Platform supporte les relations to-one depuis sa première sortie. Cependant, il était nécessaire de personnaliser le composant utilisé pour les relations to-many. Ce n’est plus le cas désormais : notre parseur de documentation d’API prend désormais en charge les cardinalités et peut les extraire si la documentation de l’API inclut les propriétés de cardinalité maximum d’OWL. Si aucune cardinalité n'est fournie, l’admin utilisera un widget to-many par défaut.  

Voici à quoi ressemble l’écran d’édition de la ressource Person grâce à cette nouvelle fonctionnalité : 

api-platform-to-many

L'admin est capable de comprendre que la ressource Person est liée aux Greetings et du coup utiliser le composant Admin On Rest approprié.

Détection de types Schema.org supplémentaires (noms, url & e-mail)

L'admin d’API Platform est capable d’utiliser le widget adéquat en fonction du type de propriété d’une ressource. Cela supporte :

Dans cette nouvelle version, l’admin d’API Platform supporte également certains types du célèbre vocabulaire de Schema.org :

  • Comme vous avez pu le voir lors des écrans précédents, si une propriété est de type  http://schema.org/name, cette propriété sera utilisée à la place de l’ID en affichant cette relation
  • Si une propriété est de type http://schema.org/url, l’URL sera cliquable depuis l’admin.
  • Si une propriété est de type http://schema.org/email, l’entrée HTML sera de type email et une validation de base aura lieu (cela fonctionne déjà depuis la version 0.1)

Le support pour les ressources en lecture seule

La version 0.1 ne permettait pas de gérer les ressources en lecture seule (pas d’opérations POST ou PUT). Nous avons amélioré notre parser de documentation afin de supporter les propriétés owl:equivalentClass. Dorénavant, si la documentation de l’API fournit ces propriétés, l’admin sera construite même si la ressource est en lecture seule (évidemment, dans ce cas-là, vous ne serez qu’en mesure de consulter les ressources mais pas les éditer).

Une personnalisation simplifiée et plus poussée

Morgan Auchedé a effectué un gros travail pour rendre l’admin entièrement et facilement personnalisable.

Vous pouvez désormais surcharger n’importe quel composant React généré par un composant personnalisé, ou par un composant d’Admin On Rest, ou de MUI React. Vous pouvez remplacer, ajouter ou retirer une entrée ou un champ spécifique. Mais vous pouvez aussi remplacer une liste entière, une vue, une création ou un formulaire d’édition, ou un bouton de suppression. Voici un exemple fourni par Morgan :

import parseHydraDocumentation from '@api-platform/api-doc-parser/lib/hydra/parseHydraDocumentation';
import { Datagrid, EditButton, ImageField, List, ShowButton, TextField } from 'admin-on-rest';
import React from 'react';
import SingleImageInput from '../components/inputs/single-image-input';

export default entrypoint => parseHydraDocumentation(entrypoint)
    .then(
        ({ api }) => {
            // Customize "Gallery" resource
            const gallery = api.resources.find(({ name }) => 'galleries' === name);
            gallery.list = (props) => (
                
                    
                        
                        {props.options.fieldFactory(props.options.resource.fields.find(({ name }) => name === 'name'))}
                        {props.options.fieldFactory(props.options.resource.fields.find(({ name }) => name === 'mainImage'))}
                        {props.hasShow && }
                        {props.hasEdit && }
                    
                
            );

            // Customize "images" field
            const images = gallery.fields.find(({ name }) => 'images' === name);
            images.field = props => (
                
            );
            images.input = props => (
                
                    
                
            );
            images.input.defaultProps = {
                addField: true,
                addLabel: true,
            };

            // Customize "mainImage" field
            const mainImage = gallery.fields.find(({ name }) => 'mainImage' === name);
            mainImage.field = props => (
                
            );
            mainImage.input = props => (
                
                    
                
            );
            mainImage.input.defaultProps = {
                addField: true,
                addLabel: true,
            };
            mainImage.input.defaultProps = {
                addField: true,
                addLabel: true,
            };

            return { api };
        },
    );

Support d’autres formats tels que GraphQL

Le parser a été créé de sorte que l'on puisse analyser d’autres formats tels que le schéma GraphQL ou Swagger/Open API. La bibliothèque api-doc-parser offre une représentation intermédiaire qui est peuplée par le parser du format correspondant. Cette représentation est utilisée par le parser ainsi que par notre générateur de  Progressive Web App React & Vue.js.

Cela signifie que lorsque des parser pour d’autres formats qu’Hydra seront disponibles (PR bienvenues !), les deux outils supporteront également ces formats.

Comme vous l’avez sûrement vu, la partie serveur d’API Platform supporte désormais GraphQL. Je vous laisse deviner quel format nous implémenterons dans la prochaine version de api-doc-parser !