added the favourites feature

master
Ondřej Hruška 6 years ago
parent 86b7db48b3
commit 3f69ef3390
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 40
      app/Http/Controllers/ProfileController.php
  2. 65
      app/Http/Controllers/TableController.php
  3. 2
      app/helpers.php
  4. 4
      resources/assets/sass/_helpers.scss
  5. 69
      resources/views/profile/_profile-card.blade.php
  6. 22
      resources/views/profile/_table-list.blade.php
  7. 108
      resources/views/profile/view.blade.php
  8. 10
      resources/views/table/_table-subpage-header.blade.php
  9. 8
      resources/views/table/_view-action-buttons.blade.php
  10. 44
      resources/views/table/favourites.blade.php
  11. 11
      resources/views/table/revisions.blade.php
  12. 4
      routes/web.php

@ -12,6 +12,18 @@ use Illuminate\Http\Request;
*/ */
class ProfileController extends Controller class ProfileController extends Controller
{ {
private function profileTableListPrepareData(User $user)
{
$data['user'] = $user;
$data['tables_count'] = $user->tables()->count();
$data['favourites_count'] = $user->favouriteTables()->count();
$data['tableSort'] = Table::resolveSortType(\Input::get('tableSort'));
$data['sortOptions'] = Table::getSortOptions();
return $data;
}
/** /**
* Show the user's profile / dashboard. * Show the user's profile / dashboard.
* *
@ -19,13 +31,31 @@ class ProfileController extends Controller
*/ */
public function view(User $user) public function view(User $user)
{ {
$data['user'] = $user; $data = $this->profileTableListPrepareData($user);
$data['tables_count'] = $user->tables()->count();
$data['tableSort'] = $sort = Table::resolveSortType(\Input::get('tableSort')); $data['pageVariant'] = 'tables';
$data['sortOptions'] = Table::getSortOptions();
$data['tables'] = $user->tables()->forList()
->tableSort($data['tableSort'])
->paginate(10);
return view('profile.view', $data);
}
/**
* Show the user's profile / dashboard.
*
* @return \Illuminate\View\View
*/
public function viewFavourites(User $user)
{
$data = $this->profileTableListPrepareData($user);
$data['pageVariant'] = 'favourites';
$data['tables'] = $user->tables()->forList()->tableSort($sort)->paginate(10); $data['tables'] = $user->favouriteTables()->forList()
->tableSort($data['tableSort'])
->paginate(10);
return view('profile.view', $data); return view('profile.view', $data);
} }

@ -22,8 +22,19 @@ use MightyPork\Exceptions\NotApplicableException;
use MightyPork\Exceptions\SimpleValidationException; use MightyPork\Exceptions\SimpleValidationException;
use MightyPork\Utils\Utils; use MightyPork\Utils\Utils;
/**
* Table view, creation, settings
*/
class TableController extends Controller class TableController extends Controller
{ {
/**
* Helper to fetch a table by user and table name
*
* @param Request $request
* @param User $user
* @param string $table
* @return Table
*/
private function resolveTable(Request $request, User $user, string $table) private function resolveTable(Request $request, User $user, string $table)
{ {
/** @var Table $tableModel */ /** @var Table $tableModel */
@ -32,6 +43,29 @@ class TableController extends Controller
return $tableModel; return $tableModel;
} }
/**
* Favourite a table
*/
public function favouriteTable(Request $request, User $user, string $table)
{
$tableModel = $this->resolveTable($request, $user, $table);
\user()->favouriteTables()->attach($tableModel);
return redirect($tableModel->viewRoute);
}
/**
* Un-favourite a table
*/
public function unfavouriteTable(Request $request, User $user, string $table)
{
$tableModel = $this->resolveTable($request, $user, $table);
\user()->favouriteTables()->detach($tableModel);
return redirect($tableModel->viewRoute);
}
/**
* Switch table's current revision
*/
public function revertTo(Request $request, User $user, string $table) public function revertTo(Request $request, User $user, string $table)
{ {
$input = $this->validate($request, [ $input = $this->validate($request, [
@ -51,6 +85,9 @@ class TableController extends Controller
return redirect($tableModel->revisionsRoute); return redirect($tableModel->revisionsRoute);
} }
/**
* Show a table
*/
public function view(Request $request, User $user, string $table) public function view(Request $request, User $user, string $table)
{ {
$input = $this->validate($request, [ $input = $this->validate($request, [
@ -91,6 +128,9 @@ class TableController extends Controller
]); ]);
} }
/**
* Delete a table
*/
public function delete(Request $request, User $user, string $table) public function delete(Request $request, User $user, string $table)
{ {
$tableModel = $this->resolveTable($request, $user, $table); $tableModel = $this->resolveTable($request, $user, $table);
@ -106,9 +146,7 @@ class TableController extends Controller
} }
/** /**
* SHow a form for creating a new table * Show a form for creating a new table
*
* @return \Illuminate\Http\Response
*/ */
public function create() public function create()
{ {
@ -170,6 +208,9 @@ class TableController extends Controller
return redirect($tableModel->viewRoute); // the route now changed return redirect($tableModel->viewRoute); // the route now changed
} }
/**
* List of table revisions
*/
public function viewRevisions(Request $request, User $user, string $table) public function viewRevisions(Request $request, User $user, string $table)
{ {
$tableModel = $this->resolveTable($request, $user, $table); $tableModel = $this->resolveTable($request, $user, $table);
@ -182,6 +223,24 @@ class TableController extends Controller
]); ]);
} }
/**
* List of table favouriting users
*/
public function viewFavourites(Request $request, User $user, string $table)
{
$tableModel = $this->resolveTable($request, $user, $table);
$users = $tableModel->favouritingUsers()->orderBy('title')->get();
return view('table.favourites', [
'table' => $tableModel,
'users' => $users,
]);
}
/**
* Store a newly created table (save form)
*/
public function storeNew(Request $request) public function storeNew(Request $request)
{ {
/** @var User $u */ /** @var User $u */

@ -7,7 +7,7 @@ const VALI_TEXT = 'string|max:4095';
const VALI_LINE = 'string|max:255'; const VALI_LINE = 'string|max:255';
const FEATURE_FORKS = false; const FEATURE_FORKS = false;
const FEATURE_FAVES = false; const FEATURE_FAVES = true;
const FEATURE_TABLE_COMMENTS = false; const FEATURE_TABLE_COMMENTS = false;
const FEATURE_PROPOSALS = false; const FEATURE_PROPOSALS = false;

@ -17,6 +17,10 @@
box-shadow: 0 2px 3px rgba(black, .3); box-shadow: 0 2px 3px rgba(black, .3);
} }
.box-shadow-thin {
box-shadow: 0 2px 3px rgba(black, .15);
}
.strike { .strike {
text-decoration: line-through; text-decoration: line-through;
} }

@ -0,0 +1,69 @@
@php
/** @var \App\Models\User $user */
@endphp
<div class="card">
<div class="card-header card-header-extra">
@icon(fa-user-circle-o fa-pr fa-large)
<h1>
@if(authed() && user()->is($user))
@sr(Your dashboard -)
@else
@sr(User's page -)
@endif
{{ $user->title }}
</h1>
@if(authed() && user()->is($user))
<a href="{{route('profile.edit')}}" class="btn ml-auto" aria-label="Edit Profile">Edit</a>
@endif
</div>
<div class="card-body">
@if($user->bio)
<div class="mb-3">
{!! Widget::collapsible($user->bio, 350, '8em')->srPrefix('About me:') !!}
</div>
@endif
<div class="mb-3">
@if($tables_count)
<a href="{{ route('profile.view', $user->name) }}" class="btn btn-sm btn-outline-primary">
@icon(fa-table fa-pr)Tables <span class="badge">{{$tables_count}}</span>
</a>
@endif
@if($favourites_count)
<a href="{{ route('profile.view-favourites', $user->name) }}" class="btn btn-sm btn-outline-primary">
@icon(fa-star fa-pr)Favourites <span class="badge">{{$favourites_count}}</span>
</a>
@endif
</div>
<table class="bio-table">
<tbody>
@if($user->website)
<tr>
<td class="text-center pr-2">@icon(fa-link, User's Website:)</td>
<td>{!! Widget::tryLink($user->website) !!}</td>
</tr>
@endif
<tr>
<td class="text-center pr-2">@icon(fa-vcard-o, User's handle:)</td>
<td>{{ $user->handle }}</td>
</tr>
<tr>
<td class="text-center pr-2">@icon(fa-calendar, Join date:)</td>
<td>
<span class="pr-1" data-toggle="tooltip" data-placement="right"
title="{{ $user->created_at->format('M n, Y \\a\\t G:i') }}">
Joined {{ $user->created_at->diffForHumans() }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>

@ -8,7 +8,7 @@
<div class="list-group list-group-flush"> <div class="list-group list-group-flush">
@if(count($tables) == 0) @if(count($tables) == 0)
<span class="list-group-item">No tables yet.</span> <span class="list-group-item">Nothing to show yet.</span>
@else @else
@foreach($tables as $table) @foreach($tables as $table)
@php @php
@ -26,22 +26,22 @@
!!}<b>{{ $table->title }}</b> !!}<b>{{ $table->title }}</b>
</span> </span>
<div class="d-flex justify-content-end col-5 small text-right"> <div class="d-flex justify-content-end col-5 small text-right">
<span title="Visits" class="d-inline-block pl-2" style="min-width: 50px;">
{{ $table->visits }}@icon(fa-eye fa-pl, ~Visits~~)
</span>
@if(FEATURE_FORKS) @if(FEATURE_FORKS)
<span title="Forks" class="d-inline-block pl-2 {{$forks==0?'hidden':''}}" style="min-width: 50px;"> <span title="Forks" class="d-inline-block pl-2 {{$forks==0?'hidden':''}}" style="min-width: 50px;">
{{ $forks }}@icon(fa-code-fork fa-pl, ~Forks~~) {{ $forks }}@icon(fa-code-fork fa-pl, ~Forks~~)
</span> </span>
@endif @endif
@if(FEATURE_FAVES) @if(FEATURE_FAVES)
<span title="Favourites" class="d-inline-block pl-2 {{$faves==0?'hidden':''}}" style="min-width: 50px;"> <span title="Favourites" class="d-inline-block pl-2 {{$faves==0?'hidden':''}}" style="min-width: 50px;">
{{ $faves }}@icon(fa-star fa-pl, ~Favourites~~) {{ $faves }}@icon(fa-star fa-pl, ~Favourites~~)
</span> </span>
@endif @endif
<span title="Visits" class="d-inline-block pl-2" style="min-width: 50px;">
{{ $table->visits }}@icon(fa-eye fa-pl, ~Visits~~)
</span>
<span title="Revisions" class="d-inline-block pl-2" style="min-width: 50px;"> <span title="Revisions" class="d-inline-block pl-2" style="min-width: 50px;">
{{ $revs }}@icon(fa-history fa-pl, ~Revisions~~) {{ $revs }}@icon(fa-history fa-pl, ~Revisions~~)
</span> </span>

@ -12,89 +12,57 @@
{{-- Dash card --}} {{-- Dash card --}}
<div class="col-md-4"> <div class="col-md-4">
@include('profile._profile-card')
</div>
{{-- Table list card --}}
<div class="col-md-8 mt-2 mt-md-0">
<div class="card"> <div class="card">
<div class="card-header card-header-extra"> <div class="card-header card-header-extra">
@icon(fa-user-circle-o fa-pr fa-large) @if($pageVariant == 'tables')
<h1>
@if(authed() && user()->is($user))
@sr(Your dashboard -)
@else
@sr(User's page -)
@endif
{{ $user->title }}
</h1>
@if(authed() && user()->is($user)) @icon(fa-table fa-pr fa-large)
<a href="{{route('profile.edit')}}" class="btn ml-auto" aria-label="Edit Profile">Edit</a> <h2>
@endif @if(authed() && user()->is($user))
</div> Your Tables:
@else
User's Tables:
@endif
</h2>
<div class="card-body"> @include('table._sort-dropdown', [
@if($user->bio) 'link' => route('profile.view',
<div class="mb-3"> Input::except(['tableSort', 'page'])
{!! Widget::collapsible($user->bio, 350, '8em')->srPrefix('About me:') !!} + ['tableSort' => '__sort'] + ['user' => $user->name])
</div> ])
@endif
<table class="bio-table"> @elseif($pageVariant == 'favourites')
<tbody>
@if($user->website)
<tr>
<td class="text-center pr-2">@icon(fa-link, User's Website:)</td>
<td>{!! Widget::tryLink($user->website) !!}</td>
</tr>
@endif
<tr> @icon(fa-star fa-pr fa-large)
<td class="text-center pr-2">@icon(fa-vcard-o, User's handle:)</td> <h2>
<td>{{ $user->handle }}</td> @if(authed() && user()->is($user))
</tr> Your Favourites:
@else
User's Favourites:
@endif
</h2>
<tr> @include('table._sort-dropdown', [
<td class="text-center pr-2">@icon(fa-table, Tables:)</td> 'link' => route('profile.view-favourites',
<td>{{ $tables_count }} table{{$tables_count!=1?'s':''}}</td> Input::except(['tableSort', 'page'])
</tr> + ['tableSort' => '__sort'] + ['user' => $user->name])
])
<tr> @endif
<td class="text-center pr-2">@icon(fa-calendar, Join date:)</td>
<td>
<span class="pr-1" data-toggle="tooltip" data-placement="right"
title="{{ $user->created_at->format('M n, Y \\a\\t G:i') }}">
Joined {{ $user->created_at->diffForHumans() }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{{-- Table list card --}}
<div class="col-md-8 mt-2 mt-md-0">
<div class="card">
<div class="card-header card-header-extra">
@icon(fa-table fa-pr fa-large)
<h2>
@if(authed() && user()->is($user))
Your Tables:
@else
User's Tables:
@endif
</h2>
@include('table._sort-dropdown', [
'link' => route('profile.view',
Input::except(['tableSort', 'page'])
+ ['tableSort' => '__sort'] + ['user' => $user->name])
])
<nav class="ml-auto" aria-label="Pages of the table list"> <nav class="ml-auto" aria-label="Pages of the table list">
{{ $tables->links(null, ['ulClass' => 'pagination-sm mb-0 pagination-outline-light']) }} {{ $tables->links(null, ['ulClass' => 'pagination-sm mb-0 pagination-outline-light']) }}
</nav> </nav>
@if(authed() && user()->is($user) && user()->confirmed) @if($pageVariant == 'tables')
<a href="{{route('table.create')}}" class="btn ml-3" aria-label="New Table">New</a> @if(authed() && user()->is($user) && user()->confirmed)
<a href="{{route('table.create')}}" class="btn ml-3" aria-label="New Table">New</a>
@endif
@endif @endif
</div> </div>

@ -0,0 +1,10 @@
<div class="row justify-content-start px-3">
<div class="d-flex w-100 align-items-center">
@include('table._header-handle')
<h1 class="mx-3" id="table-title">{{ $table->title }}</h1>
<a href="{{ $table->viewRoute }}" class="btn btn-outline-primary py-1 btn-sm" @tooltip(Back to Table)>
@icon(fa-reply, sr:Back to Table)
</a>
</div>
</div>

@ -22,7 +22,7 @@
@if(FEATURE_FAVES) @if(FEATURE_FAVES)
{{-- Passive favourite buttons with counter --}} {{-- Passive favourite buttons with counter --}}
<a href="" class="btn btn-outline-primary py-1 btn-sm" @tooltip(Favourites)> <a href="{{ $table->actionRoute('favourites') }}" class="btn btn-outline-primary py-1 btn-sm" @tooltip(Favourites)>
@icon(fa-star, sr:Favourites)&nbsp; @icon(fa-star, sr:Favourites)&nbsp;
{{ $table->favourites_count ?: '–' }} {{ $table->favourites_count ?: '–' }}
</a> </a>
@ -47,15 +47,15 @@
{{-- Active favourite button | counter --}} {{-- Active favourite button | counter --}}
<div class="btn-group" role="group" aria-label="Favourite"> <div class="btn-group" role="group" aria-label="Favourite">
@if(user()->favouritesTable($table)) @if(user()->favouritesTable($table))
<a href="" class="btn btn-outline-primary py-1 btn-sm btn-square" @tooltip(Un-favourite)> <a href="{{ $table->actionRoute('unfavourite') }}" class="btn btn-outline-primary py-1 btn-sm btn-square" @tooltip(Un-favourite)>
@icon(fa-star, sr:Un-favourite) @icon(fa-star, sr:Un-favourite)
</a> </a>
@else @else
<a href="" class="btn btn-outline-primary py-1 btn-sm btn-square" @tooltip(Favourite)> <a href="{{ $table->actionRoute('favourite') }}" class="btn btn-outline-primary py-1 btn-sm btn-square" @tooltip(Favourite)>
@icon(fa-star-o, sr:Favourite) @icon(fa-star-o, sr:Favourite)
</a> </a>
@endif @endif
<a href="" class="btn btn-outline-primary py-1 btn-sm" @tooltip(Favourite Count)> <a href="{{ $table->actionRoute('favourites') }}" class="btn btn-outline-primary py-1 btn-sm" @tooltip(Favourite Count)>
{{ $table->favourites_count ?: '–' }} {{ $table->favourites_count ?: '–' }}
</a> </a>
</div> </div>

@ -0,0 +1,44 @@
{{-- List of table revisions --}}
@extends('layouts.app')
@section('title', "Favouriting Users - $table->title")
@php
/** @var \App\Models\Table $table */
/** @var \App\Models\User[]|\Illuminate\Support\Collection $users */
@endphp
@section('content')
@include('table._table-subpage-header')
<div class="row px-3 border-top pt-3">
<div class="col-md-12">
<h2>Favouriting Users</h2>
</div>
<div class="col-md-12 d-flex flex-wrap">
@foreach($users as $user)
<div class="col-md-4 px-0">
<div class="rounded border box-shadow-thin m-1 px-2 d-flex align-items-center py-1">
<span class="flex-grow-1" style="font-size:140%;font-weight:bold">
{{ $user->title }}
</span>
<span>
<a href="{{route('profile.view', $user->name)}}"
class="btn btn-outline-secondary btn-sm"
>
@icon(fa-user fa-pr)Profile
</a>
<a href="{{route('profile.view-favourites', $user->name)}}"
class="btn btn-outline-secondary btn-sm"
>
@icon(fa-star fa-pr)Faves
</a>
</span>
</div>
</div>
@endforeach
</div>
</div>
@endsection

@ -9,16 +9,7 @@
@endphp @endphp
@section('content') @section('content')
<div class="row justify-content-start px-3"> @include('table._table-subpage-header')
<div class="d-flex w-100 align-items-center">
@include('table._header-handle')
<h1 class="mx-3" id="table-title">{{ $table->title }}</h1>
<a href="{{ $table->viewRoute }}" class="btn btn-outline-primary py-1 btn-sm" @tooltip(Back to Table)>
@icon(fa-reply, sr:Back to Table)
</a>
</div>
</div>
<div class="row px-3 border-top pt-3"> <div class="row px-3 border-top pt-3">
<div class="col-md-12"> <div class="col-md-12">

@ -43,9 +43,13 @@ Route::get('/home', function () {
// Table resource // Table resource
Route::get('@{user}', 'ProfileController@view')->name('profile.view'); Route::get('@{user}', 'ProfileController@view')->name('profile.view');
Route::get('@{user}/!favourites', 'ProfileController@viewFavourites')->name('profile.view-favourites');
Route::get('@{user}/{table}', 'TableController@view')->name('table.view'); Route::get('@{user}/{table}', 'TableController@view')->name('table.view');
Route::get('@{user}/{table}/revisions', 'TableController@viewRevisions')->name('table.revisions'); Route::get('@{user}/{table}/revisions', 'TableController@viewRevisions')->name('table.revisions');
Route::get('@{user}/{table}/export', 'TableController@export')->name('table.export'); Route::get('@{user}/{table}/export', 'TableController@export')->name('table.export');
Route::get('@{user}/{table}/favourite', 'TableController@favouriteTable')->name('table.favourite');
Route::get('@{user}/{table}/unfavourite', 'TableController@unfavouriteTable')->name('table.unfavourite');
Route::get('@{user}/{table}/favourites', 'TableController@viewFavourites')->name('table.favourites');
// Routes for confirmed users // Routes for confirmed users

Loading…
Cancel
Save