Views and bulk actions

Events happening in the community are now at Drupal community events on www.drupal.org.
infojunkie's picture

One of the useful Web patterns I've been noticing has to do with item lists and bulk actions. Given a list of items, add a checkbox in front of each item, and let the user select an action to be executed on the checked selection. Specifically, I've seen it in phpMyAdmin, Mantis, and Google Mail.

The attached module provides a solution. It comes as a Views style plugin called "Bulk Operations View", selected in the "View Type" control of the View editing screen. This new style creates a form around the view, adds a checkbox in front of each element, and exposes the available Actions as well as all node_operations provided by loaded modules. When "Execute" is clicked, the form asks for confirmation then applies the selected action on all selected nodes.

The module uses the following existing pieces:
* Views module
* Actions module
* mfredrickson's Views node selector patch, itself needing another patch that is attached here.

Known issues:
* FIXED: Doesn't work correctly for paginated views.
* Uses not one, but two ugly hacks to resolve issues of embedding a view inside itself (using the views node selector patch).
* Uses another ugly hack for the confirmation screen, namely a multi-step form.

Installation:
* Install Views modules
* Apply the Views node selector patch
* Apply views_actions.patch inside the Views module folder
* Create a folder views_actions where you place views_actions.info and views_actions.module
* Enable the modules
* In the View editing screen, a new View Type called "Bulk Operations View" should appear

At some point I'll move this to a released module, once I feel the community accepts this as useful.

******** BELOW IS THE ORIGINAL MESSAGE, KEPT HERE FOR HISTORICAL CONTINUITY *********

So I've implemented a prototype of this pattern using Views and Actions. Attached is a very simple (60 lines) module that does the following:
* Add a new field to Views called "Node: Selection". This field just adds a checkbox to each row.
* Provide a new menu callback that processes $_REQUEST and applies the selected action to each selected nid in the view.

Some things need to be done manually in the view definition itself, so let's check a demo:
* Create some nodes
* Create a new view that provides a table view on a page.
* Add a "Node: Selection" field, along with any other field you want.
* In the view header, add the following code in PHP format:

<form id="formAction" action="views_actions/do" method="POST">
  • In the view footer, add the following code in PHP format:
<select name="action">
<?php
$actions = actions_get_all_actions();
foreach ($actions as $aid => $action) {
echo "".$action['description']."";
}
?>
</select>
<input type="hidden" name="destination" value="<?php echo $_GET['q'] ?>" />
<input type="submit" value="Execute" />
</form>

That's it! Save the view and run it -- I hope it works ;-)

For fun, I also explored the ability of selecting/deselecting all visible items. To add this, do the following in the view page:
* Paste this in the "Node: Selection" label:

<input id="selectAll" type="checkbox" />
  • Append this to the view header after the form declaration:
<?php

drupal_add_js('
$(document).ready(function(){
  $("#selectAll").change(function(){
    var state = this.checked;
    $("input.select[@type=\'checkbox\']").each(function() {
      this.checked = state;
    });
  });
});
', 'inline');
?>

Of course, this is very, very raw stuff. I am just talking about it to get your feedback if it's worth going into, and if nothing like it already exists. Thanks for your comments!

AttachmentSize
views_actions.info198 bytes
views_actions.module (v1.2)11.17 KB
views_actions.patch2.61 KB

Comments

Formatting mess-up

infojunkie's picture

The view footer code was messed up in translation. Here's what it should look like:

<select name="action">
<?php
$actions = actions_get_all_actions();
foreach ($actions as $aid => $action) {
echo "<option value=\"$aid\">".$action['description']."</option>";
}
?>
</select>
<input type="hidden" name="destination" value="<?php echo $_GET['q'] ?>" />
<input type="submit" value="Execute" />
</form>
KentBye's picture

Hey Karim,
Haven't had time to check this out yet, but I wanted to pass a link and something similar that I'm working towards.

First, have a look at this Views patch that started out as a module. It is intended to "provide a form element that allows users to select nodes using a table based view. This form element can be embedded in any form, allowing wide reuse. It is my hope that this code will be incorporated in the main views distribution."

Earl urged people to check it out and help review the patch in this blog post.

I've also been looking into integrating this type of "add this node to a playlist" functionality from a view where there are multiple playlists a node could be added to. So as a workaround to a form checkbox, I've been looking at how the the views_bookmark module adds a node with Steven's AJAX-enabled patch. I modified the patch so that I could add a "plus" and "minus" image to the text as described here.

And as to where the node is added to, I want to integrate the views_bookmark addition mechanism with a drop-down list of destinations of where the node added to. But since the "add to playlist link" is AJAX-enabled, I need to write to a database table which playlist the node should be added to. So I'm planning on using a drop-down box that makes an AJAX POST with an onChange selection. I'm still in the early phases of piecing it together, and I'll have to take a closer look at what you're doing with Actions.

But here's a code snippet that takes your taxonomy terms as a list, and then executes an AJAX POST when the term is selected. At the moment the POST URL doesn't actually do anything, but I thought I'd pass along this widget mechanism since I plan on integrating something like it for what I'm working on. I modified the code from this Dynamic jQuery Form post.

<?php

drupal_add_js
('
  $(document).ready(function(){
    // Ready code here.
    if ($("#playlist-dropdown").val() > 0)
      add_playlist_id_to_db($("#playlist-dropdown").val());
  });

  function add_playlist_id_to_db(url) {
    $.post(url,{},
      function(data){
        null;
      }
    );
  }
'
, 'inline');

$output = drupal_get_form('add_to_playlist_form', $form);
return
$output;

function
add_to_playlist_form() {
    global
$base_url;
   
$vid=1;
   
$formname="playlist-dropdown";
  
   
$vocabulary = db_query("SELECT term_data.name, term_data.tid FROM term_data WHERE term_data.vid=$vid ORDER BY name");
   
$options[] = t('Select Playlist'); // Initialise the country array
    //Populate array with the AJAX Post URL (at the moment just the Taxonomy Term Path, which doesn't do anything)
   
while ($term = db_fetch_object($vocabulary)) {
     
$options[$base_url.'/taxonomy/term/'.$term->tid] = $term->name;
    }
   
//Build dropdown select
    //If we try to build OnChange directly it gets mangled, so put in array to confuse the forms api
   
$form['category'] = array(
     
'#type' => 'select',
     
'#name' => $formname,
     
'#id' => $formname,
     
'#title' => '',
     
'#default_value' => '',
     
'#options' => $options,
     
'#description' => '',
     
'#multiple' => $multiple = FALSE,
     
'#required' => $required = FALSE,
     
'#attributes' => array('onChange' => 'add_playlist_id_to_db(this.value);')
    );
        return
$form;
}

?>

So the next steps for me are to figure out how to get this approach working w/o relying on javascript and then combine how views_bookmark adds a node to a list with how the audio_attach.module (an audio.module contrib module) adds nodes to a list that can then be sorted.

Anyway, just wanted to give you a heads up that I've been thinking about similar things, and I'll check this out soon.

views form element

moshe weitzman's picture

i too wanted to do this with the aforementioned views form element by mfrederickson. i made a feature request for this exact feature: http://drupal.org/node/125810. as i mention there, i think this can be done with no php code in Views fields and soon. essentially, it can be cleaner.

also note that there are pluses and minuses to using actions versus hook_operations(). i could be convinced either way.

Thanks for your comments.

infojunkie's picture

Thanks for your comments. This is obviously a needed feature.

I had come across mfrederickson's patch when I approached the problem, but it sounded too complex for a first pass. The manual HTML form coding that I did was meant as a quick validation of the concept. Yes a cleaner approach is needed and it would be now time to try out the view selector form element.

Concerning the Ajax wizardry, I think I'll stay away from it for the time being, as actions or hook_node_operations can take care of most bulk operation needs. I somehow felt that the use case described by kentbye was not the same as my original one, and thus different design decisions were made.

Finally, concerning actions vs. hook_node_operations: thanks for informing me of this hook! What would be the pluses and minuses, I cannot guess right now. But after browsing through the node_node_operations() code, it seemed to me that using both actions and node_operations would be feasible as bulk operations, although there is some redundancy between them.

So I guess my next step is to review mfrederickson's patch and essentially follow moshe's implementation recommendations.

select all

moshe weitzman's picture

drupal already gives you the select all checkboxes thing when you add some class to your checkboxes. see the admin/content/node page or devel_variable_form in devel.module.

Code cleanup, same functionality

infojunkie's picture

Thanks to community feedback, here's a new version of the same functionality that adapts better to Views. I used mfrederickson's patch and added a Views style plugin called Bulk Operations View. This style creates a form that embeds the same view as a form element, adding to it the list of available actions and the submit button. I was initially wary of the recursion but superficial testing did not reveal any problem :-)

To enable the select all gadget, I had to modify mfrederickson's patch in his views_form.inc. Replace the line 295 that says

array_unshift($view->table_header, array('data' => '', 'class' => 'view-cell-header'));

with

array_unshift($view->table_header, theme('table_select_header_cell'));

In this version, no need to touch the view header or footer, it's all transparent.

well done

moshe weitzman's picture

now that is nice and tidy, isn't it?

could you file a feature request for mfrederickson on his views form element patch?

Next steps

infojunkie's picture
  • Incorporate node_operations
  • Filter out Actions that don't act on Nodes
  • Allow the option of adding an "are you sure" intermediate screen
  • Allow the option of specifying which actions should be allowed

What else?

Great job!

merlinofchaos's picture

I just want to comment that this is really exciting work, and I'm thrilled to see this continuing to move forward and be refined.

v1.1

infojunkie's picture
  • Incorporate node_operations: Done
  • Filter out Actions that don't act on Nodes: Done
  • Allow the option of adding an "are you sure" intermediate screen: The confirmation screen is now hard-coded

  • Allow the option of specifying which actions should be allowed: I'd appreciate some hints on modifying the Edit View screen to allow the user to specify which actions to include in the drop-down.

nice work

moshe weitzman's picture

this is sounding terrific. i would think that you could just list all actions/operations. if an admin wants to edit that list, he can write a small form_alter() hook to do so. i wouldn't bother making a UI for this, personally.

how about adding 1 or 2 default Views to the module? Maybe a copy of current admin/content/node, or maybe something entirely different.

Good call!

infojunkie's picture

This unearthed a ton of problems. Nothing like trying your own medicine, right? See in you a couple of days, hehehe.

v1.2 with admin/content/node replica

infojunkie's picture

The module now creates a default view at admin/content/node2 that replicates the original Content administration screen. I had to do some more spelunking in the Views node selector patch, so I've collected my own patches in the attached views_actions.patch, to be applied on the views/ folder.

I don't plan to add more features for the time being. I'd greatly appreciate anyone trying this out and confirming that it works. I don't think I can release it as a new module until the Views node selector patch is merged with Views and my own patches added onto it, unless someone thinks otherwise. For the time being, I will be looking at a backport to 4.7 because we have legacy sites that need this functionality.

patch followup

moshe weitzman's picture

hi kratib. it would be terrific if you would file a patch against Views, or enhance the view selector patch. as long as this code depends on a patch, it will not be useful to many people.

I need this too

harry slaughter's picture

I need this functionality immediately. I'm going to assemble the required files in my CVS sandbox and add some documentation and also work on some bugs. I just don't like doing anything outside version control :)

Karim, please let me know when you have a real home for this and I'll delete it from my sandbox, hopefully the changes I make to it will be useful.

--
Drupal tips, tricks and services
http://devbee.com/ - Effective Drupal

--
Drupal tips, tricks and services
http://devbee.net/ - Effective Drupal

Temporary Home

harry slaughter's picture

Hopefully all interested parties will coordinate on this one. This is where I'm temporarily keeping the stuff I'll be changing:

http://cvs.drupal.org/viewvc.py/drupal/contributions/sandbox/hlslaughter...

Earl says that the views enhancements implemented in viewselector module (http://cvs.drupal.org/viewvc.py/drupal/contributions/sandbox/mfredrickso...) will be incorporated into views soon. At that point, this module will have no dependencies and should be useable by the general public :)

Also, I would suggest renaming this module to something like 'views_bulk_operations' just so that it's not confused with the actions module. Yes, it will incorporate actions, but it will not be limited to operations made available by the actions module. No biggie, of course.

--
Drupal tips, tricks and services
http://devbee.com/ - Effective Drupal

--
Drupal tips, tricks and services
http://devbee.net/ - Effective Drupal

Thanks Harry

infojunkie's picture

...for your initiative and contribution. I agree about renaming the module, 'views_bulk_operations' is a good name too. The only major issue I see is that this code requires re-patching the viewselector patch. Maybe with some more work we can figure out a way to remove that need.

In any case, as soon as you confirm that the whole thing's working for you, I'll proceed with releasing it as a new module.

Here's how I finally got it

harry slaughter's picture

Here's how I finally got it all working:

http://cvs.drupal.org/viewvc.py/drupal/contributions/sandbox/hlslaughter...

I've been playing with it for a while now. It seems pretty stable.

There are only 2 small issues that I'm aware of

1) the duplication of operations when actions module is enabled (which i worked around in http://cvs.drupal.org/viewvc.py/drupal/contributions/sandbox/hlslaughter...

2) filter selections disappear after performing operations and going back to the view.

I believe the next step is trying to get Mark's patches into the next beta of views? most of his code is new stuff. i didn't notice any major changes to existing code. a change to the params of one function may be a concern. but it seems safe enough for a beta release.

once it's in, folks can begin using the new 'views actions' module.

but, i definitely wouldn't mind seeing it renamed to views_bulk_operations. maybe mark can incorporate your patch to his in a new patch along with the renaming change.

--
Drupal tips, tricks and services
http://devbee.com/ - Effective Drupal

--
Drupal tips, tricks and services
http://devbee.net/ - Effective Drupal

Module pre-released

infojunkie's picture

With a lot of help from our friends, the module has been pre-released until the viewselector patch is accepted into Views.
Cheers everyone!

Closing this thread

harry slaughter's picture

Please see the new Views Bulk Operations page.

--
Drupal tips, tricks and services
http://devbee.com/ - Effective Drupal

--
Drupal tips, tricks and services
http://devbee.net/ - Effective Drupal

Views Developers

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: