1
0
Fork 1
mirror of https://github.com/pixelfed/pixelfed.git synced 2025-01-30 10:52:18 +00:00

Merge pull request #1438 from pixelfed/frontend-ui-refactor

Custom Pages
This commit is contained in:
daniel 2019-06-19 21:32:40 -06:00 committed by GitHub
commit 6b8deecfb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 406 additions and 138 deletions

View file

@ -3,7 +3,7 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
use Auth, Cache;
use App\Page;
class PageController extends Controller
@ -13,6 +13,14 @@ class PageController extends Controller
$this->middleware(['auth', 'admin']);
}
protected function cacheKeys() {
return [
'/site/about' => 'site:about',
'/site/privacy' => 'site:privacy',
'/site/terms' => 'site:terms',
];
}
protected function authCheck($admin_only = false)
{
$auth = $admin_only ?
@ -30,6 +38,9 @@ class PageController extends Controller
'page' => 'required|string'
]);
$slug = urldecode($request->page);
if(in_array($slug, array_keys($this->cacheKeys())) == false) {
return redirect(route('admin.settings.pages'));
}
$page = Page::firstOrCreate(['slug' => $slug]);
return view('admin.pages.edit', compact('page'));
}
@ -48,6 +59,47 @@ class PageController extends Controller
$page->title = $request->input('title');
$page->active = (bool) $request->input('active');
$page->save();
if($page->cached) {
$keys = $this->cacheKeys();
$key = $keys[$page->slug];
Cache::forget($key);
}
return response()->json(['msg' => 200]);
}
public function delete(Request $request)
{
$this->validate($request, [
'id' => 'required|integer|min:1|exists:pages,id'
]);
$page = Page::findOrFail($request->input('id'));
$page->delete();
return redirect(route('admin.settings.pages'));
}
public function generatePage(Request $request)
{
$this->validate($request, [
'page' => 'required|string|in:about,terms,privacy',
]);
$page = $request->input('page');
switch ($page) {
case 'about':
Page::firstOrCreate(['slug' => '/site/about']);
break;
case 'privacy':
Page::firstOrCreate(['slug' => '/site/privacy']);
break;
case 'terms':
Page::firstOrCreate(['slug' => '/site/terms']);
break;
}
return redirect(route('admin.settings.pages'));
}
}

View file

@ -42,14 +42,19 @@ class SiteController extends Controller
public function about()
{
$stats = Cache::remember('site:about', now()->addMinutes(120), function() {
return [
return Cache::remember('site:about', now()->addMinutes(120), function() {
$page = Page::whereSlug('/site/about')->whereActive(true)->first();
$stats = [
'posts' => Status::whereLocal(true)->count(),
'users' => User::count(),
'users' => User::whereNull('status')->count(),
'admin' => User::whereIsAdmin(true)->first()
];
if($page) {
return View::make('site.about-custom')->with(compact('page', 'stats'))->render();
} else {
return View::make('site.about')->with(compact('stats'))->render();
}
});
return view('site.about', compact('stats'));
}
public function language()
@ -64,4 +69,22 @@ class SiteController extends Controller
return view('site.help.community-guidelines', compact('page'));
}
public function privacy(Request $request)
{
return Cache::remember('site:privacy', now()->addMinutes(120), function() {
$slug = '/site/privacy';
$page = Page::whereSlug($slug)->whereActive(true)->first();
return View::make('site.privacy')->with(compact('page'))->render();
});
}
public function terms(Request $request)
{
return Cache::remember('site:terms', now()->addMinutes(120), function() {
$slug = '/site/terms';
$page = Page::whereSlug($slug)->whereActive(true)->first();
return View::make('site.terms')->with(compact('page'))->render();
});
}
}

View file

@ -14,7 +14,7 @@
<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>
{{-- <span class="pl-1"><a href="#" class="font-weight-bold">Edit</a></span> --}}
</p>
<div id="editor" style="height: 400px">
{!!$page->content!!}
@ -25,10 +25,11 @@
<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>
<a class="btn btn-light font-weight-bold py-0" href="#">Set Expire Date</a>
{{-- <a class="btn btn-light font-weight-bold py-0" href="#">Set Expire Date</a> --}}
</div>
<div>
<a class="btn btn-light font-weight-bold py-0" href="#">Preview</a>
{{-- <a class="btn btn-light font-weight-bold py-0" href="#">Preview</a> --}}
<a class="btn btn-outline-danger font-weight-bold py-0 btn-delete" href="#">Delete</a>
<a class="btn btn-primary font-weight-bold py-0 btn-save" href="#">Save</a>
</div>
</div>
@ -37,7 +38,7 @@
@endsection
@push('styles')
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/quill/1.3.6/quill.snow.min.css" integrity="sha256-qc/vMbPSg7/JfxMwKeMv3wlx7ojG33FXfYfO0UJIsc0=" crossorigin="anonymous" />
<style type="text/css">
.ql-container {
box-sizing: border-box;
@ -51,16 +52,18 @@
</style>
@endpush
@push('scripts')
<!-- Include the Quill library -->
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/quill/1.3.6/quill.min.js" integrity="sha256-3oYBiGm16EW9wQH8G1VhGh43XgivbO5KaB10RhA9phE=" crossorigin="anonymous"></script>
<!-- Initialize Quill editor -->
<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;
@ -76,6 +79,21 @@
});
});
$('.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();

View file

@ -8,10 +8,8 @@
<p class="lead">Set custom page content</p>
</div>
<hr>
<p class="alert alert-warning">
<strong>Feature Unavailable:</strong> This feature will be released in a future version.
</p>
{{-- <div class="table-responsive">
@if($pages->count())
<div class="table-responsive">
<table class="table">
<thead class="bg-light">
<tr class="text-center">
@ -45,5 +43,48 @@
</div>
<div class="d-flex justify-content-center mt-5 small">
{{$pages->links()}}
</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 Page</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 Page</button>
</form>
<form class="form-inline" 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 Page</button>
</form>
</div>
@else
<div class="card bg-light 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>
</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 Page</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 Page</button>
</form>
<form class="form-inline" 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 Page</button>
</form>
</div>
@endif
@endsection

View file

@ -0,0 +1,119 @@
@extends('layouts.anon')
@section('content')
<div class="jumbotron jumbotron-fluid bg-primary text-white mb-0 py-4">
<div class="container">
<p class="h1 font-weight-light">About</p>
<p class="h3 font-weight-light py-4">{{$page->title ?? 'Pixelfed is an image sharing platform, an ethical alternative to centralized platforms.'}}</p>
</div>
</div>
<div class="bg-white">
<div class="container d-flex justify-content-center">
<div class="card mr-3" style="width:800px;margin-top:-30px;">
<div class="card-body">
{!! $page->content !!}
</div>
</div>
<div style="width:300px;margin-top:-30px;text-align: center;">
<div class="card border-left-blue mb-3">
<div class="card-body">
<p class="h2 mb-0">{{$stats['posts']}}</p>
<p class="font-weight-bold mb-0">Posts</p>
</div>
</div>
<div class="card border-left-blue mb-3">
<div class="card-body">
<p class="h2 mb-0">{{$stats['users']}}</p>
<p class="font-weight-bold mb-0">Users</p>
</div>
</div>
@if($stats['admin'])
<div class="card border-left-blue mb-3">
<div class="card-body">
<p class="h2 mb-0">
<a href="{{$stats['admin']->url()}}">
&commat;{{$stats['admin']->username}}
</a>
</p>
<p class="font-weight-bold mb-0">Instance Admin</p>
</div>
</div>
@endif
</div>
</div>
<div class="container py-5">
</div>
</div>
<div class="bg-primary pt-5 pb-4">
<div class="container">
<div class="row">
<div class="col-12 col-md-4 mb-4">
<div class="card bg-transparent" style="box-shadow: none;border:1px solid #fff">
<div class="card-body text-white text-center">
<p class="font-weight-bold lead mb-0">
Ad Free
</p>
<p class="font-weight-light mb-0">No Ads or Trackers</p>
</div>
</div>
</div>
<div class="col-12 col-md-4 mb-4">
<div class="card bg-transparent" style="box-shadow: none;border:1px solid #fff">
<div class="card-body text-white text-center">
<p class="font-weight-bold lead mb-0">
Chronological
</p>
<p class="font-weight-light mb-0">Timelines in order</p>
</div>
</div>
</div>
<div class="col-12 col-md-4 mb-4">
<div class="card bg-transparent" style="box-shadow: none;border:1px solid #fff">
<div class="card-body text-white text-center">
<p class="font-weight-bold lead mb-0">
Federated
</p>
<p class="font-weight-light mb-0">A network of millions</p>
</div>
</div>
</div>
<div class="col-12 col-md-4 mb-4">
<div class="card bg-transparent" style="box-shadow: none;border:1px solid #fff">
<div class="card-body text-white text-center">
<p class="font-weight-bold lead mb-0">
Discover
</p>
<p class="font-weight-light mb-0">Discover popular posts</p>
</div>
</div>
</div>
<div class="col-12 col-md-4 mb-4">
<div class="card bg-transparent" style="box-shadow: none;border:1px solid #fff">
<div class="card-body text-white text-center">
<p class="font-weight-bold lead mb-0">
Photo Filters
</p>
<p class="font-weight-light mb-0">Add an optional filter</p>
</div>
</div>
</div>
<div class="col-12 col-md-4 mb-4">
<div class="card bg-transparent" style="box-shadow: none;border:1px solid #fff">
<div class="card-body text-white text-center">
<p class="font-weight-bold lead mb-0">
Stories
</p>
<p class="font-weight-light mb-0">Coming Soon!</p>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('meta')
<meta property="og:description" content="Pixelfed is an image sharing platform, an ethical alternative to centralized platforms.">
@endpush

View file

@ -64,7 +64,6 @@
</div>
<div class="container py-5">
</div>
</div>
<div class="bg-primary pt-5 pb-4">
<div class="container">

View file

@ -2,6 +2,13 @@
@section('section')
@if($page && $page->content)
<div class="title">
<h3 class="font-weight-bold">Privacy Policy</h3>
</div>
<hr>
{!! $page->content !!}
@else
<div class="title">
<h3 class="font-weight-bold">Privacy Policy</h3>
</div>
@ -81,7 +88,7 @@
<p class="">Originally adapted from the <a href="https://mastodon.social/terms">Mastodon</a> privacy policy.</p>
</div>
@endif
@endsection
@push('meta')

View file

@ -2,6 +2,13 @@
@section('section')
@if($page && $page->content)
<div class="title">
<h3 class="font-weight-bold">Terms Of Use</h3>
</div>
<hr>
{!! $page->content !!}
@else
<div class="title">
<h3 class="font-weight-bold">Terms Of Use</h3>
</div>
@ -38,7 +45,7 @@
<p class="">These terms and conditions are governed by and construed in accordance with the laws of Canada and you irrevocably submit to the exclusive jurisdiction of the courts in that State or location.</p>
<h5 class="font-weight-bold">9. Additional Rules</h5>
<p class="">This website does not have any additional rules.</p>
@endif
@endsection
@push('meta')

View file

@ -27,6 +27,8 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio
Route::get('settings/pages', 'AdminController@settingsPages')->name('admin.settings.pages');
Route::get('settings/pages/edit', 'PageController@edit')->name('admin.settings.pages.edit');
Route::post('settings/pages/edit', 'PageController@store');
Route::post('settings/pages/delete', 'PageController@delete');
Route::post('settings/pages/create', 'PageController@generatePage');
Route::get('settings/maintenance', 'AdminController@settingsMaintenance')->name('admin.settings.maintenance');
Route::get('settings/backups', 'AdminController@settingsBackups')->name('admin.settings.backups');
Route::get('settings/storage', 'AdminController@settingsStorage')->name('admin.settings.storage');
@ -264,8 +266,8 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::view('fediverse', 'site.fediverse')->name('site.fediverse');
Route::view('open-source', 'site.opensource')->name('site.opensource');
Route::view('banned-instances', 'site.bannedinstances')->name('site.bannedinstances');
Route::view('terms', 'site.terms')->name('site.terms');
Route::view('privacy', 'site.privacy')->name('site.privacy');
Route::get('terms', 'SiteController@terms')->name('site.terms');
Route::get('privacy', 'SiteController@privacy')->name('site.privacy');
Route::view('platform', 'site.platform')->name('site.platform');
Route::view('language', 'site.language')->name('site.language');
Route::get('contact', 'ContactController@show')->name('site.contact');