1
0
mirror of https://github.com/Kovah/LinkAce.git synced 2025-04-21 07:22:20 +02:00

Overhaul guest views for links and lists, add new guest system settings (#161)

This commit is contained in:
Kovah 2020-10-22 13:20:08 +02:00
parent a94fdeb2b6
commit b0a1438479
No known key found for this signature in database
GPG Key ID: AAAA031BA9830D7B
23 changed files with 448 additions and 94 deletions

View File

@ -80,13 +80,13 @@ function formatDateTime(Carbon $date, bool $use_relational = false): string
*/
function getPaginationLimit()
{
$user_limit = usersettings('listitem_count');
$default = config('linkace.default.pagination');
if ($user_limit) {
return $user_limit;
if (request()->is('guest/*')) {
return systemsettings('guest_listitem_count') ?: $default;
}
return config('linkace.default.pagination');
return usersettings('listitem_count') ?: $default;
}
/**

View File

@ -4,6 +4,7 @@ namespace App\Http\Controllers\Guest;
use App\Http\Controllers\Controller;
use App\Models\Link;
use Illuminate\Http\Request;
use Illuminate\View\View;
class LinkController extends Controller
@ -11,15 +12,23 @@ class LinkController extends Controller
/**
* Display an overview of all links.
*
* @param Request $request
* @return View
*/
public function index(): View
public function index(Request $request): View
{
$links = Link::privateOnly(false)
->orderBy(
$request->input('orderBy', 'created_at'),
$request->input('orderDir', 'desc')
)
->paginate(getPaginationLimit());
return view('guest.links.index', [
'links' => $links,
'route' => $request->getBaseUrl(),
'orderBy' => $request->input('orderBy', 'created_at'),
'orderDir' => $request->input('orderDir', 'desc'),
]);
}
}

View File

@ -12,15 +12,23 @@ class ListController extends Controller
/**
* Display an overview of all lists.
*
* @param Request $request
* @return View
*/
public function index(): View
public function index(Request $request): View
{
$lists = LinkList::isPrivate(false)
->withCount('links')
->orderBy(
$request->input('orderBy', 'name'),
$request->input('orderDir', 'asc')
)
->paginate(getPaginationLimit());
return view('guest.lists.index', [
'lists' => $lists,
'orderBy' => $request->input('orderBy', 'name'),
'orderDir' => $request->input('orderDir', 'asc'),
]);
}
@ -39,15 +47,15 @@ class ListController extends Controller
->privateOnly(false)
->orderBy(
$request->input('orderBy', 'title'),
$request->input('orderDir', 'ASC')
$request->input('orderDir', 'asc')
)->paginate(getPaginationLimit());
return view('guest.lists.show', [
'list' => $list,
'list_links' => $links,
'listLinks' => $links,
'route' => $request->getBaseUrl(),
'order_by' => $request->input('orderBy', 'title'),
'order_dir' => $request->input('orderDir', 'ASC'),
'orderBy' => $request->input('orderBy', 'title'),
'orderDir' => $request->input('orderDir', 'asc'),
]);
}
}

View File

@ -26,6 +26,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read Collection|Link[] $links
* @property-read User $user
* @method static Builder|Tag byUser($user_id)
* @method static Builder|Tag isPrivate(bool $private)
*/
class LinkList extends Model
{

View File

@ -5,6 +5,7 @@ return [
'account_settings' => 'Account Settings',
'app_settings' => 'Application Settings',
'system_settings' => 'System Settings',
'guest_settings' => 'Guest Settings',
'language' => 'Language',
'timezone' => 'Timezone',
@ -86,4 +87,6 @@ return [
'update_check_version_found' => 'Update found. Version #VERSION# is available.',
'update_check_success' => 'No update found.',
'update_check_failed' => 'Could not check for updates.',
'guest_settings_info' => 'The following settings will apply to guests visiting your site, if guest mode is enabled.',
];

View File

@ -0,0 +1,80 @@
<div class="card mt-5">
<div class="card-header">
@lang('settings.guest_settings')
</div>
<div class="card-body">
<p>@lang('settings.guest_settings_info')</p>
<form action="{{ route('save-settings-system') }}" method="POST">
@csrf
<div class="row mt-4">
<div class="col-12 col-sm-8 col-md-6">
<div class="form-group">
<label for="guest_listitem_count">
@lang('settings.listitem_count')
</label>
<select id="guest_listitem_count" name="guest_listitem_count"
class="custom-select{{ $errors->has('guest_listitem_count') ? ' is-invalid' : '' }}">
@foreach(config('linkace.listitem_count_values') as $item_count)
<option value="{{ $item_count }}"
@if(systemsettings('guest_listitem_count') == $item_count) selected @endif>
{{ $item_count }} @lang('linkace.entries')
</option>
@endforeach
</select>
@if ($errors->has('guest_listitem_count'))
<p class="invalid-feedback" role="alert">
{{ $errors->first('guest_listitem_count') }}
</p>
@endif
</div>
</div>
<div class="col-12 col-sm-8 col-md-6">
<div class="form-group">
<label for="guest_link_display_mode">
@lang('settings.display_mode')
</label>
<select id="guest_link_display_mode" name="guest_link_display_mode"
class="custom-select{{ $errors->has('guest_link_display_mode') ? ' is-invalid' : '' }}">
<option value="{{ Link::DISPLAY_LIST_DETAILED }}"
@if((int)systemsettings()->get('guest_link_display_mode') === Link::DISPLAY_LIST_DETAILED)
selected
@endif>
@lang('settings.display_mode_list_detailed')
</option>
<option value="{{ Link::DISPLAY_LIST_SIMPLE }}"
@if((int)systemsettings()->get('guest_link_display_mode') === Link::DISPLAY_LIST_SIMPLE)
selected
@endif>
@lang('settings.display_mode_list_simple')
</option>
<option value="{{ Link::DISPLAY_CARDS }}"
@if((int)systemsettings()->get('guest_link_display_mode') === Link::DISPLAY_CARDS)
selected
@endif>
@lang('settings.display_mode_cards')
</option>
</select>
@if ($errors->has('guest_link_display_mode'))
<p class="invalid-feedback" role="alert">
{{ $errors->first('guest_link_display_mode') }}
</p>
@endif
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">
<x-icon.save class="mr-2"/> @lang('settings.save_settings')
</button>
</form>
</div>
</div>

View File

@ -8,4 +8,6 @@
@include('actions.settings.partials.system.general-settings')
@include('actions.settings.partials.system.guest-settings')
@endsection

View File

@ -6,14 +6,23 @@
<h3 class="mb-0">
@lang('link.links')
</h3>
<div class="dropdown ml-auto">
@include('models.links.partials.index-order-dropdown', ['baseRoute' => 'guest.links.index'])
</div>
</header>
<section class="link-wrapper my-3">
@if(!$links->isEmpty())
<section class="my-4">
@if($links->isNotEmpty())
@foreach($links as $link)
@include('guest.links.partials.single')
@endforeach
<div class="link-wrapper">
@if((int)systemsettings('guest_link_display_mode') === Link::DISPLAY_CARDS)
@include('guest.links.partials.list-cards')
@elseif((int)systemsettings('guest_link_display_mode') === Link::DISPLAY_LIST_SIMPLE)
@include('guest.links.partials.list-simple')
@else
@include('guest.links.partials.list-detailed')
@endif
</div>
@else
@ -24,8 +33,8 @@
@endif
</section>
@if(!$links->isEmpty())
{!! $links->onEachSide(1)->links() !!}
@if($links->isNotEmpty())
{!! $links->onEachSide(1)->appends(['orderBy' => $orderBy, 'orderDir' => $orderDir])->links() !!}
@endif
@endsection

View File

@ -0,0 +1,131 @@
<div class="card">
<header class="card-header">
@lang('link.add')
</header>
<div class="card-body">
<form action="{{ route('links.store') }}" method="POST">
@csrf
<div class="form-group">
<label class="label" for="url">@lang('link.url')</label>
<input name="url" id="url" type="url"
class="form-control form-control-lg{{ $errors->has('url') ? ' is-invalid' : '' }}"
placeholder="@lang('placeholder.link_url')" value="{{ old('url') ?: $bookmark_url ?? '' }}"
required autofocus>
<p class="invalid-feedback {{ $errors->has('url') ? 'd-none' : '' }}">
@lang('validation.unique', ['attribute' => trans('link.url')])
</p>
@if ($errors->has('url'))
<p class="invalid-feedback" role="alert">
{{ $errors->first('url') }}
</p>
@endif
</div>
<div class="row">
<div class="col-12 col-sm-6 col-md-7">
<div class="form-group">
<label class="label" for="title">@lang('link.title')</label>
<input name="title" id="title"
class="form-control{{ $errors->has('title') ? ' is-invalid' : '' }}"
type="text" placeholder="@lang('placeholder.link_title')"
value="{{ old('title') ?: $bookmark_title ?? '' }}">
@if ($errors->has('title'))
<p class="invalid-feedback" role="alert">
{{ $errors->first('title') }}
</p>
@endif
</div>
<div class="form-group">
<label for="description">@lang('link.description')</label>
<textarea name="description" id="description" rows="4" class="form-control"
>{{ old('description') }}</textarea>
@if ($errors->has('description'))
<p class="invalid-feedback" role="alert">
{{ $errors->first('description') }}
</p>
@endif
</div>
</div>
<div class="col-12 col-sm-6 col-md-5">
<div class="form-group">
<label for="lists">@lang('list.lists')</label>
<input name="lists" id="lists" type="text" placeholder="@lang('placeholder.list_select')"
class="tags-select" value="{{ old('lists') }}" data-tag-type="lists">
@if ($errors->has('lists'))
<p class="invalid-feedback" role="alert">
{{ $errors->first('lists') }}
</p>
@endif
</div>
<div class="form-group">
<label for="tags">@lang('tag.tags')</label>
<input name="tags" id="tags" type="text" placeholder="@lang('placeholder.tags_select')"
class="tags-select" value="{{ old('tags') }}" data-tag-type="tags">
@if ($errors->has('tags'))
<p class="invalid-feedback" role="alert">
{{ $errors->first('tags') }}
</p>
@endif
<div class="tag-suggestions mt-2 d-none">
<small>@lang('We found some tags which might be interesting...')</small>
<div class="tag-suggestions-content mt-1"></div>
</div>
</div>
<div class="form-group">
<label for="is_private">@lang('linkace.is_private')</label>
<select id="is_private" name="is_private"
class="custom-select{{ $errors->has('is_private') ? ' is-invalid' : '' }}">
<option value="0">
@lang('linkace.no')
</option>
<option value="1" @if(usersettings('links_private_default') === '1') selected @endif>
@lang('linkace.yes')
</option>
</select>
@if ($errors->has('is_private'))
<p class="invalid-feedback" role="alert">
{{ $errors->first('is_private') }}
</p>
@endif
</div>
</div>
</div>
<div class="mt-3 d-sm-flex align-items-center justify-content-end">
@if(!isset($bookmark_url))
<div class="custom-control custom-checkbox mb-3 mb-sm-0 mr-sm-4">
<input class="custom-control-input" type="checkbox" id="reload_view" name="reload_view"
@if(session('reload_view')) checked @endif>
<label class="custom-control-label" for="reload_view">
@lang('linkace.continue_adding')
</label>
</div>
@endif
<button type="submit" class="btn btn-primary">
<x-icon.save class="mr-2"/> @lang('link.add')
</button>
</div>
</form>
</div>
</div>

View File

@ -0,0 +1,5 @@
<div class="row">
@foreach($links as $link)
@include('guest.links.partials.single-card')
@endforeach
</div>

View File

@ -0,0 +1,3 @@
@foreach($links as $link)
@include('guest.links.partials.single-detailed')
@endforeach

View File

@ -0,0 +1,5 @@
<ul class="list-group">
@foreach($links as $link)
@include('guest.links.partials.single-simple')
@endforeach
</ul>

View File

@ -0,0 +1,24 @@
<div class="col-12 col-sm-6 col-md-4 mb-4">
<div class="h-100 card">
<div class="card-body h-100 border-bottom-0">
<div class="d-flex align-items-top">
<div class="mr-2">
{!! $link->getIcon('mr-1') !!}
<a href="{{ $link->url }}" {!! linkTarget() !!}>
{{ $link->shortTitle() }}
</a>
<div class="mt-2 small text-muted">{{ $link->shortUrl() }}</div>
</div>
</div>
</div>
<div class="card-footer">
<div>
<small class="text-muted">
@lang('linkace.added') {!! $link->addedAt() !!}
</small>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,55 @@
<div class="card mb-4">
<div class="card-header">
<div class="d-flex align-items-top flex-wrap">
<div class="mr-2 mw-100">
{!! $link->getIcon('mr-1') !!}
<a href="{{ $link->url }}" {!! linkTarget() !!}>{{ $link->title }}</a>
<br>
<small class="text-muted">{{ $link->shortUrl() }}</small>
</div>
<div class="ml-auto text-right">
<button type="button" class="btn btn-xs btn-outline-secondary" title="@lang('sharing.share_link')"
data-toggle="collapse" data-target="#sharing-{{ $link->id }}"
aria-expanded="false" aria-controls="sharing-{{ $link->id }}">
<x-icon.share class="fw"/>
</button>
</div>
</div>
</div>
<div class="collapse" id="sharing-{{ $link->id }}">
<div class="card-body py-2 px-3">
<div class="share-links">
{!! getShareLinks($link) !!}
</div>
</div>
</div>
<div class="card-body py-2 px-3">
<div class="row">
<div class="col-12 col-sm-6 ">
@if($link->tags->count() > 0)
<label class="small mb-0">@lang('tag.tags'):</label>
@foreach($link->tags as $tag)
<a href="{{ route('guest.tags.show', [$tag->id]) }}" class="badge badge-light">
{{ $tag->name }}
</a>
@endforeach
@else
<span class="small">@lang('tag.no_tags')</span>
@endif
</div>
<div class="col-12 col-sm-6 d-sm-flex align-items-sm-center justify-content-sm-end flex-wrap">
<div class="small text-muted mt-3 mt-sm-0">
@lang('linkace.added') {!! $link->addedAt() !!}
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,13 @@
<li class="list-group-item">
<div class="d-sm-flex align-items-center">
<div class="mr-3 one-line-sm">
<a href="{{ $link->url }}" title="{{ $link->url }}">
{!! $link->getIcon('mr-1') !!}
{{ $link->shortTitle(100) }}
</a>
</div>
<div class="mt-2 mt-sm-0 ml-auto flex-shrink-0 d-flex align-items-center">
<small class="text-muted mr-3">{!! $link->domainOfURL() !!}</small>
</div>
</div>
</li>

View File

@ -3,13 +3,13 @@
<thead>
<tr>
<th>
{!! tableSorter(trans('link.link'), $route, 'title', $order_by, $order_dir) !!}
{!! tableSorter(trans('link.link'), $route, 'title', $orderBy, $orderDir) !!}
</th>
<th>
{!! tableSorter(trans('link.url'), $route, 'url', $order_by, $order_dir) !!}
{!! tableSorter(trans('link.url'), $route, 'url', $orderBy, $orderDir) !!}
</th>
<th>
{!! tableSorter(trans('linkace.added_at'), $route, 'created_at', $order_by, $order_dir) !!}
{!! tableSorter(trans('linkace.added_at'), $route, 'created_at', $orderBy, $orderDir) !!}
</th>
</tr>
</thead>

View File

@ -3,9 +3,12 @@
@section('content')
<header class="d-flex align-items-center">
<h3 class="mb-0">
<h3 class="mb-0 mr-3">
@lang('list.lists')
</h3>
<div class="dropdown ml-auto">
@include('models.lists.partials.index-order-dropdown', ['baseRoute' => 'lists.index'])
</div>
</header>
@if(!$lists->isEmpty())
@ -25,7 +28,7 @@
@endif
@if(!$lists->isEmpty())
{!! $lists->onEachSide(1)->links() !!}
{!! $lists->onEachSide(1)->appends(['orderBy' => $orderBy, 'orderDir' => $orderDir])->links() !!}
@endif
@endsection

View File

@ -23,11 +23,11 @@
</div>
<div class="card-table">
@include('guest.links.partials.table', ['links' => $list_links])
@include('guest.links.partials.table', ['links' => $listLinks])
</div>
</div>
{!! $list_links->onEachSide(1)->links() !!}
{!! $listLinks->onEachSide(1)->appends(['orderBy' => $orderBy, 'orderDir' => $orderDir])->links() !!}
@endsection

View File

@ -13,37 +13,7 @@
<x-icon.plus class="mr-2"/>
@lang('linkace.add')
</a>
<button type="button" id="link-index-order-dd"
class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@lang('search.order_by') <x-icon.caret-down class="ml-1"/>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="link-index-order-dd">
<a class="dropdown-item small"
href="{{ route('links.index', ['orderBy' => 'created_at', 'orderDir' => 'asc']) }}">
@lang('search.order_by.created_at:asc')
</a>
<a class="dropdown-item small"
href="{{ route('links.index', ['orderBy' => 'created_at', 'orderDir' => 'desc']) }}">
@lang('search.order_by.created_at:desc')
</a>
<a class="dropdown-item small"
href="{{ route('links.index', ['orderBy' => 'url', 'orderDir' => 'asc']) }}">
@lang('search.order_by.url:asc')
</a>
<a class="dropdown-item small"
href="{{ route('links.index', ['orderBy' => 'url', 'orderDir' => 'desc']) }}">
@lang('search.order_by.url:desc')
</a>
<a class="dropdown-item small"
href="{{ route('links.index', ['orderBy' => 'title', 'orderDir' => 'asc']) }}">
@lang('search.order_by.title:asc')
</a>
<a class="dropdown-item small"
href="{{ route('links.index', ['orderBy' => 'title', 'orderDir' => 'desc']) }}">
@lang('search.order_by.title:desc')
</a>
</div>
@include('models.links.partials.index-order-dropdown', ['baseRoute' => 'links.index'])
</div>
</header>

View File

@ -0,0 +1,31 @@
<button type="button" id="link-index-order-dd"
class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@lang('search.order_by') <x-icon.caret-down class="ml-1"/>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="link-index-order-dd">
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'created_at', 'orderDir' => 'asc']) }}">
@lang('search.order_by.created_at:asc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'created_at', 'orderDir' => 'desc']) }}">
@lang('search.order_by.created_at:desc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'url', 'orderDir' => 'asc']) }}">
@lang('search.order_by.url:asc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'url', 'orderDir' => 'desc']) }}">
@lang('search.order_by.url:desc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'title', 'orderDir' => 'asc']) }}">
@lang('search.order_by.title:asc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'title', 'orderDir' => 'desc']) }}">
@lang('search.order_by.title:desc')
</a>
</div>

View File

@ -3,7 +3,7 @@
@section('content')
<header class="d-flex align-items-center">
<h3 class="mb-0">
<h3 class="mb-0 mr-3">
@lang('list.lists')
</h3>
<div class="btn-group ml-auto">
@ -11,37 +11,7 @@
<x-icon.plus class="mr-2"/>
@lang('linkace.add')
</a>
<button type="button" id="list-index-order-dd"
class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@lang('search.order_by') <x-icon.caret-down class="ml-1"/>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="list-index-order-dd">
<a class="dropdown-item small"
href="{{ route('lists.index', ['orderBy' => 'created_at', 'orderDir' => 'asc']) }}">
@lang('search.order_by.created_at:asc')
</a>
<a class="dropdown-item small"
href="{{ route('lists.index', ['orderBy' => 'created_at', 'orderDir' => 'desc']) }}">
@lang('search.order_by.created_at:desc')
</a>
<a class="dropdown-item small"
href="{{ route('lists.index', ['orderBy' => 'name', 'orderDir' => 'asc']) }}">
@lang('search.order_by.title:asc')
</a>
<a class="dropdown-item small"
href="{{ route('lists.index', ['orderBy' => 'name', 'orderDir' => 'desc']) }}">
@lang('search.order_by.title:desc')
</a>
<a class="dropdown-item small"
href="{{ route('lists.index', ['orderBy' => 'links_count', 'orderDir' => 'asc']) }}">
@lang('search.order_by.number_links:asc')
</a>
<a class="dropdown-item small"
href="{{ route('lists.index', ['orderBy' => 'links_count', 'orderDir' => 'desc']) }}">
@lang('search.order_by.number_links:desc')
</a>
</div>
@include('models.lists.partials.index-order-dropdown', ['baseRoute' => 'lists.index'])
</div>
</header>

View File

@ -0,0 +1,31 @@
<button type="button" id="list-index-order-dd"
class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@lang('search.order_by') <x-icon.caret-down class="ml-1"/>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="list-index-order-dd">
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'created_at', 'orderDir' => 'asc']) }}">
@lang('search.order_by.created_at:asc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'created_at', 'orderDir' => 'desc']) }}">
@lang('search.order_by.created_at:desc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'name', 'orderDir' => 'asc']) }}">
@lang('search.order_by.title:asc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'name', 'orderDir' => 'desc']) }}">
@lang('search.order_by.title:desc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'links_count', 'orderDir' => 'asc']) }}">
@lang('search.order_by.number_links:asc')
</a>
<a class="dropdown-item small"
href="{{ route($baseRoute, ['orderBy' => 'links_count', 'orderDir' => 'desc']) }}">
@lang('search.order_by.number_links:desc')
</a>
</div>

View File

@ -147,6 +147,12 @@ Route::group(['middleware' => ['auth']], function () {
// Guest access routes
Route::prefix('guest')->middleware(['guestaccess'])->group(function () {
Route::resource('links', GuestLinkController::class)
->only(['index'])
->names([
'index' => 'guest.links.index',
]);
Route::resource('lists', GuestListController::class)
->only(['index', 'show'])
->names([
@ -154,15 +160,10 @@ Route::prefix('guest')->middleware(['guestaccess'])->group(function () {
'show' => 'guest.lists.show',
]);
Route::resource('links', GuestLinkController::class)
->only(['index'])
->names([
'index' => 'guest.links.index',
]);
Route::resource('tags', GuestTagController::class)
->only(['show'])
->only(['index', 'show'])
->names([
'index' => 'guest.tags.index',
'show' => 'guest.tags.show',
]);
});