Skip to content

Commit

Permalink
Merge pull request #14304 from snipe/feature/sc-24018
Browse files Browse the repository at this point in the history
Added ability to bulk delete locations
  • Loading branch information
snipe authored Feb 20, 2024
2 parents 04c1d9c + cb0f902 commit 71610fb
Show file tree
Hide file tree
Showing 16 changed files with 295 additions and 49 deletions.
29 changes: 26 additions & 3 deletions app/Http/Controllers/Api/LocationsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,27 @@ public function index(Request $request)
{
$this->authorize('view', Location::class);
$allowed_columns = [
'id', 'name', 'address', 'address2', 'city', 'state', 'country', 'zip', 'created_at',
'updated_at', 'manager_id', 'image',
'assigned_assets_count', 'users_count', 'assets_count','assigned_assets_count', 'assets_count', 'rtd_assets_count', 'currency', 'ldap_ou', ];
'id',
'name',
'address',
'address2',
'city',
'state',
'country',
'zip',
'created_at',
'updated_at',
'manager_id',
'image',
'assigned_assets_count',
'users_count',
'assets_count',
'assigned_assets_count',
'assets_count',
'rtd_assets_count',
'currency',
'ldap_ou',
];

$locations = Location::with('parent', 'manager', 'children')->select([
'locations.id',
Expand All @@ -50,6 +68,7 @@ public function index(Request $request)
])->withCount('assignedAssets as assigned_assets_count')
->withCount('assets as assets_count')
->withCount('rtd_assets as rtd_assets_count')
->withCount('children as children_count')
->withCount('users as users_count');

if ($request->filled('search')) {
Expand Down Expand Up @@ -80,6 +99,10 @@ public function index(Request $request)
$locations->where('locations.country', '=', $request->input('country'));
}

if ($request->filled('manager_id')) {
$locations->where('locations.manager_id', '=', $request->input('manager_id'));
}

// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $locations->count()) ? $locations->count() : app('api_offset_value');
$limit = app('api_limit_value');
Expand Down
5 changes: 0 additions & 5 deletions app/Http/Controllers/Api/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,6 @@ public function index(Request $request)
$offset = ($request->input('offset') > $users->count()) ? $users->count() : app('api_offset_value');
$limit = app('api_limit_value');

\Log::debug('Requested offset: '. $request->input('offset'));
\Log::debug('App offset: '. app('api_offset_value'));
\Log::debug('Actual offset: '. $offset);
\Log::debug('Limit: '. $limit);

$total = $users->count();
$users = $users->skip($offset)->take($limit)->get();

Expand Down
3 changes: 0 additions & 3 deletions app/Http/Controllers/AssetModelsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,6 @@ public function postBulkDelete(Request $request)
$del_count = 0;

foreach ($models as $model) {
\Log::debug($model->id);

if ($model->assets_count > 0) {
$del_error_count++;
Expand All @@ -452,8 +451,6 @@ public function postBulkDelete(Request $request)
}
}

\Log::debug($del_count);
\Log::debug($del_error_count);

if ($del_error_count == 0) {
return redirect()->route('models.index')
Expand Down
87 changes: 86 additions & 1 deletion app/Http/Controllers/LocationsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;

/**
* This controller handles all actions related to Locations for
Expand Down Expand Up @@ -238,7 +239,7 @@ public function print_assigned($id)
* @author [A. Gianotto] [<[email protected]>]
* @param int $locationId
* @since [v6.0.14]
* @return View
* @return \Illuminate\Contracts\View\View
*/
public function getClone($locationId = null)
{
Expand Down Expand Up @@ -272,8 +273,92 @@ public function print_all_assigned($id)

}
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
}


/**
* Returns a view that allows the user to bulk delete locations
*
* @author [A. Gianotto] [<[email protected]>]
* @since [v6.3.1]
* @return \Illuminate\Contracts\View\View
*/
public function postBulkDelete(Request $request)
{
$locations_raw_array = $request->input('ids');

// Make sure some IDs have been selected
if ((is_array($locations_raw_array)) && (count($locations_raw_array) > 0)) {
$locations = Location::whereIn('id', $locations_raw_array)->get();

$valid_count = 0;
foreach ($locations as $location) {
if ($location->isDeletable()) {
$valid_count++;
}
}
return view('locations/bulk-delete', compact('locations'))->with('valid_count', $valid_count);
}

return redirect()->route('models.index')
->with('error', 'You must select at least one model to edit.');
}

/**
* Checks that locations can be deleted and deletes them if they can
*
* @author [A. Gianotto] [<[email protected]>]
* @since [v6.3.1]
* @return \Illuminate\Http\RedirectResponse
*/
public function postBulkDeleteStore(Request $request) {
$locations_raw_array = $request->input('ids');

if ((is_array($locations_raw_array)) && (count($locations_raw_array) > 0)) {
$locations = Location::whereIn('id', $locations_raw_array)->get();

$success_count = 0;
$error_count = 0;

foreach ($locations as $location) {

// Can we delete this location?
if ($location->isDeletable()) {
$location->delete();
$success_count++;
} else {
$error_count++;
}
}

\Log::debug('Success count: '.$success_count);
\Log::debug('Error count: '.$error_count);
// Complete success
if ($success_count == count($locations_raw_array)) {
return redirect()
->route('locations.index')
->with('success', trans_choice('general.bulk.delete.success', $success_count,
['object_type' => trans_choice('general.location_plural', $success_count), 'count' => $success_count]
));
}

// Partial success
if ($error_count > 0) {
return redirect()
->route('locations.index')
->with('warning', trans('general.bulk.partial_success',
['success' => $success_count, 'error' => $error_count, 'object_type' => trans('general.locations')]
));
}
}


// Nothing was selected - return to the index
return redirect()
->route('locations.index')
->with('error', trans('general.bulk.nothing_selected',
['object_type' => trans('general.locations')]
));

}
}
3 changes: 3 additions & 0 deletions app/Http/Transformers/LocationsTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ public function transformLocation(Location $location = null)
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Location::class) ? true : false,
'delete' => $location->isDeletable(),
'bulk_selectable' => [
'delete' => $location->isDeletable()
],
'clone' => (Gate::allows('create', Location::class) && ($location->deleted_at == '')),
];

Expand Down
1 change: 1 addition & 0 deletions app/Models/Location.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public function isDeletable()
return Gate::allows('delete', $this)
&& ($this->assignedAssets()->count() === 0)
&& ($this->assets()->count() === 0)
&& ($this->children()->count() === 0)
&& ($this->users()->count() === 0);
}

Expand Down
6 changes: 5 additions & 1 deletion app/Presenters/LocationPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ class LocationPresenter extends Presenter
public static function dataTableLayout()
{
$layout = [

[
'field' => 'bulk_selectable',
'checkbox' => true,
'formatter' => 'checkboxEnabledFormatter',
],
[
'field' => 'id',
'searchable' => false,
Expand Down
12 changes: 0 additions & 12 deletions app/Providers/SettingsServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,12 @@ public function boot()
$limit = abs($int_limit);
}

// \Log::debug('Max in env: '.config('app.max_results'));
// \Log::debug('Original requested limit: '.request('limit'));
// \Log::debug('Int limit: '.$int_limit);
// \Log::debug('Modified limit: '.$limit);
// \Log::debug('------------------------------');


return $limit;
});

// Make sure the offset is actually set and is an integer
\App::singleton('api_offset_value', function () {
$offset = intval(request('offset'));
// \Log::debug('Original requested offset: '.request('offset'));
// \Log::debug('Modified offset: '.$offset);
// \Log::debug('------------------------------');


return $offset;
});

Expand Down
13 changes: 12 additions & 1 deletion resources/lang/en-US/general.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@
'lock_passwords' => 'This field value will not be saved in a demo installation.',
'feature_disabled' => 'This feature has been disabled for the demo installation.',
'location' => 'Location',
'location_plural' => 'Location|Locations',
'locations' => 'Locations',
'logo_size' => 'Square logos look best with Logo + Text. Logo maximum display size is 50px high x 500px wide. ',
'logout' => 'Logout',
Expand Down Expand Up @@ -443,7 +444,6 @@
'sample_value' => 'Sample Value',
'no_headers' => 'No Columns Found',
'error_in_import_file' => 'There was an error reading the CSV file: :error',
'percent_complete' => ':percent % Complete',
'errors_importing' => 'Some Errors occurred while importing: ',
'warning' => 'WARNING: :warning',
'success_redirecting' => '"Success... Redirecting.',
Expand Down Expand Up @@ -503,5 +503,16 @@
'or' => 'or',
'url' => 'URL',
'edit_fieldset' => 'Edit fieldset fields and options',
'bulk' => [
'delete' =>
[
'header' => 'Bulk Delete :object_type',
'warn' => 'You are about to delete one :object_type|You are about to delete :count :object_type',
'success' => ':object_type successfully deleted|Successfully deleted :count :object_type',
'error' => 'Could not delete :object_type',
'nothing_selected' => 'No :object_type selected - nothing to do',
'partial' => 'Deleted :success_count :object_type, but :error_count :object_type could not be deleted',
],
],

];
70 changes: 70 additions & 0 deletions resources/views/locations/bulk-delete.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
@extends('layouts/default')

{{-- Page title --}}
@section('title')
{{ trans('general.bulk.delete.header', ['object_type' => trans_choice('general.location_plural', $valid_count)]) }}
@parent
@stop

@section('header_right')
<a href="{{ URL::previous() }}" class="btn btn-primary pull-right">
{{ trans('general.back') }}</a>
@stop

{{-- Page content --}}
@section('content')
<div class="row">
<!-- left column -->
<div class="col-md-8 col-md-offset-2">
<form class="form-horizontal" method="post" action="{{ route('locations.bulkdelete.store') }}" autocomplete="off" role="form">
{{csrf_field()}}
<div class="box box-default">
<div class="box-header with-border">
<h2 class="box-title" style="color: red">{{ trans_choice('general.bulk.delete.warn', $valid_count, ['count' => $valid_count,'object_type' => trans_choice('general.location_plural', $valid_count)]) }}</h2>
</div>

<div class="box-body">
<table class="table table-striped table-condensed">
<thead>
<tr>
<td class="col-md-1">
<label>
<input type="checkbox" id="checkAll" checked="checked">
</label>
</td>
<td class="col-md-10">{{ trans('general.name') }}</td>
</tr>
</thead>
<tbody>
@foreach ($locations as $location)
<tr{!! (($location->assets_count > 0 ) ? ' class="danger"' : '') !!}>
<td>
<input type="checkbox" name="ids[]" class="{ ($location->isDeletable() ? '' : ' disabled') }}" value="{{ $location->id }}" {!! (($location->isDeletable()) ? ' checked="checked"' : ' disabled') !!}>
</td>
<td>{{ $location->name }}</td>

</tr>
@endforeach
</tbody>
</table>
</div><!-- /.box-body -->

<div class="box-footer text-right">
<a class="btn btn-link pull-left" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>
<button type="submit" class="btn btn-success" id="submit-button"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('general.delete') }}</button>
</div><!-- /.box-footer -->
</div><!-- /.box -->
</form>
</div> <!-- .col-md-12-->
</div><!--.row-->
@stop
@section('moar_scripts')
<script>
$("#checkAll").change(function () {
$("input:checkbox").prop('checked', $(this).prop("checked"));
});
</script>
@stop
6 changes: 6 additions & 0 deletions resources/views/locations/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,17 @@
<div class="box-body">
<div class="table-responsive">

@include('partials.locations-bulk-actions')

<table
data-columns="{{ \App\Presenters\LocationPresenter::dataTableLayout() }}"
data-cookie-id-table="locationTable"
data-click-to-select="true"
data-pagination="true"
data-id-table="locationTable"
data-toolbar="#locationsBulkEditToolbar"
data-bulk-button-id="#bulkLocationsEditButton"
data-bulk-form-id="#locationsBulkForm"
data-search="true"
data-show-footer="true"
data-side-pagination="server"
Expand Down
Loading

0 comments on commit 71610fb

Please sign in to comment.