mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-10 00:34:50 +00:00
Add Stories to admin dashboard
This commit is contained in:
parent
0573213093
commit
a4a1270e70
4 changed files with 176 additions and 14 deletions
|
@ -11,6 +11,7 @@ use App\{
|
||||||
Profile,
|
Profile,
|
||||||
Report,
|
Report,
|
||||||
Status,
|
Status,
|
||||||
|
Story,
|
||||||
User
|
User
|
||||||
};
|
};
|
||||||
use DB, Cache;
|
use DB, Cache;
|
||||||
|
@ -27,6 +28,7 @@ use App\Http\Controllers\Admin\{
|
||||||
};
|
};
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use App\Services\AdminStatsService;
|
use App\Services\AdminStatsService;
|
||||||
|
use App\Services\StoryService;
|
||||||
|
|
||||||
class AdminController extends Controller
|
class AdminController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -465,4 +467,11 @@ class AdminController extends Controller
|
||||||
|
|
||||||
return response()->json($res);
|
return response()->json($res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function stories(Request $request)
|
||||||
|
{
|
||||||
|
$stories = Story::with('profile')->latest()->paginate(10);
|
||||||
|
$stats = StoryService::adminStats();
|
||||||
|
return view('admin.stories.home', compact('stories', 'stats'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,13 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link {{request()->is('*stories*')?'active':''}}" href="{{route('admin.stories')}}">
|
||||||
|
<i class="ni ni-bold-right text-primary"></i>
|
||||||
|
<span class="nav-link-text">Stories <span class="badge badge-primary ml-1">NEW</span></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{request()->is('*users*')?'active':''}}" href="{{route('admin.users')}}">
|
<a class="nav-link {{request()->is('*users*')?'active':''}}" href="{{route('admin.users')}}">
|
||||||
<i class="ni ni-bold-right text-primary"></i>
|
<i class="ni ni-bold-right text-primary"></i>
|
||||||
|
@ -49,8 +56,6 @@
|
||||||
<span class="nav-link-text">Settings</span>
|
<span class="nav-link-text">Settings</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<hr class="my-3">
|
<hr class="my-3">
|
||||||
|
|
147
resources/views/admin/stories/home.blade.php
Normal file
147
resources/views/admin/stories/home.blade.php
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
@extends('admin.partial.template-full')
|
||||||
|
|
||||||
|
@section('section')
|
||||||
|
</div>
|
||||||
|
<div class="header bg-primary pb-3 mt-n4">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="header-body">
|
||||||
|
<div class="row align-items-center py-4">
|
||||||
|
<div class="col-lg-6 col-7">
|
||||||
|
<p class="display-1 text-white d-inline-block mb-0">Stories</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-3 col-md-6">
|
||||||
|
<div class="card card-stats">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h5 class="card-title text-uppercase text-muted mb-0">Active Stories</h5>
|
||||||
|
<span class="h2 font-weight-bold mb-0">{{$stats['active']['today']}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="icon icon-shape bg-gradient-primary text-white rounded-circle shadow">
|
||||||
|
<i class="ni ni-image"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="mt-3 mb-0 text-sm">
|
||||||
|
<span class="text-success mr-2"><i class="fa fa-arrow-up"></i> {{$stats['active']['month']}}</span>
|
||||||
|
<span class="text-nowrap">in last 30 days</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-md-6">
|
||||||
|
<div class="card card-stats">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h5 class="card-title text-uppercase text-muted mb-0">Remote Stories</h5>
|
||||||
|
<span class="h2 font-weight-bold mb-0">{{$stats['remote']['month']}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="icon icon-shape bg-gradient-primary text-white rounded-circle shadow">
|
||||||
|
<i class="ni ni-circle-08"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="mt-3 mb-0 text-sm">
|
||||||
|
<span class="text-success mr-2"><i class="fa fa-arrow-up"></i> {{$stats['remote']['month']}}</span>
|
||||||
|
<span class="text-nowrap">in last 30 days</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<h5 class="text-light text-uppercase mb-0">Total Stories</h5>
|
||||||
|
<span class="text-white h2 font-weight-bold mb-0">{{$stats['total']}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<h5 class="text-light text-uppercase mb-0">Stories Per User</h5>
|
||||||
|
<span class="text-white h2 font-weight-bold mb-0">{{$stats['avg_spu']}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<h5 class="text-light text-uppercase mb-0">Storage Used</h5>
|
||||||
|
<span class="text-white h2 font-weight-bold mb-0 human-size">{{$stats['storage']['sum']}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<h5 class="text-light text-uppercase mb-0">Average Media Size</h5>
|
||||||
|
<span class="text-white h2 font-weight-bold mb-0 human-size">{{$stats['storage']['average']}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<h5 class="text-light text-uppercase mb-0">Average Duration</h5>
|
||||||
|
<span class="text-white h2 font-weight-bold mb-0">{{$stats['avg_duration']}}s</span>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<h5 class="text-light text-uppercase mb-0">Average Type</h5>
|
||||||
|
<span class="text-white h2 font-weight-bold mb-0">{{$stats['avg_type']}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid mt-4">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-dark">
|
||||||
|
<thead class="thead-dark">
|
||||||
|
<tr>
|
||||||
|
<th scope="col" class="">#</th>
|
||||||
|
<th scope="col" class="">Username</th>
|
||||||
|
<th scope="col" class="">Type</th>
|
||||||
|
<th scope="col" class="">View Count</th>
|
||||||
|
<th scope="col" class="">Created</th>
|
||||||
|
<th scope="col" class="">Expires</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($stories as $story)
|
||||||
|
<tr>
|
||||||
|
<th scope="row">
|
||||||
|
<a href="{{$story->url()}}" class="text-monospace">
|
||||||
|
{{$story->id}}
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
|
<td class="font-weight-bold">{{$story->profile->username}}</td>
|
||||||
|
<td class="font-weight-bold">{{$story->type}}</td>
|
||||||
|
<td class="font-weight-bold">{{$story->view_count ?? 0}}</td>
|
||||||
|
<td class="font-weight-bold">{{$story->created_at->diffForHumans(null, true, true, true)}}</td>
|
||||||
|
<td class="font-weight-bold">{{optional($story->expires_at)->diffForHumans(null, true, true, true)}}</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<div class="dropdown">
|
||||||
|
<a class="btn btn-sm btn-icon-only text-light" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<i class="fas fa-ellipsis-v"></i>
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
|
||||||
|
<a class="dropdown-item" href="{{$story->mediaUrl()}}">Preview</a>
|
||||||
|
<a class="dropdown-item" href="#">Delete</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center mt-5 small">
|
||||||
|
{{$stories->links()}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('.human-size').each(function(d,a) {
|
||||||
|
a.innerText = filesize(a.innerText, {round: 0});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
|
@ -14,6 +14,8 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio
|
||||||
Route::get('reports/appeals', 'AdminController@appeals');
|
Route::get('reports/appeals', 'AdminController@appeals');
|
||||||
Route::get('reports/appeal/{id}', 'AdminController@showAppeal');
|
Route::get('reports/appeal/{id}', 'AdminController@showAppeal');
|
||||||
Route::post('reports/appeal/{id}', 'AdminController@updateAppeal');
|
Route::post('reports/appeal/{id}', 'AdminController@updateAppeal');
|
||||||
|
Route::redirect('stories', '/stories/list');
|
||||||
|
Route::get('stories/list', 'AdminController@stories')->name('admin.stories');
|
||||||
Route::redirect('statuses', '/statuses/list');
|
Route::redirect('statuses', '/statuses/list');
|
||||||
Route::get('statuses/list', 'AdminController@statuses')->name('admin.statuses');
|
Route::get('statuses/list', 'AdminController@statuses')->name('admin.statuses');
|
||||||
Route::get('statuses/show/{id}', 'AdminController@showStatus');
|
Route::get('statuses/show/{id}', 'AdminController@showStatus');
|
||||||
|
@ -231,18 +233,17 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
||||||
Route::group(['prefix' => 'admin'], function () {
|
Route::group(['prefix' => 'admin'], function () {
|
||||||
Route::post('moderate', 'Api\AdminApiController@moderate');
|
Route::post('moderate', 'Api\AdminApiController@moderate');
|
||||||
});
|
});
|
||||||
Route::group(['prefix' => 'stories'], function () {
|
// Route::group(['prefix' => 'stories'], function () {
|
||||||
Route::get('v0/recent', 'StoryController@apiV1Recent');
|
// Route::get('v0/recent', 'StoryController@apiV1Recent');
|
||||||
Route::post('v0/add', 'StoryController@apiV1Add');
|
// Route::post('v0/add', 'StoryController@apiV1Add');
|
||||||
Route::get('v0/fetch/{id}', 'StoryController@apiV1Fetch');
|
// Route::get('v0/fetch/{id}', 'StoryController@apiV1Fetch');
|
||||||
Route::get('v0/profile/{id}', 'StoryController@apiV1Profile');
|
// Route::get('v0/profile/{id}', 'StoryController@apiV1Profile');
|
||||||
Route::get('v0/exists/{id}', 'StoryController@apiV1Exists');
|
// Route::get('v0/exists/{id}', 'StoryController@apiV1Exists');
|
||||||
Route::delete('v0/delete/{id}', 'StoryController@apiV1Delete');
|
// Route::delete('v0/delete/{id}', 'StoryController@apiV1Delete');
|
||||||
Route::get('v0/me', 'StoryController@apiV1Me');
|
// Route::get('v0/item/{id}', 'StoryController@apiV1Item');
|
||||||
Route::get('v0/item/{id}', 'StoryController@apiV1Item');
|
// Route::post('v0/crop', 'StoryController@cropPhoto');
|
||||||
Route::post('v0/crop', 'StoryController@cropPhoto');
|
// Route::post('v0/publish', 'StoryController@publishStory');
|
||||||
Route::post('v0/publish', 'StoryController@publishStory');
|
// });
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue