Coder Social home page Coder Social logo

marmelab / ngadmingeneratorbundle Goto Github PK

View Code? Open in Web Editor NEW
75.0 18.0 12.0 138 KB

Generate a client-side admin backend for Symfony2 applications, powered by ng-admin and LemonRestBundle

License: MIT License

PHP 67.76% JavaScript 17.97% HTML 14.27%

ngadmingeneratorbundle's Introduction

archived Archived Repository
This code is no longer maintained. Feel free to fork it, but use it at your own risks.

NgAdminGeneratorBundle Build Status

You're a fan of StanLemonRestBundle because it makes REST APIs based on Doctrine entities a piece of cake? You starred ng-admin because you love the idea of a JavaScript-powered administration panel consuming a REST API? Then, you will love NgAdminGeneratorBundle, the Symfony2 bundle that bootstraps ng-admin based on a Doctrine-powered REST API!

Installation

Setting up bundle

Using this bundle in your own project is pretty straightforward, thanks to composer:

composer require marmelab/ng-admin-generator-bundle

Then, register it to your AppKernel.php file. The NgAdminGeneratorBundle should only be used in development:

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        // ...
        if (in_array($this->getEnvironment(), array('dev', 'test'))) {
            $bundles[] = new \marmelab\NgAdminGeneratorBundle\marmelabNgAdminGeneratorBundle();
        }
        // ...
    }
}

No more configuration, you are now ready to go!

ng-admin template sample

Here is a Twig template to render your favorite administration panel:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Administration Panel</title>
    <link rel="stylesheet" href="{{ asset('components/ng-admin/build/ng-admin.min.css') }}"/>
</head>
<body ng-app="myApp">
    <script src="{{ asset('components/angular/angular.min.js') }}"></script>
    <script src="{{ asset('components/ng-admin/build/ng-admin.min.js') }}"></script>
    <script src="{{ asset('ngadmin.conf.js') }}"></script>
    <div ui-view></div>
</body>
</html>

If you got a blank page, ensure you have set correctly the ng-app and ui-view attributes.

Generating your ng-admin configuration

This bundle just adds the ng-admin:configuration:generate command to your application. By default, it outputs a JavaScript configuration based on the REST API defined by StanLemonRestBundle into STDOUT. You are free to redirect STDOUT into the file of your choice:

./app/console ng-admin:configuration:generate > public/js/ng-admin-config.js

Tip: Thanks to the Symfony2 Console component, you can truncate parts of the command name and call the ng-admin:c:g command!

Configuration sample

Here is a sample of an auto-generated configuration, based on the stanlemon/rest-demo-app demo application. This application sets up the same entities as the official ng-admin demo app, i.e. Posts, Comments, and Tags. The generator simply uses entity mapping to better know which fields to use.

var app = angular.module('myApp', ['ng-admin']);

// Deal with query parameters expected by StanLemon bundle
app.config(function(RestangularProvider) {
    RestangularProvider.addFullRequestInterceptor(function(element, operation, what, url, headers, params) {
        if (operation == "getList") {
            // custom pagination params
            params._start = (params._page - 1) * params._perPage;
            params._end = params._page * params._perPage;
            delete params._page;
            delete params._perPage;

            // custom sort params
            if (params._sortField) {
                params._orderBy = params._sortField;
                params._orderDir = params._sortDir;
                delete params._sortField;
                delete params._sortDir;
            }

            // custom filters
            if (params._filters) {
                for (var filter in params._filters) {
                    params[filter] = params._filters[filter];
                }
                delete params._filters;
            }
        }

        return { params: params };
    });
});

/* Define a `config` block for each entity, allowing to split configuration
   across several files. */
app.config(function($provide, NgAdminConfigurationProvider) {
    $provide.factory("PostAdmin", function() {
        var nga = NgAdminConfigurationProvider;
        var post = nga.entity('post');

        // Dashboard (as list) won't display referenced list of items.
        post.dashboardView()
            .fields([
                nga.field('id', 'number'),
                nga.field('title', 'string'),
                nga.field('body', 'text'),
                // We limit to 3 number of fields displayed on dashboard
            ]);

        post.listView()
            .fields([
                nga.field('id', 'number'),
                nga.field('title', 'string'),
                nga.field('body', 'text'),
                // Take more meaningful field. Here, use `name` instead of `id`
                nga.field('tags', 'reference_many')
                    .targetEntity(nga.entity('tag'))
                    .targetField(nga.field('name')),
            ])
            .listActions(['show', 'edit', 'delete']);

        post.creationView()
            .fields([
                // Do not display id: we don't have any yet
                nga.field('title', 'string'),
                nga.field('body', 'text'),
                nga.field('tags', 'reference_many')
                    .targetEntity(nga.entity('tag'))
                    .targetField(nga.field('name')),
                // No referenced_list either, as that's a brand new entity
            ]);

        post.editionView()
            .fields([
                nga.field('id', 'number').readOnly(), // don't modify id
                nga.field('title', 'string'),
                nga.field('body', 'text'),
                nga.field('tags', 'reference_many')
                    .targetEntity(nga.entity('tag'))
                    .targetField(nga.field('name')),
                nga.field('comments', 'referenced_list')
                    .targetEntity(nga.entity('comment'))
                    .targetReferenceField('post_id')
                    .targetFields([
                        nga.field('id', 'number'),
                        nga.field('body', 'text'),
                        nga.field('created_at', 'date'),

                ]),
            ]);

        /* To ease configuration per view, we repeat every field every time. If you want to display same fields
           across views, you can use for instance `post.editView().fields()` to get edition fields. */
        post.showView()
            .fields([
                nga.field('id', 'number'),
                nga.field('title', 'string'),
                nga.field('body', 'text'),
                nga.field('tags', 'reference_many')
                    .targetEntity(nga.entity('tag'))
                    .targetField(nga.field('name')),
                nga.field('comments', 'referenced_list')
                    .targetEntity(nga.entity('comment'))
                    .targetReferenceField('post_id')
                    .targetFields([
                        nga.field('id', 'number'),
                        nga.field('body', 'text'),
                        nga.field('created_at', 'date'),

                ]),
            ]);

        return post;
    });
});

// Same config block for comments
// Same config block for tags

app.config(function(NgAdminConfigurationProvider, PostAdminProvider, CommentAdminProvider, TagAdminProvider) {
    var admin = NgAdminConfigurationProvider
        .application('')
        .baseApiUrl(location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '') + '/api/')

    admin
        .addEntity(PostAdminProvider.$get())
        .addEntity(CommentAdminProvider.$get())
        .addEntity(TagAdminProvider.$get())
    ;

    NgAdminConfigurationProvider.configure(admin);
});

Contributing

Your feedback about the usage of this bundle is valuable: don't hesitate to open GitHub Issues for any problem or question you may have.

All contributions are welcome. New applications or options should be tested with the phpunit command.

License

NgAdminGeneratorBundle is licensed under the MIT Licence, courtesy of marmelab.

ngadmingeneratorbundle's People

Contributors

alexisjanvier avatar fzaninotto avatar jeromehubert avatar jpetitcolas avatar robinbressan avatar stanlemon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ngadmingeneratorbundle's Issues

working with different REST APIs

how can I configure ng-admin to work with several different URI endpoints?
e.g. var
admin = nga.application('My Admin')
.baseApiUrl('http://localhost:6007/api/v1/');
lets me use localhost:6007 as my URI
I would like to be able to use additional URIs for other entities
(service oriented architecture - not all entities are coming from the same URI)

Issue with targetToSourceKeyColumns on oneToMany Relation

Hi,

I tried to generate my ngAdmin config with the generator command, but I get this error:

[Symfony\Component\Debug\Exception\ContextErrorException]  
  Notice: Undefined index: targetToSourceKeyColumns          



Exception trace:
 () at /home/fabex/dev/recrutement/api/vendor/marmelab/ng-admin-generator-bundle/Transformer/NgAdminWithRelationshipsTransformer.php:61
 Symfony\Component\Debug\ErrorHandler->handleError() at /home/fabex/dev/recrutement/api/vendor/marmelab/ng-admin-generator-bundle/Transformer/NgAdminWithRelationshipsTransformer.php:61

Here my relational model :

Question:
    type: entity
    table: question
    repositoryClass: QuestionRepository
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    fields:
        text:
            type: string
            length: 255
            nullable: false
    oneToMany:
        answers:
            targetEntity: Answer
            mappedBy: question

Answer:
    type: entity
    table: answer
    repositoryClass: AnswerRepository
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    fields:
        text:
            type: text
            nullable: true
        valid:
            type: boolean
            nullable: true
        type:
            type: text
            nullable: false
    manyToOne:
       question:
           targetEntity: Question
           inversedBy: answers
           joinColumn:
               name: question_id
               referencedColumnName: id

Node.js implementation of generator

Hi. What do you think about creating generator using node.js and ORM like sequelize and this plugin(or other ORM's that have ability to pull current schema from a database). It may allow to generate a code independently from back-end technology stack.

OneToMany only works if resource name is plural

For Example if you name entity Comment resource as "comment" and Entity Post resource as "post" when you call the generation command you'll get an error like this one (only works if you name it comments):

Key "comments" for array with keys "comment, post" does not exist"

Multiple relations to the same entity

Hi,

Thanks for this great bundle.

I met an issue with an entity that has multiple OneToMany relations to another entity.
My Stage entity has two relations with entity City (start and end city). And vice versa.
Of course I can't name both attribute $city, so when I try to generation JS conf file, attribute name is not found.

How can I do ?

Error log:

Key "startstages" for array with keys "stages, ..." does not exist in "marmelabNgAdminGeneratorBundle:Configuration:referenced_list.js.twig" at line 5

OneToMany reference doesn't work with full object

API should return only the id of referenced entity, not an object. For instance, an API like the following would produce an error:

{
    "first_name": "John",
    "last_name": "Doe",
    "address": {
        "id": 1,
        "address": "88 Colin P Kelly Jr Street",
        "city": "San Francisco"
    }
}

It should instead return only an address_id field:

{
    "first_name": "John",
    "last_name": "Doe",
    "address_id": 1
}

This is easily done using the following Serializer annotations:

/**
 * @ORM\Column(name="address_id", type="integer", nullable=false)
 */
protected $address_id;

/**
 * @ORM\ManyToOne(targetEntity="Acme\FooBundle\Entity\Address")
 * @ORM\JoinColumn(name="address_id", referencedColumnName="id")
 * @Serializer\Exclude()
 **/
private $address;

Would be better to allow passing a full object, and use a Restangular entity transformer to fetch id directly.

Deal correctly with all relationships

Deal with all possible relationship types, based on official Doctrine docs.

  • Many-to-one unidirectional
  • One-to-one unidirectional
  • One-to-one bidirectional
  • One-to-one self referencing
  • One-to-many bidirectional
  • One-to-many unidirectional with join table
  • One-to-many self referencing
  • Many-to-many unidirectional
  • Many-to-many bidirectional
  • Many-to-many self referencing

Can't generate configuration with camelCase Doctrine fields

If I set up my Doctrine entity using camelCase convention instead of underscore_convention, generation doesn't work. Indeed, API returns underscored fields, and config use camelCase.

Solution is to use API fields for generation instead of Doctrine one.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.