Domptez vos API

grâce à ng-admin !

Marmelab

atelier d'innovation digitale

Marmelab regroupe une communauté de talents passionnés par l’innovation qui sont avant tout des faiseurs. Nous partageons un référentiel de valeurs basé sur l’amour du travail bien fait, le pragmatisme, la culture du partage de la connaissance, la curiosité, et le plaisir au quotidien.

Filiale du groupe Palo IT, Marmelab tire profit de moyens administratifs et financiers mutualisés, pour assurer son développement commercial et ses engagements auprès de ses clients sur une assise solide et performante.

Jérôme MACIAS, @jeromemacias

Ancien spécialiste du framework PHP Symfony, Jérôme travaille depuis son arrivée chez Marmelab sur des projets NodeJS dotés de librairies JavaScript front. Adepte des micro-librairies, micro-services, architectures n-tiers et du Domain Driven Design, il favorise toujours la valeur business, notamment grâce aux méthodes Lean & Agile. Jeune papa, le pragmatisme et l'efficacité sont devenus pour lui une priorité.

Alexis JANVIER, @alexisjanvier

Longtemps spécialisé dans les projets PHP, Alexis ne code presque plus qu'en JavaScript depuis son arrivée chez Marmelab. Depuis qu'il ne peut plus ressembler à un barbu pour cause de demande expresse de ses filles, il essaye de coder en GO sous VIM.

Au programme

 

  • Pourquoi ng-admin ?
  • Origine du projet
  • Mise en place d'une administration en live
  • Présentation du code
  • Démo complète
  • REX : adapter l'interface à la demande du client
  • La vie d'un projet Open Source
  • Le futur d'un projet basé sur Angular JS

Pourquoi
ng-admin ?

Frameworks full-stack avec interface d'admin générée

 

 - Python : Django admin site

 - Ruby : Rails ActiveAdmin / RailsAdmin

 - Java : Spring Batch admin / light admin

 - PHP : Symfony Sonata admin / EasyAdminBundle

Inconvenients

 

- Full stack

- Technologies back

- Couplage

Emergence des APIs

 

- réponse au besoin des applications mobiles

- généralisation avec notamment les APIs publiques

- émergence du format REST

Chez Marmelab

Avantages

- multi technos

- multi serveurs (cloud)

- plus facile à tester

ng-admin en quelques mots

- Interface d'administration pour vos APIs REST(ful)

- Composants riches

- Technologies Frontend

- Pas de dépendances applicatives

Origines du projet

- 1er POC en javascript vanilla en hackday

- Migration sur AngularJS lors d'un 2ème hackday

- 1er commit le 25 mai 2014

- Post de blog d'introduction le 15 septembre 2014

- Utilisation sur nos projets clients

Mise en place d'une administration en live

Le
code

3 dépôts Github

- admin-config : /marmelab/admin-config

- ng-admin : /marmelab/ng-admin

- ng-admin-demo : /marmelab/ng-admin-demo

admin-config

- uniquement pour la configuration

- VanillaJS (ES6)

- tests unitaires

ng-admin

- module Angularjs

- tests unitaires et fonctionnels

Posters Galore

démo

Et dans
de vrais
projets

1859 Cloud is an invitation only private investment club designed to bring together in a virtual cloud network some of the most skilled & successful financial markets professionals and investors. All Members have been rigorously selected, in relation with their financial knowledge, their reputation, their past results and the need for 1859 to cover multiple asset classes and develop a diversified global community of trading or investments styles across the globe

DÉMO !

Edition des suggestions

suggestion.editionView()
        .title('<span>Edit suggestion #{{entry.identifierValue}} \
            <span class="suggestion-status {{ entry.values.status }}"> \
            {{ entry.values.status }}</span></span>'
        )
        .fields([
            nga.field('id').editable(false),
            nga.field('tags', 'tags')
            .isDetailLink(false)
            .categories(tagCategories)
            .targetEntity(nga.entity('tags'))
            .targetField(nga.field('name', 'string'))
            .perPage(200)
            .singleApiCall(function (ids) {
                return { 'id[]': ids };
            }),
            nga.field('attachments', 'template').template('
                <cl-attachments value="entry.values[field.name()]" 
                id="entry.values.id" 
                apifilename="filename" 
                url="/admin/suggestions/{{entry.values.id}}/attachments">
                </cl-attachments>'
            ),
            nga.field('workflow', 'template').label('')
                .cssClasses('field_workflow')
                .template('<cl-suggestion-workflow entry="entry"></cl-suggestion-workflow>')
        ])
        .actions(editActions);

Directive cl-suggestion-worflow

(function (angular) {
    'use strict';
    angular.module('1859-admin').directive('clSuggestionWorkflow', [
    '$http', '$state', '$modal', 'progression', 'notification',
    function ($http, $state, $modal, progress, notification) {

        return {
            restrict: 'E',
            scope: {
                'entry': '&'
            },
            templateUrl: '/admin/scripts/directives/templates/cl-suggestion-workflow.html',
            link: function (scope) {
                scope.entry = scope.entry();
                scope.status =  scope.entry.values.status;
                var id = scope.entry.identifierValue;
                scope.askForFeedback = function (status) {
                    if (status !== 'pending') {
                        return;
                    }
                    progress.start();
                    scope.entry.values.status = 'waiting';

                    $http.put('/admin/suggestions/' + id, scope.entry.values)
                    .success(function () {
                        progress.done();
                        notification.log('Suggestion successfully returned for feedback.', {addnCls: 'humane-flatty-success'});
                        $state.go($state.current, {}, {reload: true});
                    })
                    .error(function (data) {
                        var msg = data.error || 'Suggestion could\'nt be validated.';
                        notification.log(msg, {addnCls: 'humane-flatty-error'});
                        progress.done();
                    });
                };
<svg
    viewBox="69 23 723 200"
    class="workflow"
>
    <defs>
        <marker
            orient="auto"
            overflow="visible"
            markerUnits="strokeWidth"
            id="FilledArrow_Marker"
            viewBox="-1 -3 7 6"
            markerWidth="7"
            markerHeight="6"
            class="investor_arrow"
        >
            ...
        </marker>
        <g ng-class="{ state_action: true, enabled: status === 'pending' }" 
           ng-click="askForFeedback(status)">
            <g class="arrow admin">
                <path
                    d="M 371 252 C 336.6701 263.9988 287.74802 288 268 288 C 254.0491 288 254.65203 276.02184 254.38684 262"
                    marker-end="url(#FilledArrow_Marker_2)"
                    stroke-linejoin="round"
                    stroke-linecap="round"
                    stroke-width="1.5"
                    fill="none"
                />
            </g>

Gestion des tags : ajout d'un type custom

var nga = NgAdminConfigurationProvider;

var TagsField = nga.adminDescription.getFieldConstructor('reference_many');
TagsField.prototype.type = function () {
    return 'tags';
};

nga.registerFieldType('tags', TagsField);

FieldViewConfigurationProvider.registerFieldView('tags', {
    getReadWidget: function () {
        return '<ma-string-column value="::entry.listValues[field.name()]"></ma-string-column>';
    },
    getLinkWidget: function () {
        return '<a ng-click="gotoReference()">' + this.getReadWidget() + '</a>';
    },
    getFilterWidget: function () {
        return '<ma-choices-field field="::field" datastore="::datastore" value="values[field.name()]"></ma-choices-field>';
    },
    getWriteWidget: function () {
        return '<cl-choices field="::field" datastore="::datastore" value="entry.values[field.name()]" categories="field.categories()" select-type="button"></cl-choices>';
    }
});

La vie d'un
projet
open-source

Dépôt(s) Github

Premier commit le 25 mai 2014. Depuis, c'est :

 

  • 1855 commits
  • 24 releases
  • 828 issues (1,5 / jour)
  • 419 PR
  • 36 contributeurs
  • 2275 stars
  • 276 forks

Mais c'est
plus que des
dépôts Github !

Un site de démo

http://marmelab.com/ng-admin-demo/#/dashboard

Une documentation

https://www.gitbook.com/book/marmelab/ng-admin/details

Des posts de blog

http://marmelab.com/blog/

Des talks

Des chatons

Vous
voulez
participer ?

Remontez des bugs

Des nouvelles features, des correctifs ...

forkez le dépôt et proposez vos PR

Vous ne savez
comment
faire ?

Regardez l'excellente

William Durand

présentation de

L'avenir
d'un projet
angular

?

Merci
à vous
: )

Références

Domptez vos API grâce à NG Admin

By Alexis Janvier

Domptez vos API grâce à NG Admin

En règle générale, un projet Web se compose d’une ou plusieurs partie(s) publique(s) et d’une administration privée. Si beaucoup de frameworks proposent des applications d’administration (Django Admin, Symfony Sonata Admin, Spring Light Admin, etc.), ils imposent souvent aux administrateurs leurs propres spécificités. On observe également une très forte tendance à faire communiquer le Back et le Front via une, voire plusieurs, API REST(ful, parfois). Et si on s’appuyait sur ces API pour fournir une interface d’administration exécutée sur le poste du client ? C'est de cette idée qu’est né NG Admin : ce qui n’était au début qu’un projet de hackday est devenu au fil du temps un projet Open Source très actif au sein de Marmelab et utilisé au quotidien chez beaucoup de nos clients. A travers ce BarCamp, découvrez comment ajouter une interface d'administration AngularJS à n'importe quelle API REST.

  • 991
Loading comments...

More from Alexis Janvier