Compare commits
44 Commits
v2.1.0-bet
...
v2.1
Author | SHA1 | Date | |
---|---|---|---|
fa861c0b09 | |||
0836ca5557 | |||
c029c6ca00 | |||
aa2998ac70 | |||
eedfd5abdd | |||
9a65e8f1c9 | |||
9ea1953ada | |||
8dd31961e7 | |||
c784c623ba | |||
9064495f1f | |||
e2d66fd228 | |||
9740582b6e | |||
d63423bc47 | |||
2571675b24 | |||
6040c7d4ef | |||
4b7b99431f | |||
ab690b1e25 | |||
393cc590c1 | |||
ef4df1ab32 | |||
f96a9cd9f7 | |||
790d354167 | |||
036814705f | |||
534c8f6090 | |||
309d97cb75 | |||
06869a157c | |||
f007371a79 | |||
cb6ae98907 | |||
|
189aafe61c | ||
|
efdcecfca6 | ||
cc3370c4b1 | |||
04d1e59778 | |||
|
2bbaa81ffe | ||
|
f3f5e5b615 | ||
|
adb86f1d4e | ||
|
dcfcbca530 | ||
|
89544437cd | ||
|
f38911f79e | ||
|
4326bc427c | ||
|
a6303410cf | ||
|
c5e22c7a6e | ||
|
435e47af17 | ||
|
d575560209 | ||
|
cef1ea63cf | ||
|
1618ae64c0 |
|
@ -195,12 +195,28 @@ class Album extends Model
|
||||||
return $this->getAlbumSource()->getUrlToPhoto($photo, $thumbnailName);
|
return $this->getAlbumSource()->getUrlToPhoto($photo, $thumbnailName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate standard images
|
// See if any child albums have an image
|
||||||
$images = [
|
$images = [];
|
||||||
asset('themes/base/images/empty-album-1.jpg'),
|
|
||||||
asset('themes/base/images/empty-album-2.jpg'),
|
/** @var Album $childAlbum */
|
||||||
asset('themes/base/images/empty-album-3.jpg')
|
foreach ($this->children as $childAlbum)
|
||||||
];
|
{
|
||||||
|
if ($childAlbum->photos()->count() > 0)
|
||||||
|
{
|
||||||
|
$images[] = $childAlbum->thumbnailUrl($thumbnailName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($images) == 0)
|
||||||
|
{
|
||||||
|
// Rotate standard images
|
||||||
|
$images = [
|
||||||
|
asset('themes/base/images/empty-album-1.jpg'),
|
||||||
|
asset('themes/base/images/empty-album-2.jpg'),
|
||||||
|
asset('themes/base/images/empty-album-3.jpg')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
return $images[rand(0, count($images) - 1)];
|
return $images[rand(0, count($images) - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,8 @@ class ConfigHelper
|
||||||
$currentAppName = $this->get('app_name', false);
|
$currentAppName = $this->get('app_name', false);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
'albums_menu_parents_only' => false,
|
||||||
|
'albums_menu_number_items' => 10,
|
||||||
'allow_self_registration' => true,
|
'allow_self_registration' => true,
|
||||||
'analytics_code' => '',
|
'analytics_code' => '',
|
||||||
'app_name' => trans('global.app_name'),
|
'app_name' => trans('global.app_name'),
|
||||||
|
|
|
@ -33,17 +33,12 @@ class DbHelper
|
||||||
|
|
||||||
public static function getAlbumsForCurrentUser($parentID = -1)
|
public static function getAlbumsForCurrentUser($parentID = -1)
|
||||||
{
|
{
|
||||||
$query = self::getAlbumsForCurrentUser_NonPaged();
|
$query = self::getAlbumsForCurrentUser_NonPaged('list', $parentID);
|
||||||
|
|
||||||
if ($parentID == 0)
|
|
||||||
{
|
|
||||||
$query = $query->where('albums.parent_album_id', null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $query->paginate(UserConfig::get('items_per_page'));
|
return $query->paginate(UserConfig::get('items_per_page'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getAlbumsForCurrentUser_NonPaged($permission = 'list')
|
public static function getAlbumsForCurrentUser_NonPaged($permission = 'list', $parentAlbumID = -1)
|
||||||
{
|
{
|
||||||
$albumsQuery = Album::query();
|
$albumsQuery = Album::query();
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
|
@ -75,17 +70,30 @@ class DbHelper
|
||||||
->leftJoin('permissions AS group_permissions', 'group_permissions.id', '=', 'album_group_permissions.permission_id')
|
->leftJoin('permissions AS group_permissions', 'group_permissions.id', '=', 'album_group_permissions.permission_id')
|
||||||
->leftJoin('permissions AS user_permissions', 'user_permissions.id', '=', 'album_user_permissions.permission_id')
|
->leftJoin('permissions AS user_permissions', 'user_permissions.id', '=', 'album_user_permissions.permission_id')
|
||||||
->leftJoin('user_groups', 'user_groups.group_id', '=', 'album_group_permissions.group_id')
|
->leftJoin('user_groups', 'user_groups.group_id', '=', 'album_group_permissions.group_id')
|
||||||
->where('albums.user_id', $user->id)
|
->where(function($query) use ($user, $permission)
|
||||||
->orWhere([
|
{
|
||||||
['group_permissions.section', 'album'],
|
$query->where('albums.user_id', $user->id)
|
||||||
['group_permissions.description', $permission],
|
->orWhere([
|
||||||
['user_groups.user_id', $user->id]
|
['group_permissions.section', 'album'],
|
||||||
])
|
['group_permissions.description', $permission],
|
||||||
->orWhere([
|
['user_groups.user_id', $user->id]
|
||||||
['user_permissions.section', 'album'],
|
])
|
||||||
['user_permissions.description', $permission],
|
->orWhere([
|
||||||
['album_user_permissions.user_id', $user->id]
|
['user_permissions.section', 'album'],
|
||||||
]);
|
['user_permissions.description', $permission],
|
||||||
|
['album_user_permissions.user_id', $user->id]
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$parentAlbumID = intval($parentAlbumID);
|
||||||
|
if ($parentAlbumID == 0)
|
||||||
|
{
|
||||||
|
$albumsQuery->where('albums.parent_album_id', null);
|
||||||
|
}
|
||||||
|
else if ($parentAlbumID > 0)
|
||||||
|
{
|
||||||
|
$albumsQuery->where('albums.parent_album_id', $parentAlbumID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $albumsQuery->select('albums.*')
|
return $albumsQuery->select('albums.*')
|
||||||
|
@ -103,4 +111,14 @@ class DbHelper
|
||||||
{
|
{
|
||||||
return Album::where('url_path', $urlPath)->first();
|
return Album::where('url_path', $urlPath)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getChildAlbumsCount(Album $album)
|
||||||
|
{
|
||||||
|
return self::getAlbumsForCurrentUser_NonPaged('list', $album->id)->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getChildAlbums(Album $album)
|
||||||
|
{
|
||||||
|
return self::getAlbumsForCurrentUser_NonPaged('list', $album->id)->get();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -46,7 +46,7 @@ class FileHelper
|
||||||
|
|
||||||
if (!file_exists($path))
|
if (!file_exists($path))
|
||||||
{
|
{
|
||||||
mkdir($path, 0755, true);
|
@mkdir($path, 0755, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $path;
|
return $path;
|
||||||
|
|
|
@ -124,6 +124,12 @@ class MiscHelper
|
||||||
return MiscHelper::getEnvironmentSetting('APP_INSTALLED');
|
return MiscHelper::getEnvironmentSetting('APP_INSTALLED');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function isExecEnabled()
|
||||||
|
{
|
||||||
|
$disabled = explode(',', ini_get('disable_functions'));
|
||||||
|
return !in_array('exec', $disabled);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests whether the provided URL belongs to the current application (i.e. both scheme and hostname match.)
|
* Tests whether the provided URL belongs to the current application (i.e. both scheme and hostname match.)
|
||||||
* @param $url
|
* @param $url
|
||||||
|
|
|
@ -2,8 +2,37 @@
|
||||||
|
|
||||||
namespace App\Helpers;
|
namespace App\Helpers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class ValidationHelper
|
class ValidationHelper
|
||||||
{
|
{
|
||||||
|
public function albumPathUnique($attribute, $value, $parameters, $validator)
|
||||||
|
{
|
||||||
|
$data = $validator->getData();
|
||||||
|
$parentID = intval($data['parent_album_id']);
|
||||||
|
$name = $data['name'];
|
||||||
|
|
||||||
|
if ($parentID === 0)
|
||||||
|
{
|
||||||
|
$parentID = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$queryParams = [
|
||||||
|
['name', $name],
|
||||||
|
['parent_album_id', $parentID]
|
||||||
|
];
|
||||||
|
|
||||||
|
if (count($parameters) > 0)
|
||||||
|
{
|
||||||
|
$existingAlbumID = intval($parameters[0]);
|
||||||
|
$queryParams[] = ['id', '<>', $existingAlbumID];
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = DB::table('albums')->where($queryParams)->count();
|
||||||
|
|
||||||
|
return ($count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
public function directoryExists($attribute, $value, $parameters, $validator)
|
public function directoryExists($attribute, $value, $parameters, $validator)
|
||||||
{
|
{
|
||||||
return file_exists($value) && is_dir($value);
|
return file_exists($value) && is_dir($value);
|
||||||
|
|
|
@ -122,6 +122,12 @@ class AlbumController extends Controller
|
||||||
|
|
||||||
$album = $this->loadAlbum($id, 'delete');
|
$album = $this->loadAlbum($id, 'delete');
|
||||||
|
|
||||||
|
if ($album->children()->count() > 0)
|
||||||
|
{
|
||||||
|
$request->session()->flash('error', trans('admin.delete_album_failed_children', ['album' => $album->name]));
|
||||||
|
return redirect(route('albums.index'));
|
||||||
|
}
|
||||||
|
|
||||||
// Delete all the photo files
|
// Delete all the photo files
|
||||||
/** @var Photo $photo */
|
/** @var Photo $photo */
|
||||||
foreach ($album->photos as $photo)
|
foreach ($album->photos as $photo)
|
||||||
|
@ -174,6 +180,10 @@ class AlbumController extends Controller
|
||||||
|
|
||||||
// Only get top-level albums
|
// Only get top-level albums
|
||||||
$albums = DbHelper::getAlbumsForCurrentUser(0);
|
$albums = DbHelper::getAlbumsForCurrentUser(0);
|
||||||
|
foreach ($albums as $album)
|
||||||
|
{
|
||||||
|
$this->loadChildAlbums($album);
|
||||||
|
}
|
||||||
|
|
||||||
return Theme::render('admin.list_albums', [
|
return Theme::render('admin.list_albums', [
|
||||||
'albums' => $albums,
|
'albums' => $albums,
|
||||||
|
@ -560,4 +570,13 @@ class AlbumController extends Controller
|
||||||
|
|
||||||
return $album;
|
return $album;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function loadChildAlbums(Album $album)
|
||||||
|
{
|
||||||
|
$album->child_albums = DbHelper::getChildAlbums($album);
|
||||||
|
foreach ($album->child_albums as $childAlbum)
|
||||||
|
{
|
||||||
|
$this->loadChildAlbums($childAlbum);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -15,6 +15,8 @@ use App\Http\Requests\SaveSettingsRequest;
|
||||||
use App\Label;
|
use App\Label;
|
||||||
use App\Mail\TestMailConfig;
|
use App\Mail\TestMailConfig;
|
||||||
use App\Photo;
|
use App\Photo;
|
||||||
|
use App\Services\GiteaService;
|
||||||
|
use App\Services\GithubService;
|
||||||
use App\Services\PhotoService;
|
use App\Services\PhotoService;
|
||||||
use App\Storage;
|
use App\Storage;
|
||||||
use App\User;
|
use App\User;
|
||||||
|
@ -33,9 +35,50 @@ class DefaultController extends Controller
|
||||||
View::share('is_admin', true);
|
View::share('is_admin', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function about()
|
||||||
|
{
|
||||||
|
return Theme::render('admin.about', [
|
||||||
|
'current_version' => config('app.version'),
|
||||||
|
'licence_text' => file_get_contents(sprintf('%s/LICENSE', dirname(dirname(dirname(dirname(__DIR__))))))
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function aboutLatestRelease()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$giteaService = new GiteaService();
|
||||||
|
$releaseInfo = $giteaService->checkForLatestRelease();
|
||||||
|
|
||||||
|
// Convert the publish date so we can re-format it with the user's settings
|
||||||
|
$publishDate = \DateTime::createFromFormat('Y-m-d\TH:i:sP', $releaseInfo->published_at);
|
||||||
|
|
||||||
|
// HTML-ify the body text
|
||||||
|
$body = nl2br($releaseInfo->body);
|
||||||
|
$body = preg_replace('/\*\*(.+)\*\*/', '<b>$1</b>', $body);
|
||||||
|
|
||||||
|
// Remove the "v" from the release name
|
||||||
|
$version = substr($releaseInfo->tag_name, 1);
|
||||||
|
|
||||||
|
// Determine if we can upgrade
|
||||||
|
$canUpgrade = version_compare($version, config('app.version')) > 0;
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'can_upgrade' => $canUpgrade,
|
||||||
|
'body' => $body,
|
||||||
|
'name' => $version,
|
||||||
|
'publish_date' => $publishDate->format(UserConfig::get('date_format')),
|
||||||
|
'url' => $releaseInfo->html_url
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
catch (\Exception $ex)
|
||||||
|
{
|
||||||
|
return response()->json(['error' => $ex->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function metadataUpgrade()
|
public function metadataUpgrade()
|
||||||
{
|
{
|
||||||
$albums = DbHelper::getAlbumsForCurrentUser();
|
|
||||||
$albumIDs = DbHelper::getAlbumIDsForCurrentUser();
|
$albumIDs = DbHelper::getAlbumIDsForCurrentUser();
|
||||||
|
|
||||||
$photoMetadata = DB::table('photos')
|
$photoMetadata = DB::table('photos')
|
||||||
|
@ -47,14 +90,28 @@ class DefaultController extends Controller
|
||||||
->groupBy('album_id')
|
->groupBy('album_id')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
$resultingAlbumIDs = [];
|
||||||
foreach ($photoMetadata as $metadata)
|
foreach ($photoMetadata as $metadata)
|
||||||
{
|
{
|
||||||
/** @var Album $album */
|
if (isset($metadata->min_metadata_version) && $metadata->min_metadata_version > 0)
|
||||||
|
{
|
||||||
|
$resultingAlbumIDs[$metadata->album_id] = $metadata->min_metadata_version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now load the full album definitions
|
||||||
|
$albumsQuery = DbHelper::getAlbumsForCurrentUser_NonPaged();
|
||||||
|
$albumsQuery->whereIn('id', array_keys($resultingAlbumIDs));
|
||||||
|
$albums = $albumsQuery->paginate(UserConfig::get('items_per_page'));
|
||||||
|
|
||||||
|
/** @var Album $album */
|
||||||
|
foreach ($resultingAlbumIDs as $albumID => $metadataMinVersion)
|
||||||
|
{
|
||||||
foreach ($albums as $album)
|
foreach ($albums as $album)
|
||||||
{
|
{
|
||||||
if ($album->id == $metadata->album_id)
|
if ($album->id == $albumID)
|
||||||
{
|
{
|
||||||
$album->min_metadata_version = $metadata->min_metadata_version;
|
$album->min_metadata_version = $metadataMinVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,13 +126,23 @@ class DefaultController extends Controller
|
||||||
{
|
{
|
||||||
$this->authorizeAccessToAdminPanel();
|
$this->authorizeAccessToAdminPanel();
|
||||||
|
|
||||||
$albumCount = DbHelper::getAlbumsForCurrentUser()->count();
|
$albumCount = count(DbHelper::getAlbumIDsForCurrentUser());
|
||||||
$photoCount = Photo::all()->count();
|
$photoCount = Photo::all()->count();
|
||||||
$groupCount = Group::all()->count();
|
$groupCount = Group::all()->count();
|
||||||
$labelCount = Label::all()->count();
|
$labelCount = Label::all()->count();
|
||||||
$userCount = User::where('is_activated', true)->count();
|
$userCount = User::where('is_activated', true)->count();
|
||||||
|
|
||||||
$metadataUpgradeNeeded = Photo::min('metadata_version') < PhotoService::METADATA_VERSION;
|
$minMetadataVersion = Photo::min('metadata_version');
|
||||||
|
$metadataUpgradeNeeded = $minMetadataVersion > 0 && $minMetadataVersion < PhotoService::METADATA_VERSION;
|
||||||
|
|
||||||
|
// Default to a supported function call to get the OS version
|
||||||
|
$osVersion = sprintf('%s %s', php_uname('s'), php_uname('r'));
|
||||||
|
|
||||||
|
// If the exec() function is enabled, we can do a bit better
|
||||||
|
if (MiscHelper::isExecEnabled())
|
||||||
|
{
|
||||||
|
$osVersion = exec('lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om');
|
||||||
|
}
|
||||||
|
|
||||||
return Theme::render('admin.index', [
|
return Theme::render('admin.index', [
|
||||||
'album_count' => $albumCount,
|
'album_count' => $albumCount,
|
||||||
|
@ -86,7 +153,7 @@ class DefaultController extends Controller
|
||||||
'metadata_upgrade_needed' => $metadataUpgradeNeeded,
|
'metadata_upgrade_needed' => $metadataUpgradeNeeded,
|
||||||
'photo_count' => $photoCount,
|
'photo_count' => $photoCount,
|
||||||
'php_version' => phpversion(),
|
'php_version' => phpversion(),
|
||||||
'os_version' => exec('lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om'),
|
'os_version' => $osVersion,
|
||||||
'server_name' => gethostname(),
|
'server_name' => gethostname(),
|
||||||
'upload_file_size' => ini_get('upload_max_filesize'),
|
'upload_file_size' => ini_get('upload_max_filesize'),
|
||||||
'upload_max_limit' => ini_get('post_max_size'),
|
'upload_max_limit' => ini_get('post_max_size'),
|
||||||
|
@ -148,6 +215,7 @@ class DefaultController extends Controller
|
||||||
'smtp_password'
|
'smtp_password'
|
||||||
];
|
];
|
||||||
$checkboxKeys = [
|
$checkboxKeys = [
|
||||||
|
'albums_menu_parents_only',
|
||||||
'allow_self_registration',
|
'allow_self_registration',
|
||||||
'enable_visitor_hits',
|
'enable_visitor_hits',
|
||||||
'hotlink_protection',
|
'hotlink_protection',
|
||||||
|
@ -158,6 +226,7 @@ class DefaultController extends Controller
|
||||||
'smtp_encryption',
|
'smtp_encryption',
|
||||||
];
|
];
|
||||||
$updateKeys = [
|
$updateKeys = [
|
||||||
|
'albums_menu_number_items',
|
||||||
'app_name',
|
'app_name',
|
||||||
'date_format',
|
'date_format',
|
||||||
'sender_address',
|
'sender_address',
|
||||||
|
|
|
@ -296,6 +296,12 @@ class PhotoController extends Controller
|
||||||
// Load the linked album
|
// Load the linked album
|
||||||
$album = $this->loadAlbum($request->get('album_id'));
|
$album = $this->loadAlbum($request->get('album_id'));
|
||||||
|
|
||||||
|
if (is_null($request->files->get('archive')))
|
||||||
|
{
|
||||||
|
$request->session()->flash('error', trans('admin.upload_bulk_no_file'));
|
||||||
|
return redirect(route('albums.show', ['id' => $album->id]));
|
||||||
|
}
|
||||||
|
|
||||||
$archiveFile = UploadedFile::createFromBase($request->files->get('archive'));
|
$archiveFile = UploadedFile::createFromBase($request->files->get('archive'));
|
||||||
if ($archiveFile->getError() != UPLOAD_ERR_OK)
|
if ($archiveFile->getError() != UPLOAD_ERR_OK)
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,20 +71,28 @@ class AlbumController extends Controller
|
||||||
else if ($requestedView != 'slideshow')
|
else if ($requestedView != 'slideshow')
|
||||||
{
|
{
|
||||||
$photos = $album->photos()
|
$photos = $album->photos()
|
||||||
->orderBy(DB::raw('COALESCE(taken_at, created_at)'))
|
->orderBy(DB::raw('COALESCE(taken_at, created_at), name, id'))
|
||||||
->paginate(UserConfig::get('items_per_page'));
|
->paginate(UserConfig::get('items_per_page'));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The slideshow view needs access to all photos, not paged
|
// The slideshow view needs access to all photos, not paged
|
||||||
$photos = $album->photos()
|
$photos = $album->photos()
|
||||||
->orderBy(DB::raw('COALESCE(taken_at, created_at)'))
|
->orderBy(DB::raw('COALESCE(taken_at, created_at), name, id'))
|
||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load child albums and their available children
|
||||||
|
$childAlbums = DbHelper::getChildAlbums($album);
|
||||||
|
foreach ($childAlbums as $childAlbum)
|
||||||
|
{
|
||||||
|
$childAlbum->children_count = DbHelper::getChildAlbumsCount($childAlbum);
|
||||||
|
}
|
||||||
|
|
||||||
return Theme::render(sprintf('gallery.album_%s', $requestedView), [
|
return Theme::render(sprintf('gallery.album_%s', $requestedView), [
|
||||||
'album' => $album,
|
'album' => $album,
|
||||||
'allowed_views' => $validViews,
|
'allowed_views' => $validViews,
|
||||||
|
'child_albums' => $childAlbums,
|
||||||
'current_view' => $requestedView,
|
'current_view' => $requestedView,
|
||||||
'photos' => $photos
|
'photos' => $photos
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -19,6 +19,13 @@ class DefaultController extends Controller
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$albums = DbHelper::getAlbumsForCurrentUser(0);
|
$albums = DbHelper::getAlbumsForCurrentUser(0);
|
||||||
|
|
||||||
|
/** @var Album $album */
|
||||||
|
foreach ($albums as $album)
|
||||||
|
{
|
||||||
|
$album->children_count = DbHelper::getChildAlbumsCount($album);
|
||||||
|
}
|
||||||
|
|
||||||
$resetStatus = $request->session()->get('status');
|
$resetStatus = $request->session()->get('status');
|
||||||
|
|
||||||
// Record the visit to the index (no album or photo to record a hit against though)
|
// Record the visit to the index (no album or photo to record a hit against though)
|
||||||
|
|
|
@ -105,14 +105,40 @@ class PhotoController extends Controller
|
||||||
// Load the Next/Previous buttons
|
// Load the Next/Previous buttons
|
||||||
$thisPhotoDate = is_null($photo->taken_at) ? $photo->created_at : $photo->taken_at;
|
$thisPhotoDate = is_null($photo->taken_at) ? $photo->created_at : $photo->taken_at;
|
||||||
|
|
||||||
$previousPhoto = $album->photos()
|
// I don't like the idea of using a totally raw SQL query, but it's the only sure-fire way to number the rows
|
||||||
->where(DB::raw('COALESCE(taken_at, created_at)'), '<', $thisPhotoDate)
|
// so we can get the previous/next photos accurately - and we don't have to load all data for the photo objects
|
||||||
->orderBy(DB::raw('COALESCE(taken_at, created_at)'), 'desc')
|
$previousPhoto = null;
|
||||||
->first();
|
$nextPhoto = null;
|
||||||
$nextPhoto = $album->photos()
|
|
||||||
->where(DB::raw('COALESCE(taken_at, created_at)'), '>', $thisPhotoDate)
|
$allAlbumPhotos = DB::select(
|
||||||
->orderBy(DB::raw('COALESCE(taken_at, created_at)'))
|
DB::raw(
|
||||||
->first();
|
'SELECT p.id, (@row_number:=@row_number + 1) AS row_number
|
||||||
|
FROM photos p, (SELECT @row_number:=0) AS t
|
||||||
|
WHERE p.album_id = :album_id
|
||||||
|
ORDER BY COALESCE(p.taken_at, p.created_at), p.name, p.id;'
|
||||||
|
),
|
||||||
|
[
|
||||||
|
'album_id' => $album->id
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
for ($i = 0; $i < count($allAlbumPhotos); $i++)
|
||||||
|
{
|
||||||
|
if ($allAlbumPhotos[$i]->id === $photo->id)
|
||||||
|
{
|
||||||
|
if ($i > 0)
|
||||||
|
{
|
||||||
|
$previousPhoto = Photo::where('id', $allAlbumPhotos[$i - 1]->id)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($i + 1 < count($allAlbumPhotos))
|
||||||
|
{
|
||||||
|
$nextPhoto = Photo::where('id', $allAlbumPhotos[$i + 1]->id)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Record the visit to the photo
|
// Record the visit to the photo
|
||||||
if (UserConfig::get('enable_visitor_hits'))
|
if (UserConfig::get('enable_visitor_hits'))
|
||||||
|
|
|
@ -55,7 +55,7 @@ class InstallController extends Controller
|
||||||
|
|
||||||
if ($request->getMethod() == 'POST')
|
if ($request->getMethod() == 'POST')
|
||||||
{
|
{
|
||||||
$request->session()->set('install_stage', 2);
|
$request->session()->put('install_stage', 2);
|
||||||
return redirect(route('install.database'));
|
return redirect(route('install.database'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,12 +150,13 @@ class InstallController extends Controller
|
||||||
|
|
||||||
Artisan::call('cache:clear');
|
Artisan::call('cache:clear');
|
||||||
Artisan::call('migrate', ['--force' => true]);
|
Artisan::call('migrate', ['--force' => true]);
|
||||||
|
Artisan::call('db:seed', ['--force' => true]);
|
||||||
|
|
||||||
$versionNumber = UserConfig::getOrCreateModel('app_version');
|
$versionNumber = UserConfig::getOrCreateModel('app_version');
|
||||||
$versionNumber->value = config('app.version');
|
$versionNumber->value = config('app.version');
|
||||||
$versionNumber->save();
|
$versionNumber->save();
|
||||||
|
|
||||||
$request->session()->set('install_stage', 3);
|
$request->session()->put('install_stage', 3);
|
||||||
return redirect(route('install.administrator'));
|
return redirect(route('install.administrator'));
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
|
|
|
@ -63,7 +63,25 @@ class GlobalConfiguration
|
||||||
private function addAlbumsToView()
|
private function addAlbumsToView()
|
||||||
{
|
{
|
||||||
$albums = DbHelper::getAlbumsForCurrentUser_NonPaged()->get();
|
$albums = DbHelper::getAlbumsForCurrentUser_NonPaged()->get();
|
||||||
View::share('albums', $albums);
|
View::share('g_albums', $albums);
|
||||||
|
|
||||||
|
if (UserConfig::get('albums_menu_parents_only'))
|
||||||
|
{
|
||||||
|
// Only show top-level albums in the nav bar
|
||||||
|
$navbarAlbums = $albums->filter(function($value, $key)
|
||||||
|
{
|
||||||
|
return is_null($value->parent_album_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If not just showing top-level albums, we can show all
|
||||||
|
$navbarAlbums = $albums;
|
||||||
|
}
|
||||||
|
|
||||||
|
$navbarAlbumsToDisplay = UserConfig::get('albums_menu_number_items');
|
||||||
|
View::share('g_albums_menu', $navbarAlbums->take($navbarAlbumsToDisplay));
|
||||||
|
View::share('g_more_albums', $navbarAlbums->count() - $navbarAlbumsToDisplay);
|
||||||
|
|
||||||
$albumsToUpload = DbHelper::getAlbumsForCurrentUser_NonPaged('upload-photos')->get();
|
$albumsToUpload = DbHelper::getAlbumsForCurrentUser_NonPaged('upload-photos')->get();
|
||||||
View::share('g_albums_upload', $albumsToUpload);
|
View::share('g_albums_upload', $albumsToUpload);
|
||||||
|
|
|
@ -24,10 +24,11 @@ class SaveSettingsRequest extends FormRequest
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'albums_menu_number_items' => 'required|integer|min:1',
|
||||||
'app_name' => 'required|max:255',
|
'app_name' => 'required|max:255',
|
||||||
'date_format' => 'required',
|
'date_format' => 'required',
|
||||||
'smtp_server' => 'required',
|
'smtp_server' => 'required',
|
||||||
'smtp_port' => 'required:integer'
|
'smtp_port' => 'required|integer'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ class StoreAlbumRequest extends FormRequest
|
||||||
case 'POST':
|
case 'POST':
|
||||||
return [
|
return [
|
||||||
'description' => '',
|
'description' => '',
|
||||||
'name' => 'required|unique:albums|max:255',
|
'name' => 'required|album_path_unique|max:255',
|
||||||
'storage_id' => 'required|sometimes'
|
'storage_id' => 'required|sometimes'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class StoreAlbumRequest extends FormRequest
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'description' => 'sometimes',
|
'description' => 'sometimes',
|
||||||
'name' => 'required|sometimes|max:255|unique:albums,name,' . $albumId,
|
'name' => 'required|sometimes|max:255|album_path_unique:' . $albumId,
|
||||||
'storage_id' => 'required|sometimes'
|
'storage_id' => 'required|sometimes'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ class AppServiceProvider extends ServiceProvider
|
||||||
Validator::extend('is_dir', (ValidationHelper::class . '@directoryExists'));
|
Validator::extend('is_dir', (ValidationHelper::class . '@directoryExists'));
|
||||||
Validator::extend('dir_empty', (ValidationHelper::class . '@isDirectoryEmpty'));
|
Validator::extend('dir_empty', (ValidationHelper::class . '@isDirectoryEmpty'));
|
||||||
Validator::extend('is_writeable', (ValidationHelper::class . '@isPathWriteable'));
|
Validator::extend('is_writeable', (ValidationHelper::class . '@isPathWriteable'));
|
||||||
|
Validator::extend('album_path_unique', (ValidationHelper::class . '@albumPathUnique'));
|
||||||
|
|
||||||
// Model observers
|
// Model observers
|
||||||
Album::observe(AlbumObserver::class);
|
Album::observe(AlbumObserver::class);
|
||||||
|
|
112
app/Services/GiteaService.php
Normal file
112
app/Services/GiteaService.php
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
class GiteaService
|
||||||
|
{
|
||||||
|
private $cacheFile = null;
|
||||||
|
private $config = [];
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->config = config('services.gitea');
|
||||||
|
$this->cacheFile = storage_path('app/gitea_cache.txt');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkForLatestRelease()
|
||||||
|
{
|
||||||
|
$cacheData = null;
|
||||||
|
|
||||||
|
if ($this->doesCacheExist())
|
||||||
|
{
|
||||||
|
// Get the etag from the cache
|
||||||
|
$cacheData = $this->getCacheData();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Lookup and store the version information
|
||||||
|
$statusCode = -1;
|
||||||
|
$result = $this->getLatestReleaseFromGitea($statusCode);
|
||||||
|
|
||||||
|
if ($statusCode == 200)
|
||||||
|
{
|
||||||
|
$releases = json_decode($result[1]);
|
||||||
|
|
||||||
|
$latestRelease = null;
|
||||||
|
foreach ($releases as $release)
|
||||||
|
{
|
||||||
|
if (is_null($latestRelease) || version_compare($release->tag_name, $latestRelease->tag_name) > 0)
|
||||||
|
{
|
||||||
|
$latestRelease = $release;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$cacheData = $this->setCacheData($latestRelease);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitHub compatibility
|
||||||
|
$cacheData->html_url = sprintf($this->config['releases_url'], $this->config['repo_owner'], $this->config['repo_name']);
|
||||||
|
|
||||||
|
return $cacheData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function doesCacheExist()
|
||||||
|
{
|
||||||
|
$exists = file_exists($this->cacheFile);
|
||||||
|
|
||||||
|
if ($exists)
|
||||||
|
{
|
||||||
|
// Check modified time on the file
|
||||||
|
$stat = stat($this->cacheFile);
|
||||||
|
|
||||||
|
$diff = time() - $stat['mtime'];
|
||||||
|
if ($diff > $this->config['cache_time_seconds'])
|
||||||
|
{
|
||||||
|
$exists = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCacheData()
|
||||||
|
{
|
||||||
|
return json_decode(file_get_contents($this->cacheFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLatestReleaseFromGitea(&$statusCode)
|
||||||
|
{
|
||||||
|
$httpHeaders = [
|
||||||
|
sprintf('User-Agent: aheathershaw/blue-twilight (v%s)', config('app.version'))
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isset($this->config['api_key']) && !empty($this->config['api_key']))
|
||||||
|
{
|
||||||
|
$httpHeaders[] = sprintf('Authorization: %s', $this->config['api_key']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$apiUrl = sprintf('%s/repos/%s/%s/releases', $this->config['api_url'], $this->config['repo_owner'], $this->config['repo_name']);
|
||||||
|
|
||||||
|
$ch = curl_init($apiUrl);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);
|
||||||
|
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
$result = curl_exec($ch);
|
||||||
|
|
||||||
|
if ($result === false)
|
||||||
|
{
|
||||||
|
throw new \Exception(sprintf('Error from Gitea: %s', curl_error($ch)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
|
||||||
|
return explode("\r\n\r\n", $result, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setCacheData($data)
|
||||||
|
{
|
||||||
|
file_put_contents($this->cacheFile, json_encode(get_object_vars($data)));
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
100
app/Services/GithubService.php
Normal file
100
app/Services/GithubService.php
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
class GithubService
|
||||||
|
{
|
||||||
|
private $cacheFile = null;
|
||||||
|
private $config = [];
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->config = config('services.github');
|
||||||
|
$this->cacheFile = storage_path('app/github_cache.txt');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkForLatestRelease()
|
||||||
|
{
|
||||||
|
$releaseInfo = [];
|
||||||
|
$etag = '';
|
||||||
|
|
||||||
|
if ($this->doesCacheExist())
|
||||||
|
{
|
||||||
|
// Get the etag from the cache
|
||||||
|
$cacheData = $this->getCacheData();
|
||||||
|
$etag = $cacheData->latest_release->etag;
|
||||||
|
$releaseInfo = $cacheData->latest_release->release_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup and store the version information
|
||||||
|
$statusCode = -1;
|
||||||
|
$result = $this->getLatestReleaseFromGithub($etag, $statusCode);
|
||||||
|
|
||||||
|
if ($statusCode == 200)
|
||||||
|
{
|
||||||
|
// Store the etag (in HTTP headers) for future reference
|
||||||
|
$matches = [];
|
||||||
|
$etag = '';
|
||||||
|
if (preg_match('/^etag: "(.+)"/mi', $result[0], $matches))
|
||||||
|
{
|
||||||
|
$etag = $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$releaseInfo = json_decode($result[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($etag))
|
||||||
|
{
|
||||||
|
$this->setCacheData([
|
||||||
|
'latest_release' => [
|
||||||
|
'etag' => $etag,
|
||||||
|
'release_info' => $releaseInfo
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $releaseInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function doesCacheExist()
|
||||||
|
{
|
||||||
|
return file_exists($this->cacheFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCacheData()
|
||||||
|
{
|
||||||
|
return json_decode(file_get_contents($this->cacheFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLatestReleaseFromGithub($etag = '', &$statusCode)
|
||||||
|
{
|
||||||
|
$httpHeaders = [
|
||||||
|
sprintf('User-Agent: pandy06269/blue-twilight (v%s)', config('app.version'))
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!empty($etag))
|
||||||
|
{
|
||||||
|
$httpHeaders[] = sprintf('If-None-Match: "%s"', $etag);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ch = curl_init($this->config['latest_release_url']);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);
|
||||||
|
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
$result = curl_exec($ch);
|
||||||
|
|
||||||
|
if ($result === false)
|
||||||
|
{
|
||||||
|
throw new \Exception(sprintf('Error from Github: %s', curl_error($ch)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
|
||||||
|
return explode("\r\n\r\n", $result, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setCacheData(array $data)
|
||||||
|
{
|
||||||
|
file_put_contents($this->cacheFile, json_encode($data));
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
return [
|
return [
|
||||||
// Version number of Blue Twilight
|
// Version number of Blue Twilight
|
||||||
'version' => '2.1.0-beta.3',
|
'version' => '2.1.2',
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
@ -14,29 +14,15 @@ return [
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'gitea' => [
|
||||||
|
'api_url' => 'https://apps.andysh.uk/api/v1',
|
||||||
|
'cache_time_seconds' => 3600,
|
||||||
|
'releases_url' => 'https://apps.andysh.uk/%s/%s/releases',
|
||||||
|
'repo_name' => 'blue-twilight',
|
||||||
|
'repo_owner' => 'aheathershaw'
|
||||||
|
],
|
||||||
|
|
||||||
'recaptcha' => [
|
'recaptcha' => [
|
||||||
'verify_url' => 'https://www.google.com/recaptcha/api/siteverify'
|
'verify_url' => 'https://www.google.com/recaptcha/api/siteverify'
|
||||||
]
|
]
|
||||||
|
|
||||||
/*'mailgun' => [
|
|
||||||
'domain' => env('MAILGUN_DOMAIN'),
|
|
||||||
'secret' => env('MAILGUN_SECRET'),
|
|
||||||
],
|
|
||||||
|
|
||||||
'ses' => [
|
|
||||||
'key' => env('SES_KEY'),
|
|
||||||
'secret' => env('SES_SECRET'),
|
|
||||||
'region' => 'us-east-1',
|
|
||||||
],
|
|
||||||
|
|
||||||
'sparkpost' => [
|
|
||||||
'secret' => env('SPARKPOST_SECRET'),
|
|
||||||
],
|
|
||||||
|
|
||||||
'stripe' => [
|
|
||||||
'model' => App\User::class,
|
|
||||||
'key' => env('STRIPE_KEY'),
|
|
||||||
'secret' => env('STRIPE_SECRET'),
|
|
||||||
],*/
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
10
public/css/blue-twilight.min.css
vendored
10
public/css/blue-twilight.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -136,6 +136,14 @@ class BlueTwilightInstaller
|
||||||
|
|
||||||
private function fetchComposerSignature()
|
private function fetchComposerSignature()
|
||||||
{
|
{
|
||||||
|
if (!boolval(ini_get('allow_url_fopen')))
|
||||||
|
{
|
||||||
|
$this->echoError('allow_url_fopen is disabled so we cannot use Composer');
|
||||||
|
echo '<br/>';
|
||||||
|
$this->echoError('You will need to install the vendor libraries manually - <a href="https://github.com/pandy06269/blue-twilight/wiki/Install-Vendor-libraries-manually" target="_blank">see this page for more details</a>');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$signatureUrl = 'https://composer.github.io/installer.sig';
|
$signatureUrl = 'https://composer.github.io/installer.sig';
|
||||||
$this->composerSignature = trim(file_get_contents($signatureUrl));
|
$this->composerSignature = trim(file_get_contents($signatureUrl));
|
||||||
if (strlen($this->composerSignature) == 0)
|
if (strlen($this->composerSignature) == 0)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
2
public/js/blue-twilight.min.js
vendored
2
public/js/blue-twilight.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -48,6 +48,9 @@ class BlueTwilightUpdater
|
||||||
cd <?php echo $this->baseDirectory; ?>
|
cd <?php echo $this->baseDirectory; ?>
|
||||||
|
|
||||||
php artisan clear-compiled
|
php artisan clear-compiled
|
||||||
|
php artisan cache:clear
|
||||||
|
php artisan config:clear
|
||||||
|
php artisan view:clear
|
||||||
/path/to/composer.phar install
|
/path/to/composer.phar install
|
||||||
</pre>
|
</pre>
|
||||||
</body>
|
</body>
|
||||||
|
@ -65,6 +68,8 @@ php artisan clear-compiled
|
||||||
<?php
|
<?php
|
||||||
$steps = [
|
$steps = [
|
||||||
['Removing compiled cache', 'removeCompiledCached'],
|
['Removing compiled cache', 'removeCompiledCached'],
|
||||||
|
['Fetching Composer signature', 'fetchComposerSignature'],
|
||||||
|
['Installing Composer', 'installComposer'],
|
||||||
['Updating dependencies using Composer', 'runComposer']
|
['Updating dependencies using Composer', 'runComposer']
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -92,6 +97,31 @@ php artisan clear-compiled
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function fetchComposerSignature()
|
||||||
|
{
|
||||||
|
if (!boolval(ini_get('allow_url_fopen')))
|
||||||
|
{
|
||||||
|
$this->echoError('allow_url_fopen is disabled so we cannot use Composer');
|
||||||
|
echo '<br/>';
|
||||||
|
$this->echoError('You will need to install the vendor libraries manually - <a href="https://github.com/pandy06269/blue-twilight/wiki/Install-Vendor-libraries-manually" target="_blank">see this page for more details</a>');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$signatureUrl = 'https://composer.github.io/installer.sig';
|
||||||
|
$this->composerSignature = trim(file_get_contents($signatureUrl));
|
||||||
|
if (strlen($this->composerSignature) == 0)
|
||||||
|
{
|
||||||
|
$this->echoError(sprintf("Failed downloading the Composer signature from %s", $signatureUrl));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->echoOK($this->composerSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private function removeCompiledCached()
|
private function removeCompiledCached()
|
||||||
{
|
{
|
||||||
ob_start();
|
ob_start();
|
||||||
|
@ -155,6 +185,55 @@ php artisan clear-compiled
|
||||||
echo '</span>' . PHP_EOL;
|
echo '</span>' . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function installComposer()
|
||||||
|
{
|
||||||
|
$rc = -1;
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
system('php -r "copy(\'https://getcomposer.org/installer\', \'composer-setup.php\');"', $rc);
|
||||||
|
$result = ob_get_clean();
|
||||||
|
echo nl2br($result);
|
||||||
|
|
||||||
|
if ($rc != 0)
|
||||||
|
{
|
||||||
|
$this->echoError('Failed to fetch Composer');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
system(sprintf('php -r "if (hash_file(\'SHA384\', \'composer-setup.php\') === \'%s\') { echo \'Installer verified\'; } else { echo \'Installer corrupt\'; unlink(\'composer-setup.php\'); } echo PHP_EOL;"', $this->composerSignature), $rc);
|
||||||
|
$result = ob_get_clean();
|
||||||
|
echo nl2br($result);
|
||||||
|
if ($rc != 0)
|
||||||
|
{
|
||||||
|
$this->echoError('Composer verification failed');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
system('php composer-setup.php', $rc);
|
||||||
|
$result = ob_get_clean();
|
||||||
|
echo nl2br($result);
|
||||||
|
if ($rc != 0)
|
||||||
|
{
|
||||||
|
$this->echoError('Failed to install Composer');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
system('php -r "unlink(\'composer-setup.php\');"', $rc);
|
||||||
|
$result = ob_get_clean();
|
||||||
|
echo nl2br($result);
|
||||||
|
if ($rc != 0)
|
||||||
|
{
|
||||||
|
$this->echoError('Failed to remove Composer setup file');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->echoOK();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private function runComposer()
|
private function runComposer()
|
||||||
{
|
{
|
||||||
ob_start();
|
ob_start();
|
||||||
|
|
16
readme.md
16
readme.md
|
@ -35,4 +35,18 @@ The link to the demo system is: http://demo.showmy.photos. Login with:
|
||||||
|
|
||||||
I'd love to get you up and running. If you need assistance installing the Blue Twilight PHP photo gallery, or would like to me to do it for you, please get in touch using the contact form located at:
|
I'd love to get you up and running. If you need assistance installing the Blue Twilight PHP photo gallery, or would like to me to do it for you, please get in touch using the contact form located at:
|
||||||
|
|
||||||
[www.andyheathershaw.uk/contact](http://www.andyheathershaw.uk/contact)
|
[www.andyheathershaw.uk/contact](https://www.andyheathershaw.uk/contact)
|
||||||
|
|
||||||
|
## More Apps by Andy
|
||||||
|
|
||||||
|
Be sure to check out more apps written by Andy:
|
||||||
|
|
||||||
|
[Simply Remind Me - email & SMS service](https://simplyremind.me)
|
||||||
|
|
||||||
|
A free email & SMS reminder service so you don't forget the important things in life. Supports recurring reminders and repeated events.
|
||||||
|
|
||||||
|
Create a public countdown page to share your holiday or birthday with the world.
|
||||||
|
|
||||||
|
[Solid Tools for Developers - online debugging tools](https://soliddevtools.com)
|
||||||
|
|
||||||
|
A suite of online debugging and diagnostics tools aimed at software developers. Includes a dig tool for DNS lookups, a ping tool to check server availability, a strong password generator and many more.
|
1133
resources/assets/bootstrap/css/bootstrap-grid.css
vendored
1133
resources/assets/bootstrap/css/bootstrap-grid.css
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,39 +1,46 @@
|
||||||
html {
|
/*!
|
||||||
|
* Bootstrap Reboot v4.1.2 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2018 The Bootstrap Authors
|
||||||
|
* Copyright 2011-2018 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||||
|
*/
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
-ms-text-size-adjust: 100%;
|
-ms-text-size-adjust: 100%;
|
||||||
-ms-overflow-style: scrollbar;
|
-ms-overflow-style: scrollbar;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: inherit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@-ms-viewport {
|
@-ms-viewport {
|
||||||
width: device-width;
|
width: device-width;
|
||||||
}
|
}
|
||||||
|
|
||||||
article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {
|
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: normal;
|
font-weight: 400;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: #212529;
|
color: #212529;
|
||||||
|
text-align: left;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
[tabindex="-1"]:focus {
|
[tabindex="-1"]:focus {
|
||||||
outline: none !important;
|
outline: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
|
@ -44,7 +51,7 @@ hr {
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: .5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
@ -56,7 +63,7 @@ abbr[title],
|
||||||
abbr[data-original-title] {
|
abbr[data-original-title] {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
-webkit-text-decoration: underline dotted;
|
-webkit-text-decoration: underline dotted;
|
||||||
text-decoration: underline dotted;
|
text-decoration: underline dotted;
|
||||||
cursor: help;
|
cursor: help;
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +89,7 @@ ul ol {
|
||||||
}
|
}
|
||||||
|
|
||||||
dt {
|
dt {
|
||||||
font-weight: bold;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
dd {
|
dd {
|
||||||
|
@ -140,7 +147,7 @@ a:not([href]):not([tabindex]) {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
|
a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +160,7 @@ pre,
|
||||||
code,
|
code,
|
||||||
kbd,
|
kbd,
|
||||||
samp {
|
samp {
|
||||||
font-family: monospace, monospace;
|
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +168,7 @@ pre {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
-ms-overflow-style: scrollbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
|
@ -174,19 +182,7 @@ img {
|
||||||
|
|
||||||
svg:not(:root) {
|
svg:not(:root) {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
vertical-align: middle;
|
||||||
|
|
||||||
a,
|
|
||||||
area,
|
|
||||||
button,
|
|
||||||
[role="button"],
|
|
||||||
input,
|
|
||||||
label,
|
|
||||||
select,
|
|
||||||
summary,
|
|
||||||
textarea {
|
|
||||||
-ms-touch-action: manipulation;
|
|
||||||
touch-action: manipulation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
|
@ -196,18 +192,22 @@ table {
|
||||||
caption {
|
caption {
|
||||||
padding-top: 0.75rem;
|
padding-top: 0.75rem;
|
||||||
padding-bottom: 0.75rem;
|
padding-bottom: 0.75rem;
|
||||||
color: #868e96;
|
color: #6c757d;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
caption-side: bottom;
|
caption-side: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
text-align: left;
|
text-align: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-bottom: .5rem;
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:focus {
|
button:focus {
|
||||||
|
@ -318,6 +318,7 @@ output {
|
||||||
|
|
||||||
summary {
|
summary {
|
||||||
display: list-item;
|
display: list-item;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
template {
|
template {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,8 @@
|
||||||
html{box-sizing:border-box;font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}*,::after,::before{box-sizing:inherit}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#868e96;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}
|
/*!
|
||||||
|
* Bootstrap Reboot v4.1.2 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2018 The Bootstrap Authors
|
||||||
|
* Copyright 2011-2018 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||||
|
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
File diff suppressed because one or more lines are too long
6024
resources/assets/bootstrap/css/bootstrap.css
vendored
6024
resources/assets/bootstrap/css/bootstrap.css
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6461
resources/assets/bootstrap/js/bootstrap.bundle.js
vendored
Normal file
6461
resources/assets/bootstrap/js/bootstrap.bundle.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
resources/assets/bootstrap/js/bootstrap.bundle.js.map
Normal file
1
resources/assets/bootstrap/js/bootstrap.bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
7
resources/assets/bootstrap/js/bootstrap.bundle.min.js
vendored
Normal file
7
resources/assets/bootstrap/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7367
resources/assets/bootstrap/js/bootstrap.js
vendored
7367
resources/assets/bootstrap/js/bootstrap.js
vendored
File diff suppressed because it is too large
Load Diff
1
resources/assets/bootstrap/js/bootstrap.js.map
Normal file
1
resources/assets/bootstrap/js/bootstrap.js.map
Normal file
File diff suppressed because one or more lines are too long
11
resources/assets/bootstrap/js/bootstrap.min.js
vendored
11
resources/assets/bootstrap/js/bootstrap.min.js
vendored
File diff suppressed because one or more lines are too long
1
resources/assets/bootstrap/js/bootstrap.min.js.map
Normal file
1
resources/assets/bootstrap/js/bootstrap.min.js.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -7,6 +7,11 @@
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.meta-label,
|
||||||
|
.meta-value {
|
||||||
|
vertical-align: middle !important;
|
||||||
|
}
|
||||||
|
|
||||||
.photo .loading {
|
.photo .loading {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -22,4 +27,12 @@
|
||||||
|
|
||||||
.photo .loading img {
|
.photo .loading img {
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-red {
|
||||||
|
color: #ff0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
[v-cloak] {
|
||||||
|
display: none;
|
||||||
}
|
}
|
47
resources/assets/js/admin.js
Normal file
47
resources/assets/js/admin.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* This model is used by admin/about.blade.php, to perform a version check against Github.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function AboutViewModel(urls) {
|
||||||
|
this.el = '#about-app';
|
||||||
|
|
||||||
|
this.data = {
|
||||||
|
can_upgrade: false,
|
||||||
|
is_loading: true,
|
||||||
|
version_body: '',
|
||||||
|
version_date: '',
|
||||||
|
version_name: '',
|
||||||
|
version_url: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
this.computed = {
|
||||||
|
};
|
||||||
|
|
||||||
|
this.methods = {
|
||||||
|
init: function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
$.ajax(
|
||||||
|
urls.latest_release_url,
|
||||||
|
{
|
||||||
|
complete: function() {
|
||||||
|
self.is_loading = false;
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
error: function (xhr, textStatus, errorThrown) {
|
||||||
|
},
|
||||||
|
method: 'GET',
|
||||||
|
success: function (data) {
|
||||||
|
self.version_body = data.body;
|
||||||
|
self.version_date = data.publish_date;
|
||||||
|
self.version_name = data.name;
|
||||||
|
self.version_url = data.url;
|
||||||
|
|
||||||
|
// Set this last so any watchers on this property execute after all version data has been set
|
||||||
|
self.can_upgrade = data.can_upgrade;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -676,6 +676,13 @@ function UploadPhotosViewModel(album_id, queue_token, language, urls) {
|
||||||
// Get the selected files
|
// Get the selected files
|
||||||
var files = fileSelect[0].files;
|
var files = fileSelect[0].files;
|
||||||
|
|
||||||
|
if (files.length === 0)
|
||||||
|
{
|
||||||
|
alert(language.no_file_selected);
|
||||||
|
event.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset statistics
|
// Reset statistics
|
||||||
this.currentStatus = '';
|
this.currentStatus = '';
|
||||||
this.statusMessages = [];
|
this.statusMessages = [];
|
||||||
|
|
|
@ -4,6 +4,23 @@ return [
|
||||||
'create_album_link' => 'Create album',
|
'create_album_link' => 'Create album',
|
||||||
'panel_header' => 'Actions',
|
'panel_header' => 'Actions',
|
||||||
],
|
],
|
||||||
|
'about' => [
|
||||||
|
'current_version' => 'You are running version',
|
||||||
|
'date_published_label' => 'Release date:',
|
||||||
|
'intro' => 'Blue Twilight is an <a href="https://andysh.uk/software/" target="_blank">App by Andy</a>.',
|
||||||
|
'intro_2' => 'It is made with <i class="fa fa-heart text-red"></i> in the UK by software developer <a href="https://andysh.uk" target="_blank">Andy Heathershaw</a>.',
|
||||||
|
'latest_version_loading' => 'Checking for the latest release...',
|
||||||
|
'licence_header' => 'Licence',
|
||||||
|
'links_header' => 'Useful Links',
|
||||||
|
'project_website_link' => 'Project Website',
|
||||||
|
'title' => 'About Blue Twilight',
|
||||||
|
'up_to_date' => 'Good job - your installation of Blue Twilight is up-to-date!',
|
||||||
|
'update_available' => 'An update is available to Blue Twilight.',
|
||||||
|
'user_guide_link' => 'User Guide',
|
||||||
|
'version_label' => 'Version',
|
||||||
|
'versions_header' => 'About & Version',
|
||||||
|
'website_link' => 'Main Website'
|
||||||
|
],
|
||||||
'album_appearance_heading' => 'Appearance',
|
'album_appearance_heading' => 'Appearance',
|
||||||
'album_appearance_intro' => 'The settings shown below control how this album appears to visitors in the gallery.',
|
'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_heading' => 'Album information',
|
||||||
|
@ -34,6 +51,7 @@ return [
|
||||||
'others' => ' others'
|
'others' => ' others'
|
||||||
],
|
],
|
||||||
'analyse_photos_failed' => 'The following items could not be analysed and were removed:',
|
'analyse_photos_failed' => 'The following items could not be analysed and were removed:',
|
||||||
|
'analyse_photos_failed_metadata' => 'The following items could not be analysed:',
|
||||||
'anonymous_users' => 'Anonymous (not logged in)',
|
'anonymous_users' => 'Anonymous (not logged in)',
|
||||||
'bulk_photos_changed' => ':number photo was updated successfully.|:number photos were updated successfully.',
|
'bulk_photos_changed' => ':number photo was updated successfully.|:number photos were updated successfully.',
|
||||||
'cannot_delete_own_user_account' => 'It is not possible to delete your own user account. Please ask another administrator to delete it for you.',
|
'cannot_delete_own_user_account' => 'It is not possible to delete your own user account. Please ask another administrator to delete it for you.',
|
||||||
|
@ -61,6 +79,7 @@ return [
|
||||||
'default_storage_legend' => 'Default storage location for new albums.',
|
'default_storage_legend' => 'Default storage location for new albums.',
|
||||||
'delete_album' => 'Delete album :name',
|
'delete_album' => 'Delete album :name',
|
||||||
'delete_album_confirm' => 'Are you sure you want to permanently delete this album and all its contents?',
|
'delete_album_confirm' => 'Are you sure you want to permanently delete this album and all its contents?',
|
||||||
|
'delete_album_failed_children' => 'The album ":album" contains child albums and cannot be deleted. Please delete or move the child albums first.',
|
||||||
'delete_album_success_message' => 'The album ":album" was deleted successfully.',
|
'delete_album_success_message' => 'The album ":album" was deleted successfully.',
|
||||||
'delete_album_warning' => 'This is a permanent action that cannot be undone!',
|
'delete_album_warning' => 'This is a permanent action that cannot be undone!',
|
||||||
'delete_bulk_photos_message' => 'Are you sure you want to delete the selected photos? This action cannot be undone!',
|
'delete_bulk_photos_message' => 'Are you sure you want to delete the selected photos? This action cannot be undone!',
|
||||||
|
@ -110,6 +129,7 @@ return [
|
||||||
'is_uploading' => 'Uploading in progress...',
|
'is_uploading' => 'Uploading in progress...',
|
||||||
'labels_intro' => 'Your labels are displayed below. The number in brackets indicates the number of photos linked to that label. Click a label to delete it.',
|
'labels_intro' => 'Your labels are displayed below. The number in brackets indicates the number of photos linked to that label. Click a label to delete it.',
|
||||||
'legend' => 'Legend/Key',
|
'legend' => 'Legend/Key',
|
||||||
|
'list_albums' => 'Go to your albums',
|
||||||
'list_albums_intro' => 'Albums contain collections of individual photographs in the same way as a physical photo album or memory book.',
|
'list_albums_intro' => 'Albums contain collections of individual photographs in the same way as a physical photo album or memory book.',
|
||||||
'list_albums_title' => 'Albums',
|
'list_albums_title' => 'Albums',
|
||||||
'list_groups_intro' => 'Organise your users into categories or types by using groups. You can assign permissions on albums to groups of users to make administration and management easier.',
|
'list_groups_intro' => 'Organise your users into categories or types by using groups. You can assign permissions on albums to groups of users to make administration and management easier.',
|
||||||
|
@ -123,8 +143,10 @@ return [
|
||||||
'manage_widget' => [
|
'manage_widget' => [
|
||||||
'panel_header' => 'Manage'
|
'panel_header' => 'Manage'
|
||||||
],
|
],
|
||||||
|
'metadata_no_albums_text' => 'You have no photo albums yet or all your albums are empty. Click the button below to list your albums or create a new album.',
|
||||||
|
'metadata_no_albums_title' => 'No Albums or Photos',
|
||||||
'metadata_upgrade' => [
|
'metadata_upgrade' => [
|
||||||
'can_be_upgraded' => 'Metadata can be updated (version :version_from --> :version_to)',
|
'can_be_upgraded' => 'Metadata can be updated (version :version_from » :version_to)',
|
||||||
'confirm' => 'Are you sure you want to update the metadata of the :name album?',
|
'confirm' => 'Are you sure you want to update the metadata of the :name album?',
|
||||||
'intro' => 'Blue Twilight analyses your photos to capture metadata such as the camera and location used to capture the photo. Sometimes we capture more metadata than we have done previously, which requires your original photos to be re-analysed.',
|
'intro' => 'Blue Twilight analyses your photos to capture metadata such as the camera and location used to capture the photo. Sometimes we capture more metadata than we have done previously, which requires your original photos to be re-analysed.',
|
||||||
'intro_2' => 'This page shows you which of your albums contain photos that need to be re-analysed to get the latest metadata information.',
|
'intro_2' => 'This page shows you which of your albums contain photos that need to be re-analysed to get the latest metadata information.',
|
||||||
|
@ -177,6 +199,9 @@ return [
|
||||||
'security_text' => 'You can assign permissions on this album to either groups (recommended) or directly to users.',
|
'security_text' => 'You can assign permissions on this album to either groups (recommended) or directly to users.',
|
||||||
'security_users_heading' => 'User Permissions',
|
'security_users_heading' => 'User Permissions',
|
||||||
'settings' => [
|
'settings' => [
|
||||||
|
'albums_menu_heading' => 'Albums Navigation Menu',
|
||||||
|
'albums_menu_number_items' => 'Number of albums to display:',
|
||||||
|
'albums_menu_parents_only' => 'Only show top-level albums',
|
||||||
'analytics_cookie_link_1' => 'Information about the EU Cookie Law directive',
|
'analytics_cookie_link_1' => 'Information about the EU Cookie Law directive',
|
||||||
'analytics_cookie_link_2' => 'Cookie Consent by Insites',
|
'analytics_cookie_link_2' => 'Cookie Consent by Insites',
|
||||||
'analytics_cookie_warning_1' => 'If you are based in Europe and you enable visitor tracking, you will need to comply with the EU Cookie Law. The easiest way to do so is using a script like Cookie Consent by Insites.',
|
'analytics_cookie_warning_1' => 'If you are based in Europe and you enable visitor tracking, you will need to comply with the EU Cookie Law. The easiest way to do so is using a script like Cookie Consent by Insites.',
|
||||||
|
@ -234,6 +259,7 @@ return [
|
||||||
],
|
],
|
||||||
'title' => 'Gallery Admin',
|
'title' => 'Gallery Admin',
|
||||||
'upload_bulk_heading' => 'Upload a zip archive',
|
'upload_bulk_heading' => 'Upload a zip archive',
|
||||||
|
'upload_bulk_no_file' => 'No archive was uploaded. Please select a file to upload.',
|
||||||
'upload_bulk_text' => 'You can use the form below to upload a zip archive that contains your photographs. Any valid image files in the zip archive will be imported. Common hidden folders used by operating systems will be ignored.',
|
'upload_bulk_text' => 'You can use the form below to upload a zip archive that contains your photographs. Any valid image files in the zip archive will be imported. Common hidden folders used by operating systems will be ignored.',
|
||||||
'upload_bulk_text2' => 'Your web server is configured to allow files up to :max_upload_size to be uploaded.',
|
'upload_bulk_text2' => 'Your web server is configured to allow files up to :max_upload_size to be uploaded.',
|
||||||
'upload_disabled_heading' => 'Uploading is not supported on this system.',
|
'upload_disabled_heading' => 'Uploading is not supported on this system.',
|
||||||
|
@ -244,6 +270,7 @@ return [
|
||||||
'upload_file_status_failed' => ':file_name failed to upload',
|
'upload_file_status_failed' => ':file_name failed to upload',
|
||||||
'upload_file_status_progress' => ':current of :total files completed',
|
'upload_file_status_progress' => ':current of :total files completed',
|
||||||
'upload_file_status_success' => ':file_name uploaded successfully',
|
'upload_file_status_success' => ':file_name uploaded successfully',
|
||||||
|
'upload_no_file' => 'Please select a photo file to upload.',
|
||||||
'upload_single_file_heading' => 'Upload photos individually',
|
'upload_single_file_heading' => 'Upload photos individually',
|
||||||
'upload_single_file_text' => 'You can use the form below to upload individual files. To upload multiple files at once, hold down CTRL in the file browser.',
|
'upload_single_file_text' => 'You can use the form below to upload individual files. To upload multiple files at once, hold down CTRL in the file browser.',
|
||||||
'upload_single_file_text2' => 'Your web server is configured to allow files up to :file_size. If you browser does not support HTML 5 (most modern browsers do), the combined size of all selected files must be less than :max_upload_size.',
|
'upload_single_file_text2' => 'Your web server is configured to allow files up to :file_size. If you browser does not support HTML 5 (most modern browsers do), the combined size of all selected files must be less than :max_upload_size.',
|
||||||
|
|
|
@ -13,6 +13,7 @@ return [
|
||||||
'bulk_edit_photos_label' => 'Bulk edit selected photos:',
|
'bulk_edit_photos_label' => 'Bulk edit selected photos:',
|
||||||
'bulk_edit_photos_placeholder' => 'Select an action',
|
'bulk_edit_photos_placeholder' => 'Select an action',
|
||||||
'cancel_action' => 'Cancel',
|
'cancel_action' => 'Cancel',
|
||||||
|
'close_action' => 'Close',
|
||||||
'continue_action' => 'Continue',
|
'continue_action' => 'Continue',
|
||||||
'create_action' => 'Create',
|
'create_action' => 'Create',
|
||||||
'create_album_label' => 'Create a new album:',
|
'create_album_label' => 'Create a new album:',
|
||||||
|
@ -20,6 +21,7 @@ return [
|
||||||
'default_storage_label' => 'Use as the default storage location for new albums',
|
'default_storage_label' => 'Use as the default storage location for new albums',
|
||||||
'delete_action' => 'Delete',
|
'delete_action' => 'Delete',
|
||||||
'description_label' => 'Description:',
|
'description_label' => 'Description:',
|
||||||
|
'download_action' => 'Download',
|
||||||
'edit_action' => 'Edit',
|
'edit_action' => 'Edit',
|
||||||
'email_label' => 'E-mail address:',
|
'email_label' => 'E-mail address:',
|
||||||
'labels_label' => 'Labels:',
|
'labels_label' => 'Labels:',
|
||||||
|
|
|
@ -12,6 +12,7 @@ return [
|
||||||
'camera_make' => 'Camera make:',
|
'camera_make' => 'Camera make:',
|
||||||
'camera_model' => 'Camera model:',
|
'camera_model' => 'Camera model:',
|
||||||
'camera_software' => 'Camera software:',
|
'camera_software' => 'Camera software:',
|
||||||
|
'child_albums' => 'more album|more albums',
|
||||||
'date_taken' => 'Date taken:',
|
'date_taken' => 'Date taken:',
|
||||||
'file_name' => 'File name:',
|
'file_name' => 'File name:',
|
||||||
'focal_length' => 'Focal length:',
|
'focal_length' => 'Focal length:',
|
||||||
|
@ -29,9 +30,11 @@ return [
|
||||||
'next_button' => 'Next Photo »',
|
'next_button' => 'Next Photo »',
|
||||||
'open_album_link' => 'Open Album',
|
'open_album_link' => 'Open Album',
|
||||||
'other_albums_description' => 'You may also be interested in the following albums.',
|
'other_albums_description' => 'You may also be interested in the following albums.',
|
||||||
|
'other_albums_description_empty' => 'The <b>:album_name</b> album does not contain any photos - however you may also be interested in the following albums.',
|
||||||
'other_albums_heading' => 'More Albums in :album_name',
|
'other_albums_heading' => 'More Albums in :album_name',
|
||||||
'photos' => 'photo|photos',
|
'photos' => 'photo|photos',
|
||||||
'previous_button' => '« Previous Photo',
|
'previous_button' => '« Previous Photo',
|
||||||
|
'show_more_albums' => '... and :count other|... and :count others',
|
||||||
'show_more_labels' => '... and :count other|... and :count others',
|
'show_more_labels' => '... and :count other|... and :count others',
|
||||||
'show_raw_exif_data' => 'Show all EXIF data',
|
'show_raw_exif_data' => 'Show all EXIF data',
|
||||||
'shutter_speed' => 'Shutter speed:',
|
'shutter_speed' => 'Shutter speed:',
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
return [
|
return [
|
||||||
'breadcrumb' => [
|
'breadcrumb' => [
|
||||||
|
'about' => 'About',
|
||||||
'admin' => 'Admin',
|
'admin' => 'Admin',
|
||||||
'albums' => 'Albums',
|
'albums' => 'Albums',
|
||||||
'create_album' => 'Create album',
|
'create_album' => 'Create album',
|
||||||
|
|
|
@ -113,6 +113,7 @@ return [
|
||||||
'attributes' => [],
|
'attributes' => [],
|
||||||
|
|
||||||
// Added by Andy H. for custom validators
|
// Added by Andy H. for custom validators
|
||||||
|
'album_path_unique' => 'An album with the same name already exists.',
|
||||||
'dir_empty' => 'The path must be an empty folder.',
|
'dir_empty' => 'The path must be an empty folder.',
|
||||||
'is_dir' => 'The folder must be a valid directory.',
|
'is_dir' => 'The folder must be a valid directory.',
|
||||||
'is_writeable' => 'Unable to write to this folder - please check permissions.',
|
'is_writeable' => 'Unable to write to this folder - please check permissions.',
|
||||||
|
|
115
resources/views/themes/base/admin/about.blade.php
Normal file
115
resources/views/themes/base/admin/about.blade.php
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
@extends(Theme::viewName('layout'))
|
||||||
|
@section('title', trans('admin.about.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"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
||||||
|
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.about')</li>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h1>@lang('admin.about.title')</h1>
|
||||||
|
<p>
|
||||||
|
@lang('admin.about.intro')<br/>
|
||||||
|
@lang('admin.about.intro_2')
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="nav nav-tabs mt-5">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" data-toggle="tab" href="#versions-tabpanel" role="tab">@lang('admin.about.versions_header')</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" data-toggle="tab" href="#licence-tabpanel" role="tab">@lang('admin.about.licence_header')</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">@lang('admin.about.links_header')</a>
|
||||||
|
<div class="dropdown-menu">
|
||||||
|
<a class="dropdown-item" href="https://andysh.uk/software/blue-twilight-php-photo-gallery/" target="_blank">@lang('admin.about.website_link')</a>
|
||||||
|
<a class="dropdown-item" href="https://andysh.uk/software/blue-twilight-php-photo-gallery/manual/" target="_blank">@lang('admin.about.user_guide_link')</a>
|
||||||
|
<a class="dropdown-item" href="https://apps.andysh.uk/aheathershaw/blue-twilight" target="_blank">@lang('admin.about.project_website_link')</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane active" id="versions-tabpanel" role="tabpanel">
|
||||||
|
<div class="row" id="about-app">
|
||||||
|
<div class="col-md-6 text-center">
|
||||||
|
<p>@lang('admin.about.current_version')</p>
|
||||||
|
<p class="m-0" style="font-size: 2.5rem;">{{ $current_version }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 text-center pt-2">
|
||||||
|
<div v-if="is_loading">
|
||||||
|
<p><img src="{{ asset('ripple.svg') }}"></p>
|
||||||
|
<p class="m-0">@lang('admin.about.latest_version_loading')</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p v-cloak v-if="!is_loading && !can_upgrade" class="text-success">
|
||||||
|
<i class="fa fa-check fa-fw"></i> @lang('admin.about.up_to_date')
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div v-cloak v-if="!is_loading && can_upgrade" class="text-danger">
|
||||||
|
<p><i class="fa fa-warning fa-fw"></i> @lang('admin.about.update_available')</p>
|
||||||
|
<p class="mt-0" style="font-size: 2.5rem;" v-text="version_name"></p>
|
||||||
|
<p><a class="btn btn-secondary text-white" href="#version-update-modal" data-toggle="modal">View details</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal" id="version-update-modal">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">@lang('admin.about.version_label') <span v-text="version_name"></span></h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<p class="m-0"><b>@lang('admin.about.update_available')</b></p>
|
||||||
|
<p class="m-0">@lang('admin.about.date_published_label') <span v-text="version_date"></span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p v-html="version_body"></p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a class="btn btn-primary" v-bind:href="version_url">@lang('forms.download_action')</a>
|
||||||
|
<a class="btn btn-secondary" href="#" data-dismiss="modal">@lang('forms.cancel_action')</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane" id="licence-tabpanel" role="tabpanel">
|
||||||
|
<textarea class="form-control" rows="20" style="border: 0;">
|
||||||
|
{!! $licence_text !!}
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function()
|
||||||
|
{
|
||||||
|
var viewModel = new AboutViewModel({
|
||||||
|
latest_release_url: '{{ route('admin.aboutLatestRelease') }}'
|
||||||
|
});
|
||||||
|
|
||||||
|
var app = new Vue(viewModel);
|
||||||
|
app.$watch('can_upgrade', function(value)
|
||||||
|
{
|
||||||
|
$('#version-update-modal').modal();
|
||||||
|
});
|
||||||
|
app.init();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
|
@ -65,7 +65,7 @@
|
||||||
<p>Your analysis has completed.</p>
|
<p>Your analysis has completed.</p>
|
||||||
|
|
||||||
<div v-if="numberFailed > 0">
|
<div v-if="numberFailed > 0">
|
||||||
<p class="text-danger">@lang('admin.analyse_photos_failed')</p>
|
<p class="text-danger">@lang('admin.analyse_photos_failed_metadata')</p>
|
||||||
<ul class="text-danger" v-for="image in imagesFailed">
|
<ul class="text-danger" v-for="image in imagesFailed">
|
||||||
<li><span v-text="image.name"></span>: <span v-text="image.reason"></span></li>
|
<li><span v-text="image.name"></span>: <span v-text="image.reason"></span></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -63,11 +63,10 @@
|
||||||
@include(Theme::viewName('partials.admin_storages_rackspace_options'))
|
@include(Theme::viewName('partials.admin_storages_rackspace_options'))
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label class="custom-control custom-checkbox">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="custom-control-input" name="is_default"@if (old('is_default')) checked="checked"@endif>
|
<input type="checkbox" class="form-check-input" id="is-default" name="is_default"@if (old('is_default')) checked="checked"@endif>
|
||||||
<span class="custom-control-indicator"></span>
|
<label class="form-check-label" for="is-default">@lang('forms.default_storage_label')</label>
|
||||||
<span class="custom-control-description">@lang('forms.default_storage_label')</span>
|
</div>
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<a href="{{ route('storage.index') }}" class="btn btn-link">@lang('forms.cancel_action')</a>
|
<a href="{{ route('storage.index') }}" class="btn btn-link">@lang('forms.cancel_action')</a>
|
||||||
|
|
|
@ -75,12 +75,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="is_admin" name="is_admin" @if (old('is_admin'))checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="is_admin" @if (old('is_admin'))checked="checked"@endif>
|
<label class="form-check-label" for="is_admin">@lang('forms.admin_user_label')</label>
|
||||||
<span class="custom-control-indicator"></span>
|
|
||||||
<span class="custom-control-description">@lang('forms.admin_user_label')</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||||
<li class="breadcrumb-item"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
<li class="breadcrumb-item"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
||||||
<li class="breadcrumb-item"><a href="{{ route('albums.index') }}">@lang('navigation.breadcrumb.albums')</a></li>
|
<li class="breadcrumb-item"><a href="{{ route('albums.index') }}">@lang('navigation.breadcrumb.albums')</a></li>
|
||||||
<li class="breadcrumb-item"><a href="{{ route('albums.show', ['id' => $album->id]) }}">{{ $album->name }}</a></li>
|
@include(Theme::viewName('partials.admin_album_breadcrumb'), ['show_current_link' => true])
|
||||||
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.delete_album')</li>
|
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.delete_album')</li>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||||
<li class="breadcrumb-item"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
<li class="breadcrumb-item"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
||||||
<li class="breadcrumb-item"><a href="{{ route('albums.index') }}">@lang('navigation.breadcrumb.albums')</a></li>
|
<li class="breadcrumb-item"><a href="{{ route('albums.index') }}">@lang('navigation.breadcrumb.albums')</a></li>
|
||||||
<li class="breadcrumb-item"><a href="{{ route('albums.show', ['id' => $album->id]) }}">{{ $album->name }}</a></li>
|
@include(Theme::viewName('partials.admin_album_breadcrumb'), ['show_current_link' => true])
|
||||||
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.edit_album')</li>
|
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.edit_album')</li>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
|
|
@ -31,20 +31,14 @@
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="is-default" name="is_default"@if (old('is_default', $storage->is_default)) checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="is_default"@if (old('is_default', $storage->is_default)) checked="checked"@endif>
|
<label class="form-check-label" for="is-default">@lang('forms.default_storage_label')</label>
|
||||||
<span class="custom-control-indicator"></span>
|
|
||||||
<span class="custom-control-description">@lang('forms.default_storage_label')</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="is-active" name="is_active"@if (old('is_active', $storage->is_active)) checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="is_active"@if (old('is_active', $storage->is_active)) checked="checked"@endif>
|
<label class="form-check-label" for="is-active">@lang('forms.storage_active_label')</label>
|
||||||
<span class="custom-control-indicator"></span>
|
|
||||||
<span class="custom-control-description">@lang('forms.storage_active_label')</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($storage->source == 'LocalFilesystemSource')
|
@if ($storage->source == 'LocalFilesystemSource')
|
||||||
|
|
|
@ -87,21 +87,15 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="is-admin" name="is_admin"@if (old('is_admin', $user->is_admin)) checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="is_admin"@if (old('is_admin', $user->is_admin)) checked="checked"@endif>
|
<label class="form-check-label" for="is-admin">@lang('forms.admin_user_label')</label>
|
||||||
<span class="custom-control-indicator"></span>
|
|
||||||
<span class="custom-control-description">@lang('forms.admin_user_label')</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (!$user->is_activated)
|
@if (!$user->is_activated)
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="is-activated" name="is_activated"@if (old('is_activated', $user->is_activated)) checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="is_activated"@if (old('is_activated', $user->is_activated)) checked="checked"@endif>
|
<label class="form-check-label" for="is-activated">@lang('forms.activate_user_label')</label>
|
||||||
<span class="custom-control-indicator"></span>
|
|
||||||
<span class="custom-control-description">@lang('forms.activate_user_label')</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -112,12 +106,9 @@
|
||||||
<p style="margin-bottom: 20px;">@lang('admin.user_groups_list_select', ['name' => $user->name])</p>
|
<p style="margin-bottom: 20px;">@lang('admin.user_groups_list_select', ['name' => $user->name])</p>
|
||||||
|
|
||||||
@foreach ($groups as $group)
|
@foreach ($groups as $group)
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="user-group-{{ $group->id }}" name="user_group_id[]" value="{{ $group->id }}" @if (in_array($group->id, $users_groups)) checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="user_group_id[]" value="{{ $group->id }}" @if (in_array($group->id, $users_groups)) checked="checked"@endif>
|
<label class="form-check-label" for="user-group-{{ $group->id }}">{{ $group->name }}</label>
|
||||||
<span class="custom-control-indicator"></span>
|
|
||||||
<span class="custom-control-description">{{ $group->name }}</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@else
|
@else
|
||||||
|
|
|
@ -16,18 +16,18 @@
|
||||||
<i class="fa fa-fw fa-info"></i> @lang('admin.metadata_upgrade.intro')
|
<i class="fa fa-fw fa-info"></i> @lang('admin.metadata_upgrade.intro')
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>@lang('admin.metadata_upgrade.intro_2')</p>
|
|
||||||
<p class="mb-4">@lang('admin.metadata_upgrade.intro_3')</p>
|
|
||||||
|
|
||||||
@if (count($albums) == 0)
|
@if (count($albums) == 0)
|
||||||
<div class="text-center">
|
<div class="text-center mt-5">
|
||||||
<h4 class="text-danger"><b>@lang('admin.no_albums_title')</b></h4>
|
<h4 class="text-danger"><b>@lang('admin.metadata_no_albums_title')</b></h4>
|
||||||
<p>@lang('admin.no_albums_text')</p>
|
<p>@lang('admin.metadata_no_albums_text')</p>
|
||||||
<p style="margin-top: 40px;">
|
<p style="margin-top: 40px;">
|
||||||
<a href="{{ route('albums.create') }}" class="btn btn-lg btn-success"><i class="fa fa-fw fa-plus"></i> @lang('admin.create_album')</a>
|
<a href="{{ route('albums.index') }}" class="btn btn-lg btn-success"><i class="fa fa-fw fa-plus"></i> @lang('admin.list_albums')</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
|
<p>@lang('admin.metadata_upgrade.intro_2')</p>
|
||||||
|
<p class="mb-4">@lang('admin.metadata_upgrade.intro_3')</p>
|
||||||
|
|
||||||
<table class="table table-hover table-striped">
|
<table class="table table-hover table-striped">
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach ($albums as $album)
|
@foreach ($albums as $album)
|
||||||
|
|
|
@ -77,6 +77,29 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>@lang('admin.settings.albums_menu_heading')</legend>
|
||||||
|
|
||||||
|
<div class="form-check mb-3">
|
||||||
|
<input type="checkbox" class="form-check-input" id="albums-menu-parents-only" name="albums_menu_parents_only" @if (old('albums_menu_parents_only', UserConfig::get('albums_menu_parents_only')))checked="checked"@endif>
|
||||||
|
<label class="form-check-label" for="albums-menu-parents-only">
|
||||||
|
<strong>@lang('admin.settings.albums_menu_parents_only')</strong>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-control-label" for="albums-menu-number-items">@lang('admin.settings.albums_menu_number_items')</label>
|
||||||
|
<input type="number" class="form-control{{ $errors->has('albums_menu_number_items') ? ' is-invalid' : '' }}" id="albums-menu-number-items" name="albums_menu_number_items" value="{{ old('albums_menu_number_items', $config['albums_menu_number_items']) }}" style="max-width: 100px;">
|
||||||
|
|
||||||
|
@if ($errors->has('albums_menu_number_items'))
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
<strong>{{ $errors->first('albums_menu_number_items') }}</strong>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@ -84,11 +107,10 @@
|
||||||
<p>To help spread the word about Blue Twilight, I'd really appreciate it if you left the "Powered by" notice in your gallery's footer.</p>
|
<p>To help spread the word about Blue Twilight, I'd really appreciate it if you left the "Powered by" notice in your gallery's footer.</p>
|
||||||
<p>If you do want to remove it, however, I understand - just check the box below.</p>
|
<p>If you do want to remove it, however, I understand - just check the box below.</p>
|
||||||
|
|
||||||
<div class="form-check" style="margin-top: 20px;">
|
<div class="form-check mt-2">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="remove-copyright" name="remove_copyright" @if (old('remove_copyright', UserConfig::get('remove_copyright')))checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="remove_copyright" @if (old('remove_copyright', UserConfig::get('remove_copyright')))checked="checked"@endif>
|
<label class="form-check-label" for="remove-copyright">
|
||||||
<span class="custom-control-indicator"></span>
|
<strong>Remove "Powered by" notice from the public gallery</strong>
|
||||||
<span class="custom-control-description"><strong>Remove "Powered by" notice from the public gallery</strong></span>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
@ -166,11 +188,10 @@
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="smtp-encryption" name="smtp_encryption" @if (UserConfig::get('smtp_encryption'))checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="smtp_encryption" @if (UserConfig::get('smtp_encryption'))checked="checked"@endif>
|
<label class="form-check-label" for="smtp-encryption">
|
||||||
<span class="custom-control-indicator"></span>
|
<strong>Requires encrypted connection</strong>
|
||||||
<span class="custom-control-description"><strong>Requires encrypted connection</strong></span>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -193,30 +214,27 @@
|
||||||
|
|
||||||
{{-- Security --}}
|
{{-- Security --}}
|
||||||
<div role="tabpanel" class="tab-pane" id="security-tab">
|
<div role="tabpanel" class="tab-pane" id="security-tab">
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="allow-self-registration" name="allow_self_registration" @if (old('allow_self_registration', UserConfig::get('allow_self_registration')))checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="allow_self_registration" @if (old('allow_self_registration', UserConfig::get('allow_self_registration')))checked="checked"@endif>
|
<label class="form-check-label" for="allow-self-registration">
|
||||||
<span class="custom-control-indicator"></span>
|
|
||||||
<span class="custom-control-description"><strong>@lang('admin.settings.security_allow_self_registration')</strong><br/>
|
<span class="custom-control-description"><strong>@lang('admin.settings.security_allow_self_registration')</strong><br/>
|
||||||
@lang('admin.settings.security_allow_self_registration_description')</span>
|
@lang('admin.settings.security_allow_self_registration_description')</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin-top: 20px;">
|
<div class="form-check mt-3">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="require-email-verification" name="require_email_verification" @if (old('require_email_verification', UserConfig::get('require_email_verification')))checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="require_email_verification" @if (old('require_email_verification', UserConfig::get('require_email_verification')))checked="checked"@endif>
|
<label class="form-check-label" for="require-email-verification">
|
||||||
<span class="custom-control-indicator"></span>
|
<strong>Require e-mail verification for self-registered accounts</strong><br/>
|
||||||
<span class="custom-control-description"><strong>Require e-mail verification for self-registered accounts</strong><br/>
|
<span class="text-danger">It is strongly recommended to enable this option.</span>
|
||||||
<span class="text-danger">It is strongly recommended to enable this option.</span></span>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin-top: 20px;">
|
<div class="form-check mt-3">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="recaptcha-enabled-registration" name="recaptcha_enabled_registration" @if (old('recaptcha_enabled_registration', UserConfig::get('recaptcha_enabled_registration')))checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="recaptcha_enabled_registration" @if (old('recaptcha_enabled_registration', UserConfig::get('recaptcha_enabled_registration')))checked="checked"@endif>
|
<label class="form-check-label" for="recaptcha-enabled-registration">
|
||||||
<span class="custom-control-indicator"></span>
|
<strong>Enable <a href="https://www.google.com/recaptcha" target="_blank">reCAPTCHA</a> for self-registrations</strong><br/>
|
||||||
<span class="custom-control-description"><strong>Enable <a href="https://www.google.com/recaptcha" target="_blank">reCAPTCHA</a> for self-registrations</strong><br/>
|
<span class="text-danger">It is strongly recommended to enable this option.</span>
|
||||||
<span class="text-danger">It is strongly recommended to enable this option.</span></span>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -249,19 +267,17 @@
|
||||||
<fieldset style="margin-top: 20px;">
|
<fieldset style="margin-top: 20px;">
|
||||||
<legend>@lang('admin.settings_image_protection')</legend>
|
<legend>@lang('admin.settings_image_protection')</legend>
|
||||||
|
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="restrict-original-download" name="restrict_original_download" @if (old('restrict_original_download', UserConfig::get('restrict_original_download')))checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="restrict_original_download" @if (old('restrict_original_download', UserConfig::get('restrict_original_download')))checked="checked"@endif>
|
<label class="form-check-label" for="restrict-original-download">
|
||||||
<span class="custom-control-indicator"></span>
|
<strong>@lang('forms.settings_restrict_originals_download')</strong><br/>
|
||||||
<span class="custom-control-description"><strong>@lang('forms.settings_restrict_originals_download')</strong><br/>
|
@lang('forms.settings_restrict_originals_download_help')
|
||||||
@lang('forms.settings_restrict_originals_download_help')</span>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin-top: 20px;">
|
<div class="form-check mt-3">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="hotlink-protection" name="hotlink_protection" @if (old('hotlink_protection', UserConfig::get('hotlink_protection')))checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="hotlink_protection" @if (old('hotlink_protection', UserConfig::get('hotlink_protection')))checked="checked"@endif>
|
<label class="form-check-label" for="hotlink-protection">
|
||||||
<span class="custom-control-indicator"></span>
|
|
||||||
<span class="custom-control-description"><strong>@lang('forms.settings_hotlink_protection')</strong><br/>
|
<span class="custom-control-description"><strong>@lang('forms.settings_hotlink_protection')</strong><br/>
|
||||||
@lang('forms.settings_hotlink_protection_help')</span>
|
@lang('forms.settings_hotlink_protection_help')</span>
|
||||||
</label>
|
</label>
|
||||||
|
@ -280,12 +296,11 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="form-check mt-4">
|
||||||
<label class="custom-control custom-checkbox">
|
<input type="checkbox" class="form-check-input" id="enable-visitor-hits" name="enable_visitor_hits" @if (old('enable_visitor_hits', UserConfig::get('enable_visitor_hits')))checked="checked"@endif>
|
||||||
<input type="checkbox" class="custom-control-input" name="enable_visitor_hits" @if (old('enable_visitor_hits', UserConfig::get('enable_visitor_hits')))checked="checked"@endif>
|
<label class="form-check-label" for="enable-visitor-hits">
|
||||||
<span class="custom-control-indicator"></span>
|
<strong>@lang('admin.settings.analytics_enable_visitor_hits')</strong><br/>
|
||||||
<span class="custom-control-description"><strong>@lang('admin.settings.analytics_enable_visitor_hits')</strong><br/>
|
@lang('admin.settings.analytics_enable_visitor_hits_description')
|
||||||
@lang('admin.settings.analytics_enable_visitor_hits_description')</span>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,20 @@
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||||
<li class="breadcrumb-item"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
<li class="breadcrumb-item"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
||||||
<li class="breadcrumb-item"><a href="{{ route('albums.index') }}">@lang('navigation.breadcrumb.albums')</a></li>
|
<li class="breadcrumb-item"><a href="{{ route('albums.index') }}">@lang('navigation.breadcrumb.albums')</a></li>
|
||||||
<li class="breadcrumb-item active">{{ $album->name }}</li>
|
@foreach ($album->albumParentTree() as $parentAlbum)
|
||||||
|
@if ($parentAlbum->id == $album->id)
|
||||||
|
<li class="breadcrumb-item active">{{ $album->name }}</li>
|
||||||
|
@else
|
||||||
|
<li class="breadcrumb-item"><a href="{{ route('albums.show', ['id' => $parentAlbum->id]) }}">{{ $parentAlbum->name }}</a></li>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a class="pull-right btn btn-secondary" href="{{ $album->url() }}" target="_blank"><i class="fa fa-fw fa-eye"></i> @lang('admin.open_album')</a>
|
<a class="pull-right btn btn-secondary" href="{{ $album->url() }}"><i class="fa fa-fw fa-eye"></i> @lang('admin.open_album')</a>
|
||||||
|
|
||||||
<h1 class="page-title">{{ $album->name }}</h1>
|
<h1 class="page-title">{{ $album->name }}</h1>
|
||||||
<p>{!! nl2br(e($album->description)) !!}</p>
|
<p>{!! nl2br(e($album->description)) !!}</p>
|
||||||
|
@ -85,6 +91,7 @@
|
||||||
language.select_all_choice_visible_action = '{!! addslashes(trans('admin.select_all_choice.visible_action')) !!}';
|
language.select_all_choice_visible_action = '{!! addslashes(trans('admin.select_all_choice.visible_action')) !!}';
|
||||||
language.image_failed = '{!! addslashes(trans('admin.upload_file_status_failed')) !!}';
|
language.image_failed = '{!! addslashes(trans('admin.upload_file_status_failed')) !!}';
|
||||||
language.image_uploaded = '{!! addslashes(trans('admin.upload_file_status_success')) !!}';
|
language.image_uploaded = '{!! addslashes(trans('admin.upload_file_status_success')) !!}';
|
||||||
|
language.no_file_selected = '{!! addslashes(trans('admin.upload_no_file')) !!}';
|
||||||
language.replace_image_message = '{!! addslashes(trans('admin.replace_image_message')) !!}';
|
language.replace_image_message = '{!! addslashes(trans('admin.replace_image_message')) !!}';
|
||||||
language.replace_image_title = '{!! addslashes(trans('admin.replace_image_title')) !!}';
|
language.replace_image_title = '{!! addslashes(trans('admin.replace_image_title')) !!}';
|
||||||
language.upload_status = '{!! addslashes(trans('admin.upload_file_status_progress')) !!}';
|
language.upload_status = '{!! addslashes(trans('admin.upload_file_status_progress')) !!}';
|
||||||
|
@ -105,7 +112,7 @@
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
// Populate the list of albums in the view model
|
// Populate the list of albums in the view model
|
||||||
@foreach ($albums as $album)
|
@foreach ($g_albums as $album)
|
||||||
@if(Gate::check('edit', $album) && Gate::check('upload-photos', $album))
|
@if(Gate::check('edit', $album) && Gate::check('upload-photos', $album))
|
||||||
editViewModel.data.albums.push({
|
editViewModel.data.albums.push({
|
||||||
'id': '{{ $album->id }}',
|
'id': '{{ $album->id }}',
|
||||||
|
@ -214,6 +221,9 @@
|
||||||
$('#upload-progress-modal').modal('hide');
|
$('#upload-progress-modal').modal('hide');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
appUpload.$watch('statusMessages', function($value) {
|
||||||
|
$('#upload-progress-modal').modal('handleUpdate');
|
||||||
|
})
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
|
@ -1,8 +1,6 @@
|
||||||
@extends(Theme::viewName('layout'))
|
@extends(Theme::viewName('layout'))
|
||||||
@section('title', $album->name)
|
@section('title', $album->name)
|
||||||
|
|
||||||
@php ($hasChildren = $album->children()->count() > 0)
|
|
||||||
|
|
||||||
@section('breadcrumb')
|
@section('breadcrumb')
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||||
@include(Theme::viewName('partials.album_breadcrumb'))
|
@include(Theme::viewName('partials.album_breadcrumb'))
|
||||||
|
@ -15,7 +13,7 @@
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
@can('edit', $album)
|
@can('edit', $album)
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<a class="btn btn-secondary" href="{{ route('albums.show', ['id' => $album->id]) }}" target="_blank"><i class="fa fa-fw fa-eye"></i> @lang('gallery.manage_album_link_2')</a>
|
<a class="btn btn-secondary" href="{{ route('albums.show', ['id' => $album->id]) }}"><i class="fa fa-fw fa-eye"></i> @lang('gallery.manage_album_link_2')</a>
|
||||||
</div>
|
</div>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
|
@ -51,24 +49,34 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($hasChildren)
|
@if (count($child_albums) > 0)
|
||||||
<h2 style="margin-top: 60px;"><small class="text-muted">@lang('gallery.other_albums_heading', ['album_name' => $album->name])</small></h2>
|
|
||||||
<p class="mb-4">@lang('gallery.other_albums_description')</p>
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@foreach ($album->children as $childAlbum)
|
<div class="col text-center">
|
||||||
<div class="col-sm-4 col-md-3" style="max-width: 250px;">
|
<h2 style="margin-top: 60px;"><small class="text-muted">@lang('gallery.other_albums_heading', ['album_name' => $album->name])</small></h2>
|
||||||
<div class="card mb-3">
|
<p class="mb-4">@lang('gallery.other_albums_description')</p>
|
||||||
<img class="card-img-top" src="{{ $childAlbum->thumbnailUrl('preview') }}" style="max-height: 120px;"/>
|
|
||||||
<div class="card-body">
|
<div class="row">
|
||||||
<h5 class="card-title"><a href="{{ $childAlbum->url() }}">{{ $childAlbum->name }}</a></h5>
|
@foreach ($child_albums as $childAlbum)
|
||||||
|
<div class="col-sm-4 col-md-3 text-left" style="max-width: 250px;">
|
||||||
|
<div class="card mb-3">
|
||||||
|
<img class="card-img-top" src="{{ $childAlbum->thumbnailUrl('preview') }}" style="max-height: 120px;"/>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title"><a href="{{ $childAlbum->url() }}">{{ $childAlbum->name }}</a></h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<small class="text-muted">
|
||||||
|
<i class="fa fa-fw fa-photo"></i> {{ number_format($childAlbum->photos_count) }} {{ trans_choice('gallery.photos', $childAlbum->photos_count) }}
|
||||||
|
|
||||||
|
@if ($childAlbum->children_count > 0)
|
||||||
|
<i class="fa fa-fw fa-book ml-3"></i> {{ number_format($childAlbum->children_count) }} {{ trans_choice('gallery.child_albums', $childAlbum->children_count) }}
|
||||||
|
@endif
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
@endforeach
|
||||||
<small class="text-muted"><i class="fa fa-fw fa-photo"></i> {{ $childAlbum->photos_count }} photos</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
@extends(Theme::viewName('layout'))
|
@extends(Theme::viewName('layout'))
|
||||||
@section('title', $album->name)
|
@section('title', $album->name)
|
||||||
|
|
||||||
@php ($hasChildren = $album->children()->count() > 0)
|
|
||||||
|
|
||||||
@section('breadcrumb')
|
@section('breadcrumb')
|
||||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||||
@include(Theme::viewName('partials.album_breadcrumb'))
|
@include(Theme::viewName('partials.album_breadcrumb'))
|
||||||
|
@ -14,7 +12,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<a class="btn btn-secondary" href="{{ route('albums.show', ['id' => $album->id]) }}" target="_blank"><i class="fa fa-fw fa-eye"></i> @lang('gallery.manage_album_link_2')</a>
|
<a class="btn btn-secondary" href="{{ route('albums.show', ['id' => $album->id]) }}"><i class="fa fa-fw fa-eye"></i> @lang('gallery.manage_album_link_2')</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,26 +20,32 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<h1>@lang('gallery.album_no_results_heading')</h1>
|
@if (count($child_albums) == 0)
|
||||||
<p style="line-height: 1.6em;">@lang('gallery.album_no_results_text', ['admin_link' => sprintf('<a href="%s">%s</a>', route('admin'), trans('admin.title'))])</p>
|
<h1>@lang('gallery.album_no_results_heading')</h1>
|
||||||
<p style="margin-bottom: 30px; line-height: 1.6em;">@lang('gallery.album_no_results_text_2')</p>
|
<p style="line-height: 1.6em;">@lang('gallery.album_no_results_text', ['admin_link' => sprintf('<a href="%s">%s</a>', route('admin'), trans('admin.title'))])</p>
|
||||||
|
<p style="margin-bottom: 30px; line-height: 1.6em;">@lang('gallery.album_no_results_text_2')</p>
|
||||||
|
|
||||||
<img src="{{ asset('themes/base/images/smartphone-photo.jpg') }}" class="img-fluid rounded" style="display: inline;" />
|
<img src="{{ asset('themes/base/images/smartphone-photo.jpg') }}" class="img-fluid rounded" style="display: inline;" />
|
||||||
|
@else
|
||||||
@if ($hasChildren)
|
<h2><small class="text-muted">@lang('gallery.other_albums_heading', ['album_name' => $album->name])</small></h2>
|
||||||
<h2 style="margin-top: 60px;"><small class="text-muted">@lang('gallery.other_albums_heading', ['album_name' => $album->name])</small></h2>
|
<p class="mb-4">@lang('gallery.other_albums_description_empty', ['album_name' => $album->name])</p>
|
||||||
<p class="mb-4">@lang('gallery.other_albums_description')</p>
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@foreach ($album->children as $childAlbum)
|
@foreach ($child_albums as $childAlbum)
|
||||||
<div class="col-sm-4 col-md-3" style="max-width: 250px;">
|
<div class="col-sm-4 col-md-3 text-left" style="max-width: 250px;">
|
||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<img class="card-img-top" src="{{ $childAlbum->thumbnailUrl('preview') }}" style="max-height: 120px;"/>
|
<img class="card-img-top" src="{{ $childAlbum->thumbnailUrl('preview') }}" style="max-height: 120px;"/>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title"><a href="{{ $childAlbum->url() }}">{{ $childAlbum->name }}</a></h5>
|
<h5 class="card-title"><a href="{{ $childAlbum->url() }}">{{ $childAlbum->name }}</a></h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<small class="text-muted"><i class="fa fa-fw fa-photo"></i> {{ $childAlbum->photos_count }} photos</small>
|
<small class="text-muted">
|
||||||
|
<i class="fa fa-fw fa-photo"></i> {{ number_format($childAlbum->photos_count) }} {{ trans_choice('gallery.photos', $childAlbum->photos_count) }}
|
||||||
|
|
||||||
|
@if ($childAlbum->children_count > 0)
|
||||||
|
<i class="fa fa-fw fa-book ml-3"></i> {{ number_format($childAlbum->children_count) }} {{ trans_choice('gallery.child_albums', $childAlbum->children_count) }}
|
||||||
|
@endif
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
@can('edit', $album)
|
@can('edit', $album)
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<a class="btn btn-secondary" href="{{ route('albums.show', ['id' => $album->id]) }}" target="_blank"><i class="fa fa-fw fa-eye"></i> @lang('gallery.manage_album_link_2')</a>
|
<a class="btn btn-secondary" href="{{ route('albums.show', ['id' => $album->id]) }}"><i class="fa fa-fw fa-eye"></i> @lang('gallery.manage_album_link_2')</a>
|
||||||
</div>
|
</div>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
|
@ -56,24 +56,34 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($album->children()->count() > 0)
|
@if (count($child_albums) > 0)
|
||||||
<h2 style="margin-top: 60px;"><small class="text-muted">@lang('gallery.other_albums_heading', ['album_name' => $album->name])</small></h2>
|
|
||||||
<p class="mb-4">@lang('gallery.other_albums_description')</p>
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@foreach ($album->children as $childAlbum)
|
<div class="col text-center">
|
||||||
<div class="col-sm-4 col-md-3" style="max-width: 250px;">
|
<h2 style="margin-top: 60px;"><small class="text-muted">@lang('gallery.other_albums_heading', ['album_name' => $album->name])</small></h2>
|
||||||
<div class="card mb-3">
|
<p class="mb-4">@lang('gallery.other_albums_description')</p>
|
||||||
<img class="card-img-top" src="{{ $childAlbum->thumbnailUrl('preview') }}" style="max-height: 120px;"/>
|
|
||||||
<div class="card-body">
|
<div class="row">
|
||||||
<h5 class="card-title"><a href="{{ $childAlbum->url() }}">{{ $childAlbum->name }}</a></h5>
|
@foreach ($child_albums as $childAlbum)
|
||||||
|
<div class="col-sm-4 col-md-3 text-left" style="max-width: 250px;">
|
||||||
|
<div class="card mb-3">
|
||||||
|
<img class="card-img-top" src="{{ $childAlbum->thumbnailUrl('preview') }}" style="max-height: 120px;"/>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title"><a href="{{ $childAlbum->url() }}">{{ $childAlbum->name }}</a></h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<small class="text-muted">
|
||||||
|
<i class="fa fa-fw fa-photo"></i> {{ number_format($childAlbum->photos_count) }} {{ trans_choice('gallery.photos', $childAlbum->photos_count) }}
|
||||||
|
|
||||||
|
@if ($childAlbum->children_count > 0)
|
||||||
|
<i class="fa fa-fw fa-book ml-3"></i> {{ number_format($childAlbum->children_count) }} {{ trans_choice('gallery.child_albums', $childAlbum->children_count) }}
|
||||||
|
@endif
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
@endforeach
|
||||||
<small class="text-muted"><i class="fa fa-fw fa-photo"></i> {{ $childAlbum->photos_count }} photos</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,7 +20,13 @@
|
||||||
@endcan
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<small class="text-muted"><i class="fa fa-fw fa-photo"></i> {{ $album->photos_count }} photos</small>
|
<small class="text-muted">
|
||||||
|
<i class="fa fa-fw fa-photo"></i> {{ number_format($album->photos_count) }} {{ trans_choice('gallery.photos', $album->photos_count) }}
|
||||||
|
|
||||||
|
@if ($album->children_count > 0)
|
||||||
|
<i class="fa fa-fw fa-book ml-3"></i> {{ number_format($album->children_count) }} {{ trans_choice('gallery.child_albums', $album->children_count) }}
|
||||||
|
@endif
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,11 +21,10 @@
|
||||||
<p>@lang('admin.statistics_enable_public_intro')</p>
|
<p>@lang('admin.statistics_enable_public_intro')</p>
|
||||||
<form method="post" action="{{ route('admin.statistics.save') }}">
|
<form method="post" action="{{ route('admin.statistics.save') }}">
|
||||||
{{ csrf_field() }}
|
{{ csrf_field() }}
|
||||||
<label class="custom-control custom-checkbox">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="custom-control-input" name="enable_public_statistics" @if (UserConfig::get('public_statistics')) checked="checked"@endif/>
|
<input type="checkbox" class="form-check-input" id="enable-public-statistics" name="enable_public_statistics" @if (UserConfig::get('public_statistics')) checked="checked"@endif/>
|
||||||
<span class="custom-control-indicator"></span>
|
<label class="form-check-label" for="enable-public-statistics">@lang('admin.statistics_enable_public_checkbox')</label>
|
||||||
<span class="custom-control-description">@lang('admin.statistics_enable_public_checkbox')</span>
|
</div><br/>
|
||||||
</label><br/>
|
|
||||||
<button class="btn btn-success"><i class="fa fa-floppy-o"></i> @lang('forms.save_action')</button>
|
<button class="btn btn-success"><i class="fa fa-floppy-o"></i> @lang('forms.save_action')</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
@foreach ($album->albumParentTree() as $parentAlbum)
|
||||||
|
@if ($parentAlbum->id == $album->id)
|
||||||
|
@if (!empty($show_current_link) && $show_current_link)
|
||||||
|
<li class="breadcrumb-item active"><a href="{{ route('albums.show', ['id' => $album->id]) }}">{{ $album->name }}</a></li>
|
||||||
|
@else
|
||||||
|
<li class="breadcrumb-item active">{{ $album->name }}</li>
|
||||||
|
@endif
|
||||||
|
@else
|
||||||
|
<li class="breadcrumb-item"><a href="{{ route('albums.show', ['id' => $parentAlbum->id]) }}">{{ $parentAlbum->name }}</a></li>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
|
@ -5,7 +5,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="meta-label">@lang('admin.sysinfo_widget.app_version')</td>
|
<td class="meta-label">@lang('admin.sysinfo_widget.app_version')</td>
|
||||||
<td class="meta-value">{{ $app_version }}</td>
|
<td class="meta-value">{{ $app_version }} <a href="{{ route('admin.about') }}" class="btn btn-info ml-2"><i class="fa fa-question"></i></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="meta-label">@lang('admin.sysinfo_widget.hostname')</td>
|
<td class="meta-label">@lang('admin.sysinfo_widget.hostname')</td>
|
||||||
|
|
|
@ -7,25 +7,27 @@
|
||||||
@else
|
@else
|
||||||
<h4>@lang('admin.album_cameras_heading')</h4>
|
<h4>@lang('admin.album_cameras_heading')</h4>
|
||||||
<p>@lang('admin.album_cameras_text')</p>
|
<p>@lang('admin.album_cameras_text')</p>
|
||||||
<table class="table table-striped table-responsive">
|
<div class="table-responsive">
|
||||||
<thead>
|
<table class="table table-striped">
|
||||||
<tr>
|
<thead>
|
||||||
<th>@lang('admin.album_camera_make')</th>
|
<tr>
|
||||||
<th>@lang('admin.album_camera_model')</th>
|
<th>@lang('admin.album_camera_make')</th>
|
||||||
<th>@lang('admin.album_camera_software')</th>
|
<th>@lang('admin.album_camera_model')</th>
|
||||||
<th>@lang('admin.album_camera_photo_count')</th>
|
<th>@lang('admin.album_camera_software')</th>
|
||||||
</tr>
|
<th>@lang('admin.album_camera_photo_count')</th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</thead>
|
||||||
@foreach ($cameras as $camera)
|
<tbody>
|
||||||
<tr>
|
@foreach ($cameras as $camera)
|
||||||
<td>{{ $camera->camera_make }}</td>
|
<tr>
|
||||||
<td>{{ $camera->camera_model }}</td>
|
<td>{{ $camera->camera_make }}</td>
|
||||||
<td>{{ $camera->camera_software }}</td>
|
<td>{{ $camera->camera_model }}</td>
|
||||||
<td>{{ $camera->photo_count }}</td>
|
<td>{{ $camera->camera_software }}</td>
|
||||||
</tr>
|
<td>{{ $camera->photo_count }}</td>
|
||||||
@endforeach
|
</tr>
|
||||||
</tbody>
|
@endforeach
|
||||||
</table>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
|
@ -23,10 +23,11 @@
|
||||||
<input type="hidden" name="queue_token" value="{{ $queue_token }}"/>
|
<input type="hidden" name="queue_token" value="{{ $queue_token }}"/>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="custom-file">
|
{{--<label class="custom-file">
|
||||||
<input type="file" name="photo[]" id="single-upload-files" class="custom-file-input" multiple="multiple">
|
<input type="file" name="photo[]" id="single-upload-files" multiple="multiple">
|
||||||
<span class="custom-file-control"></span>
|
<span class="custom-file-control"></span>
|
||||||
</label>
|
</label>--}}
|
||||||
|
<input type="file" name="photo[]" id="single-upload-files" multiple="multiple">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -50,10 +51,11 @@
|
||||||
<input type="hidden" name="queue_token" value="{{ $queue_token }}"/>
|
<input type="hidden" name="queue_token" value="{{ $queue_token }}"/>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="custom-file">
|
{{--<label class="custom-file">
|
||||||
<input type="file" id="single-upload-files" class="custom-file-input" multiple="multiple" name="archive">
|
<input type="file" id="single-upload-files" class="custom-file-input" multiple="multiple" name="archive">
|
||||||
<span class="custom-file-control"></span>
|
<span class="custom-file-control"></span>
|
||||||
</label>
|
</label>--}}
|
||||||
|
<input type="file" id="single-upload-files" multiple="multiple" name="archive">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -80,20 +82,23 @@
|
||||||
<p v-text="currentStatus"></p>
|
<p v-text="currentStatus"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="statusMessages.length > 0">
|
<div v-if="statusMessages.length > 0"style="max-height: 300px; overflow: scroll;">
|
||||||
<p v-if="!isUploadInProgress" class="text-danger" style="font-weight: bold">
|
<p v-if="!isUploadInProgress" class="text-danger" style="font-weight: bold">
|
||||||
<span v-text="imagesFailed"></span> @lang('admin.upload_file_number_failed')
|
<span v-text="imagesFailed"></span> @lang('admin.upload_file_number_failed')
|
||||||
</p>
|
</p>
|
||||||
<p v-if="imagesUploaded > 0">
|
<p v-if="imagesUploaded > 0" class="text-right">
|
||||||
@lang('admin.upload_file_failed_continue')<br /><br/>
|
@lang('admin.upload_file_failed_continue')<br /><br/>
|
||||||
<a href="{{ route('albums.analyse', ['id' => $album->id, 'queue_token' => $queue_token]) }}" class="btn btn-primary">@lang('forms.continue_action')</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul v-for="message in statusMessages">
|
<ul v-for="message in statusMessages">
|
||||||
<li v-bind:class="{ message: message.message_class }" v-text="message.message_text"></li>
|
<li v-bind:class="message.message_class" v-text="message.message_text"></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="modal-footer" v-if="!isUploadInProgress">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal" v-if="imagesUploaded === 0">@lang('forms.close_action')</button>
|
||||||
|
<a href="{{ route('albums.analyse', ['id' => $album->id, 'queue_token' => $queue_token]) }}" class="btn btn-primary" v-if="imagesUploaded > 0">@lang('forms.continue_action')</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
<p style="font-size: smaller;">
|
<p style="font-size: smaller;">
|
||||||
<b>
|
<b>
|
||||||
@lang('global.powered_by', [
|
@lang('global.powered_by', [
|
||||||
'link_start' => '<a href="https://www.andyheathershaw.uk/software/blue-twilight" target="_blank">',
|
'link_start' => '<a href="https://andysh.uk/software/blue-twilight-php-photo-gallery/" target="_blank">',
|
||||||
'link_end' => '</a>',
|
'link_end' => '</a>',
|
||||||
])
|
])
|
||||||
</b><br/>
|
</b><br/>
|
||||||
@lang('global.copyright', [
|
@lang('global.copyright', [
|
||||||
'link_start' => '<a href="https://www.andyheathershaw.uk/" target="_blank">',
|
'link_start' => '<a href="https://andysh.uk/" target="_blank">',
|
||||||
'link_end' => '</a>',
|
'link_end' => '</a>',
|
||||||
'years' => (date('Y') == 2016 ? '2016' : '2016-' . date('Y'))
|
'years' => (date('Y') == 2016 ? '2016' : '2016-' . date('Y'))
|
||||||
])
|
])
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
<p style="font-size: smaller;">
|
<p style="font-size: smaller;">
|
||||||
<b>
|
<b>
|
||||||
@lang('global.powered_by', [
|
@lang('global.powered_by', [
|
||||||
'link_start' => '<a href="https://www.andyheathershaw.uk/software/blue-twilight" target="_blank">',
|
'link_start' => '<a href="https://andysh.uk/software/blue-twilight-php-photo-gallery/" target="_blank">',
|
||||||
'link_end' => '</a>',
|
'link_end' => '</a>',
|
||||||
])
|
])
|
||||||
</b><br/>
|
</b><br/>
|
||||||
@lang('global.copyright', [
|
@lang('global.copyright', [
|
||||||
'link_start' => '<a href="https://www.andyheathershaw.uk/" target="_blank">',
|
'link_start' => '<a href="https://andysh.uk/" target="_blank">',
|
||||||
'link_end' => '</a>',
|
'link_end' => '</a>',
|
||||||
'years' => (date('Y') == 2016 ? '2016' : '2016-' . date('Y'))
|
'years' => (date('Y') == 2016 ? '2016' : '2016-' . date('Y'))
|
||||||
])
|
])
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
<label for="email" class="col-md-4 col-form-label text-md-right">@lang('forms.email_label')</label>
|
<label for="email" class="col-md-4 col-form-label text-md-right">@lang('forms.email_label')</label>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" autofocus>
|
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" autofocus>
|
||||||
|
|
||||||
@if ($errors->has('email'))
|
@if ($errors->has('email'))
|
||||||
<div class="form-control-feedback">
|
<div class="invalid-feedback">
|
||||||
<strong>{{ $errors->first('email') }}</strong>
|
<strong>{{ $errors->first('email') }}</strong>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
@ -19,10 +19,10 @@
|
||||||
<label for="password" class="col-md-4 col-form-label text-md-right">@lang('forms.password_label')</label>
|
<label for="password" class="col-md-4 col-form-label text-md-right">@lang('forms.password_label')</label>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<input id="password" type="password" class="form-control" name="password">
|
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password">
|
||||||
|
|
||||||
@if ($errors->has('password'))
|
@if ($errors->has('password'))
|
||||||
<div class="form-control-feedback">
|
<div class="invalid-feedback">
|
||||||
<strong>{{ $errors->first('password') }}</strong>
|
<strong>{{ $errors->first('password') }}</strong>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
@ -33,8 +33,8 @@
|
||||||
<div class="col-md-4"><!-- --></div>
|
<div class="col-md-4"><!-- --></div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<label class="form-check-label">
|
<input class="form-check-input" type="checkbox" id="remember-me" name="remember">
|
||||||
<input class="form-check-input" type="checkbox" name="remember"> @lang('forms.remember_me_label')
|
<label class="form-check-label" for="remember-me">@lang('forms.remember_me_label')
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,11 @@
|
||||||
<p>{{ $album->description }}</p>
|
<p>{{ $album->description }}</p>
|
||||||
<p style="margin-bottom: 0;">
|
<p style="margin-bottom: 0;">
|
||||||
<b>{{ $album->photos_count }}</b> {{ trans_choice('admin.stats_widget.photos', $album->photos_count) }} ·
|
<b>{{ $album->photos_count }}</b> {{ trans_choice('admin.stats_widget.photos', $album->photos_count) }} ·
|
||||||
@if ($album->min_metadata_version < $current_metadata_version)
|
@if (
|
||||||
|
isset($album->min_metadata_version) &&
|
||||||
|
intval($album->min_metadata_version) > 0 &&
|
||||||
|
intval($album->min_metadata_version) < $current_metadata_version
|
||||||
|
)
|
||||||
<span class="text-danger">@lang('admin.metadata_upgrade.can_be_upgraded', ['version_from' => $album->min_metadata_version, 'version_to' => $current_metadata_version])</span>
|
<span class="text-danger">@lang('admin.metadata_upgrade.can_be_upgraded', ['version_from' => $album->min_metadata_version, 'version_to' => $current_metadata_version])</span>
|
||||||
@else
|
@else
|
||||||
<span class="text-success">@lang('admin.metadata_upgrade.is_up_to_date')</span>
|
<span class="text-success">@lang('admin.metadata_upgrade.is_up_to_date')</span>
|
||||||
|
|
|
@ -14,15 +14,19 @@
|
||||||
</li>
|
</li>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
@if (count($albums) > 0)
|
@if (count($g_albums) > 0)
|
||||||
<li class="nav-item dropdown ml-2">
|
<li class="nav-item dropdown ml-2">
|
||||||
<a class="nav-link dropdown-toggle" href="{{ url('/') }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" href="{{ url('/') }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
<i class="fa fa-book"></i> @lang('navigation.navbar.albums')
|
<i class="fa fa-book"></i> @lang('navigation.navbar.albums')
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
@foreach ($albums as $album)
|
@foreach ($g_albums_menu as $album)
|
||||||
<a class="dropdown-item" href="{{ $album->url() }}">{{ $album->name }}</a>
|
<a class="dropdown-item" href="{{ $album->url() }}">{{ $album->name }}</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
|
@if ($g_more_albums > 0)
|
||||||
|
<a class="dropdown-item" href="{{ route('home') }}">{{ trans_choice('gallery.show_more_albums', $g_more_albums) }}</a>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
|
@ -44,7 +48,7 @@
|
||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (count($albums) > 0 && \App\User::currentOrAnonymous()->can('statistics.public-access'))
|
@if (count($g_albums) > 0 && \App\User::currentOrAnonymous()->can('statistics.public-access'))
|
||||||
<li class="nav-item ml-2">
|
<li class="nav-item ml-2">
|
||||||
<a class="nav-link" href="{{ route('statistics.index') }}"><i class="fa fa-bar-chart"></i> @lang('navigation.navbar.statistics')</a>
|
<a class="nav-link" href="{{ route('statistics.index') }}"><i class="fa fa-bar-chart"></i> @lang('navigation.navbar.statistics')</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -82,4 +86,4 @@
|
||||||
</ul>
|
</ul>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<div>
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox" for="permission|{{ $key_id }}|{{ $permission->id }}">
|
<input type="checkbox" class="form-check-input" id="permission|{{ $key_id }}|{{ $permission->id }}" name="permissions[{{ $object_id }}][]" value="{{ $permission->id }}"{{ call_user_func($callback, $callback_object, $permission) ? ' checked="checked"' : '' }}>
|
||||||
<input type="checkbox" class="custom-control-input" id="permission|{{ $key_id }}|{{ $permission->id }}" name="permissions[{{ $object_id }}][]" value="{{ $permission->id }}"{{ call_user_func($callback, $callback_object, $permission) ? ' checked="checked"' : '' }}>
|
<label class="form-check-label" for="permission|{{ $key_id }}|{{ $permission->id }}">
|
||||||
<span class="custom-control-indicator"></span>
|
{{ trans(sprintf('permissions.%s.%s', $permission->section, $permission->description)) }}
|
||||||
<span class="custom-control-description">{{ trans(sprintf('permissions.%s.%s', $permission->section, $permission->description)) }}</span>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
|
@ -1,6 +1,6 @@
|
||||||
<tr data-album-id="{{ $album->id }}" class="{{ $is_child ? 'hidden' : '' }}" @if (!is_null($album->parent_album_id)) data-parent-album-id="{{ $album->parent_album_id }}" @endif>
|
<tr data-album-id="{{ $album->id }}" class="{{ $is_child ? 'hidden' : '' }}" @if (!is_null($album->parent_album_id)) data-parent-album-id="{{ $album->parent_album_id }}" @endif>
|
||||||
<td style="width: 20px;">
|
<td style="width: 20px;">
|
||||||
@if ($album->children()->count() > 0)
|
@if (count($album->child_albums) > 0)
|
||||||
<i class="album-expand-handle fa fa-fw fa-plus mt-2"></i>
|
<i class="album-expand-handle fa fa-fw fa-plus mt-2"></i>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
|
@ -14,7 +14,12 @@
|
||||||
@endcannot
|
@endcannot
|
||||||
</span><br/>
|
</span><br/>
|
||||||
<p>{{ $album->description }}</p>
|
<p>{{ $album->description }}</p>
|
||||||
<p style="margin-bottom: 0;"><b>{{ $album->photos_count }}</b> {{ trans_choice('admin.stats_widget.photos', $album->photos_count) }}</p>
|
<p style="margin-bottom: 0;">
|
||||||
|
<b>{{ $album->photos_count }}</b> {{ trans_choice('admin.stats_widget.photos', $album->photos_count) }}
|
||||||
|
@if (count($album->child_albums) > 0)
|
||||||
|
· <b>{{ count($album->child_albums) }}</b> {{ trans_choice('admin.stats_widget.albums', count($album->child_albums)) }}
|
||||||
|
@endif
|
||||||
|
</p>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
|
@ -27,6 +32,6 @@
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@foreach ($album->children as $album)
|
@foreach ($album->child_albums as $album)
|
||||||
@include (Theme::viewName('partials.single_album_admin'), ['is_child' => true])
|
@include (Theme::viewName('partials.single_album_admin'), ['is_child' => true])
|
||||||
@endforeach
|
@endforeach
|
|
@ -16,6 +16,8 @@ Auth::routes();
|
||||||
// Administration
|
// Administration
|
||||||
Route::group(['prefix' => 'admin'], function () {
|
Route::group(['prefix' => 'admin'], function () {
|
||||||
Route::get('/', 'Admin\DefaultController@index')->name('admin');
|
Route::get('/', 'Admin\DefaultController@index')->name('admin');
|
||||||
|
Route::get('/about', 'Admin\DefaultController@about')->name('admin.about');
|
||||||
|
Route::get('/about/latest-release', 'Admin\DefaultController@aboutLatestRelease')->name('admin.aboutLatestRelease');
|
||||||
Route::get('/photo-metadata', 'Admin\DefaultController@metadataUpgrade')->name('admin.metadataUpgrade');
|
Route::get('/photo-metadata', 'Admin\DefaultController@metadataUpgrade')->name('admin.metadataUpgrade');
|
||||||
Route::post('quick-upload', 'Admin\DefaultController@quickUpload')->name('admin.quickUpload');
|
Route::post('quick-upload', 'Admin\DefaultController@quickUpload')->name('admin.quickUpload');
|
||||||
Route::post('settings/save', 'Admin\DefaultController@saveSettings')->name('admin.saveSettings');
|
Route::post('settings/save', 'Admin\DefaultController@saveSettings')->name('admin.saveSettings');
|
||||||
|
|
Loading…
Reference in New Issue
Block a user