Skip to content

Commit 1b04be2

Browse files
Initial commit - straight from my local
0 parents  commit 1b04be2

File tree

7 files changed

+297
-0
lines changed

7 files changed

+297
-0
lines changed

Diff for: LICENSE

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
BSD 3-Clause License
2+
3+
Copyright (c) 2018, DNA Designed Communications Limited
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
* Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
* Neither the name of the copyright holder nor the names of its
17+
contributors may be used to endorse or promote products derived from
18+
this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Diff for: Readme.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# GridField Bulk Delete
2+
3+
## Introduction
4+
5+
Add a `GridFieldBulkDeleteForm` component to a gridfield config to add an option to delete the records within that list.
6+
7+
## Requirements
8+
* [silverstripe/framework](https://github.com/silverstripe/framework)
9+
10+
## Install
11+
12+
```
13+
composer require heyday/gridfield-bulk-delete
14+
```
15+
16+
## Configuration
17+
18+
### Add to gridfield config
19+
20+
```
21+
$config->addComponent(new GridFieldBulkDeleteForm('buttons-after-right'));
22+
```
23+
24+
Forked from: [dnadesign/gridfield-bulk-delete](https://github.com/dnadesign/gridfield-bulk-delete)

Diff for: _config.php

Whitespace-only changes.

Diff for: _config/config.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
Name: gridfield-bulkdelete
3+
---
4+
SilverStripe\Admin\LeftAndMain:
5+
extra_requirements_javascript:
6+
- 'heyday/gridfield-bulk-delete:client/js/bulkdelete_confirm.js'

Diff for: client/js/bulkdelete_confirm.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
(function ($) {
2+
$.entwine(function ($) {
3+
/**
4+
* force a confirm when clearing form submissions
5+
*/
6+
7+
$('.cms-edit-form').on('click', '.bulkdelete_button', function (e) {
8+
9+
var button = $(e.target);
10+
11+
var action = $.trim(button.text());
12+
var message = 'Are you sure you want to ' + action.toLowerCase() + '?';
13+
14+
if (!confirm(message)) {
15+
e.preventDefault();
16+
return false;
17+
} else {
18+
this._super(e);
19+
}
20+
});
21+
22+
});
23+
24+
}(jQuery));

Diff for: composer.json

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "heyday/gridfield-bulk-delete",
3+
"description": "A GridField component allowing to delete records in bulk",
4+
"type": "silverstripe-vendormodule",
5+
"keywords": [
6+
"silverstripe",
7+
"gridfield",
8+
"bulk",
9+
"delete"
10+
],
11+
"license": "BSD-3-Clause",
12+
"authors": [
13+
{
14+
"name": "Wunderman Thompson NZ",
15+
"email": "[email protected]"
16+
}
17+
],
18+
"minimum-stability": "dev",
19+
"prefer-stable": true,
20+
"require": {
21+
"silverstripe/cms": "^4.4@dev",
22+
"silverstripe/admin": "^1.4@dev",
23+
"silverstripe/vendor-plugin": "^1"
24+
},
25+
"extra": {
26+
"expose": [
27+
"client/js"
28+
]
29+
},
30+
"autoload": {
31+
"psr-4": {
32+
"DNADesign\\GridFieldBulkDelete\\": "src/"
33+
}
34+
}
35+
}

Diff for: src/GridFieldBulkDeleteForm.php

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
<?php
2+
3+
namespace Heyday\GridFieldBulkDelete;
4+
5+
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
6+
use SilverStripe\Forms\GridField\GridField_FormAction;
7+
use SilverStripe\Forms\GridField\GridField_DataManipulator;
8+
use SilverStripe\Forms\GridField\GridField_ActionProvider;
9+
use SilverStripe\Forms\GridField\GridFieldPaginator;
10+
use SilverStripe\Forms\GridField\GridField;
11+
use SilverStripe\Control\Controller;
12+
use SilverStripe\ORM\SS_List;
13+
14+
/**
15+
* Adds a dropdown and a button
16+
* Allowig users to delete records in the gridfield in bulk
17+
* with the option to delete only records older than 1,2,3 or 6 months.
18+
*
19+
* Also, if available, a queued job will be used if too many record need to be deleted.
20+
* Both this task and queuedjob loop trhough the record and invoke "delete"
21+
* so any dependant record may be deleted as well.
22+
*
23+
*/
24+
class GridFieldBulkDeleteForm implements GridField_HTMLProvider, GridField_ActionProvider
25+
{
26+
/**
27+
* @var string
28+
*/
29+
const STATUS_GOOD = 'good';
30+
31+
/**
32+
* @var string
33+
*/
34+
protected $targetFragment;
35+
36+
/**
37+
* @var string
38+
*/
39+
protected $message;
40+
41+
/**
42+
* @var string
43+
*/
44+
protected $status = self::STATUS_GOOD;
45+
46+
public function __construct($targetFragment = 'before', $threshold = null)
47+
{
48+
$this->targetFragment = $targetFragment;
49+
50+
if ($threshold && $threshold > 0) {
51+
$this->use_queued_threshold = $threshold;
52+
}
53+
}
54+
55+
/**
56+
* Return all HTML fragment of delete form
57+
*
58+
* @param GridField $gridField
59+
* @return array
60+
*/
61+
public function getHTMLFragments($gridField)
62+
{
63+
$form = $gridField->getForm();
64+
$records = $this->getFilteredRecordList($gridField);
65+
if (!$records->exists()) {
66+
/**
67+
* If a message exists, but no record
68+
* it means we have deleted them all
69+
* so display the message anyway
70+
*/
71+
if ($this->message) {
72+
$fragment = sprintf('<p class="message %s">%s</p>', $this->status, $this->message);
73+
return [$this->targetFragment => $fragment];
74+
}
75+
// Otherwise hide the form
76+
return [];
77+
}
78+
79+
$singleton = singleton($gridField->getModelClass());
80+
if (!$singleton->canDelete()) {
81+
return [];
82+
}
83+
84+
$buttonTitle = sprintf('Delete %s record(s)', $records->Count());
85+
86+
$button = new GridField_FormAction(
87+
$gridField,
88+
'bulkdelete',
89+
$buttonTitle,
90+
'bulkdelete',
91+
null
92+
);
93+
94+
$button->setForm($gridField->getForm());
95+
$button->addExtraClass('bulkdelete_button'); // For JS purpose
96+
$button->addExtraClass('font-icon-trash btn btn-outline-danger'); // For styling purpose
97+
98+
// Set message
99+
if ($this->message) {
100+
$form->setMessage($this->message, $this->status);
101+
}
102+
103+
$template = '<div><table><tr><td style="vertical-align:top;"><div style="margin-left: 7px;">%s</div></td></tr></table></div>';
104+
105+
$fragment = sprintf($template, $button->Field());
106+
107+
return [
108+
$this->targetFragment => $fragment
109+
];
110+
}
111+
112+
/**
113+
* export is an action button
114+
*
115+
* @param GridField
116+
* @return array
117+
*/
118+
public function getActions($gridField)
119+
{
120+
return ['bulkdelete'];
121+
}
122+
123+
/**
124+
* export is an action button
125+
*
126+
* @param string $actionName
127+
* @param mixed $arguments
128+
* @param mixed $data
129+
*
130+
* @return array
131+
*/
132+
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
133+
{
134+
if ($actionName == 'bulkdelete') {
135+
return $this->handleBulkDelete($gridField);
136+
}
137+
}
138+
139+
/**
140+
* Handle the export, for both the action button and the URL
141+
*/
142+
public function handleBulkDelete(GridField $gridField)
143+
{
144+
$records = $this->getFilteredRecordList($gridField);
145+
146+
$ids = [];
147+
foreach ($records as $record) {
148+
$ids[] = $record->ID;
149+
$record->delete();
150+
}
151+
152+
$this->message = sprintf('%s records have been successfully deleted.', count($ids));
153+
$this->status = self::STATUS_GOOD;
154+
155+
Controller::curr()->getResponse()->setStatusCode(
156+
200,
157+
$this->message
158+
);
159+
160+
return;
161+
}
162+
163+
/**
164+
* To get the entire list of records with the potential filters
165+
* we need to remove the pagination but apply all other filters
166+
*/
167+
public function getFilteredRecordList(GridField $gridfield): SS_List
168+
{
169+
$list = $gridfield->getList();
170+
171+
foreach ($gridfield->getComponents() as $item) {
172+
if ($item instanceof GridField_DataManipulator && !$item instanceof GridFieldPaginator) {
173+
$list = $item->getManipulatedData($gridfield, $list);
174+
}
175+
}
176+
177+
return $list;
178+
}
179+
}

0 commit comments

Comments
 (0)