added order saving, dragging and pinning

This commit is contained in:
KodeStar 2018-02-03 00:22:42 +00:00
parent 7c859b629e
commit 25bbf6f99a
18 changed files with 283 additions and 43 deletions

View file

@ -17,10 +17,73 @@ class ItemController extends Controller
*/ */
public function dash() public function dash()
{ {
$data['apps'] = Item::all(); $data['apps'] = Item::pinned()->orderBy('order', 'asc')->get();
$data['all_apps'] = Item::all();
return view('welcome', $data); return view('welcome', $data);
} }
/**
* Set order on the dashboard.
*
* @return \Illuminate\Http\Response
*/
public function setOrder(Request $request)
{
$order = array_filter($request->input('order'));
foreach($order as $o => $id) {
$item = Item::find($id);
$item->order = $o;
$item->save();
}
}
/**
* Pin item on the dashboard.
*
* @return \Illuminate\Http\Response
*/
public function pin($id)
{
$item = Item::findOrFail($id);
$item->pinned = true;
$item->save();
return redirect()->route('dash');
}
/**
* Unpin item on the dashboard.
*
* @return \Illuminate\Http\Response
*/
public function unpin($id)
{
$item = Item::findOrFail($id);
$item->pinned = false;
$item->save();
return redirect()->route('dash');
}
/**
* Unpin item on the dashboard.
*
* @return \Illuminate\Http\Response
*/
public function pinToggle($id, $ajax=false)
{
$item = Item::findOrFail($id);
$new = ((bool)$item->pinned === true) ? false : true;
$item->pinned = $new;
$item->save();
if($ajax) {
$data['apps'] = Item::pinned()->get();
$data['ajax'] = true;
return view('sortable', $data);
} else {
return redirect()->route('dash');
}
}
/** /**
* Display a listing of the resource. * Display a listing of the resource.

View file

@ -13,5 +13,6 @@ class VerifyCsrfToken extends Middleware
*/ */
protected $except = [ protected $except = [
// //
'order'
]; ];
} }

View file

@ -11,7 +11,7 @@ class Item extends Model
{ {
// //
protected $fillable = [ protected $fillable = [
'title', 'url', 'colour', 'icon', 'description', 'pinned' 'title', 'url', 'colour', 'icon', 'description', 'pinned', 'order'
]; ];
public static function supportedList() public static function supportedList()
@ -25,4 +25,15 @@ class Item extends Model
{ {
return array_keys(self::supportedList()); return array_keys(self::supportedList());
} }
/**
* Scope a query to only include pinned items.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePinned($query)
{
return $query->where('pinned', 1);
}
} }

View file

@ -21,6 +21,7 @@ class CreateItemsTable extends Migration
$table->string('url'); $table->string('url');
$table->text('description')->nullable(); $table->text('description')->nullable();
$table->boolean('pinned')->default(false); $table->boolean('pinned')->default(false);
$table->integer('order')->default(0);
$table->timestamps(); $table->timestamps();
}); });
} }

71
public/css/app.css vendored
View file

@ -318,7 +318,8 @@ body {
padding: 20px; padding: 20px;
} }
#app main { #app main,
#app #sortable {
padding: 10px; padding: 10px;
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
@ -337,9 +338,12 @@ body {
flex-wrap: wrap; flex-wrap: wrap;
-ms-flex-line-pack: center; -ms-flex-line-pack: center;
align-content: center; align-content: center;
list-style: none;
margin: 0;
} }
#app main .config { #app main .config,
#app #sortable .config {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 0; right: 0;
@ -351,12 +355,6 @@ body {
color: white; color: white;
} }
.item-container {
width: 340px;
-webkit-transition: all .35s ease-in-out;
transition: all .35s ease-in-out;
}
.message-container { .message-container {
width: 100%; width: 100%;
} }
@ -370,15 +368,12 @@ body {
top: 0; top: 0;
} }
#app.header .item-container {
width: 280px;
}
#app.header .item, #app.header .item,
#app.header .add-item { #app.header .add-item {
-webkit-transform: scale(0.8); -webkit-transform: scale(0.8);
transform: scale(0.8); transform: scale(0.8);
opacity: 0.7; opacity: 0.7;
margin: 20px 0;
} }
#app.sidebar nav { #app.sidebar nav {
@ -404,6 +399,10 @@ body {
outline: 1px solid transparent; outline: 1px solid transparent;
} }
.add-item.active {
display: block;
}
.add-item a { .add-item a {
display: block; display: block;
width: 100%; width: 100%;
@ -436,9 +435,9 @@ body {
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
display: flex; display: flex;
-webkit-box-align: start; -webkit-box-align: center;
-ms-flex-align: start; -ms-flex-align: center;
align-items: flex-start; align-items: center;
} }
.item:after { .item:after {
@ -482,7 +481,8 @@ body {
margin: 0 40px; margin: 0 40px;
} }
.module-container header { .module-container header,
.module-container footer {
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
display: flex; display: flex;
@ -500,12 +500,17 @@ body {
position: relative; position: relative;
} }
.module-container header .section-title { .module-container header .section-title,
.module-container footer .section-title {
font-size: 18px; font-size: 18px;
color: #5b5b5b; color: #5b5b5b;
margin-left: 25px; margin-left: 25px;
} }
.module-container footer {
border-top: 1px solid #dbdce3;
}
.module-container .table { .module-container .table {
width: 100%; width: 100%;
margin: 0; margin: 0;
@ -649,7 +654,37 @@ div.create .input input {
} }
.app-icon { .app-icon {
max-width: 50px; max-width: 60px;
margin-right: 10px;
}
.sidenav h2 {
font-weight: 300;
padding: 20px;
}
.sidenav ul {
list-style: none;
margin: 0;
padding: 20px;
}
.sidenav ul li {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
padding: 5px;
}
.sidenav ul li a {
color: #2b3542;
}
.sidenav ul li a.active {
color: #46b0e6;
} }
/*! Huebee v2.0.0 /*! Huebee v2.0.0

32
public/js/app.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
{ {
"/css/app.css": "/css/app.css?id=6ca0518736a7940b1f8a", "/css/app.css": "/css/app.css?id=9826be622435e2ba23ee",
"/js/app.js": "/js/app.js?id=04ddfaaf5e66ed51b426" "/js/app.js": "/js/app.js?id=c40626c00c299e2aeed0"
} }

View file

@ -1,4 +1,23 @@
$.when( $.ready ).then(function() { $.when( $.ready ).then(function() {
$( "#sortable" ).sortable({
stop: function (event, ui) {
var idsInOrder = $("#sortable").sortable('toArray', {
attribute: 'data-id'
});
$.post(
'/order',
{ order:idsInOrder }
);
}
});
$("#sortable").sortable("disable");
$('.color-picker').each( function( i, elem ) { $('.color-picker').each( function( i, elem ) {
var hueb = new Huebee( elem, { var hueb = new Huebee( elem, {
// options // options
@ -12,7 +31,9 @@ $.when( $.ready ).then(function() {
if(active) { if(active) {
$('.add-item').hide(); $('.add-item').hide();
$('#app').removeClass('sidebar'); $('#app').removeClass('sidebar');
$("#sortable").sortable("disable")
} else { } else {
$("#sortable").sortable("enable")
setTimeout( setTimeout(
function() function()
{ {
@ -27,4 +48,15 @@ $.when( $.ready ).then(function() {
app.toggleClass('sidebar'); app.toggleClass('sidebar');
}); });
$('#pinlist').on('click', 'a', function(e) {
e.preventDefault();
var current = $(this);
var id = current.data('id');
$.get('items/pintoggle/'+id+'/true', function(data) {
var inner = $(data).filter('#sortable').html();
$('#sortable').html(inner);
current.toggleClass('active');
});
});
}); });

7
resources/assets/js/jquery-ui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -66,7 +66,7 @@ body {
} }
} }
main { main, #sortable {
padding: 10px; padding: 10px;
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -75,6 +75,8 @@ body {
position: relative; position: relative;
flex-wrap: wrap; flex-wrap: wrap;
align-content: center; align-content: center;
list-style: none;
margin: 0;
.config { .config {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
@ -89,8 +91,8 @@ body {
} }
} }
.item-container { .item-container {
width: 340px; //width: 340px;
transition: all .35s ease-in-out; //transition: width .35s ease-in-out;
} }
.message-container { .message-container {
width: 100%; width: 100%;
@ -105,11 +107,12 @@ body {
top: 0; top: 0;
} }
.item-container { .item-container {
width: 280px; //width: 240px;
} }
.item, .add-item { .item, .add-item {
transform: scale(0.8); transform: scale(0.8);
opacity: 0.7; opacity: 0.7;
margin: 20px 0;
} }
} }
&.sidebar { &.sidebar {
@ -132,6 +135,9 @@ body {
position: relative; position: relative;
display: none; display: none;
outline: 1px solid transparent; outline: 1px solid transparent;
&.active {
display: block;
}
a { a {
display: block; display: block;
width: 100%; width: 100%;
@ -158,7 +164,7 @@ body {
transition: all .35s ease-in-out; transition: all .35s ease-in-out;
outline: 1px solid transparent; outline: 1px solid transparent;
display: flex; display: flex;
align-items: flex-start; align-items: center;
&:after { &:after {
content: ""; content: "";
position: absolute; position: absolute;
@ -194,7 +200,7 @@ body {
max-width: 1000px; max-width: 1000px;
width: 100%; width: 100%;
margin: 0 40px; margin: 0 40px;
header { header, footer {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@ -210,6 +216,9 @@ body {
margin-left: 25px; margin-left: 25px;
} }
} }
footer {
border-top: 1px solid #dbdce3;
}
.table { .table {
width: 100%; width: 100%;
margin:0; margin:0;
@ -329,5 +338,29 @@ div.create {
} }
.app-icon { .app-icon {
max-width: 50px; max-width: 60px;
margin-right: 10px;
}
.sidenav {
h2 {
font-weight: 300;
padding: 20px;
}
ul {
list-style: none;
margin: 0;
padding: 20px;
li {
display: flex;
justify-content: space-between;
padding: 5px;
a {
color: #2b3542;
&.active {
color: #46b0e6;
}
}
}
}
} }

View file

@ -1,3 +1,4 @@
<section class="add-item"> <?php $addclass = (isset($ajax)) ? ' active' : ''; ?>
<section class="add-item{{ $addclass }}">
<a id="add-item" href="">Pin item to dash</a> <a id="add-item" href="">Pin item to dash</a>
</section> </section>

View file

@ -12,12 +12,19 @@
</head> </head>
<body> <body>
<div id="app"> <div id="app">
<nav> <nav class="sidenav">
<ul> @if(isset($all_apps))
<li><a href=""><i class="fa fa-dash"></i></a></li> <h2>Pinned Items</h2>
<li><a href=""><i class="fa fa-dash"></i></a></li> <ul id="pinlist">
<li><a href=""><i class="fa fa-dash"></i></a></li> @foreach($all_apps as $app)
<?php
$active = ((bool)$app->pinned === true) ? 'active' : '';
?>
<li>{{ $app->title }}<a class="{{ $active }}" data-id="{{ $app->id }}" href="{{ route('items.pintoggle', $app->id) }}"><i class="fas fa-thumbtack"></i></a></li>
@endforeach
</ul> </ul>
@endif
</nav> </nav>
<div class="content"> <div class="content">
<header class="appheader"> <header class="appheader">
@ -54,6 +61,8 @@
</div> </div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>!window.jQuery && document.write('<script src="/js/jquery-3.3.1.min.js"><\/script>')</script> <script>!window.jQuery && document.write('<script src="/js/jquery-3.3.1.min.js"><\/script>')</script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="/js/app.js"></script> <script src="/js/app.js"></script>
</body> </body>
</html> </html>

View file

@ -1,4 +1,4 @@
<section class="item-container"> <section class="item-container" data-id="{{ $app->id }}">
<div class="item" style="background-color: {{ $app->colour }}"> <div class="item" style="background-color: {{ $app->colour }}">
@if($app->icon) @if($app->icon)
<img class="app-icon" src="{{ asset('storage/'.$app->icon) }}" /> <img class="app-icon" src="{{ asset('storage/'.$app->icon) }}" />
@ -6,7 +6,7 @@
<i class="fas fa-app-store-ios"></i> <i class="fas fa-app-store-ios"></i>
@endif @endif
{{ $app->title }} {{ $app->title }}
Item
<a class="link" href="{{ $app->url }}"><i class="fas fa-arrow-alt-to-right"></i></a> <a class="link" href="{{ $app->url }}"><i class="fas fa-arrow-alt-to-right"></i></a>
</div> </div>
</section> </section>

View file

@ -2,8 +2,8 @@
<header> <header>
<div class="section-title">Add application</div> <div class="section-title">Add application</div>
<div class="module-actions"> <div class="module-actions">
<a href="{{ route('items.index') }}" class="button"><i class="fa fa-ban"></i><span>Cancel</span></a>
<button type="submit"class="button"><i class="fa fa-save"></i><span>Save</span></button> <button type="submit"class="button"><i class="fa fa-save"></i><span>Save</span></button>
<a href="{{ route('items.index') }}" class="button"><i class="fa fa-ban"></i><span>Cancel</span></a>
</div> </div>
</header> </header>
<div class="create"> <div class="create">
@ -49,5 +49,12 @@
</div> </div>
<footer>
<div class="section-title">&nbsp;</div>
<div class="module-actions">
<button type="submit"class="button"><i class="fa fa-save"></i><span>Save</span></button>
<a href="{{ route('items.index') }}" class="button"><i class="fa fa-ban"></i><span>Cancel</span></a>
</div>
</footer>
</section> </section>

View file

@ -0,0 +1,6 @@
<div id="sortable">
@foreach($apps as $app)
@include('item')
@endforeach
@include('add')
</div>

View file

@ -2,10 +2,7 @@
@section('content') @section('content')
@if($apps->first()) @if($apps->first())
@foreach($apps as $app) @include('sortable')
@include('item')
@endforeach
@include('add')
@else @else
There are currently no Applications, <a href="{{ route('items.create') }}">add one here</a> There are currently no Applications, <a href="{{ route('items.create') }}">add one here</a>
@include('add') @include('add')

View file

@ -16,3 +16,7 @@ Route::get('/', 'ItemController@dash')->name('dash');
Route::resources([ Route::resources([
'items' => 'ItemController', 'items' => 'ItemController',
]); ]);
Route::get('items/pin/{id}', 'ItemController@pin')->name('items.pin');
Route::get('items/unpin/{id}', 'ItemController@unpin')->name('items.unpin');
Route::get('items/pintoggle/{id}/{ajax?}', 'ItemController@pinToggle')->name('items.pintoggle');
Route::post('order', 'ItemController@setOrder')->name('items.order');

1
webpack.mix.js vendored
View file

@ -12,6 +12,7 @@ let mix = require('laravel-mix');
*/ */
mix.scripts([ mix.scripts([
//'resources/assets/js/jquery-ui.min.js',
'resources/assets/js/huebee.js', 'resources/assets/js/huebee.js',
'resources/assets/js/app.js' 'resources/assets/js/app.js'
], 'public/js/app.js') ], 'public/js/app.js')