mirror of
https://github.com/linuxserver/Heimdall.git
synced 2025-11-12 19:02:53 +09:00
fixes to alerts and soft deleting
This commit is contained in:
@@ -90,11 +90,19 @@ class ItemController extends Controller
|
|||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\Response
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
|
$trash = (bool)$request->input('trash');
|
||||||
|
|
||||||
$data['apps'] = Item::all();
|
$data['apps'] = Item::all();
|
||||||
|
$data['trash'] = Item::onlyTrashed()->get();
|
||||||
|
if($trash) {
|
||||||
|
return view('items.trash', $data);
|
||||||
|
} else {
|
||||||
return view('items.list', $data);
|
return view('items.list', $data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the form for creating a new resource.
|
* Show the form for creating a new resource.
|
||||||
@@ -197,11 +205,35 @@ class ItemController extends Controller
|
|||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\Response
|
||||||
*/
|
*/
|
||||||
public function destroy($id)
|
public function destroy(Request $request, $id)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
$force = (bool)$request->input('force');
|
||||||
|
if($force) {
|
||||||
|
Item::withTrashed()
|
||||||
|
->where('id', $id)
|
||||||
|
->forceDelete();
|
||||||
|
} else {
|
||||||
Item::find($id)->delete();
|
Item::find($id)->delete();
|
||||||
return redirect()->route('dash')
|
}
|
||||||
|
|
||||||
|
return redirect()->route('items.index')
|
||||||
->with('success','Item deleted successfully');
|
->with('success','Item deleted successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the specified resource from soft deletion.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function restore($id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
Item::withTrashed()
|
||||||
|
->where('id', $id)
|
||||||
|
->restore();
|
||||||
|
return redirect()->route('items.index')
|
||||||
|
->with('success','Item restored successfully');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
app/Item.php
11
app/Item.php
@@ -4,16 +4,25 @@ namespace App;
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Symfony\Component\ClassLoader\ClassMapGenerator;
|
use Symfony\Component\ClassLoader\ClassMapGenerator;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
|
||||||
class Item extends Model
|
class Item extends Model
|
||||||
{
|
{
|
||||||
|
use SoftDeletes;
|
||||||
|
|
||||||
//
|
//
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'title', 'url', 'colour', 'icon', 'description', 'pinned', 'order'
|
'title', 'url', 'colour', 'icon', 'description', 'pinned', 'order'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be mutated to dates.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $dates = ['deleted_at'];
|
||||||
|
|
||||||
public static function supportedList()
|
public static function supportedList()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class CreateItemsTable extends Migration
|
|||||||
$table->text('description')->nullable();
|
$table->text('description')->nullable();
|
||||||
$table->boolean('pinned')->default(false);
|
$table->boolean('pinned')->default(false);
|
||||||
$table->integer('order')->default(0);
|
$table->integer('order')->default(0);
|
||||||
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
77
public/css/app.css
vendored
77
public/css/app.css
vendored
@@ -357,11 +357,65 @@ body {
|
|||||||
|
|
||||||
.message-container {
|
.message-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding: 10px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-container .alert {
|
.message-container2 {
|
||||||
margin: 30px;
|
width: 100%;
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
margin: 30px auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
max-width: 800px;
|
||||||
|
background: #f1f4f7;
|
||||||
|
padding: 5px 20px;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding-left: 80px;
|
||||||
|
-webkit-box-shadow: 0 0 15px 3px rgba(0, 0, 0, 0.3);
|
||||||
|
box-shadow: 0 0 15px 3px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert.alert-success,
|
||||||
|
.alert.alert-danger {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert.alert-success:before,
|
||||||
|
.alert.alert-danger:before {
|
||||||
|
content: "\F00C";
|
||||||
|
font-family: 'Font Awesome 5 Pro';
|
||||||
|
font-weight: 900;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 60px;
|
||||||
|
background: #1cd41c;
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
line-height: 57px;
|
||||||
|
font-size: 24px;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert.alert-danger:before {
|
||||||
|
content: "\F00D";
|
||||||
|
background: #c00;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app.header .appheader {
|
#app.header .appheader {
|
||||||
@@ -658,9 +712,22 @@ div.create .input input {
|
|||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidenav {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenav .close-sidenav {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
.sidenav h2 {
|
.sidenav h2 {
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidenav ul {
|
.sidenav ul {
|
||||||
@@ -687,6 +754,12 @@ div.create .input input {
|
|||||||
color: #46b0e6;
|
color: #46b0e6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.trashed {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #91a1b3;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Huebee v2.0.0
|
/*! Huebee v2.0.0
|
||||||
http://huebee.buzz
|
http://huebee.buzz
|
||||||
---------------------------------------------- */
|
---------------------------------------------- */
|
||||||
|
|||||||
14
public/js/app.js
vendored
14
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"/css/app.css": "/css/app.css?id=9826be622435e2ba23ee",
|
"/css/app.css": "/css/app.css?id=70beb203b1a0bdd09b29",
|
||||||
"/js/app.js": "/js/app.js?id=c40626c00c299e2aeed0"
|
"/js/app.js": "/js/app.js?id=aa9e426dc7b92d42d3b2"
|
||||||
}
|
}
|
||||||
14
resources/assets/js/app.js
vendored
14
resources/assets/js/app.js
vendored
@@ -1,7 +1,14 @@
|
|||||||
$.when( $.ready ).then(function() {
|
$.when( $.ready ).then(function() {
|
||||||
|
|
||||||
|
if($('.message-container').length) {
|
||||||
|
setTimeout(
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
$('.message-container').fadeOut();
|
||||||
|
}, 3500);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
$( "#sortable" ).sortable({
|
$( "#sortable" ).sortable({
|
||||||
stop: function (event, ui) {
|
stop: function (event, ui) {
|
||||||
@@ -41,12 +48,17 @@ $.when( $.ready ).then(function() {
|
|||||||
}, 350);
|
}, 350);
|
||||||
|
|
||||||
}
|
}
|
||||||
}).on('click', '#add-item', function(e) {
|
}).on('click', '#add-item, #pin-item', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var app = $('#app');
|
var app = $('#app');
|
||||||
var active = (app.hasClass('sidebar'));
|
var active = (app.hasClass('sidebar'));
|
||||||
app.toggleClass('sidebar');
|
app.toggleClass('sidebar');
|
||||||
|
|
||||||
|
}).on('click', '.close-sidenav', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var app = $('#app');
|
||||||
|
app.removeClass('sidebar');
|
||||||
|
|
||||||
});
|
});
|
||||||
$('#pinlist').on('click', 'a', function(e) {
|
$('#pinlist').on('click', 'a', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
63
resources/assets/sass/_app.scss
vendored
63
resources/assets/sass/_app.scss
vendored
@@ -96,11 +96,52 @@ body {
|
|||||||
}
|
}
|
||||||
.message-container {
|
.message-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.alert {
|
padding: 10px 20px;
|
||||||
margin: 30px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.message-container2 {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
.alert {
|
||||||
|
margin: 30px auto;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 800px;
|
||||||
|
background: #f1f4f7;
|
||||||
|
padding: 5px 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-left: 80px;
|
||||||
|
box-shadow: 0 0 15px 3px rgba(0,0,0,0.3);
|
||||||
|
&.alert-success, &.alert-danger {
|
||||||
|
position: relative;
|
||||||
|
&:before {
|
||||||
|
content: "\f00c";
|
||||||
|
font-family: 'Font Awesome 5 Pro';
|
||||||
|
font-weight: 900;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 60px;
|
||||||
|
background: #1cd41c;
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
line-height: 57px;
|
||||||
|
font-size: 24px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.alert-danger {
|
||||||
|
&:before {
|
||||||
|
content: "\f00d";
|
||||||
|
background: #c00;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
&.header {
|
&.header {
|
||||||
.appheader {
|
.appheader {
|
||||||
@@ -343,9 +384,18 @@ div.create {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidenav {
|
.sidenav {
|
||||||
|
position: relative;
|
||||||
|
.close-sidenav {
|
||||||
|
position: absolute;
|
||||||
|
top:20px;
|
||||||
|
right: 20px;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
h2 {
|
h2 {
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
ul {
|
ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
@@ -364,3 +414,8 @@ div.create {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.trashed {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #91a1b3;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<nav class="sidenav">
|
<nav class="sidenav">
|
||||||
|
<a class="close-sidenav" href=""><i class="fas fa-times-circle"></i></a>
|
||||||
@if(isset($all_apps))
|
@if(isset($all_apps))
|
||||||
<h2>Pinned Items</h2>
|
<h2>Pinned Items</h2>
|
||||||
<ul id="pinlist">
|
<ul id="pinlist">
|
||||||
@@ -41,7 +42,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@if (count($errors) < 0)
|
@if (count($errors) > 0)
|
||||||
<div class="message-container">
|
<div class="message-container">
|
||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger">
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -3,7 +3,13 @@
|
|||||||
@section('content')
|
@section('content')
|
||||||
<section class="module-container">
|
<section class="module-container">
|
||||||
<header>
|
<header>
|
||||||
<div class="section-title">Application list</div>
|
<div class="section-title">
|
||||||
|
Application list
|
||||||
|
@if( isset($trash) && $trash->count() > 0 )
|
||||||
|
<a class="trashed" href="{{ route('items.index', ['trash' => true]) }}">View trash ({{ $trash->count() }})</a>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</div>
|
||||||
<div class="module-actions">
|
<div class="module-actions">
|
||||||
<a href="{{ route('items.create') }}" title="" class="button"><i class="fa fa-plus"></i><span>Add</span></a>
|
<a href="{{ route('items.create') }}" title="" class="button"><i class="fa fa-plus"></i><span>Add</span></a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
54
resources/views/items/trash.blade.php
Normal file
54
resources/views/items/trash.blade.php
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
@extends('app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<section class="module-container">
|
||||||
|
<header>
|
||||||
|
<div class="section-title">
|
||||||
|
Showing Deleted Applications
|
||||||
|
</div>
|
||||||
|
<div class="module-actions">
|
||||||
|
<a href="{{ route('items.index') }}" title="" class="button"><i class="fa fa-ban"></i><span>Cancel</span></a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Url</th>
|
||||||
|
<th class="text-center" width="100">Restore</th>
|
||||||
|
<th class="text-center" width="100">Delete</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@if($trash->first())
|
||||||
|
@foreach($trash as $app)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $app->title }}</td>
|
||||||
|
<td>{{ $app->description }}</td>
|
||||||
|
<td>{{ $app->url }}</td>
|
||||||
|
<td class="text-center"><a href="{!! route('items.restore', $app->id) !!}" title="Restore {!! $app->title !!}"><i class="fas fa-edit"></i></a></td>
|
||||||
|
<td class="text-center">
|
||||||
|
{!! Form::open(['method' => 'DELETE','route' => ['items.destroy', $app->id],'style'=>'display:inline']) !!}
|
||||||
|
<input type="hidden" name="force" value="1" />
|
||||||
|
<button type="submit"><i class="fa fa-trash-alt"></i></button>
|
||||||
|
{!! Form::close() !!}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
@else
|
||||||
|
<tr>
|
||||||
|
<td colspan="5" class="form-error text-center">
|
||||||
|
<strong>No items found</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
@endsection
|
||||||
@@ -4,8 +4,15 @@
|
|||||||
@if($apps->first())
|
@if($apps->first())
|
||||||
@include('sortable')
|
@include('sortable')
|
||||||
@else
|
@else
|
||||||
There are currently no Applications, <a href="{{ route('items.create') }}">add one here</a>
|
<div class="message-container2">
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<p>There are currently no pinned Applications, <a href="{{ route('items.create') }}">Add an application here</a> or <a id="pin-item" href="">Pin an item to the dash</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="sortable">
|
||||||
@include('add')
|
@include('add')
|
||||||
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ Route::resources([
|
|||||||
'items' => 'ItemController',
|
'items' => 'ItemController',
|
||||||
]);
|
]);
|
||||||
Route::get('items/pin/{id}', 'ItemController@pin')->name('items.pin');
|
Route::get('items/pin/{id}', 'ItemController@pin')->name('items.pin');
|
||||||
|
Route::get('items/restore/{id}', 'ItemController@restore')->name('items.restore');
|
||||||
Route::get('items/unpin/{id}', 'ItemController@unpin')->name('items.unpin');
|
Route::get('items/unpin/{id}', 'ItemController@unpin')->name('items.unpin');
|
||||||
Route::get('items/pintoggle/{id}/{ajax?}', 'ItemController@pinToggle')->name('items.pintoggle');
|
Route::get('items/pintoggle/{id}/{ajax?}', 'ItemController@pinToggle')->name('items.pintoggle');
|
||||||
Route::post('order', 'ItemController@setOrder')->name('items.order');
|
Route::post('order', 'ItemController@setOrder')->name('items.order');
|
||||||
Reference in New Issue
Block a user