refs #3: it's now possible to set a default view for an album when a user hasn't requested one. Finished off the "edit album" page in admin. Switched session management to database sessions (much more reliable.)
This commit is contained in:
parent
58b055e9cd
commit
36fcb6d765
@ -19,7 +19,7 @@ class Album extends Model
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name', 'description', 'url_alias', 'is_private', 'user_id', 'storage_id'
|
||||
'name', 'description', 'url_alias', 'is_private', 'user_id', 'storage_id', 'default_view'
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@ namespace App\Exceptions;
|
||||
use Exception;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Illuminate\Session\TokenMismatchException;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
@ -44,6 +45,11 @@ class Handler extends ExceptionHandler
|
||||
*/
|
||||
public function render($request, Exception $exception)
|
||||
{
|
||||
if ($exception instanceof TokenMismatchException)
|
||||
{
|
||||
return redirect()->back()->withInput()->with('error', 'Your session has expired. Please try the request again.');
|
||||
}
|
||||
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,11 @@ use App\Configuration;
|
||||
|
||||
class ConfigHelper
|
||||
{
|
||||
public function allowedAlbumViews()
|
||||
{
|
||||
return ['default', 'slideshow'];
|
||||
}
|
||||
|
||||
public function allowedDateFormats()
|
||||
{
|
||||
return [
|
||||
@ -78,6 +83,7 @@ class ConfigHelper
|
||||
'allow_self_registration' => true,
|
||||
'app_name' => trans('global.app_name'),
|
||||
'date_format' => $this->allowedDateFormats()[0],
|
||||
'default_album_view' => $this->allowedAlbumViews()[0],
|
||||
'hotlink_protection' => false,
|
||||
'items_per_page' => 12,
|
||||
'items_per_page_admin' => 10,
|
||||
|
@ -155,8 +155,15 @@ class AlbumController extends Controller
|
||||
$postLimit = MiscHelper::convertToBytes(ini_get('post_max_size')) / (1024*1024);
|
||||
$fileUploadOrPostLowerLimit = ($postLimit < $fileUploadLimit) ? $postLimit : $fileUploadLimit;
|
||||
|
||||
$allowedAlbumViews = [];
|
||||
foreach (UserConfig::allowedAlbumViews() as $view)
|
||||
{
|
||||
$allowedAlbumViews[$view] = trans(sprintf('gallery.album_views.%s', $view));
|
||||
}
|
||||
|
||||
return Theme::render('admin.show_album', [
|
||||
'album' => $album,
|
||||
'allowed_views' => $allowedAlbumViews,
|
||||
'bulk_actions' => [
|
||||
'rotate_left' => trans('admin.photo_actions.rotate_left'),
|
||||
'rotate_right' => trans('admin.photo_actions.rotate_right'),
|
||||
@ -193,6 +200,7 @@ class AlbumController extends Controller
|
||||
$album = new Album();
|
||||
$album->fill($request->only(['name', 'description', 'storage_id']));
|
||||
|
||||
$album->default_view = UserConfig::get('default_album_view');
|
||||
$album->is_private = (strtolower($request->get('is_private')) == 'on');
|
||||
$album->user_id = Auth::user()->id;
|
||||
|
||||
@ -214,10 +222,22 @@ class AlbumController extends Controller
|
||||
$this->authorize('admin-access');
|
||||
|
||||
$album = $this->loadAlbum($id);
|
||||
$album->fill($request->only(['name', 'description']));
|
||||
$album->save();
|
||||
$album->fill(['name', 'description']);
|
||||
$album->is_private = (strtolower($request->get('is_private')) == 'on');
|
||||
|
||||
return Theme::render('admin.show_album', ['album' => $album]);
|
||||
// These keys are optional and may or may not be in the request, depending on the page requesting it
|
||||
foreach (['storage_id', 'default_view'] as $key)
|
||||
{
|
||||
if ($request->has($key))
|
||||
{
|
||||
$album->$key = $request->get($key);
|
||||
}
|
||||
}
|
||||
|
||||
$album->save();
|
||||
$request->session()->flash('success', trans('admin.album_saved_successfully', ['name' => $album->name]));
|
||||
|
||||
return redirect(route('albums.show', ['id' => $id]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -377,7 +377,7 @@ class PhotoController extends Controller
|
||||
|
||||
public function updateBulk(Request $request, $albumId)
|
||||
{
|
||||
$photoIds = $request->get('select-photo');
|
||||
$this->authorize('admin-access');
|
||||
|
||||
/** @var Album $album */
|
||||
$album = Album::where('id', intval($albumId))->first();
|
||||
@ -388,6 +388,31 @@ class PhotoController extends Controller
|
||||
return null;
|
||||
}
|
||||
|
||||
$numberChanged = 0;
|
||||
|
||||
if ($request->has('bulk-apply'))
|
||||
{
|
||||
$numberChanged = $this->applyBulkActions($request, $album);
|
||||
}
|
||||
else
|
||||
{
|
||||
$numberChanged = $this->updatePhotoDetails($request, $album);
|
||||
}
|
||||
|
||||
$request->session()->flash('success', trans_choice('admin.bulk_photos_changed', $numberChanged, ['number' => $numberChanged]));
|
||||
|
||||
return redirect(route('albums.show', array('id' => $albumId)));
|
||||
}
|
||||
|
||||
private function applyBulkActions(Request $request, Album $album)
|
||||
{
|
||||
$photoIds = $request->get('select-photo');
|
||||
if (is_null($photoIds) || !is_array($photoIds) || count($photoIds) == 0)
|
||||
{
|
||||
$request->session()->flash('warning', trans('admin.no_photo_selected_message'));
|
||||
return 0;
|
||||
}
|
||||
|
||||
$action = $request->get('bulk-action');
|
||||
$numberChanged = 0;
|
||||
|
||||
@ -449,12 +474,12 @@ class PhotoController extends Controller
|
||||
break;
|
||||
}
|
||||
|
||||
$photo->save();
|
||||
|
||||
$numberChanged++;
|
||||
}
|
||||
|
||||
$request->session()->flash('success', trans_choice('admin.bulk_photos_changed', $numberChanged, ['number' => $numberChanged]));
|
||||
|
||||
return redirect(route('albums.show', array('id' => $albumId)));
|
||||
return $numberChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -472,4 +497,27 @@ class PhotoController extends Controller
|
||||
|
||||
return $album;
|
||||
}
|
||||
|
||||
private function updatePhotoDetails(Request $request, Album $album)
|
||||
{
|
||||
$numberChanged = 0;
|
||||
$photos = $request->get('photo');
|
||||
|
||||
foreach ($photos as $photoId => $value)
|
||||
{
|
||||
/** @var Photo $photo */
|
||||
$photo = $album->photos()->where('id', intval($photoId))->first();
|
||||
if (is_null($photo))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$photo->fill($value);
|
||||
$photo->save();
|
||||
|
||||
$numberChanged++;
|
||||
}
|
||||
|
||||
return $numberChanged;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace App\Http\Controllers\Gallery;
|
||||
use App\Album;
|
||||
use App\Facade\Theme;
|
||||
use App\Facade\UserConfig;
|
||||
use App\Helpers\ConfigHelper;
|
||||
use App\Helpers\DbHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests;
|
||||
@ -23,12 +24,17 @@ class AlbumController extends Controller
|
||||
return null;
|
||||
}
|
||||
|
||||
$validViews = ['default', 'slideshow'];
|
||||
$validViews = UserConfig::allowedAlbumViews();
|
||||
$requestedView = strtolower($request->get('view'));
|
||||
if (!in_array($requestedView, $validViews))
|
||||
{
|
||||
$requestedView = $album->default_view;
|
||||
|
||||
if (!in_array($requestedView, $validViews))
|
||||
{
|
||||
$requestedView = $validViews[0];
|
||||
}
|
||||
}
|
||||
|
||||
$this->authorizeForUser($this->getUser(), 'album.view', $album);
|
||||
|
||||
@ -47,6 +53,7 @@ class AlbumController extends Controller
|
||||
|
||||
return Theme::render(sprintf('gallery.album_%s', $requestedView), [
|
||||
'album' => $album,
|
||||
'allowed_views' => $validViews,
|
||||
'current_view' => $requestedView,
|
||||
'photos' => $photos
|
||||
]);
|
||||
|
@ -23,10 +23,24 @@ class StoreAlbumRequest extends FormRequest
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
switch ($this->method())
|
||||
{
|
||||
case 'POST':
|
||||
return [
|
||||
'description' => '',
|
||||
'name' => 'required|unique:albums|max:255',
|
||||
'storage_id' => 'required'
|
||||
'storage_id' => 'required|sometimes'
|
||||
];
|
||||
|
||||
case 'PATCH':
|
||||
case 'PUT':
|
||||
$albumId = intval($this->segment(3));
|
||||
|
||||
return [
|
||||
'description' => 'sometimes',
|
||||
'name' => 'required|sometimes|max:255|unique:albums,name,' . $albumId,
|
||||
'storage_id' => 'required|sometimes'
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,9 @@ class Photo extends Model
|
||||
'camera_software',
|
||||
'width',
|
||||
'height',
|
||||
'is_analysed'
|
||||
'is_analysed',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
/**
|
||||
@ -46,9 +48,18 @@ class Photo extends Model
|
||||
return $this->belongsTo(Album::class);
|
||||
}
|
||||
|
||||
public function thumbnailUrl($thumbnailName = null)
|
||||
public function thumbnailUrl($thumbnailName = null, $cacheBust = true)
|
||||
{
|
||||
return $this->album->getAlbumSource()->getUrlToPhoto($this, $thumbnailName);
|
||||
$url = $this->album->getAlbumSource()->getUrlToPhoto($this, $thumbnailName);
|
||||
|
||||
if ($cacheBust)
|
||||
{
|
||||
// Append the timestamp of the last update to avoid browser caching
|
||||
$theDate = is_null($this->updated_at) ? $this->created_at : $this->updated_at;
|
||||
$url .= sprintf('%s_=%d', (strpos($url, '?') === false ? '?' : '&'), $theDate->format('U'));
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function url()
|
||||
|
@ -16,7 +16,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
'driver' => env('SESSION_DRIVER', 'database'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -31,7 +31,7 @@ return [
|
||||
|
||||
'lifetime' => 120,
|
||||
|
||||
'expire_on_close' => false,
|
||||
'expire_on_close' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -70,7 +70,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'connection' => null,
|
||||
'connection' => 'mysql',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -122,7 +122,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'cookie' => 'laravel_session',
|
||||
'cookie' => 'twilight_session',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
32
database/migrations/2016_10_05_120046_add_album_view.php
Normal file
32
database/migrations/2016_10_05_120046_add_album_view.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddAlbumView extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('albums', function (Blueprint $table) {
|
||||
$table->string('default_view', 50);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('albums', function (Blueprint $table) {
|
||||
$table->dropColumn('default_view');
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateSessionsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('sessions', function ($table) {
|
||||
$table->string('id')->unique();
|
||||
$table->integer('user_id')->nullable();
|
||||
$table->string('ip_address', 45)->nullable();
|
||||
$table->text('user_agent')->nullable();
|
||||
$table->text('payload');
|
||||
$table->integer('last_activity');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('sessions');
|
||||
}
|
||||
}
|
2
public/themes/base/css/app.css
vendored
2
public/themes/base/css/app.css
vendored
@ -1,4 +1,4 @@
|
||||
.album-slideshow-container .image-preview {
|
||||
.album-slideshow-container #image-preview {
|
||||
height: 600px;
|
||||
max-width: 100%;
|
||||
width: 800px;
|
||||
|
@ -4,10 +4,17 @@ return [
|
||||
'create_album_link' => 'Create album',
|
||||
'panel_header' => 'Actions',
|
||||
],
|
||||
'album_appearance_heading' => 'Appearance',
|
||||
'album_appearance_intro' => 'The settings shown below control how this album appears to visitors in the gallery.',
|
||||
'album_basic_info_heading' => 'Album information',
|
||||
'album_basic_info_intro' => 'The album\'s name and description are displayed to visitors in the gallery. If you wish to change them, you can do so below.',
|
||||
'album_no_photos_p1' => 'No photos in this album',
|
||||
'album_no_photos_p2' => 'Click the "Upload photos" button below to get started.',
|
||||
'album_no_photos_button' => 'Upload photos',
|
||||
'album_photos_tab' => 'Photos',
|
||||
'album_saved_successfully' => 'The ":name" album was updated successfully.',
|
||||
'album_security_heading' => 'Security',
|
||||
'album_security_intro' => 'The settings below affect the visibility of this album to other users.',
|
||||
'album_settings_tab' => 'Settings',
|
||||
'album_upload_tab' => 'Upload',
|
||||
'analyse_photos_failed' => 'The following items could not be analysed and were removed:',
|
||||
@ -25,6 +32,8 @@ return [
|
||||
'create_user' => 'Create user',
|
||||
'create_user_intro' => 'You can use the form below to create a user account. Users created using this form will be activate immediately.',
|
||||
'create_user_title' => 'Create a user account',
|
||||
'danger_zone_heading' => 'Danger zone',
|
||||
'danger_zone_intro' => 'The options below WILL cause data loss - please be careful!',
|
||||
'delete_album' => 'Delete album :name',
|
||||
'delete_album_confirm' => 'Are you sure you want to permanently delete this album and all its contents?',
|
||||
'delete_album_warning' => 'This is a permanent action that cannot be undone!',
|
||||
@ -41,6 +50,7 @@ return [
|
||||
'delete_user_confirm' => 'Are you sure you want to permanently remove :name\'s user account? They will be immediately logged out.',
|
||||
'delete_user_warning' => 'This is a permanent action that cannot be reversed!',
|
||||
'edit_album' => 'Edit photo album: :album_name',
|
||||
'edit_album_action' => 'Edit album details',
|
||||
'edit_album_intro' => 'Photo albums contain individual photographs together in the same way as a physical photo album or memory book.',
|
||||
'edit_album_intro2' => 'Complete the form below to edit the properties of the album: :album_name.',
|
||||
'edit_storage' => 'Edit storage location: :storage_name',
|
||||
@ -55,6 +65,7 @@ return [
|
||||
'move_successful_message' => 'The photo ":name" was moved successfully to the ":album" album.',
|
||||
'no_albums_text' => 'You have no photo albums yet. Click the button below to create one.',
|
||||
'no_albums_title' => 'No Photo Albums',
|
||||
'no_photo_selected_message' => 'Please select at least one photo.',
|
||||
'no_storages_text' => 'You need a storage location to store your uploaded photographs.',
|
||||
'no_storages_text2' => 'This can be on your server\'s local filesystem or a cloud location such as Amazon S3 or Rackspace.',
|
||||
'no_storages_title' => 'No storage locations defined',
|
||||
@ -69,6 +80,8 @@ return [
|
||||
'rotate_left' => 'Rotate left',
|
||||
'rotate_right' => 'Rotate right'
|
||||
],
|
||||
'save_changes_heading' => 'Save changes',
|
||||
'save_changes_intro' => 'If you have made any changes to the above fields, you\'ll need to hit the Save Changes button below.',
|
||||
'settings_image_protection' => 'Image Protection',
|
||||
'settings_recaptcha' => 'reCAPTCHA settings',
|
||||
'settings_save_action' => 'Update Settings',
|
||||
|
@ -10,6 +10,7 @@ return [
|
||||
'cancel_action' => 'Cancel',
|
||||
'continue_action' => 'Continue',
|
||||
'create_action' => 'Create',
|
||||
'default_album_view_label' => 'Default view mode in the gallery:',
|
||||
'default_storage_label' => 'Use as the default storage location for new albums',
|
||||
'delete_action' => 'Delete',
|
||||
'description_label' => 'Description:',
|
||||
|
@ -26,8 +26,8 @@
|
||||
@if (count($errors) > 0)
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@foreach ($errors->all() as $form_error)
|
||||
<li>{{ $form_error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -155,10 +155,70 @@
|
||||
|
||||
{{-- Settings --}}
|
||||
<div role="tabpanel" class="tab-pane" id="settings-tab">
|
||||
<div class="btn-toolbar">
|
||||
<a href="{{ route('albums.edit', ['id' => $album->id]) }}" class="btn btn-default">@lang('forms.edit_action')</a>
|
||||
<a href="{{ route('albums.delete', ['id' => $album->id]) }}" class="btn btn-danger">@lang('forms.delete_action')</a>
|
||||
{!! Form::model($album, ['route' => ['albums.update', $album->id], 'method' => 'PUT']) !!}
|
||||
<h4><i class="fa fa-fw fa-info"></i> @lang('admin.album_basic_info_heading')</h4>
|
||||
<p>@lang('admin.album_basic_info_intro')</p>
|
||||
|
||||
<div class="form-group" style="margin-top: 20px;">
|
||||
{!! Form::label('name', trans('forms.name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('name', old('name'), ['class' => 'form-control']) !!}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
{!! Form::label('description', trans('forms.description_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::textarea('description', old('description'), ['class' => 'form-control']) !!}
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<h4><i class="fa fa-fw fa-paint-brush"></i> @lang('admin.album_appearance_heading')</h4>
|
||||
<p>@lang('admin.album_appearance_intro')</p>
|
||||
|
||||
<div class="form-group" style="margin-top: 20px;">
|
||||
<label class="control-label">@lang('forms.default_album_view_label')</label>
|
||||
{!! Form::select('default_view', $allowed_views, old('default_view'), ['class' => 'form-control']) !!}
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<h4><i class="fa fa-fw fa-lock"></i> @lang('admin.album_security_heading')</h4>
|
||||
<p>@lang('admin.album_security_intro')</p>
|
||||
|
||||
<div class="checkbox" style="margin-top: 20px;">
|
||||
<label>
|
||||
<input type="checkbox" name="is_private"@if ($album->is_private) checked="checked"@endif>
|
||||
<strong>@lang('forms.private_album_label')</strong>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading">@lang('admin.danger_zone_heading')</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-danger">@lang('admin.danger_zone_intro')</p>
|
||||
<p>
|
||||
<a href="{{ route('albums.delete', ['id' => $album->id]) }}" class="btn btn-danger">@lang('forms.delete_action')</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">@lang('admin.save_changes_heading')</div>
|
||||
<div class="panel-body">
|
||||
<p>@lang('admin.save_changes_intro')</p>
|
||||
<p class="text-right">
|
||||
<button type="submit" class="btn btn-success">@lang('forms.save_action')</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{!! Form::close() !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,8 +2,9 @@
|
||||
<div class="field-group">
|
||||
<label class="control-label">@lang('forms.album_view_label')</label>
|
||||
<select name="view" class="form-control" id="album-view-selector">
|
||||
<option value="default"@if (isset($current_view) && $current_view == 'default') selected="selected"@endif>@lang('gallery.album_views.default')</option>
|
||||
<option value="slideshow"@if (isset($current_view) && $current_view == 'slideshow') selected="selected"@endif>@lang('gallery.album_views.slideshow')</option>
|
||||
@foreach ($allowed_views as $view)
|
||||
<option value="{{ $view }}"@if (isset($current_view) && $current_view == $view) selected="selected"@endif>@lang('gallery.album_views.' . $view)</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
|
Loading…
Reference in New Issue
Block a user