浏览代码

Added ability to add custom dashboard actions

Michel Weimerskirch 9 年之前
父节点
当前提交
b712dd9f99

+ 31 - 0
Admin/Admin.php

@@ -3026,4 +3026,35 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
 
         return $list;
     }
+
+    /**
+     * Get the list of actions that can be accessed directly from the dashboard.
+     * 
+     * @return array
+     */
+    public function getDashboardActions()
+    {
+        $actions = array();
+
+        if ($this->hasRoute('create') && $this->isGranted('CREATE')) {
+            $actions['create'] = array(
+                'label'              => 'link_add',
+                'translation_domain' => 'SonataAdminBundle',
+                'template'           => 'SonataAdminBundle:CRUD:dashboard__action_create.html.twig',
+                'url'                => $this->generateUrl('create'),
+                'icon'               => 'plus-circle',
+            );
+        }
+
+        if ($this->hasRoute('list') && $this->isGranted('LIST')) {
+            $actions['list'] = array(
+                'label'              => 'link_list',
+                'translation_domain' => 'SonataAdminBundle',
+                'url'                => $this->generateUrl('list'),
+                'icon'               => 'list',
+            );
+        }
+
+        return $actions;
+    }
 }

+ 60 - 0
Resources/doc/reference/dashboard.rst

@@ -356,3 +356,63 @@ On ``top`` and ``bottom`` positions, you can also specify an optional ``class``
                         position: top
                         class: col-md-6
                         type: sonata.admin.block.admin_list
+
+Configuring what actions are available for each item on the dashboard
+---------------------------------------------------------------------
+
+By default. A "list" and a "create" option are available for each item on the
+dashboard. If you created a custom action and want to display it along the
+other two on the dashboard, you can do so by overriding the
+``getDashboardActions()`` method of your admin class:
+
+.. code-block:: php
+
+    <?php
+    // src/AppBundle/Admin/PostAdmin.php
+
+    class PostAdmin extends Admin
+    {
+        // ...
+
+        public function getDashboardActions()
+        {
+            $actions = parent::getDashboardActions();
+
+            $actions['import'] = array(
+                'label'              => 'Import',
+                'url'                => $this->generateUrl('import'),
+                'icon'               => 'import',
+                'translation_domain' => 'SonataAdminBundle', // optional
+                'template'           => 'SonataAdminBundle:CRUD:dashboard__action.html.twig', // optional
+            );
+
+            return $actions;
+        }
+
+    }
+
+You can also hide an action from the dashboard by unsetting it:
+
+.. code-block:: php
+
+    <?php
+    // src/AppBundle/Admin/PostAdmin.php
+
+    class PostAdmin extends Admin
+    {
+        // ...
+
+        public function getDashboardActions()
+        {
+            $actions = parent::getDashboardActions();
+
+            unset($actions['list']);
+
+            return $actions;
+        }
+
+    }
+
+If you do this, you need to be aware that the action is only hidden. it will
+still be available by directly calling its URL, unless you prevent that using
+proper security measures (e.g. ACL or role based).

+ 4 - 28
Resources/views/Block/block_admin_list.html.twig

@@ -27,40 +27,16 @@ file that was distributed with this source code.
                     <table class="table table-hover">
                         <tbody>
                             {% for admin in group.items %}
-                                {% if admin.hasRoute('create') and admin.isGranted('CREATE') or admin.hasroute('list') and admin.isGranted('LIST') %}
+                                {% if admin.dashboardActions|length > 0 %}
                                             <tr>
                                                 <td class="sonata-ba-list-label" width="40%">
                                                     {{ admin.label|trans({}, admin.translationdomain) }}
                                                 </td>
                                                 <td>
                                                     <div class="btn-group">
-                                                        {% if admin.hasroute('create') and admin.isGranted('CREATE') %}
-                                                            {% if admin.subClasses is empty %}
-                                                                <a class="btn btn-link btn-flat" href="{{ admin.generateUrl('create')}}">
-                                                                    <i class="fa fa-plus-circle"></i>
-                                                                    {% trans from 'SonataAdminBundle' %}link_add{% endtrans %}
-                                                                </a>
-                                                            {% else %}
-                                                                <a class="btn btn-link btn-flat dropdown-toggle" data-toggle="dropdown" href="#">
-                                                                    <i class="fa fa-plus-circle"></i>
-                                                                    {% trans from 'SonataAdminBundle' %}link_add{% endtrans %}
-                                                                    <span class="caret"></span>
-                                                                </a>
-                                                                <ul class="dropdown-menu">
-                                                                    {% for subclass in admin.subclasses|keys %}
-                                                                        <li>
-                                                                            <a href="{{ admin.generateUrl('create', {'subclass': subclass}) }}">{{ subclass|trans({}, admin.translationdomain) }}</a>
-                                                                        </li>
-                                                                    {% endfor %}
-                                                                </ul>
-                                                            {% endif %}
-                                                        {% endif %}
-                                                        {% if admin.hasroute('list') and admin.isGranted('LIST') %}
-                                                            <a class="btn btn-link btn-flat" href="{{ admin.generateUrl('list')}}">
-                                                                <i class="fa fa-list"></i>
-                                                                {% trans from 'SonataAdminBundle' %}link_list{% endtrans -%}
-                                                            </a>
-                                                        {% endif %}
+                                                        {% for action in admin.dashboardActions %}
+                                                            {% include action.template|default('SonataAdminBundle:CRUD:dashboard__action.html.twig') with {'action': action} %}
+                                                        {% endfor %}
                                                     </div>
                                                 </td>
                                             </tr>

+ 4 - 0
Resources/views/CRUD/dashboard__action.html.twig

@@ -0,0 +1,4 @@
+<a class="btn btn-link btn-flat" href="{{ action.url }}">
+    <i class="fa fa-{{ action.icon }}"></i>
+    {{ action.label|trans({}, action.translation_domain|default('SonataAdminBundle')) }}
+</a>

+ 19 - 0
Resources/views/CRUD/dashboard__action_create.html.twig

@@ -0,0 +1,19 @@
+{% if admin.subClasses is empty %}
+    <a class="btn btn-link btn-flat" href="{{ action.url }}">
+        <i class="fa fa-{{ action.icon }}"></i>
+        {{ action.label|trans({}, action.translation_domain|default('SonataAdminBundle')) }}
+    </a>
+{% else %}
+    <a class="btn btn-link btn-flat dropdown-toggle" data-toggle="dropdown" href="#">
+        <i class="fa fa-{{ action.icon }}"></i>
+        {{ action.label|trans({}, action.translation_domain|default('SonataAdminBundle')) }}
+        <span class="caret"></span>
+    </a>
+    <ul class="dropdown-menu">
+        {% for subclass in admin.subclasses|keys %}
+            <li>
+                <a href="{{ admin.generateUrl('create', {'subclass': subclass}) }}">{{ subclass|trans({}, action.translation_domain|default('SonataAdminBundle')) }}</a>
+            </li>
+        {% endfor %}
+    </ul>
+{% endif %}

+ 35 - 0
Tests/Admin/AdminTest.php

@@ -1671,6 +1671,41 @@ class AdminTest extends \PHPUnit_Framework_TestCase
 
         $this->assertSame($expected, $admin->getActionButtons('list', null));
     }
+
+    /**
+     * @covers Sonata\AdminBundle\Admin\Admin::getDashboardActions
+     * @dataProvider provideGetBaseRouteName
+     */
+    public function testDefaultDashboardActionsArePresent($objFqn, $expected)
+    {
+        $pathInfo = new \Sonata\AdminBundle\Route\PathInfoBuilder($this->getMock('Sonata\AdminBundle\Model\AuditManagerInterface'));
+
+        $routeGenerator = new DefaultRouteGenerator(
+            $this->getMock('Symfony\Component\Routing\RouterInterface'),
+            new RoutesCache($this->cacheTempFolder, true)
+        );
+
+        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
+        $admin->setRouteBuilder($pathInfo);
+        $admin->setRouteGenerator($routeGenerator);
+        $admin->initialize();
+
+        $securityHandler = $this->getMock('Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface');
+        $securityHandler->expects($this->any())
+            ->method('isGranted')
+            ->will($this->returnCallback(function (AdminInterface $adminIn, $attributes, $object = null) use ($admin) {
+                if ($admin == $adminIn && ($attributes == 'CREATE' || $attributes == 'LIST')) {
+                    return true;
+                }
+
+                return false;
+            }));
+
+        $admin->setSecurityHandler($securityHandler);
+
+        $this->assertArrayHasKey('list', $admin->getDashboardActions());
+        $this->assertArrayHasKey('create', $admin->getDashboardActions());
+    }
 }
 
 class DummySubject