Pixel

Découverte de NOVA, la nouvelle solution proposée par Laravel

28/09/2018

Notre objectif des deux journées dédiées au lancement 9Weeks (Voir l’article 48h pour lancer 9Weeks) était de réaliser un back-office rapidement afin d’administrer le programme proposé par Frianbiz. Nous avons alors décidé d’utiliser Nova, le nouvel outil mis au point par l’équipe de Laravel présenté à la Laracoin 2018. Le but était d’avoir une application pour gérer une équipe avec des compétences et des projets composés de lots et de contacts.

Installation et mise en place

Après avoir acquis une licence développeur à 99$, il était nécessaire de télécharger le zip fourni et l’intégrer à notre projet Laravel précédemment créé.

Très rapidement, nous avons eu accès à l’interface avec sa page d’authentification. Illustration page d'authentification

Éléments exploités

Une fois l’outil intégré, nous avons commencé à utiliser les Resources. Ces classes permettent de transposer graphiquement un modèle : Par exemple, un utilisateur sera défini par un avatar, un nom et un email.

class User extends Resource
{
    public static $model = \App\Models\User::class;
    public function fields(Request $request)
    {
        return [
            Avatar::make('Avatar', 'avatar')->disk('public'),
            Text::make('Nom', 'last_name')
                ->sortable()
                ->rules('required', 'max:255'),
            Text::make('Email')
                ->sortable()
                ->rules('required', 'email', 'max:254')
                ->creationRules('unique:users,email')
                ->updateRules('unique:users,email,{{resourceId}}'),
            BelongsToMany::make('Tags')->searchable(),
            // ...
        ];
   }
}

Liste des users Formulaire d'un user

Ensuite, afin d’assigner le bon utilisateur au bon projet, nous avons cherché à les filtrer par compétence (ou par tag). Pour ce faire, nous avons créé une classe héritant de Filter, où nous avons défini la requête ainsi que les options possibles :

class UserTags extends Filter
{
    public $name = "Compétence";
    public function apply(Request $request, $query, $value)
    {
        return $query->whereIn('id', function($query) use ($value) {
            $query->select('user_id')
                  ->from('user_tags')
                  ->where('tag_id', $value);
        });
    }
    
    public function options(Request $request)
    {
         return Tag::all()->pluck("id", "name");
    }
}

Illustration des filtres De plus, Nova nous propose d’exécuter des Actions sur un ou plusieurs items d’une liste, par exemple, si l’on souhaite terminer plusieurs lots d’un projet.

Pour cela, rien de plus simple, nous avons créé un fichier qui hérite de la classe Action et défini l’action souhaitée dans la méthode handle() : dans notre cas, passer la valeur isDone à true sur les lots sélectionnés.

class isDoneBatch extends Action
{
    use InteractsWithQueue, Queueable, SerializesModels;
    public $name = "Terminer";
    public function handle(ActionFields $fields, Collection $models
    {
        foreach ($models as $batch) {
            $batch->isDone = true;
            $batch->save();
        }
    }
}

Enfin, nous voulions afficher les compétences des utilisateurs sous forme de labels. Pour ce faire, nous avons souhaité créer un Package.

Nous n’avions plus qu’à éditer le fichier IndexField.vue et à ajouter notre Field personnalisé à la Resource :

<!-- IndexField.vue -->
<template>
    <div>
        <span v-for="item in field.value" class="label label-default">{{ item.name }}</span>
    </div>
</template>
// Resources/User.php
public function fields(Request $request)
{
    return [
        // …
        TagsList::make('Compétences', 'Tags')->hideFromDetail(),
        // …
    ];
}

Notre back-office est pensé pour administrer et suivre les projets. L’équipe Frianbiz ainsi que les contacts associés aux clients ont une visibilité sur les projets et leurs intervenants.

Cependant, cette visibilité doit avoir ses limites dès lors où un contact se connecte.

Pour ce faire, nous avons utilisé le système des Policies !

L’idée est de bloquer ou de délimiter les accès aux Resources par rapport au contexte du contact tout en laissant une visibilité totale aux membres de l’équipe Frianbiz.

Premièrement, il faut créer la Policy associée à notre Model (ici Project) :

class ProjectPolicy
{
    use HandlesAuthorization;
    public function view(User $user, Project $project)
    {
        return true;
    }
    public function create(User $user)
    {
        return $user->isTeamMember();
    }
}

Tous les utilisateurs peuvent visualiser les projets mais seuls les membres de l’équipe Frianbiz peuvent créer des projets.

Ensuite enregistrer l’association Policy / Model :

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        Project::class => ProjectPolicy::class,
        Tag::class => TagPolicy::class,
        Client::class => ClientPolicy::class,
        User::class => UserPolicy::class,
        Batch::class => BatchPolicy::class,
    ];
}

Et voilà, les contacts n’auront qu’un accès en visualisation sur la Resource Project !

On peut aussi voir le travail des Policies sur les autres Resources (Client, Tag, Equipe) qui ne sont pas accessibles par les contacts. Liste des projets pour un administrateur A noter que les Policies sont aussi appliquées lors des accès aux relations que vous définissez dans vos Resources.

Impressions

Le bilan à tirer de ce POC est que l’outil Nova s’adapte parfaitement au besoin du back office du programme 9 weeks. Grâce à une simplicité d’utilisation et de personnalisation, une documentation claire et une librairie de Packages déjà conséquente, la réalisation d’un back office en 2 jours à et trois développeurs fut un succès.

Néanmoins, la personnalisation reste limitée, l’interface n’est pas responsive et les fichiers de traduction ne sont pas complets. Enfin, l’outil est encore trop récent pour avoir une importante communauté.

Mais Nova est un produit très prometteur, qui a besoin d’un peu de temps pour devenir entièrement opérationnel et riche.

A noter que cet article relate un POC réalisé dans le cadre d’un hackathon. Il y a surement de meilleurs façons d’utiliser les fonctionnalités de l’outil Nova et la possibilité de réaliser un code de meilleur qualité.

Liens utiles

Site de Nova | Article de présentation par Taylor Otwell | Packages Nova

#Laravel
#Nova
#9weeks
#Web
red pixel blue pixel