diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c155d4da5950235a1a047217bdacd825ca88b93..5d40ff6f4bb27cfe13cbc5e2d379f9a86b0b4eb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,10 @@ - Fix remote account post counts ([149cf9dc](https://github.com/pixelfed/pixelfed/commit/149cf9dc)) - Enforce blocks on incoming likes, shares, replies and follows on all endpoints ([1545e37c](https://github.com/pixelfed/pixelfed/commit/1545e37c)) - Fix unlisted post web redirect and api response ([6033d837](https://github.com/pixelfed/pixelfed/commit/6033d837)) +- Remove quilljs from admin page editor, fixes #3616 ([75fbd373](https://github.com/pixelfed/pixelfed/commit/75fbd373)) +- Fix AdminStatService cache key, fixes #3612 ([d1dbed89](https://github.com/pixelfed/pixelfed/commit/d1dbed89)) +- Improve mute/block v1 api endpoints, fixes #3540 ([c3e8a0e4](https://github.com/pixelfed/pixelfed/commit/c3e8a0e4)) +- Set Last-Modified header for atom feeds, fixes #2988 ([c18dcde3](https://github.com/pixelfed/pixelfed/commit/c18dcde3)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.11.3 (2022-05-09)](https://github.com/pixelfed/pixelfed/compare/v0.11.2...v0.11.3) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 72f76f25d3d1355bcffc2c50ede74a2dcfbe2a76..68558a3c2c005c15d0da3166c034afb918893176 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -873,12 +873,15 @@ class ApiV1Controller extends Controller ->whereFilterableType('App\Profile') ->whereFilterType('block') ->simplePaginate($limit) - ->pluck('filterable_id'); + ->pluck('filterable_id') + ->map(function($id) { + return AccountService::get($id, true); + }) + ->filter(function($account) { + return $account && isset($account['id']); + }); - $profiles = Profile::findOrFail($blocked); - $resource = new Fractal\Resource\Collection($profiles, new AccountTransformer()); - $res = $this->fractal->createData($resource)->toArray(); - return $this->json($res); + return $this->json($blocked); } /** @@ -1725,19 +1728,21 @@ class ApiV1Controller extends Controller ]); $user = $request->user(); - $limit = $request->input('limit') ?? 40; + $limit = $request->input('limit', 40); $mutes = UserFilter::whereUserId($user->profile_id) ->whereFilterableType('App\Profile') ->whereFilterType('mute') ->simplePaginate($limit) - ->pluck('filterable_id'); - - $accounts = Profile::find($mutes); + ->pluck('filterable_id') + ->map(function($id) { + return AccountService::get($id, true); + }) + ->filter(function($account) { + return $account && isset($account['id']); + }); - $resource = new Fractal\Resource\Collection($accounts, new AccountTransformer()); - $res = $this->fractal->createData($resource)->toArray(); - return $this->json($res); + return $this->json($mutes); } /** diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 147d958429a1f3c9c56949e42426b102ec91661e..179db033d0312611e005b99f759ed62ef29516fc 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -118,8 +118,7 @@ class ProfileController extends Controller 'list' => $settings->show_profile_followers ] ]; - $ui = $request->has('ui') && $request->input('ui') == 'memory' ? 'profile.memory' : 'profile.show'; - return view($ui, compact('profile', 'settings')); + return view('profile.show', compact('profile', 'settings')); } } @@ -210,7 +209,7 @@ class ProfileController extends Controller ->whereProfileId($pid) ->whereVisibility('public') ->whereType('photo') - ->latest() + ->orderByDesc('id') ->take(10) ->get() ->map(function($status) { @@ -224,10 +223,14 @@ class ProfileController extends Controller }) ->values(); $permalink = config('app.url') . "/users/{$profile['username']}.atom"; + $headers = ['Content-Type' => 'application/atom+xml']; + if($items && $items->count()) { + $headers['Last-Modified'] = now()->parse($items->first()['created_at'])->toRfc7231String(); + } return response() ->view('atom.user', compact('profile', 'items', 'permalink')) - ->header('Content-Type', 'application/atom+xml'); + ->withHeaders($headers); } public function meRedirect() diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php index 7202f7c6efcf943bf091ae619696ad80b8f20a83..f4cac26bebd2915a038a7836b128468e0d7d32b3 100644 --- a/app/Http/Controllers/SiteController.php +++ b/app/Http/Controllers/SiteController.php @@ -80,7 +80,7 @@ class SiteController extends Controller { $page = Cache::remember('site:privacy', now()->addDays(120), function() { $slug = '/site/privacy'; - $page = Page::whereSlug($slug)->whereActive(true)->first(); + return Page::whereSlug($slug)->whereActive(true)->first(); }); return View::make('site.privacy')->with(compact('page'))->render(); } diff --git a/app/Services/AdminStatsService.php b/app/Services/AdminStatsService.php index 2117207f3e915e816751e8763d2a75ec2784fc9f..9e345355aa4a7ff8a4be3d856a66b5fc837e7dda 100644 --- a/app/Services/AdminStatsService.php +++ b/app/Services/AdminStatsService.php @@ -113,7 +113,7 @@ class AdminStatsService protected static function additionalDataSummary() { $ttl = now()->addHours(24); - return Cache::remember('admin:dashboard:home:data:v0:24hr', $ttl, function() { + return Cache::remember('admin:dashboard:home:data-summary:v0:24hr', $ttl, function() { return [ 'statuses' => PrettyNumber::convert(Status::count()), 'profiles' => PrettyNumber::convert(Profile::count()), diff --git a/resources/views/admin/pages/edit.blade.php b/resources/views/admin/pages/edit.blade.php index de1a7feb8b021e64bbf3c3dc7c2465daf7b05466..5a3530e0d8a896cec93617de4c3ab539336acd9a 100644 --- a/resources/views/admin/pages/edit.blade.php +++ b/resources/views/admin/pages/edit.blade.php @@ -1,27 +1,36 @@ -@extends('admin.partial.template') - -@include('admin.settings.sidebar') +@extends('admin.partial.template-full') @section('section') - <div class="title"> - <h3 class="font-weight-bold">Edit Page</h3> - <p class="lead">{{$page->slug}}</p> - </div> - <hr> - - <div> +</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">Edit Page</p> + <p class="lead text-white mt-n4 mb-0">{{$page->slug}}</p> + </div> + </div> + </div> + </div> +</div> +<div class="container-fluid mt-4"> <input type="hidden" id="slug" name="slug" value="{{$page->slug}}"> <input class="form-control form-control-lg" id="title" name="title" placeholder="Title"> <p class="small text-muted"> Page URL: <span class="page-url font-weight-bold">{{$page->url()}}</span> {{-- <span class="pl-1"><a href="#" class="font-weight-bold">Edit</a></span> --}} </p> - <div id="editor" style="height: 400px"> + <div id="editor" class="d-none" style="height: 400px"> {!!$page->content!!} </div> + <div id="rawEditor" style="height: 400px"> + <label class="font-weight-bold">Raw HTML</label> + <textarea class="form-control" rows="8" id="rawText" v-pre>{{$page->content}}</textarea> + </div> <div class="mt-3 d-flex justify-content-between"> <div> - <div class="custom-control custom-switch d-inline pr-3"> + <div class="custom-control custom-switch"> <input type="checkbox" class="custom-control-input" id="activeSwitch" {{$page->active?'checked="true"':''}}> <label class="custom-control-label font-weight-bold" for="activeSwitch">Active</label> </div> @@ -34,69 +43,69 @@ </div> </div> </div> - +</div> @endsection @push('styles') -<link rel="stylesheet" href="{{mix('css/quill.css')}}"/> <style type="text/css"> .ql-container { box-sizing: border-box; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI", - Roboto,Helvetica,Arial,sans-serif; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; font-size: 16px; height: 100%; margin: 0px; position: relative; } +.custom-control { + padding-left: 3.5rem; +} </style> @endpush @push('scripts') -<script src="{{mix('js/quill.js')}}"></script> - <script> - window.editor = new Quill('#editor', { - theme: 'snow' - }); - $('.btn-save').on('click', function(e) { - e.preventDefault(); - let confirm = window.confirm('Are you sure you want to save this page?'); - if(confirm !== true) { - return; - } - let html = editor.container.firstChild.innerHTML; - let title = $('#title').val(); - let active = $('#activeSwitch')[0].checked; - axios.post(window.location.href, { - slug: '{{$page->slug}}', - title: title, - content: html, - active: active - }).then((res) => { - window.location.href = '{{$page->url()}}'; - }).catch((err) => { - console.log(err) + window.useRaw = true; + + $('.btn-save').on('click', function(e) { + e.preventDefault(); + let confirm = window.confirm('Are you sure you want to save this page?'); + if(confirm !== true) { + return; + } + let html = window.useRaw ? + $('#rawText').val() : + editor.root.innerHTML; + let title = $('#title').val(); + let active = $('#activeSwitch')[0].checked; + axios.post(window.location.href, { + slug: '{{$page->slug}}', + title: title, + content: html, + active: active + }).then((res) => { + window.location.href = '{{$page->url()}}'; + }).catch((err) => { + console.log(err) + }); }); - }); - $('.btn-delete').on('click', function(e) { - e.preventDefault(); - let confirm = window.confirm('Are you sure you want to delete this page?'); - if(confirm == true) { - axios.post('/i/admin/settings/pages/delete', { - id: '{{$page->id}}' - }).then(res => { - window.location.href = '/i/admin/settings/pages'; - }).catch(err => { - swal('Error', 'An error occured!', 'error'); - console.log(err); - }); - } - }); + $('.btn-delete').on('click', function(e) { + e.preventDefault(); + let confirm = window.confirm('Are you sure you want to delete this page?'); + if(confirm == true) { + axios.post('/i/admin/settings/pages/delete', { + id: '{{$page->id}}' + }).then(res => { + window.location.href = '/i/admin/settings/pages'; + }).catch(err => { + swal('Error', 'An error occured!', 'error'); + console.log(err); + }); + } + }); - $('#title').on('change input', function(e) { - e.preventDefault(); - let title = this.value.split(' ').join('-').toLowerCase(); - }) + $('#title').on('change input', function(e) { + e.preventDefault(); + let title = this.value.split(' ').join('-').toLowerCase(); + }) </script> -@endpush \ No newline at end of file +@endpush diff --git a/resources/views/admin/pages/home.blade.php b/resources/views/admin/pages/home.blade.php index cb315c27b84e5f0332113bcb31afcc5de7f1756f..bab2946476559d6f283bc5b8a0b0383d25127b63 100644 --- a/resources/views/admin/pages/home.blade.php +++ b/resources/views/admin/pages/home.blade.php @@ -1,11 +1,56 @@ @extends('admin.partial.template-full') @section('section') - <div class="title"> - <h3 class="font-weight-bold">Pages</h3> - <p class="lead">Set custom page content</p> - </div> - <hr> +</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">Pages</p> + <p class="lead text-white mt-n4 mb-0">Manage public and custom page content</p> + </div> + + @if($pages->count() < 4) + <div class="col-12"> + <hr> + <div class="btn-group"> + @if(!$pages->contains('slug', '=', '/site/about')) + <form class="form-inline mr-1" method="post" action="/i/admin/settings/pages/create"> + @csrf + <input type="hidden" name="page" value="about"> + <button type="submit" class="btn btn-default font-weight-bold">Customize About Page</button> + </form> + @endif + @if(!$pages->contains('slug', '=', '/site/privacy')) + <form class="form-inline mr-1" method="post" action="/i/admin/settings/pages/create"> + @csrf + <input type="hidden" name="page" value="privacy"> + <button type="submit" class="btn btn-default font-weight-bold">Customize Privacy Page</button> + </form> + @endif + @if(!$pages->contains('slug', '=', '/site/terms')) + <form class="form-inline mr-1" method="post" action="/i/admin/settings/pages/create"> + @csrf + <input type="hidden" name="page" value="terms"> + <button type="submit" class="btn btn-default font-weight-bold">Customize Terms Page</button> + </form> + @endif + @if(!$pages->contains('slug', '=', '/site/kb/community-guidelines')) + <form class="form-inline" method="post" action="/i/admin/settings/pages/create"> + @csrf + <input type="hidden" name="page" value="community_guidelines"> + <button type="submit" class="btn btn-default font-weight-bold">Customize Guidelines Page</button> + </form> + @endif + </div> + </div> + @endif + </div> + </div> + </div> +</div> +<div class="container-fluid mt-4"> @if($pages->count()) <div class="table-responsive"> <table class="table"> @@ -46,57 +91,11 @@ <div class="d-flex justify-content-center mt-5 small"> {{$pages->links()}} </div> - <hr> - <div class="btn-group"> - <form class="form-inline mr-1" method="post" action="/i/admin/settings/pages/create"> - @csrf - <input type="hidden" name="page" value="about"> - <button type="submit" class="btn btn-outline-secondary font-weight-bold">Create About</button> - </form> - <form class="form-inline mr-1" method="post" action="/i/admin/settings/pages/create"> - @csrf - <input type="hidden" name="page" value="privacy"> - <button type="submit" class="btn btn-outline-secondary font-weight-bold">Create Privacy</button> - </form> - <form class="form-inline mr-1" method="post" action="/i/admin/settings/pages/create"> - @csrf - <input type="hidden" name="page" value="terms"> - <button type="submit" class="btn btn-outline-secondary font-weight-bold">Create Terms</button> - </form> - <form class="form-inline" method="post" action="/i/admin/settings/pages/create"> - @csrf - <input type="hidden" name="page" value="community_guidelines"> - <button type="submit" class="btn btn-outline-secondary font-weight-bold">Create Guidelines</button> - </form> - </div> - @else - <div class="card bg-light shadow-none rounded-0"> + @else + <div class="card border shadow-none rounded-0"> <div class="card-body text-center"> - <p class="lead text-muted font-weight-bold py-5 mb-0">No custom pages found</p> + <p class="lead text-muted font-weight-bold py-5">No custom pages found</p> </div> </div> - <hr> - <div class="btn-group"> - <form class="form-inline mr-1" method="post" action="/i/admin/settings/pages/create"> - @csrf - <input type="hidden" name="page" value="about"> - <button type="submit" class="btn btn-outline-secondary font-weight-bold">Create About</button> - </form> - <form class="form-inline mr-1" method="post" action="/i/admin/settings/pages/create"> - @csrf - <input type="hidden" name="page" value="privacy"> - <button type="submit" class="btn btn-outline-secondary font-weight-bold">Create Privacy</button> - </form> - <form class="form-inline mr-1" method="post" action="/i/admin/settings/pages/create"> - @csrf - <input type="hidden" name="page" value="terms"> - <button type="submit" class="btn btn-outline-secondary font-weight-bold">Create Terms</button> - </form> - <form class="form-inline" method="post" action="/i/admin/settings/pages/create"> - @csrf - <input type="hidden" name="page" value="community_guidelines"> - <button type="submit" class="btn btn-outline-secondary font-weight-bold">Create Guidelines</button> - </form> - </div> @endif @endsection