Implement deletion functionality for uploaded images and files

This commit is contained in:
Kevin MacMartin 2018-01-21 20:55:07 -05:00
parent 5c2ad8cccb
commit 27ef5d09e5
7 changed files with 179 additions and 26 deletions

View file

@ -105,7 +105,7 @@ class DashboardController extends Controller {
$directory = base_path() . '/public/uploads/' . $request['model'] . '/img/'; $directory = base_path() . '/public/uploads/' . $request['model'] . '/img/';
file::makeDirectory($directory, 0755, true, true); file::makeDirectory($directory, 0755, true, true);
$image = Image::make($request->file('file')); $image = Image::make($request->file('file'));
$image->save($directory . $request['id'] . "-" . $request['name'] . '.jpg'); $image->save($directory . $request['id'] . '-' . $request['name'] . '.jpg');
} else { } else {
return 'file-upload-fail'; return 'file-upload-fail';
} }
@ -128,7 +128,7 @@ class DashboardController extends Controller {
if ($request->hasFile('file')) { if ($request->hasFile('file')) {
$directory = base_path() . '/public/uploads/' . $request['model'] . '/files/'; $directory = base_path() . '/public/uploads/' . $request['model'] . '/files/';
file::makeDirectory($directory, 0755, true, true); file::makeDirectory($directory, 0755, true, true);
$request->file('file')->move($directory, $request['id'] . "-" . $request['name'] . '.' . $request['ext']); $request->file('file')->move($directory, $request['id'] . '-' . $request['name'] . '.' . $request['ext']);
} else { } else {
return 'file-upload-fail'; return 'file-upload-fail';
} }
@ -242,4 +242,49 @@ class DashboardController extends Controller {
return 'success'; return 'success';
} }
/**
* Dashboard Image Delete: Delete images
*/
public function deleteImageDelete(Request $request)
{
$this->validate($request, [
'id' => 'required',
'model' => 'required',
'name' => 'required'
]);
$image = base_path() . '/public/uploads/' . $request['model'] . '/img/' . $request['id'] . '-' . $request['name'] . '.jpg';
if (!file_exists($image)) {
return 'image-not-exists-fail';
} else if (!unlink($image)) {
return 'image-delete-fail';
}
return 'success';
}
/**
* Dashboard File Delete: Delete files
*/
public function deleteFileDelete(Request $request)
{
$this->validate($request, [
'id' => 'required',
'model' => 'required',
'name' => 'required',
'ext' => 'required'
]);
$file = base_path() . '/public/uploads/' . $request['model'] . '/files/' . $request['id'] . '-' . $request['name'] . '.' . $request['ext'];
if (!file_exists($file)) {
return 'file-not-exists-fail';
} else if (!unlink($file)) {
return 'file-delete-fail';
}
return 'success';
}
} }

View file

@ -207,9 +207,11 @@ The following is a list of possible `types` in the `columns` array for Editable
* `hidden`: Fields that will contain values to pass to the update function but won't appear on the page (this must be used for the sort column) * `hidden`: Fields that will contain values to pass to the update function but won't appear on the page (this must be used for the sort column)
* `image`: Fields that contain image uploads * `image`: Fields that contain image uploads
* `name`: not part of the database and is instead used in the filename * `name`: not part of the database and is instead used in the filename
* `delete`: (optional) if true then uploaded images can be deleted
* `file`: Fields that contains file uploads * `file`: Fields that contains file uploads
* `name`: not part of the database and is instead used in the filename * `name`: not part of the database and is instead used in the filename
* `ext` required key containing the file extension * `ext` required key containing the file extension
* `delete`: (optional) if true then uploaded files can be deleted
* `display`: Displayed information that can't be edited * `display`: Displayed information that can't be edited
#### Edit Item Functionality #### Edit Item Functionality

View file

@ -2,7 +2,7 @@
jQuery.fn.reverse = [].reverse; jQuery.fn.reverse = [].reverse;
// show the confirmation modal and run the supplied command if confirm is pressed // show the confirmation modal and run the supplied command if confirm is pressed
function askConfirmation(message, command) { function askConfirmation(message, command, cancelCommand) {
const $confirmationModal = $("#confirmation-modal"), const $confirmationModal = $("#confirmation-modal"),
$heading = $confirmationModal.find(".panel-heading"), $heading = $confirmationModal.find(".panel-heading"),
$cancelButton = $confirmationModal.find(".btn.cancel-button"), $cancelButton = $confirmationModal.find(".btn.cancel-button"),
@ -35,8 +35,17 @@ function askConfirmation(message, command) {
closeConfirmationModal(); closeConfirmationModal();
}; };
// functionality to run when clicking the cancel button
const cancelModal = function() {
if (cancelCommand !== undefined) {
cancelCommand();
}
closeConfirmationModal();
};
// hide the modal when the cancel button is pressed // hide the modal when the cancel button is pressed
$cancelButton.on("click", closeConfirmationModal); $cancelButton.on("click", cancelModal);
// hide the modal when the escape key is pressed // hide the modal when the escape key is pressed
$(document).on("keyup", escapeModal); $(document).on("keyup", escapeModal);
@ -103,6 +112,7 @@ function showAlert(message, command) {
function editListInit() { function editListInit() {
const editList = document.getElementById("edit-list"), const editList = document.getElementById("edit-list"),
$editList = $(editList), $editList = $(editList),
$token = $("#token"),
model = $editList.data("model"), model = $editList.data("model"),
path = $editList.data("path"); path = $editList.data("path");
@ -145,7 +155,7 @@ function editListInit() {
data: { data: {
model: model, model: model,
id: itemId, id: itemId,
_token: $("#token").val() _token: $token.val()
} }
}).always(function(response) { }).always(function(response) {
if (response === "success") { if (response === "success") {
@ -177,7 +187,7 @@ function editListInit() {
url: postUrl, url: postUrl,
data: { data: {
id: itemId, id: itemId,
_token: $("#token").val() _token: $token.val()
} }
}).always(function(response) { }).always(function(response) {
if (response === "success") { if (response === "success") {
@ -212,7 +222,7 @@ function editListInit() {
model: model, model: model,
order: sortOrder, order: sortOrder,
column: sortCol, column: sortCol,
_token: $("#token").val() _token: $token.val()
} }
}).always(function(response) { }).always(function(response) {
if (response !== "success") { if (response !== "success") {
@ -267,7 +277,7 @@ function editItemInit() {
$mkdEditors = $(".mkd-editor"), $mkdEditors = $(".mkd-editor"),
$fileUploads = $(".file-upload"), $fileUploads = $(".file-upload"),
$imgUploads = $(".image-upload"), $imgUploads = $(".image-upload"),
$token = $("#_token"), $token = $("#token"),
$spinner = $("#loading-modal"), $spinner = $("#loading-modal"),
fadeTime = 250, fadeTime = 250,
model = $editItem.data("model"), model = $editItem.data("model"),
@ -440,6 +450,74 @@ function editItemInit() {
} }
}; };
$(".edit-button.delete.image").on("click", function(e) {
const $this = $(this),
name = $this.data("name");
if (!submitting) {
submitting = true;
askConfirmation("Are you sure you want to delete this image?", function() {
// delete the image
$.ajax({
type: "DELETE",
url: "/dashboard/image-delete",
data: {
id: id,
model: model,
name: name,
_token: $token.val()
}
}).always(function(response) {
if (response === "success") {
$(`#current-image-${name}`).slideUp(200);
} else {
showAlert("ERROR: Failed to delete the image: " + response);
}
submitting = false;
});
}, function() {
submitting = false;
});
}
});
$(".edit-button.delete.file").on("click", function(e) {
const $this = $(this),
name = $this.data("name"),
ext = $this.data("ext");
if (!submitting) {
submitting = true;
askConfirmation("Are you sure you want to delete this file?", function() {
// delete the file
$.ajax({
type: "DELETE",
url: "/dashboard/file-delete",
data: {
id: id,
model: model,
name: name,
ext: ext,
_token: $token.val()
}
}).always(function(response) {
if (response === "success") {
$(`#current-file-${name}`).slideUp(200);
} else {
showAlert("ERROR: Failed to delete the file: " + response);
}
submitting = false;
});
}, function() {
submitting = false;
});
}
});
// allow start time selection to start on the hour and every 15 minutes after // allow start time selection to start on the hour and every 15 minutes after
for (hours = 0; hours <= 23; hours++) { for (hours = 0; hours <= 23; hours++) {
for (minutes = 0; minutes <= 3; minutes++) { for (minutes = 0; minutes <= 3; minutes++) {
@ -518,7 +596,6 @@ function editItemInit() {
// populate the formData object // populate the formData object
getFormData(); getFormData();
// console.log(JSON.stringify(formData));
// submit the update // submit the update
$.ajax({ $.ajax({

View file

@ -397,23 +397,38 @@ body {
max-width: 100%; max-width: 100%;
} }
.current-file { .edit-button {
margin-bottom: ($grid-gutter-width / 2);
display: inline-block;
padding: 5px 10px; padding: 5px 10px;
border: 1px solid darken($c-dashboard-dark, 5%);
border-radius: 5px; border-radius: 5px;
background-color: $c-dashboard-dark;
color: $c-text-light;
text-transform: uppercase; text-transform: uppercase;
transition: background-color 150ms; transition: background-color 150ms;
cursor: pointer;
&:hover, &:focus {
text-decoration: none;
}
&.view {
border: 1px solid darken($c-dashboard-dark, 5%);
background-color: $c-dashboard-dark;
color: $c-text-light;
&:hover { &:hover {
background-color: lighten($c-dashboard-dark, 5%); background-color: lighten($c-dashboard-dark, 5%);
text-decoration: none;
} }
} }
.no-file { &.delete {
margin-bottom: 15px; border: 1px solid darken($c-dashboard-delete, 5%);
background-color: $c-dashboard-delete;
color: $c-text-light;
&:hover {
background-color: lighten($c-dashboard-delete, 5%);
}
}
} }
.back-button { .back-button {

View file

@ -14,7 +14,7 @@
@endif @endif
<form id="edit-item" class="edit-item" data-id="{{ $id }}" data-model="{{ $model }}" data-path="{{ isset($path) ? $path : $model }}"> <form id="edit-item" class="edit-item" data-id="{{ $id }}" data-model="{{ $model }}" data-path="{{ isset($path) ? $path : $model }}">
<input type="hidden" name="_token" id="_token" value="{{ csrf_token() }}" /> <input type="hidden" id="token" value="{{ csrf_token() }}" />
<div class="container-fluid"> <div class="container-fluid">
@foreach($columns as $column) @foreach($columns as $column)
@ -51,9 +51,15 @@
@set('current_image', "/uploads/$model/img/$id-" . $column['name'] . '.jpg') @set('current_image', "/uploads/$model/img/$id-" . $column['name'] . '.jpg')
@if(file_exists(base_path() . '/public' . $current_image)) @if(file_exists(base_path() . '/public' . $current_image))
<div id="current-image-{{ $column['name'] }}">
<img class="current-image" src="{{ $current_image }}" /> <img class="current-image" src="{{ $current_image }}" />
@else
<div class="no-file">(No Image Set)</div> @if(array_key_exists('delete', $column) && $column['delete'])
<span class="edit-button delete image" data-name="{{ $column['name'] }}">
Delete Image
</span>
@endif
</div>
@endif @endif
@elseif($column['type'] == 'file') @elseif($column['type'] == 'file')
<input class="file-upload" type="file" name="{{ $column['name'] }}" id="{{ $column['name'] }}" data-ext="{{ $column['ext'] }}" /> <input class="file-upload" type="file" name="{{ $column['name'] }}" id="{{ $column['name'] }}" data-ext="{{ $column['ext'] }}" />
@ -61,9 +67,15 @@
@set('current_file', "/uploads/$model/files/$id-" . $column['name'] . '.' . $column['ext']) @set('current_file', "/uploads/$model/files/$id-" . $column['name'] . '.' . $column['ext'])
@if(file_exists(base_path() . '/public' . $current_file)) @if(file_exists(base_path() . '/public' . $current_file))
<a class="current-file" href="{{ $current_file }}" target="_blank">View Current {{ strtoupper($column['ext']) }}</a> <div id="current-file-{{ $column['name'] }}">
@else <a class="edit-button view" href="{{ $current_file }}" target="_blank">View {{ strtoupper($column['ext']) }}</a>
<div class="no-file">(No {{ strtoupper($column['ext']) }} Set)</div>
@if(array_key_exists('delete', $column) && $column['delete'])
<span class="edit-button delete file" data-name="{{ $column['name'] }}" data-ext="{{ $column['ext'] }}">
Delete {{ strtoupper($column['ext']) }}
</span>
@endif
</div>
@endif @endif
@elseif($column['type'] == 'display') @elseif($column['type'] == 'display')
<div class="text-display">{{ $value }}</div> <div class="text-display">{{ $value }}</div>

View file

@ -12,7 +12,7 @@
@section('dashboard-body') @section('dashboard-body')
<div id="edit-list-wrapper"> <div id="edit-list-wrapper">
<input type="hidden" name="_token" id="token" value="{{ csrf_token() }}" /> <input type="hidden" id="token" value="{{ csrf_token() }}" />
@if($filter) @if($filter)
<input id="filter-input" class="search" placeholder="Filter" /> <input id="filter-input" class="search" placeholder="Filter" />

View file

@ -38,6 +38,8 @@ Route::group([ 'prefix' => 'dashboard' ], function() {
Route::post('/edit', 'DashboardController@postEdit'); Route::post('/edit', 'DashboardController@postEdit');
Route::post('/reorder', 'DashboardController@postReorder'); Route::post('/reorder', 'DashboardController@postReorder');
Route::delete('/delete', 'DashboardController@deleteDelete'); Route::delete('/delete', 'DashboardController@deleteDelete');
Route::delete('/image-delete', 'DashboardController@deleteImageDelete');
Route::delete('/file-delete', 'DashboardController@deleteFileDelete');
}); });
/* /*