mirror of https://github.com/pixelfed/pixelfed
commit
ee22faeb8b
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\UserFilter;
|
||||
use App\Services\UserFilterService;
|
||||
|
||||
class UserFilterObserver
|
||||
{
|
||||
/**
|
||||
* Handle the user filter "created" event.
|
||||
*
|
||||
* @param \App\UserFilter $userFilter
|
||||
* @return void
|
||||
*/
|
||||
public function created(UserFilter $userFilter)
|
||||
{
|
||||
$this->filterCreate($userFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the user filter "updated" event.
|
||||
*
|
||||
* @param \App\UserFilter $userFilter
|
||||
* @return void
|
||||
*/
|
||||
public function updated(UserFilter $userFilter)
|
||||
{
|
||||
$this->filterCreate($userFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the user filter "deleted" event.
|
||||
*
|
||||
* @param \App\UserFilter $userFilter
|
||||
* @return void
|
||||
*/
|
||||
public function deleted(UserFilter $userFilter)
|
||||
{
|
||||
$this->filterDelete($userFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the user filter "restored" event.
|
||||
*
|
||||
* @param \App\UserFilter $userFilter
|
||||
* @return void
|
||||
*/
|
||||
public function restored(UserFilter $userFilter)
|
||||
{
|
||||
$this->filterCreate($userFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the user filter "force deleted" event.
|
||||
*
|
||||
* @param \App\UserFilter $userFilter
|
||||
* @return void
|
||||
*/
|
||||
public function forceDeleted(UserFilter $userFilter)
|
||||
{
|
||||
$this->filterDelete($userFilter);
|
||||
}
|
||||
|
||||
protected function filterCreate(UserFilter $userFilter)
|
||||
{
|
||||
if($userFilter->filterable_type !== 'App\Profile') {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($userFilter->filter_type) {
|
||||
case 'mute':
|
||||
UserFilterService::mute($userFilter->user_id, $userFilter->filterable_id);
|
||||
break;
|
||||
|
||||
case 'block':
|
||||
UserFilterService::block($userFilter->user_id, $userFilter->filterable_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function filterDelete(UserFilter $userFilter)
|
||||
{
|
||||
if($userFilter->filterable_type !== 'App\Profile') {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($userFilter->filter_type) {
|
||||
case 'mute':
|
||||
UserFilterService::unmute($userFilter->user_id, $userFilter->filterable_id);
|
||||
break;
|
||||
|
||||
case 'block':
|
||||
UserFilterService::unblock($userFilter->user_id, $userFilter->filterable_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Cache, Redis;
|
||||
|
||||
use App\{
|
||||
Follower,
|
||||
Profile,
|
||||
UserFilter
|
||||
};
|
||||
|
||||
class UserFilterService {
|
||||
|
||||
const USER_MUTES_KEY = 'pf:services:mutes:ids:';
|
||||
const USER_BLOCKS_KEY = 'pf:services:blocks:ids:';
|
||||
|
||||
public static function mutes(int $profile_id) : array
|
||||
{
|
||||
$key = self::USER_MUTES_KEY . $profile_id;
|
||||
$cached = Redis::zrevrange($key, 0, -1);
|
||||
if($cached) {
|
||||
return $cached;
|
||||
} else {
|
||||
$ids = UserFilter::whereFilterType('mute')
|
||||
->whereUserId($profile_id)
|
||||
->pluck('filterable_id')
|
||||
->toArray();
|
||||
foreach ($ids as $muted_id) {
|
||||
Redis::zadd($key, (int) $muted_id, (int) $muted_id);
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
}
|
||||
|
||||
public static function blocks(int $profile_id) : array
|
||||
{
|
||||
$key = self::USER_BLOCKS_KEY . $profile_id;
|
||||
$cached = Redis::zrevrange($key, 0, -1);
|
||||
if($cached) {
|
||||
return $cached;
|
||||
} else {
|
||||
$ids = UserFilter::whereFilterType('block')
|
||||
->whereUserId($profile_id)
|
||||
->pluck('filterable_id')
|
||||
->toArray();
|
||||
foreach ($ids as $blocked_id) {
|
||||
Redis::zadd($key, $blocked_id, $blocked_id);
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
}
|
||||
|
||||
public static function filters(int $profile_id) : array
|
||||
{
|
||||
return array_merge(self::mutes($profile_id), self::blocks($profile_id));
|
||||
}
|
||||
|
||||
public static function mute(int $profile_id, int $muted_id)
|
||||
{
|
||||
$key = self::USER_MUTES_KEY . $profile_id;
|
||||
$mutes = self::mutes($profile_id);
|
||||
$exists = in_array($muted_id, $mutes);
|
||||
if(!$exists) {
|
||||
Redis::zadd($key, $muted_id, $muted_id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function unmute(int $profile_id, string $muted_id)
|
||||
{
|
||||
$key = self::USER_MUTES_KEY . $profile_id;
|
||||
$mutes = self::mutes($profile_id);
|
||||
$exists = in_array($muted_id, $mutes);
|
||||
if($exists) {
|
||||
Redis::zrem($key, $muted_id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function block(int $profile_id, int $blocked_id)
|
||||
{
|
||||
$key = self::USER_BLOCKS_KEY . $profile_id;
|
||||
$exists = in_array($blocked_id, self::blocks($profile_id));
|
||||
if(!$exists) {
|
||||
Redis::zadd($key, $blocked_id, $blocked_id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function unblock(int $profile_id, string $blocked_id)
|
||||
{
|
||||
$key = self::USER_BLOCKS_KEY . $profile_id;
|
||||
$exists = in_array($blocked_id, self::blocks($profile_id));
|
||||
if($exists) {
|
||||
Redis::zrem($key, $blocked_id);
|
||||
}
|
||||
return $exists;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{14:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)}),ace.require(["ace/theme/monokai"],function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)})}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[14,0]]]);
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{15:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)}),ace.require(["ace/theme/monokai"],function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)})}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[15,0]]]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,26 +1,27 @@
|
||||
{
|
||||
"/js/manifest.js": "/js/manifest.js?id=01c8731923a46c30aaed",
|
||||
"/js/vendor.js": "/js/vendor.js?id=383c6f227a3b8d8d1c71",
|
||||
"/js/ace.js": "/js/ace.js?id=4a28163d5fd63e64d6af",
|
||||
"/js/vendor.js": "/js/vendor.js?id=fac92a458473b287c543",
|
||||
"/js/ace.js": "/js/ace.js?id=585114d8896dc0c24020",
|
||||
"/js/activity.js": "/js/activity.js?id=a414018a6c03ddd2a492",
|
||||
"/js/app.js": "/js/app.js?id=e44ab72ffa230a7a56c1",
|
||||
"/css/app.css": "/css/app.css?id=73af4bf8ced6e3c406ee",
|
||||
"/css/appdark.css": "/css/appdark.css?id=10d573d6faab9ee2eeca",
|
||||
"/css/landing.css": "/css/landing.css?id=385cadd3ef179fae26cc",
|
||||
"/css/app.css": "/css/app.css?id=67710dadf879498b096a",
|
||||
"/css/appdark.css": "/css/appdark.css?id=6c52e68ca396700f0836",
|
||||
"/css/landing.css": "/css/landing.css?id=6164f7c333f0ab25b7f3",
|
||||
"/css/quill.css": "/css/quill.css?id=81604d62610b0dbffad6",
|
||||
"/js/collectioncompose.js": "/js/collectioncompose.js?id=a117b4e0b1d2fd859de5",
|
||||
"/js/collections.js": "/js/collections.js?id=5c9926c1f532e17026fc",
|
||||
"/js/collectioncompose.js": "/js/collectioncompose.js?id=afac91fbc98cde05f305",
|
||||
"/js/collections.js": "/js/collections.js?id=fecadca26c0cab56015c",
|
||||
"/js/components.js": "/js/components.js?id=b981ec12e26469676c4e",
|
||||
"/js/compose.js": "/js/compose.js?id=f27e95963a805f49dd03",
|
||||
"/js/developers.js": "/js/developers.js?id=a395f12c52bb0eada6ab",
|
||||
"/js/discover.js": "/js/discover.js?id=e8165d745727c3c71c62",
|
||||
"/js/hashtag.js": "/js/hashtag.js?id=b4ffe6499880acf0591c",
|
||||
"/js/loops.js": "/js/loops.js?id=017e807837b173d82724",
|
||||
"/js/mode-dot.js": "/js/mode-dot.js?id=8224e306cf53e3336620",
|
||||
"/js/profile.js": "/js/profile.js?id=575df314fa611b303ef7",
|
||||
"/js/quill.js": "/js/quill.js?id=9edfe94c043a1bc68860",
|
||||
"/js/search.js": "/js/search.js?id=b1bd588d07e682f8fce5",
|
||||
"/js/status.js": "/js/status.js?id=709b96bbcc47b605497b",
|
||||
"/js/theme-monokai.js": "/js/theme-monokai.js?id=344fb8527bb66574e4cd",
|
||||
"/js/timeline.js": "/js/timeline.js?id=1dbd02afede65e4144c3"
|
||||
"/js/compose.js": "/js/compose.js?id=17f022113cb2947ccdbd",
|
||||
"/js/compose-classic.js": "/js/compose-classic.js?id=52685de8819dc6008fc8",
|
||||
"/js/developers.js": "/js/developers.js?id=9636d4060ca6b359d8a2",
|
||||
"/js/discover.js": "/js/discover.js?id=0fc453a7630b144fcf4e",
|
||||
"/js/hashtag.js": "/js/hashtag.js?id=1e5990f89b6bfe7e037b",
|
||||
"/js/loops.js": "/js/loops.js?id=9c31302552d789d5f35b",
|
||||
"/js/mode-dot.js": "/js/mode-dot.js?id=993d7fee684361edddbc",
|
||||
"/js/profile.js": "/js/profile.js?id=2e555fe6c8406d7536e0",
|
||||
"/js/quill.js": "/js/quill.js?id=1ab4119a62cc484034d9",
|
||||
"/js/search.js": "/js/search.js?id=f312959df65e86a307a3",
|
||||
"/js/status.js": "/js/status.js?id=0857ea680bd2eb9c0b05",
|
||||
"/js/theme-monokai.js": "/js/theme-monokai.js?id=700e5dc735365e184e41",
|
||||
"/js/timeline.js": "/js/timeline.js?id=d8650e1b8a63fd491ccd"
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
Vue.component(
|
||||
'micro-ui',
|
||||
require('./components/Micro.vue').default
|
||||
);
|
@ -0,0 +1,22 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-5">
|
||||
<div class="col-12">
|
||||
<p class="font-weight-bold text-lighter text-uppercase">Cities in {{$places->first()->country}}</p>
|
||||
<div class="card border shadow-none">
|
||||
<div class="card-body row pl-md-5 ml-md-5">
|
||||
@foreach($places as $place)
|
||||
<div class="col-12 col-md-4 mb-2">
|
||||
<a href="{{$place->cityUrl()}}" class="text-dark pr-3 b-3">{{$place->name}}</a>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="card-footer bg-white pb-0 d-flex justify-content-center">
|
||||
{{$places->links()}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
@ -0,0 +1,22 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-5">
|
||||
<div class="col-12">
|
||||
<p class="font-weight-bold text-lighter text-uppercase">Countries</p>
|
||||
<div class="card border shadow-none">
|
||||
<div class="card-body row pl-md-5 ml-md-5">
|
||||
@foreach($places as $place)
|
||||
<div class="col-12 col-md-4 mb-2">
|
||||
<a href="{{$place->countryUrl()}}" class="text-dark pr-3 b-3">{{$place->country}}</a>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="card-footer bg-white pb-0 d-flex justify-content-center">
|
||||
{{$places->links()}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
@ -0,0 +1,48 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
|
||||
<div class="profile-header row my-5">
|
||||
<div class="col-12 col-md-2">
|
||||
<div class="profile-avatar">
|
||||
<div class="bg-pixelfed mb-3 d-flex align-items-center justify-content-center display-4 font-weight-bold text-white" style="width: 132px; height: 132px; border-radius: 100%"><i class="fas fa-map-pin"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-9 d-flex align-items-center">
|
||||
<div class="profile-details">
|
||||
<div class="username-bar pb-2 d-flex align-items-center">
|
||||
<div class="ml-4">
|
||||
<p class="h3 font-weight-lighter">{{$place->name}}, {{$place->country}}</p>
|
||||
<p class="small text-muted">({{$place->lat}}, {{$place->long}})</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tag-timeline">
|
||||
<div class="row">
|
||||
@if($posts->count() > 0)
|
||||
@foreach($posts as $status)
|
||||
<div class="col-4 p-0 p-sm-2 p-md-3">
|
||||
<a class="card info-overlay card-md-border-0" href="{{$status->url()}}">
|
||||
<div class="square {{$status->firstMedia()->filter_class}}">
|
||||
<div class="square-content" style="background-image: url('{{$status->thumb()}}')"></div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@endforeach
|
||||
@else
|
||||
<div class="col-12 bg-white p-5 border">
|
||||
<p class="lead text-center text-dark mb-0">No results for this location</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript" src="{{ mix('js/compose.js') }}"></script>
|
||||
<script type="text/javascript">App.boot();</script>
|
||||
@endpush
|
@ -0,0 +1,64 @@
|
||||
@extends('settings.template')
|
||||
|
||||
@section('section')
|
||||
|
||||
<div class="title">
|
||||
<h3 class="font-weight-bold">Send Invite</h3>
|
||||
<p class="lead">Invite friends or family to join you on <span class="font-weight-bold">{{config('pixelfed.domain.app')}}</span></p>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
@if(config('pixelfed.user_invites.limit.daily') != 0)
|
||||
<div class="alert alert-warning">
|
||||
<div class="font-weight-bold">Warning</div>
|
||||
<p class="mb-0">You may only send {{config('pixelfed.user_invites.limit.daily')}} invite(s) per day.</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="post">
|
||||
@csrf
|
||||
<div class="form-group">
|
||||
<label>Email address</label>
|
||||
<input type="email" class="form-control" name="email" placeholder="friend@example.org" autocomplete="off">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Message</label>
|
||||
<textarea class="form-control" name="message" placeholder="Add an optional message" rows="2"></textarea>
|
||||
<p class="help-text mb-0 text-right small text-muted"><span class="message-count">0</span>/<span class="message-limit">500</span></p>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" class="form-check-input" id="tos" name="tos">
|
||||
<label class="form-check-label font-weight-bold small" for="tos">I confirm this invitation is not in violation of the <a href="{{route('site.terms')}}">Terms of Service</a> and <a href="{{route('site.privacy')}}">Privacy Policy</a>.</label>
|
||||
</div>
|
||||
<hr>
|
||||
<p class="float-right">
|
||||
<button type="submit" class="btn btn-primary font-weight-bold py-0 form-submit">Send Invite</button>
|
||||
</p>
|
||||
</form>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
|
||||
$('textarea[name="message"]').on('change keyup paste', function(e) {
|
||||
let el = $(this);
|
||||
let len = el.val().length;
|
||||
let limit = $('.message-limit').text();
|
||||
|
||||
if(len > 100) {
|
||||
el.attr('rows', '4');
|
||||
}
|
||||
|
||||
if(len > limit) {
|
||||
let diff = len - limit;
|
||||
$('.message-count').addClass('text-danger').text('-'+diff);
|
||||
$('.form-submit').attr('disabled','');
|
||||
} else {
|
||||
$('.message-count').removeClass('text-danger').text(len);
|
||||
$('.form-submit').removeAttr('disabled');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@endpush
|
@ -0,0 +1,45 @@
|
||||
@extends('settings.template')
|
||||
|
||||
@section('section')
|
||||
|
||||
<div class="title">
|
||||
<h3 class="font-weight-bold">Invites</h3>
|
||||
<p class="lead">Send email invites to your friends and family!</p>
|
||||
</div>
|
||||
<hr>
|
||||
@if($invites->count() > 0)
|
||||
<table class="table table-light">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Email</th>
|
||||
<th scope="col">Valid For</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($invites as $invite)
|
||||
<tr>
|
||||
<th scope="row">{{$invite->id}}</th>
|
||||
<td>{{$invite->email}}</td>
|
||||
<td>{{$invite->message}}</td>
|
||||
<td>
|
||||
@if($invite->used_at == null)
|
||||
<button class="btn btn-outline-danger btn-sm">Delete</button>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@else
|
||||
<div class="d-flex align-items-center justify-content-center text-center pb-4">
|
||||
<div>
|
||||
<p class="pt-5"><i class="far fa-envelope-open text-lighter fa-6x"></i></p>
|
||||
<p class="lead">You haven't invited anyone yet.</p>
|
||||
<p><a class="btn btn-primary btn-lg py-0 font-weight-bold" href="{{route('settings.invites.create')}}">Invite someone</a></p>
|
||||
<p class="font-weight-lighter text-muted">You have <b class="font-weight-bold text-dark">{{$limit - $used}}</b> invites left.</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endsection
|
Loading…
Reference in New Issue