mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-12-23 05:23:17 +00:00
Merge pull request #1424 from pixelfed/frontend-ui-refactor
Add Contact Form
This commit is contained in:
commit
07182a5797
15 changed files with 238 additions and 15 deletions
|
@ -13,6 +13,6 @@ class Contact extends Model
|
|||
|
||||
public function adminUrl()
|
||||
{
|
||||
return url('/i/admin/contact/show/' . $this->id);
|
||||
return url('/i/admin/messages/show/' . $this->id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\{
|
||||
Contact,
|
||||
FailedJob,
|
||||
Hashtag,
|
||||
Instance,
|
||||
|
@ -47,6 +48,10 @@ class AdminController extends Controller
|
|||
$data = Cache::remember('admin:dashboard:home:data', now()->addMinutes(15), function() {
|
||||
$day = config('database.default') == 'pgsql' ? 'DATE_PART(\'day\',' : 'day(';
|
||||
return [
|
||||
'contact' => [
|
||||
'count' => PrettyNumber::convert(Contact::whereNull('read_at')->count()),
|
||||
'graph' => Contact::selectRaw('count(*) as count, '.$day.'created_at) as day')->whereNull('read_at')->whereBetween('created_at',[now()->subDays(14), now()])->groupBy('day')->orderBy('day')->pluck('count')
|
||||
],
|
||||
'failedjobs' => [
|
||||
'count' => PrettyNumber::convert(FailedJob::where('failed_at', '>=', \Carbon\Carbon::now()->subDay())->count()),
|
||||
'graph' => FailedJob::selectRaw('count(*) as count, '.$day.'failed_at) as d')->groupBy('d')->whereBetween('failed_at',[now()->subDays(24), now()])->orderBy('d')->pluck('count')
|
||||
|
@ -248,4 +253,30 @@ class AdminController extends Controller
|
|||
return view('admin.hashtags.home', compact('hashtags'));
|
||||
}
|
||||
|
||||
public function messagesHome(Request $request)
|
||||
{
|
||||
$messages = Contact::orderByDesc('id')->paginate(10);
|
||||
return view('admin.messages.home', compact('messages'));
|
||||
}
|
||||
|
||||
public function messagesShow(Request $request, $id)
|
||||
{
|
||||
$message = Contact::findOrFail($id);
|
||||
return view('admin.messages.show', compact('message'));
|
||||
}
|
||||
|
||||
public function messagesMarkRead(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'id' => 'required|integer|min:1'
|
||||
]);
|
||||
$id = $request->input('id');
|
||||
$message = Contact::findOrFail($id);
|
||||
if($message->read_at) {
|
||||
return;
|
||||
}
|
||||
$message->read_at = now();
|
||||
$message->save();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,16 +5,19 @@ namespace App\Http\Controllers;
|
|||
use Illuminate\Http\Request;
|
||||
use Auth;
|
||||
use App\Contact;
|
||||
use App\Jobs\ContactPipeline\ContactPipeline;
|
||||
|
||||
class ContactController extends Controller
|
||||
{
|
||||
public function show(Request $request)
|
||||
{
|
||||
abort_if(!config('instance.email') && !config('instance.contact.enabled'), 404);
|
||||
return view('site.contact');
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
abort_if(!config('instance.contact.enabled'), 404);
|
||||
abort_if(!Auth::check(), 403);
|
||||
|
||||
$this->validate($request, [
|
||||
|
@ -26,11 +29,12 @@ class ContactController extends Controller
|
|||
$request_response = $request->input('request_response') == 'on' ? true : false;
|
||||
$user = Auth::user();
|
||||
|
||||
$max = config('instance.contact.max_per_day');
|
||||
$contact = Contact::whereUserId($user->id)
|
||||
->whereDate('created_at', '>', now()->subDays(1))
|
||||
->whereDate('created_at', '>', now()->subDays($max))
|
||||
->count();
|
||||
|
||||
if($contact >= 2) {
|
||||
if($contact >= $max) {
|
||||
return redirect()->back()->with('error', 'You have recently sent a message. Please try again later.');
|
||||
}
|
||||
|
||||
|
@ -40,6 +44,8 @@ class ContactController extends Controller
|
|||
$contact->message = $message;
|
||||
$contact->save();
|
||||
|
||||
ContactPipeline::dispatchNow($contact);
|
||||
|
||||
return redirect()->back()->with('status', 'Success - Your message has been sent to admins.');
|
||||
}
|
||||
}
|
||||
|
|
44
app/Jobs/ContactPipeline/ContactPipeline.php
Normal file
44
app/Jobs/ContactPipeline/ContactPipeline.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs\ContactPipeline;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use App\Contact;
|
||||
use App\Mail\ContactAdmin;
|
||||
use Mail;
|
||||
|
||||
class ContactPipeline implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $contact;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Contact $contact)
|
||||
{
|
||||
$this->contact = $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$contact = $this->contact;
|
||||
$email = config('instance.email');
|
||||
if(config('instance.contact.enabled') == false || $contact->read_at !== null || filter_var($email, FILTER_VALIDATE_EMAIL) == false) {
|
||||
return;
|
||||
}
|
||||
Mail::to($email)->send(new ContactAdmin($contact));
|
||||
}
|
||||
}
|
|
@ -2,4 +2,9 @@
|
|||
|
||||
return [
|
||||
'email' => env('INSTANCE_CONTACT_EMAIL'),
|
||||
|
||||
'contact' => [
|
||||
'enabled' => env('INSTANCE_CONTACT_FORM', false),
|
||||
'max_per_day' => env('INSTANCE_CONTACT_MAX_PER_DAY', 1),
|
||||
],
|
||||
];
|
|
@ -12,5 +12,7 @@ return [
|
|||
'l10nWip' => 'We’re still working on localization support',
|
||||
'currentLocale' => 'Current locale',
|
||||
'selectLocale' => 'Select one of the supported languages',
|
||||
'contact' => 'Contact',
|
||||
'contact-us' => 'Contact Us',
|
||||
|
||||
];
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
</div>
|
||||
|
||||
<hr>
|
||||
<table class="table table-responsive">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
|
@ -45,4 +46,5 @@
|
|||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@endsection
|
|
@ -11,10 +11,10 @@
|
|||
<div class="col-md-4">
|
||||
<div class="card" style="min-height:125px">
|
||||
<div class="card-body">
|
||||
<p class="small text-uppercase font-weight-bold text-muted">Alerts</p>
|
||||
<p class="h2 mb-0">0</p>
|
||||
<p class="small text-uppercase font-weight-bold text-muted">New Messages</p>
|
||||
<p class="h2 mb-0">{{$data['contact']['count']}}</p>
|
||||
</div>
|
||||
<canvas width="100" height="10" class="sparkline mb-1" data-chart_values="[0,0]"></canvas>
|
||||
<canvas width="100" height="10" class="sparkline mb-1" data-chart_values="{{$data['contact']['graph']}}"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
36
resources/views/admin/messages/home.blade.php
Normal file
36
resources/views/admin/messages/home.blade.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
@extends('admin.partial.template-full')
|
||||
|
||||
@section('section')
|
||||
<div class="title">
|
||||
<h3 class="font-weight-bold d-inline-block">Messages</h3>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">User</th>
|
||||
<th scope="col">Message</th>
|
||||
<th scope="col">Created</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($messages as $msg)
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/i/admin/messages/show/{{$msg->id}}" class="btn btn-sm btn-outline-primary">
|
||||
{{$msg->id}}
|
||||
</a>
|
||||
</td>
|
||||
<td class="font-weight-bold"><a href="{{$msg->user->url()}}">{{$msg->user->username}}</a></td>
|
||||
<td class="font-weight-bold">{{str_limit($msg->message, 40)}}</td>
|
||||
<td class="font-weight-bold">{{$msg->created_at->diffForHumans()}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{$messages->links()}}
|
||||
@endsection
|
68
resources/views/admin/messages/show.blade.php
Normal file
68
resources/views/admin/messages/show.blade.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
@extends('admin.partial.template-full')
|
||||
|
||||
@section('section')
|
||||
<div class="title">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="font-weight-bold"># {{$message->id}}</div>
|
||||
<div class="font-weight-bold h3">Message</div>
|
||||
<div>
|
||||
@if($message->read_at)
|
||||
<span class="btn btn-outline-secondary btn-sm disabled" disabled>Read</span>
|
||||
@else
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" id="markRead">Mark Read</button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-12 col-md-3 text-md-right">
|
||||
@if($message->response_requested)
|
||||
<p class="text-dark font-weight-bold">Response Requested</p>
|
||||
@endif
|
||||
<p class="text-dark">Sent {{$message->created_at->diffForHumans()}}</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
|
||||
<div class="card shadow-none border">
|
||||
<div class="card-header bg-white">
|
||||
<div class="media">
|
||||
<img src="{{$message->user->profile->avatarUrl()}}" class="mr-3 rounded-circle" width="40px" height="40px">
|
||||
<div class="media-body">
|
||||
<h5 class="my-0">@{{$message->user->username}}</h5>
|
||||
<span class="text-muted">{{$message->user->email}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="mb-0">{{$message->message}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-3">
|
||||
{{-- @if($message->responded_at == null)
|
||||
<button class="btn btn-primary font-weight-bold btn-block">Send Response</button>
|
||||
<hr>
|
||||
@endif
|
||||
<button class="btn btn-outline-danger font-weight-bold btn-block">Delete</button> --}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
$('#markRead').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
axios.post('/i/admin/messages/mark-read', {
|
||||
id: '{{$message->id}}',
|
||||
}).then(res => {
|
||||
window.location.href = window.location.href;
|
||||
})
|
||||
})
|
||||
</script>
|
||||
@endpush
|
|
@ -8,8 +8,8 @@
|
|||
<li class="nav-item mx-2 {{request()->is('*admin/dashboard')?'active':''}}">
|
||||
<a class="nav-link" href="{{route('admin.home')}}">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item mx-2 {{request()->is('*apps*')?'active':''}}">
|
||||
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.apps')}}">Apps</a>
|
||||
<li class="nav-item mx-2 {{request()->is('*messages*')?'active':''}}">
|
||||
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.messages')}}">Messages</a>
|
||||
</li>
|
||||
<li class="nav-item mx-2 {{request()->is('*hashtags*')?'active':''}}">
|
||||
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.hashtags')}}">Hashtags</a>
|
||||
|
@ -37,6 +37,7 @@
|
|||
More
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item font-weight-bold {{request()->is('*apps*')?'active':''}}" href="{{route('admin.apps')}}">Apps</a>
|
||||
<a class="dropdown-item font-weight-bold {{request()->is('*discover*')?'active':''}}" href="{{route('admin.discover')}}">Discover</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item font-weight-bold" href="/horizon">Horizon</a>
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
<div class="container py-5">
|
||||
<p class="mb-0 text-uppercase font-weight-bold small text-justify">
|
||||
<a href="{{route('site.about')}}" class="text-primary pr-3">{{__('site.about')}}</a>
|
||||
@if(config('instance.contact.enabled') || config('instance.email'))
|
||||
<a href="{{route('site.contact')}}" class="text-primary pr-3">{{__('site.contact-us')}}</a>
|
||||
@endif
|
||||
<a href="{{route('site.help')}}" class="text-primary pr-3">{{__('site.help')}}</a>
|
||||
<a href="{{route('site.opensource')}}" class="text-primary pr-3">{{__('site.opensource')}}</a>
|
||||
<a href="{{route('site.terms')}}" class="text-primary pr-3">{{__('site.terms')}}</a>
|
||||
|
|
|
@ -3,11 +3,23 @@
|
|||
@section('section')
|
||||
|
||||
<div class="title">
|
||||
<h3 class="font-weight-bold">Contact</h3>
|
||||
<h3 class="font-weight-bold">{{__('site.contact-us')}}</h3>
|
||||
</div>
|
||||
<hr>
|
||||
<section>
|
||||
@auth
|
||||
<p class="lead">
|
||||
@if(config('instance.email') && config('instance.contact.enabled'))
|
||||
You can contact the admins by sending an email to <span class="font-weight-bold">{{config('instance.email')}}</span> or by using the form below.
|
||||
@elseif(config('instance.email') && !config('instance.contact.enabled'))
|
||||
You can contact the admins by sending an email to <span class="font-weight-bold">{{config('instance.email')}}</span>.
|
||||
@elseif(!config('instance.email') && config('instance.contact.enabled'))
|
||||
You can contact the admins by using the form below.
|
||||
@else
|
||||
The admins have not set a contact email address.
|
||||
@endif
|
||||
</p>
|
||||
@if(config('instance.contact.enabled'))
|
||||
<form method="POST">
|
||||
@csrf
|
||||
<div class="form-group">
|
||||
|
@ -21,12 +33,15 @@
|
|||
</div>
|
||||
<button type="submit" class="btn btn-primary font-weight-bold py-0">Submit</button>
|
||||
</form>
|
||||
@endif
|
||||
@else
|
||||
<p class="lead">
|
||||
@if(filter_var(config('instance.email'), FILTER_VALIDATE_EMAIL) == true)
|
||||
You can contact the admins by sending an email to {{config('instance.email')}}.
|
||||
@else
|
||||
The admins have not listed any public email. Please log in to send a message.
|
||||
@if(config('instance.email') && config('instance.contact.enabled'))
|
||||
You can contact the admins by sending an email to <span class="font-weight-bold">{{config('instance.email')}}</span> or log in to send a message.
|
||||
@elseif (!config('instance.email') && config('instance.contact.enabled'))
|
||||
The admins have not set a contact email address. Please log in to send a message.
|
||||
@elseif (config('instance.email') && !config('instance.contact.enabled'))
|
||||
You can contact the admins by sending an email to <span class="font-weight-bold">{{config('instance.email')}}</span>.
|
||||
@endif
|
||||
</p>
|
||||
@endauth
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
<li class="nav-item">
|
||||
<hr>
|
||||
</li>
|
||||
@if(config('instance.contact.enabled') || config('instance.email'))
|
||||
<li class="nav-item pl-3 {{request()->is('site/contact')?'active':''}}">
|
||||
<a class="nav-link font-weight-light text-muted" href="{{route('site.contact')}}">{{__('site.contact-us')}}</a>
|
||||
</li>
|
||||
@endif
|
||||
<li class="nav-item pl-3 {{request()->is('site/terms')?'active':''}}">
|
||||
<a class="nav-link font-weight-light text-muted" href="{{route('site.terms')}}">{{__('site.terms')}}</a>
|
||||
</li>
|
||||
|
|
|
@ -44,6 +44,10 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio
|
|||
Route::get('discover/category/edit/{id}', 'AdminController@discoverCategoryEdit');
|
||||
Route::post('discover/category/edit/{id}', 'AdminController@discoverCategoryUpdate');
|
||||
Route::post('discover/category/hashtag/create', 'AdminController@discoveryCategoryTagStore')->name('admin.discover.create-hashtag');
|
||||
|
||||
Route::get('messages/home', 'AdminController@messagesHome')->name('admin.messages');
|
||||
Route::get('messages/show/{id}', 'AdminController@messagesShow');
|
||||
Route::post('messages/mark-read', 'AdminController@messagesMarkRead');
|
||||
});
|
||||
|
||||
Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofactor', 'localization'])->group(function () {
|
||||
|
@ -264,7 +268,8 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
Route::view('privacy', 'site.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');
|
||||
Route::post('contact', 'ContactController@store');
|
||||
Route::group(['prefix'=>'kb'], function() {
|
||||
Route::view('getting-started', 'site.help.getting-started')->name('help.getting-started');
|
||||
Route::view('sharing-media', 'site.help.sharing-media')->name('help.sharing-media');
|
||||
|
|
Loading…
Reference in a new issue