mirror of
https://github.com/YunoHost-Apps/pixelfed_ynh.git
synced 2024-09-03 20:06:04 +02:00
Add modlog notifications
This commit is contained in:
parent
6689a6fe3c
commit
51642fc40d
6 changed files with 171 additions and 12 deletions
66
app/Observers/ModLogObserver.php
Normal file
66
app/Observers/ModLogObserver.php
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Observers;
|
||||||
|
|
||||||
|
use App\Notification;
|
||||||
|
use App\ModLog;
|
||||||
|
use App\Services\ModLogService;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
class ModLogObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle the mod log "created" event.
|
||||||
|
*
|
||||||
|
* @param \App\ModLog $modLog
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function created(ModLog $modLog)
|
||||||
|
{
|
||||||
|
ModLogService::boot()->load($modLog)->fanout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the mod log "updated" event.
|
||||||
|
*
|
||||||
|
* @param \App\ModLog $modLog
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function updated(ModLog $modLog)
|
||||||
|
{
|
||||||
|
ModLogService::boot()->load($modLog)->fanout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the mod log "deleted" event.
|
||||||
|
*
|
||||||
|
* @param \App\ModLog $modLog
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function deleted(ModLog $modLog)
|
||||||
|
{
|
||||||
|
ModLogService::boot()->load($modLog)->unfanout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the mod log "restored" event.
|
||||||
|
*
|
||||||
|
* @param \App\ModLog $modLog
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function restored(ModLog $modLog)
|
||||||
|
{
|
||||||
|
ModLogService::boot()->load($modLog)->fanout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the mod log "force deleted" event.
|
||||||
|
*
|
||||||
|
* @param \App\ModLog $modLog
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function forceDeleted(ModLog $modLog)
|
||||||
|
{
|
||||||
|
ModLogService::boot()->load($modLog)->unfanout();
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ namespace App\Providers;
|
||||||
use App\Observers\{
|
use App\Observers\{
|
||||||
AvatarObserver,
|
AvatarObserver,
|
||||||
NotificationObserver,
|
NotificationObserver,
|
||||||
|
ModLogObserver,
|
||||||
StatusHashtagObserver,
|
StatusHashtagObserver,
|
||||||
UserObserver,
|
UserObserver,
|
||||||
UserFilterObserver,
|
UserFilterObserver,
|
||||||
|
@ -12,6 +13,7 @@ use App\Observers\{
|
||||||
use App\{
|
use App\{
|
||||||
Avatar,
|
Avatar,
|
||||||
Notification,
|
Notification,
|
||||||
|
ModLog,
|
||||||
StatusHashtag,
|
StatusHashtag,
|
||||||
User,
|
User,
|
||||||
UserFilter
|
UserFilter
|
||||||
|
@ -35,6 +37,7 @@ class AppServiceProvider extends ServiceProvider
|
||||||
|
|
||||||
Avatar::observe(AvatarObserver::class);
|
Avatar::observe(AvatarObserver::class);
|
||||||
Notification::observe(NotificationObserver::class);
|
Notification::observe(NotificationObserver::class);
|
||||||
|
ModLog::observe(ModLogObserver::class);
|
||||||
StatusHashtag::observe(StatusHashtagObserver::class);
|
StatusHashtag::observe(StatusHashtagObserver::class);
|
||||||
User::observe(UserObserver::class);
|
User::observe(UserObserver::class);
|
||||||
UserFilter::observe(UserFilterObserver::class);
|
UserFilter::observe(UserFilterObserver::class);
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
|
use Auth;
|
||||||
use App\ModLog;
|
use App\ModLog;
|
||||||
|
use App\Notification;
|
||||||
use App\User;
|
use App\User;
|
||||||
|
|
||||||
class ModLogService {
|
class ModLogService {
|
||||||
|
@ -95,4 +97,46 @@ class ModLogService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function load($modLog)
|
||||||
|
{
|
||||||
|
$this->log = $modLog;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fanout()
|
||||||
|
{
|
||||||
|
$log = $this->log;
|
||||||
|
|
||||||
|
$msg = "{$log->user_username} commented on a modlog";
|
||||||
|
$rendered = "<span class='font-weight-bold'>{$log->user_username}</span> commented on a <a href='/i/admin/users/modlogs/{$log->user_id}}' class='font-weight-bold text-decoration-none'>modlog</a>";
|
||||||
|
$item_id = $log->id;
|
||||||
|
$item_type = 'App\ModLog';
|
||||||
|
$action = 'admin.user.modlog.comment';
|
||||||
|
|
||||||
|
$admins = User::whereNull('status')
|
||||||
|
->whereNotIn('id', [$log->user_id])
|
||||||
|
->whereIsAdmin(true)
|
||||||
|
->pluck('profile_id')
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
foreach($admins as $user) {
|
||||||
|
$n = new Notification;
|
||||||
|
$n->profile_id = $user;
|
||||||
|
$n->actor_id = $log->admin->profile_id;
|
||||||
|
$n->item_id = $item_id;
|
||||||
|
$n->item_type = $item_type;
|
||||||
|
$n->action = $action;
|
||||||
|
$n->message = $msg;
|
||||||
|
$n->rendered = $rendered;
|
||||||
|
$n->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unfanout()
|
||||||
|
{
|
||||||
|
Notification::whereItemType('App\ModLog')
|
||||||
|
->whereItemId($this->log->id)
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,8 @@ class NotificationTransformer extends Fractal\TransformerAbstract
|
||||||
protected $defaultIncludes = [
|
protected $defaultIncludes = [
|
||||||
'account',
|
'account',
|
||||||
'status',
|
'status',
|
||||||
'relationship'
|
'relationship',
|
||||||
|
'modlog'
|
||||||
];
|
];
|
||||||
|
|
||||||
public function transform(Notification $notification)
|
public function transform(Notification $notification)
|
||||||
|
@ -54,6 +55,7 @@ class NotificationTransformer extends Fractal\TransformerAbstract
|
||||||
'share' => 'share',
|
'share' => 'share',
|
||||||
'like' => 'favourite',
|
'like' => 'favourite',
|
||||||
'comment' => 'comment',
|
'comment' => 'comment',
|
||||||
|
'admin.user.modlog.comment' => 'modlog'
|
||||||
];
|
];
|
||||||
return $verbs[$verb];
|
return $verbs[$verb];
|
||||||
}
|
}
|
||||||
|
@ -62,4 +64,25 @@ class NotificationTransformer extends Fractal\TransformerAbstract
|
||||||
{
|
{
|
||||||
return $this->item($notification->actor, new RelationshipTransformer());
|
return $this->item($notification->actor, new RelationshipTransformer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function includeModlog(Notification $notification)
|
||||||
|
{
|
||||||
|
$n = $notification;
|
||||||
|
if($n->item_id && $n->item_type == 'App\ModLog') {
|
||||||
|
$ml = $n->item;
|
||||||
|
if(!empty($ml)) {
|
||||||
|
$res = $this->item($ml, function($ml) {
|
||||||
|
return [
|
||||||
|
'id' => $ml->object_uid,
|
||||||
|
'url' => url('/i/admin/users/modlogs/' . $ml->object_uid)
|
||||||
|
];
|
||||||
|
});
|
||||||
|
return $res;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<div class="card notification-card shadow-none border">
|
<div class="card notification-card shadow-none border">
|
||||||
<div class="card-header bg-white">
|
<div class="card-header bg-white">
|
||||||
<p class="mb-0 d-flex align-items-center justify-content-between">
|
<p class="mb-0 d-flex align-items-center justify-content-between">
|
||||||
<span><i class="far fa-bell fa-lg text-white"></i></span>
|
<span data-toggle="tooltip" data-placement="bottom"><i class="fas fa-redo fa-lg text-white"></i></span>
|
||||||
<span class="small text-dark text-uppercase font-weight-bold">Alerts</span>
|
<span class="small text-dark text-uppercase font-weight-bold">Alerts</span>
|
||||||
<a class="text-decoration-none text-muted" href="/account/activity"><i class="fas fa-inbox fa-lg"></i></a>
|
<a class="text-decoration-none text-muted" href="/account/activity"><i class="fas fa-inbox fa-lg"></i></a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -43,6 +43,11 @@
|
||||||
<a :href="n.account.url" class="font-weight-bold text-dark word-break" :title="n.account.username">{{truncate(n.account.username)}}</a> shared your <a class="font-weight-bold" v-bind:href="n.status.reblog.url">post</a>.
|
<a :href="n.account.url" class="font-weight-bold text-dark word-break" :title="n.account.username">{{truncate(n.account.username)}}</a> shared your <a class="font-weight-bold" v-bind:href="n.status.reblog.url">post</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="n.type == 'modlog'">
|
||||||
|
<p class="my-0">
|
||||||
|
<a :href="n.account.url" class="font-weight-bold text-dark word-break" :title="n.account.username">{{truncate(n.account.username)}}</a> updated a <a class="font-weight-bold" v-bind:href="n.modlog.url">modlog</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="small text-muted font-weight-bold" :title="n.created_at">{{timeAgo(n.created_at)}}</div>
|
<div class="small text-muted font-weight-bold" :title="n.created_at">{{timeAgo(n.created_at)}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -193,6 +198,32 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, interval);
|
}, interval);
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshNotifications() {
|
||||||
|
let self = this;
|
||||||
|
axios.get('/api/pixelfed/v1/notifications')
|
||||||
|
.then(res => {
|
||||||
|
let data = res.data.filter(n => {
|
||||||
|
if(n.type == 'share' || self.notificationMaxId >= n.id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if(data.length > 0) {
|
||||||
|
let ids = data.map(n => n.id);
|
||||||
|
let max = Math.max(ids);
|
||||||
|
if(max <= self.notificationMaxId) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
self.notificationMaxId = max;
|
||||||
|
self.notifications = data;
|
||||||
|
let beep = new Audio('/static/beep.mp3');
|
||||||
|
beep.volume = 0.7;
|
||||||
|
beep.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -675,9 +675,9 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchData() {
|
fetchData() {
|
||||||
|
let self = this;
|
||||||
axios.get('/api/v2/profile/'+this.statusUsername+'/status/'+this.statusId)
|
axios.get('/api/v2/profile/'+this.statusUsername+'/status/'+this.statusId)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
let self = this;
|
|
||||||
self.status = response.data.status;
|
self.status = response.data.status;
|
||||||
self.user = response.data.user;
|
self.user = response.data.user;
|
||||||
window._sharedData.curUser = self.user;
|
window._sharedData.curUser = self.user;
|
||||||
|
@ -696,15 +696,7 @@ export default {
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
$('head title').text(this.status.account.username + ' posted a photo: ' + this.status.favourites_count + ' likes');
|
$('head title').text(this.status.account.username + ' posted a photo: ' + this.status.favourites_count + ' likes');
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if(!error.response) {
|
swal('Oops!', 'An error occured, please try refreshing the page.', 'error');
|
||||||
} else {
|
|
||||||
switch(error.response.status) {
|
|
||||||
case 401:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue