#111: Implemented the /me feed endpoint

This commit is contained in:
Andy Heathershaw 2018-10-14 20:08:31 +01:00
parent 2304b23564
commit d6d2420eb7
8 changed files with 126 additions and 1 deletions

View File

@ -20,6 +20,56 @@ use Symfony\Component\HttpFoundation\Request;
class UserController extends Controller class UserController extends Controller
{ {
public function activityFeed()
{
return Theme::render('gallery.user_activity_feed', [
'user' => $this->getUser()
]);
}
public function activityFeedJson()
{
$user = $this->getUser();
$result = [];
$activities = UserActivity::with('photo')
->with('photoComment')
->with('user')
->join('user_followers', 'user_followers.following_user_id', '=', 'user_activity.user_id')
->where([
'user_followers.user_id' => $user->id
])
->orderBy('activity_at', 'desc')
->limit(100) // TODO: make this configurable
->select('user_activity.*')
->get();
/** @var UserActivity $activity */
foreach ($activities as $activity)
{
$userName = $activity->user->name;
$userProfileUrl = $activity->user->profileUrl();
$userAvatar = Theme::gravatarUrl($activity->user->email, 32);
$newItem = [
'activity_at' => date(UserConfig::get('date_format'), strtotime($activity->activity_at)),
'avatar' => $userAvatar,
'description' => trans(sprintf('gallery.user_feed_type.%s', $activity->type))
];
$params = [];
$params['user_name'] = $userName;
$params['user_url'] = $userProfileUrl;
$params['photo_name'] = $activity->photo->name;
$params['photo_url'] = $activity->photo->url();
$newItem['params'] = $params;
$result[] = $newItem;
}
return response()->json($result);
}
public function confirmEmailChangeState(Request $request) public function confirmEmailChangeState(Request $request)
{ {
$user = $this->getUser(); $user = $this->getUser();

View File

@ -17,4 +17,9 @@ class UserActivity extends Model
{ {
return $this->belongsTo(PhotoComment::class); return $this->belongsTo(PhotoComment::class);
} }
public function user()
{
return $this->belongsTo(User::class);
}
} }

View File

@ -77,6 +77,9 @@ return [
'title' => 'Statistics', 'title' => 'Statistics',
'uploaded_12_months' => 'Photos uploaded in the last 12 months', 'uploaded_12_months' => 'Photos uploaded in the last 12 months',
], ],
'user_activity_feed' => [
'title' => 'My Activity Feed'
],
'user_feed_type' => [ 'user_feed_type' => [
'photo' => [ 'photo' => [
'comment_replied' => ':user_name replied to a comment on the :photo_name photo.', 'comment_replied' => ':user_name replied to a comment on the :photo_name photo.',

View File

@ -2,6 +2,7 @@
return [ return [
'breadcrumb' => [ 'breadcrumb' => [
'about' => 'About', 'about' => 'About',
'activity_feed' => 'My Activity Feed',
'admin' => 'Admin', 'admin' => 'Admin',
'albums' => 'Albums', 'albums' => 'Albums',
'approve_comment' => 'Approve comment', 'approve_comment' => 'Approve comment',
@ -33,6 +34,7 @@ return [
'users' => 'Users' 'users' => 'Users'
], ],
'navbar' => [ 'navbar' => [
'activity_feed' => 'Activity',
'admin' => 'Manage', 'admin' => 'Manage',
'albums' => 'Albums', 'albums' => 'Albums',
'change_password' => 'Change password', 'change_password' => 'Change password',

View File

@ -0,0 +1,52 @@
@extends(Theme::viewName('layout'))
@section('title', trans('gallery.user_activity_feed.title'))
@section('breadcrumb')
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.activity_feed')</li>
@endsection
@section('content')
<div class="container" id="user-app">
<div class="row">
<div class="col">
<div v-if="is_loading">
<p class="text-center mb-1">
<img src="{{ asset('ripple.svg') }}" alt="@lang('global.please_wait')" title="@lang('global.please_wait')"/>
</p>
<p class="text-center">
@lang('global.please_wait')
</p>
</div>
<div v-if="feed_items.length > 0">
<div class="card mb-2" v-for="feed_item in feed_items">
<div class="card-body row">
<div class="col-2 col-md-1 pr-0" style="max-width: 47px;">
<img class="rounded-circle" v-bind:src="feed_item.avatar"/>
</div>
<div class="col-10 col-md-11">
<span v-html="feed_item.description"></span><br/>
<span class="text-muted" style="font-size: smaller;" v-html="feed_item.activity_at"></span>
</div>
</div>
</div>
</div>
<div class="text-center" v-if="!is_loading && feed_items.length == 0">
<h4 class="text-danger"><b>@lang('gallery.user_activity_feed.no_activity_p1')</b></h4>
<p>@lang('gallery.user_activity_feed.no_activity_p2', ['user_name' => $user->name])</p>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script type="text/javascript">
var viewModel = new UserViewModel({
feed_url: '{{ route('userActivityFeedJson') }}?t={{ time() }}'
});
var app = new Vue(viewModel);
app.loadFeedItems();
</script>
@endpush

View File

@ -131,7 +131,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="text-center" v-if="feed_items.length == 0"> <div class="text-center" v-if="!is_loading && feed_items.length == 0">
<h4 class="text-danger"><b>@lang('gallery.user_profile.no_feed_activity_p1')</b></h4> <h4 class="text-danger"><b>@lang('gallery.user_profile.no_feed_activity_p1')</b></h4>
<p>@lang('gallery.user_profile.no_feed_activity_p2', ['user_name' => $user->name])</p> <p>@lang('gallery.user_profile.no_feed_activity_p2', ['user_name' => $user->name])</p>
</div> </div>

View File

@ -6,6 +6,13 @@
<div class="collapse navbar-collapse" id="navbar-content"> <div class="collapse navbar-collapse" id="navbar-content">
<ul class="navbar-nav mr-auto"> <ul class="navbar-nav mr-auto">
@if (!Auth::guest())
<li class="nav-item">
<a class="nav-link" href="{{ route('userActivityFeed') }}">
<i class="fa fa-rss"></i> @lang('navigation.navbar.activity_feed')
</a>
</li>
@endif
@can('photo.quick_upload') @can('photo.quick_upload')
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#" data-toggle="modal" data-target="#quick-upload-modal"> <a class="nav-link" href="#" data-toggle="modal" data-target="#quick-upload-modal">

View File

@ -152,6 +152,12 @@ Route::post('u/{idOrAlias}/unfollow', 'Gallery\UserController@unFollowUser', ['m
Route::get('u/{idOrAlias}', 'Gallery\UserController@show') Route::get('u/{idOrAlias}', 'Gallery\UserController@show')
->name('viewUser') ->name('viewUser')
->where('idOrAlias', '.*'); ->where('idOrAlias', '.*');
Route::get('me', 'Gallery\UserController@activityFeed')
->name('userActivityFeed')
->middleware('auth');
Route::get('me.json', 'Gallery\UserController@activityFeedJson')
->name('userActivityFeedJson')
->middleware('auth');
Route::get('me/confirm-email-change', 'Gallery\UserController@confirmEmailChangeState') Route::get('me/confirm-email-change', 'Gallery\UserController@confirmEmailChangeState')
->name('userSettings.confirmEmailChangeState') ->name('userSettings.confirmEmailChangeState')
->middleware('auth'); ->middleware('auth');