mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-09 16:24:51 +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,
|
||||
Report,
|
||||
Status,
|
||||
Story,
|
||||
User
|
||||
};
|
||||
use DB, Cache;
|
||||
|
@ -27,6 +28,7 @@ use App\Http\Controllers\Admin\{
|
|||
};
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Services\AdminStatsService;
|
||||
use App\Services\StoryService;
|
||||
|
||||
class AdminController extends Controller
|
||||
{
|
||||
|
@ -465,4 +467,11 @@ class AdminController extends Controller
|
|||
|
||||
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>
|
||||
</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">
|
||||
<a class="nav-link {{request()->is('*users*')?'active':''}}" href="{{route('admin.users')}}">
|
||||
<i class="ni ni-bold-right text-primary"></i>
|
||||
|
@ -49,8 +56,6 @@
|
|||
<span class="nav-link-text">Settings</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<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/appeal/{id}', 'AdminController@showAppeal');
|
||||
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::get('statuses/list', 'AdminController@statuses')->name('admin.statuses');
|
||||
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::post('moderate', 'Api\AdminApiController@moderate');
|
||||
});
|
||||
Route::group(['prefix' => 'stories'], function () {
|
||||
Route::get('v0/recent', 'StoryController@apiV1Recent');
|
||||
Route::post('v0/add', 'StoryController@apiV1Add');
|
||||
Route::get('v0/fetch/{id}', 'StoryController@apiV1Fetch');
|
||||
Route::get('v0/profile/{id}', 'StoryController@apiV1Profile');
|
||||
Route::get('v0/exists/{id}', 'StoryController@apiV1Exists');
|
||||
Route::delete('v0/delete/{id}', 'StoryController@apiV1Delete');
|
||||
Route::get('v0/me', 'StoryController@apiV1Me');
|
||||
Route::get('v0/item/{id}', 'StoryController@apiV1Item');
|
||||
Route::post('v0/crop', 'StoryController@cropPhoto');
|
||||
Route::post('v0/publish', 'StoryController@publishStory');
|
||||
});
|
||||
// Route::group(['prefix' => 'stories'], function () {
|
||||
// Route::get('v0/recent', 'StoryController@apiV1Recent');
|
||||
// Route::post('v0/add', 'StoryController@apiV1Add');
|
||||
// Route::get('v0/fetch/{id}', 'StoryController@apiV1Fetch');
|
||||
// Route::get('v0/profile/{id}', 'StoryController@apiV1Profile');
|
||||
// Route::get('v0/exists/{id}', 'StoryController@apiV1Exists');
|
||||
// Route::delete('v0/delete/{id}', 'StoryController@apiV1Delete');
|
||||
// Route::get('v0/item/{id}', 'StoryController@apiV1Item');
|
||||
// Route::post('v0/crop', 'StoryController@cropPhoto');
|
||||
// Route::post('v0/publish', 'StoryController@publishStory');
|
||||
// });
|
||||
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue