diff --git a/app/Contact.php b/app/Contact.php new file mode 100644 index 000000000..afbabc58e --- /dev/null +++ b/app/Contact.php @@ -0,0 +1,18 @@ +belongsTo(User::class); + } + + public function adminUrl() + { + return url('/i/admin/contact/show/' . $this->id); + } +} diff --git a/app/Http/Controllers/Admin/AdminSupportController.php b/app/Http/Controllers/Admin/AdminSupportController.php new file mode 100644 index 000000000..95a45d518 --- /dev/null +++ b/app/Http/Controllers/Admin/AdminSupportController.php @@ -0,0 +1,12 @@ +query('col') ?? 'id'; $dir = $request->query('dir') ?? 'desc'; $stats = $this->collectUserStats($request); - $users = User::withCount('statuses')->orderBy($col, $dir)->paginate(10); + $users = User::withCount('statuses')->orderBy($col, $dir)->simplePaginate(10); return view('admin.users.home', compact('users', 'stats')); } @@ -115,7 +116,7 @@ class AdminController extends Controller public function statuses(Request $request) { - $statuses = Status::orderBy('id', 'desc')->paginate(10); + $statuses = Status::orderBy('id', 'desc')->simplePaginate(10); return view('admin.statuses.home', compact('statuses')); } @@ -207,11 +208,11 @@ class AdminController extends Controller $order = $request->input('order') ?? 'desc'; $limit = $request->input('limit') ?? 12; if($search) { - $profiles = Profile::select('id','username')->where('username','like', "%$search%")->orderBy('id','desc')->paginate($limit); + $profiles = Profile::select('id','username')->where('username','like', "%$search%")->orderBy('id','desc')->simplePaginate($limit); } else if($filter && $order) { - $profiles = Profile::select('id','username')->withCount(['likes','statuses','followers'])->orderBy($filter, $order)->paginate($limit); + $profiles = Profile::select('id','username')->withCount(['likes','statuses','followers'])->orderBy($filter, $order)->simplePaginate($limit); } else { - $profiles = Profile::select('id','username')->orderBy('id','desc')->paginate($limit); + $profiles = Profile::select('id','username')->orderBy('id','desc')->simplePaginate($limit); } return view('admin.profiles.home', compact('profiles')); diff --git a/app/Http/Controllers/ContactController.php b/app/Http/Controllers/ContactController.php new file mode 100644 index 000000000..da1591fe3 --- /dev/null +++ b/app/Http/Controllers/ContactController.php @@ -0,0 +1,45 @@ +validate($request, [ + 'message' => 'required|string|min:5|max:500', + 'request_response' => 'string|max:3' + ]); + + $message = $request->input('message'); + $request_response = $request->input('request_response') == 'on' ? true : false; + $user = Auth::user(); + + $contact = Contact::whereUserId($user->id) + ->whereDate('created_at', '>', now()->subDays(1)) + ->count(); + + if($contact >= 2) { + return redirect()->back()->with('error', 'You have recently sent a message. Please try again later.'); + } + + $contact = new Contact; + $contact->user_id = $user->id; + $contact->response_requested = $request_response; + $contact->message = $message; + $contact->save(); + + return redirect()->back()->with('status', 'Success - Your message has been sent to admins.'); + } +} diff --git a/app/Mail/ContactAdmin.php b/app/Mail/ContactAdmin.php new file mode 100644 index 000000000..97294aaec --- /dev/null +++ b/app/Mail/ContactAdmin.php @@ -0,0 +1,37 @@ +contact = $contact; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + $contact = $this->contact; + return $this->markdown('emails.contact.admin')->with(compact('contact')); + } +} diff --git a/database/migrations/2019_06_06_032316_create_contacts_table.php b/database/migrations/2019_06_06_032316_create_contacts_table.php new file mode 100644 index 000000000..2dabd047f --- /dev/null +++ b/database/migrations/2019_06_06_032316_create_contacts_table.php @@ -0,0 +1,37 @@ +bigIncrements('id'); + $table->bigInteger('user_id')->unsigned()->index(); + $table->boolean('response_requested')->default(false); + $table->text('message'); + $table->text('response'); + $table->timestamp('read_at')->nullable(); + $table->timestamp('responded_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('contacts'); + } +} diff --git a/public/js/profile.js b/public/js/profile.js index 17a33c6d6..578185361 100644 Binary files a/public/js/profile.js and b/public/js/profile.js differ diff --git a/public/js/status.js b/public/js/status.js index 459cbe287..f6d4dab73 100644 Binary files a/public/js/status.js and b/public/js/status.js differ diff --git a/public/js/timeline.js b/public/js/timeline.js index 53b55e716..1762e954d 100644 Binary files a/public/js/timeline.js and b/public/js/timeline.js differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 2759e92d5..9a8a45a03 100644 Binary files a/public/mix-manifest.json and b/public/mix-manifest.json differ diff --git a/resources/assets/js/components/presenter/MixedAlbumPresenter.vue b/resources/assets/js/components/presenter/MixedAlbumPresenter.vue index 004f82edd..790ce11ce 100644 --- a/resources/assets/js/components/presenter/MixedAlbumPresenter.vue +++ b/resources/assets/js/components/presenter/MixedAlbumPresenter.vue @@ -18,8 +18,8 @@ -
- +
+

Error: Problem rendering preview.

@@ -42,8 +42,8 @@ -
- +
+

Error: Problem rendering preview.

diff --git a/resources/assets/js/components/presenter/PhotoAlbumPresenter.vue b/resources/assets/js/components/presenter/PhotoAlbumPresenter.vue index 7bc7ec6e8..b4f75c09a 100644 --- a/resources/assets/js/components/presenter/PhotoAlbumPresenter.vue +++ b/resources/assets/js/components/presenter/PhotoAlbumPresenter.vue @@ -13,8 +13,8 @@ :interval="0" > -
- +
+
@@ -31,9 +31,9 @@ background="#ffffff" :interval="0" > - +
- +
diff --git a/resources/assets/js/components/presenter/PhotoPresenter.vue b/resources/assets/js/components/presenter/PhotoPresenter.vue index 3b6ef4f10..fbd43b5a8 100644 --- a/resources/assets/js/components/presenter/PhotoPresenter.vue +++ b/resources/assets/js/components/presenter/PhotoPresenter.vue @@ -5,14 +5,14 @@

{{ status.spoiler_text ? status.spoiler_text : 'CW / NSFW / Hidden Media'}}

(click to show)

-
- +
+
-
- +
+
diff --git a/resources/views/admin/media/home.blade.php b/resources/views/admin/media/home.blade.php index aed694726..4344afb73 100644 --- a/resources/views/admin/media/home.blade.php +++ b/resources/views/admin/media/home.blade.php @@ -85,7 +85,7 @@
- {{$media->links()}} + {{$media->appends(['layout'=>request()->layout])->links()}}
@else
@@ -99,7 +99,7 @@

- {{$media->links()}} + {{$media->appends(['layout'=>request()->layout])->links()}}
@endif @endsection diff --git a/resources/views/emails/contact/admin.blade.php b/resources/views/emails/contact/admin.blade.php new file mode 100644 index 000000000..46c3dfb8a --- /dev/null +++ b/resources/views/emails/contact/admin.blade.php @@ -0,0 +1,23 @@ +@component('mail::message') +# New Support Message + +
+ +@if($contact->response_requested) +**This user has requested a response from you.** +@endif + +
+ +[**{{$contact->user->username}}**]({{$contact->user->url()}}) has sent the following message: + +@component('mail::panel') +{{ $contact->message }} +@endcomponent + + +@component('mail::button', ['url' => $contact->adminUrl(), 'color' => 'primary']) +View Message +@endcomponent + +@endcomponent \ No newline at end of file diff --git a/resources/views/site/contact.blade.php b/resources/views/site/contact.blade.php new file mode 100644 index 000000000..3b45cc25a --- /dev/null +++ b/resources/views/site/contact.blade.php @@ -0,0 +1,49 @@ +@extends('site.partial.template') + +@section('section') + +
+

Contact

+
+
+
+ @auth +
+ @csrf +
+ + + 0/500 +
+
+ + +
+ +
+ @else +

+ @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. + @endif +

+ @endauth +
+@endsection + +@auth +@push('styles') + +@endpush + +@push('scripts') + +@endpush +@endauth \ No newline at end of file diff --git a/resources/views/site/partial/template.blade.php b/resources/views/site/partial/template.blade.php index 8ef6baa88..6da30f78f 100644 --- a/resources/views/site/partial/template.blade.php +++ b/resources/views/site/partial/template.blade.php @@ -10,10 +10,24 @@ @include('site.partial.sidebar')
@if (session('status')) -
+
{{ session('status') }}
@endif + @if (session('error')) +
+ {{ session('error') }} +
+ @endif + @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif @yield('section')
diff --git a/resources/views/vendor/mail/html/button.blade.php b/resources/views/vendor/mail/html/button.blade.php new file mode 100644 index 000000000..512c1d8c7 --- /dev/null +++ b/resources/views/vendor/mail/html/button.blade.php @@ -0,0 +1,19 @@ + + + + + diff --git a/resources/views/vendor/mail/html/footer.blade.php b/resources/views/vendor/mail/html/footer.blade.php new file mode 100644 index 000000000..33f7dad76 --- /dev/null +++ b/resources/views/vendor/mail/html/footer.blade.php @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/resources/views/vendor/mail/html/header.blade.php b/resources/views/vendor/mail/html/header.blade.php new file mode 100644 index 000000000..eefabab92 --- /dev/null +++ b/resources/views/vendor/mail/html/header.blade.php @@ -0,0 +1,7 @@ + + + + {{ $slot }} + + + diff --git a/resources/views/vendor/mail/html/layout.blade.php b/resources/views/vendor/mail/html/layout.blade.php new file mode 100644 index 000000000..eded4957c --- /dev/null +++ b/resources/views/vendor/mail/html/layout.blade.php @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + diff --git a/resources/views/vendor/mail/html/message.blade.php b/resources/views/vendor/mail/html/message.blade.php new file mode 100644 index 000000000..1ae9ed8f1 --- /dev/null +++ b/resources/views/vendor/mail/html/message.blade.php @@ -0,0 +1,27 @@ +@component('mail::layout') + {{-- Header --}} + @slot('header') + @component('mail::header', ['url' => config('app.url')]) + {{ config('app.name') }} + @endcomponent + @endslot + + {{-- Body --}} + {{ $slot }} + + {{-- Subcopy --}} + @isset($subcopy) + @slot('subcopy') + @component('mail::subcopy') + {{ $subcopy }} + @endcomponent + @endslot + @endisset + + {{-- Footer --}} + @slot('footer') + @component('mail::footer') + © {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.') + @endcomponent + @endslot +@endcomponent diff --git a/resources/views/vendor/mail/html/panel.blade.php b/resources/views/vendor/mail/html/panel.blade.php new file mode 100644 index 000000000..783af16ce --- /dev/null +++ b/resources/views/vendor/mail/html/panel.blade.php @@ -0,0 +1,13 @@ + + + + + diff --git a/resources/views/vendor/mail/html/promotion.blade.php b/resources/views/vendor/mail/html/promotion.blade.php new file mode 100644 index 000000000..f78b358c3 --- /dev/null +++ b/resources/views/vendor/mail/html/promotion.blade.php @@ -0,0 +1,7 @@ + + + + + diff --git a/resources/views/vendor/mail/html/promotion/button.blade.php b/resources/views/vendor/mail/html/promotion/button.blade.php new file mode 100644 index 000000000..1dcb2ee46 --- /dev/null +++ b/resources/views/vendor/mail/html/promotion/button.blade.php @@ -0,0 +1,13 @@ + + + + +
+ + + + +
+ {{ $slot }} +
+
diff --git a/resources/views/vendor/mail/html/subcopy.blade.php b/resources/views/vendor/mail/html/subcopy.blade.php new file mode 100644 index 000000000..f559e8f1b --- /dev/null +++ b/resources/views/vendor/mail/html/subcopy.blade.php @@ -0,0 +1,7 @@ + + + + + diff --git a/resources/views/vendor/mail/html/table.blade.php b/resources/views/vendor/mail/html/table.blade.php new file mode 100644 index 000000000..a5f3348b2 --- /dev/null +++ b/resources/views/vendor/mail/html/table.blade.php @@ -0,0 +1,3 @@ +
+{{ Illuminate\Mail\Markdown::parse($slot) }} +
diff --git a/resources/views/vendor/mail/html/themes/default.css b/resources/views/vendor/mail/html/themes/default.css new file mode 100644 index 000000000..e5a447178 --- /dev/null +++ b/resources/views/vendor/mail/html/themes/default.css @@ -0,0 +1,292 @@ +/* Base */ + +body, +body *:not(html):not(style):not(br):not(tr):not(code) { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; + box-sizing: border-box; +} + +body { + background-color: #f8fafc; + color: #74787e; + height: 100%; + hyphens: auto; + line-height: 1.4; + margin: 0; + -moz-hyphens: auto; + -ms-word-break: break-all; + width: 100% !important; + -webkit-hyphens: auto; + -webkit-text-size-adjust: none; + word-break: break-all; + word-break: break-word; +} + +p, +ul, +ol, +blockquote { + line-height: 1.4; + text-align: left; +} + +a { + color: #3869d4; +} + +a img { + border: none; +} + +/* Typography */ + +h1 { + color: #3d4852; + font-size: 19px; + font-weight: bold; + margin-top: 0; + text-align: left; +} + +h2 { + color: #3d4852; + font-size: 16px; + font-weight: bold; + margin-top: 0; + text-align: left; +} + +h3 { + color: #3d4852; + font-size: 14px; + font-weight: bold; + margin-top: 0; + text-align: left; +} + +p { + color: #3d4852; + font-size: 16px; + line-height: 1.5em; + margin-top: 0; + text-align: left; +} + +p.sub { + font-size: 12px; +} + +img { + max-width: 100%; +} + +/* Layout */ + +.wrapper { + background-color: #f8fafc; + margin: 0; + padding: 0; + width: 100%; + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + -premailer-width: 100%; +} + +.content { + margin: 0; + padding: 0; + width: 100%; + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + -premailer-width: 100%; +} + +/* Header */ + +.header { + padding: 25px 0; + text-align: center; +} + +.header a { + color: #bbbfc3; + font-size: 19px; + font-weight: bold; + text-decoration: none; + text-shadow: 0 1px 0 white; +} + +/* Body */ + +.body { + background-color: #ffffff; + border-bottom: 1px solid #edeff2; + border-top: 1px solid #edeff2; + margin: 0; + padding: 0; + width: 100%; + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + -premailer-width: 100%; +} + +.inner-body { + background-color: #ffffff; + margin: 0 auto; + padding: 0; + width: 570px; + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + -premailer-width: 570px; +} + +/* Subcopy */ + +.subcopy { + border-top: 1px solid #edeff2; + margin-top: 25px; + padding-top: 25px; +} + +.subcopy p { + font-size: 12px; +} + +/* Footer */ + +.footer { + margin: 0 auto; + padding: 0; + text-align: center; + width: 570px; + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + -premailer-width: 570px; +} + +.footer p { + color: #aeaeae; + font-size: 12px; + text-align: center; +} + +/* Tables */ + +.table table { + margin: 30px auto; + width: 100%; + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + -premailer-width: 100%; +} + +.table th { + border-bottom: 1px solid #edeff2; + padding-bottom: 8px; + margin: 0; +} + +.table td { + color: #74787e; + font-size: 15px; + line-height: 18px; + padding: 10px 0; + margin: 0; +} + +.content-cell { + padding: 35px; +} + +/* Buttons */ + +.action { + margin: 30px auto; + padding: 0; + text-align: center; + width: 100%; + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + -premailer-width: 100%; +} + +.button { + border-radius: 3px; + box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16); + color: #fff; + display: inline-block; + text-decoration: none; + -webkit-text-size-adjust: none; +} + +.button-blue, +.button-primary { + background-color: #3490dc; + border-top: 10px solid #3490dc; + border-right: 18px solid #3490dc; + border-bottom: 10px solid #3490dc; + border-left: 18px solid #3490dc; +} + +.button-green, +.button-success { + background-color: #38c172; + border-top: 10px solid #38c172; + border-right: 18px solid #38c172; + border-bottom: 10px solid #38c172; + border-left: 18px solid #38c172; +} + +.button-red, +.button-error { + background-color: #e3342f; + border-top: 10px solid #e3342f; + border-right: 18px solid #e3342f; + border-bottom: 10px solid #e3342f; + border-left: 18px solid #e3342f; +} + +/* Panels */ + +.panel { + margin: 0 0 21px; +} + +.panel-content { + background-color: #f1f5f8; + padding: 16px; +} + +.panel-item { + padding: 0; +} + +.panel-item p:last-of-type { + margin-bottom: 0; + padding-bottom: 0; +} + +/* Promotions */ + +.promotion { + background-color: #ffffff; + border: 2px dashed #9ba2ab; + margin: 0; + margin-bottom: 25px; + margin-top: 25px; + padding: 24px; + width: 100%; + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + -premailer-width: 100%; +} + +.promotion h1 { + text-align: center; +} + +.promotion p { + font-size: 15px; + text-align: center; +} diff --git a/resources/views/vendor/mail/text/button.blade.php b/resources/views/vendor/mail/text/button.blade.php new file mode 100644 index 000000000..97444ebdc --- /dev/null +++ b/resources/views/vendor/mail/text/button.blade.php @@ -0,0 +1 @@ +{{ $slot }}: {{ $url }} diff --git a/resources/views/vendor/mail/text/footer.blade.php b/resources/views/vendor/mail/text/footer.blade.php new file mode 100644 index 000000000..3338f620e --- /dev/null +++ b/resources/views/vendor/mail/text/footer.blade.php @@ -0,0 +1 @@ +{{ $slot }} diff --git a/resources/views/vendor/mail/text/header.blade.php b/resources/views/vendor/mail/text/header.blade.php new file mode 100644 index 000000000..aaa3e5754 --- /dev/null +++ b/resources/views/vendor/mail/text/header.blade.php @@ -0,0 +1 @@ +[{{ $slot }}]({{ $url }}) diff --git a/resources/views/vendor/mail/text/layout.blade.php b/resources/views/vendor/mail/text/layout.blade.php new file mode 100644 index 000000000..9378baa07 --- /dev/null +++ b/resources/views/vendor/mail/text/layout.blade.php @@ -0,0 +1,9 @@ +{!! strip_tags($header) !!} + +{!! strip_tags($slot) !!} +@isset($subcopy) + +{!! strip_tags($subcopy) !!} +@endisset + +{!! strip_tags($footer) !!} diff --git a/resources/views/vendor/mail/text/message.blade.php b/resources/views/vendor/mail/text/message.blade.php new file mode 100644 index 000000000..1ae9ed8f1 --- /dev/null +++ b/resources/views/vendor/mail/text/message.blade.php @@ -0,0 +1,27 @@ +@component('mail::layout') + {{-- Header --}} + @slot('header') + @component('mail::header', ['url' => config('app.url')]) + {{ config('app.name') }} + @endcomponent + @endslot + + {{-- Body --}} + {{ $slot }} + + {{-- Subcopy --}} + @isset($subcopy) + @slot('subcopy') + @component('mail::subcopy') + {{ $subcopy }} + @endcomponent + @endslot + @endisset + + {{-- Footer --}} + @slot('footer') + @component('mail::footer') + © {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.') + @endcomponent + @endslot +@endcomponent diff --git a/resources/views/vendor/mail/text/panel.blade.php b/resources/views/vendor/mail/text/panel.blade.php new file mode 100644 index 000000000..3338f620e --- /dev/null +++ b/resources/views/vendor/mail/text/panel.blade.php @@ -0,0 +1 @@ +{{ $slot }} diff --git a/resources/views/vendor/mail/text/promotion.blade.php b/resources/views/vendor/mail/text/promotion.blade.php new file mode 100644 index 000000000..3338f620e --- /dev/null +++ b/resources/views/vendor/mail/text/promotion.blade.php @@ -0,0 +1 @@ +{{ $slot }} diff --git a/resources/views/vendor/mail/text/promotion/button.blade.php b/resources/views/vendor/mail/text/promotion/button.blade.php new file mode 100644 index 000000000..aaa3e5754 --- /dev/null +++ b/resources/views/vendor/mail/text/promotion/button.blade.php @@ -0,0 +1 @@ +[{{ $slot }}]({{ $url }}) diff --git a/resources/views/vendor/mail/text/subcopy.blade.php b/resources/views/vendor/mail/text/subcopy.blade.php new file mode 100644 index 000000000..3338f620e --- /dev/null +++ b/resources/views/vendor/mail/text/subcopy.blade.php @@ -0,0 +1 @@ +{{ $slot }} diff --git a/resources/views/vendor/mail/text/table.blade.php b/resources/views/vendor/mail/text/table.blade.php new file mode 100644 index 000000000..3338f620e --- /dev/null +++ b/resources/views/vendor/mail/text/table.blade.php @@ -0,0 +1 @@ +{{ $slot }}