Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-detect base actions #100

Open
jonom opened this issue Feb 20, 2015 · 4 comments
Open

Auto-detect base actions #100

jonom opened this issue Feb 20, 2015 · 4 comments

Comments

@jonom
Copy link
Contributor

jonom commented Feb 20, 2015

I don't know if this is possible but it would be cool if the basic bulk edit actions (unlink,edit,delete) were automatically limited to match what's enabled on the rows.

I.e. if 'unlink' isn't shown on the gridfield then it's not shown in the bulk edit dropdown either.

@colymba
Copy link
Collaborator

colymba commented Apr 10, 2015

This sounds like a good idea.

But what if someone decides to remove the buttons to only use the dropdown bulk edit? Might have to have this as a config option for the component rather than the default?...

@jonom
Copy link
Contributor Author

jonom commented Apr 13, 2015

Yes good point. A config option sounds good then - perhaps a global setting that can be overridden for individual instances?

@colymba
Copy link
Collaborator

colymba commented Mar 6, 2018

This hasn't got much love in years, but now with all the new bulkactions, this could be revived...

Thinking a good option might be too rely on testing the various canXXX actions on the data object...

@mooror
Copy link
Contributor

mooror commented Oct 10, 2024

Recently I decided to add the Bulk Manager component to all GridFieldConfig classes so that I can use the component globally. I also wanted a way to detect sane defaults on a per Grid basis, so I created my own sub class that does this.

For anyone interested in the code, here it is:

<?php

use Colymba\BulkManager\BulkAction\DeleteHandler;
use Colymba\BulkManager\BulkAction\EditHandler;
use Colymba\BulkManager\BulkAction\PublishHandler;
use Colymba\BulkManager\BulkAction\UnlinkHandler;
use Colymba\BulkManager\BulkAction\UnPublishHandler;
use Colymba\BulkManager\BulkManager;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridField_ColumnProvider;
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
use SilverStripe\Forms\GridField\GridField_URLHandler;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;

/**
 * GridField component for editing attached models in bulk.
 *
 * This has the added ability to automatically set available bulk
 * actions based on the GridField objects and what components
 * are already applied to the grid
 */
class AutoActionsBulkManager extends BulkManager implements GridField_HTMLProvider, GridField_ColumnProvider, GridField_URLHandler
{
    /**
     * Set to true if automatic action selection is enabled
     *
     * @var boolean
     */
    protected bool $automaticActionSelection = false;

    /**
     * If the actions have automatically been configured
     *
     * This is checked to prevent the configuration code
     * from being run multiple times
     *
     * @var boolean
     */
    protected bool $automaticActionsConfigured = false;

    /**
     * BulkManager component constructor.
     *
     * @param array $editableFields List of editable fields
     * @param bool  $defaultActions Use default actions list. False to start fresh
     * @param bool  $defaultVersionedActions Use default versioned actions list
     * @param bool  $autoActions Automatically sets actions based on the other components in the Gridfield
     */
    public function __construct(
        $editableFields = null,
        $defaultActions = true,
        $defaultVersionedActions = false,
        $autoActions = false
    ) {
        if ($autoActions) {
            $this->automaticActionSelection = true;
        } else {
            parent::__construct($editableFields, $defaultActions, $defaultVersionedActions);
        }
    }

    /**
     * Configures the actions automatically based on
     * the GridField objects and what components
     * are already applied to the grid
     *
     * @return void
     */
    public function configureAutomaticBulkActions(GridField $gridField, bool $force = false)
    {
        if ($this->automaticActionSelection && (!$this->automaticActionsConfigured || $force)) {
            $config = $gridField->getConfig();
            $modelClass = $gridField->getModelClass();
            $gridSingleton = singleton($modelClass);

            // If the grid has a delete action
            if ($deleteComponent = $config->getComponentByType(GridFieldDeleteAction::class)) {
                if ($deleteComponent->getRemoveRelation()) {
                    // If the delete action is in unlink mode, add unlink action
                    $this->addBulkAction(UnlinkHandler::class);
                } else {
                    // otherwise, add the delete action
                    $this->addBulkAction(DeleteHandler::class);
                }
            }

            // Add editable action that allows for summary fields to be edited
            if ($dataColumnsComponent = $config->getComponentByType(GridFieldDataColumns::class)) {
                // if (isset($gridSingleton::$bulk_editable_fields)) {
                if ($gridSingleton->config()->get("bulk_editable_fields")) {
                    $displayFields = $gridSingleton->config()->get("bulk_editable_fields");
                } else {
                    $displayFields = $dataColumnsComponent->getDisplayFields($gridField);
                    $displayFields = array_filter(array_keys($displayFields), function ($value) use ($gridSingleton) {
                        return (!str_contains($value, ".") && $gridSingleton->hasDatabaseField($value));
                    });
                }
                $this->config["editableFields"] = $displayFields;
                $this->addBulkAction(EditHandler::class);
            }

            // If the gridfield objects have the versioned extension applied to them
            if ($gridSingleton->hasExtension(Versioned::class) && $gridSingleton->hasStages()) {
                // Add publish and unpublish actions
                $this->addBulkAction(UnPublishHandler::class);
                $this->addBulkAction(PublishHandler::class);
            }

            $this->automaticActionsConfigured = true;
        }
    }

    public function getHTMLFragments($gridField)
    {
        $this->configureAutomaticBulkActions($gridField);
        return parent::getHTMLFragments($gridField);
    }

    public function handleBulkAction($gridField, $request)
    {
        $this->configureAutomaticBulkActions($gridField);
        return parent::handleBulkAction($gridField, $request);
    }
}

To use, add it to your Grid and set the last option to true:

$owner->addComponent(AutoActionsBulkManager::create(null, false, false, true));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants