Merged in BLUE-8-openstack-storage-driver (pull request #1)
BLUE-8 openstack storage driver
This commit is contained in:
commit
aa9eee9bf5
2
.idea/webServers.xml
generated
2
.idea/webServers.xml
generated
@ -3,7 +3,7 @@
|
||||
<component name="WebServers">
|
||||
<option name="servers">
|
||||
<webServer id="b14a34b0-0127-4886-964a-7be75a2281ac" name="Development" url="http://blue-twilight-dev.andys.eu">
|
||||
<fileTransfer host="scar.andys.eu" port="22" rootFolder="/srv/www/blue-twilight-dev" accessType="SFTP">
|
||||
<fileTransfer host="scar.andys.eu" port="22" privateKey="C:\Users\aheathershaw\.ssh\id_rsa" rootFolder="/srv/www/blue-twilight-dev" accessType="SFTP" keyPair="true">
|
||||
<advancedOptions>
|
||||
<advancedOptions dataProtectionLevel="Private" />
|
||||
</advancedOptions>
|
||||
|
@ -5,6 +5,7 @@ namespace App\AlbumSources;
|
||||
use App\Album;
|
||||
use App\Photo;
|
||||
use App\Storage;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
|
||||
interface IAlbumSource
|
||||
@ -23,20 +24,20 @@ interface IAlbumSource
|
||||
*/
|
||||
function deleteThumbnail(Photo $photo, $thumbnail = null);
|
||||
|
||||
/**
|
||||
* Fetches the contents of a thumbnail for a photo.
|
||||
* @param Photo $photo Photo to fetch the thumbnail for.
|
||||
* @param string $thumbnail Thumbnail to fetch (or null to fetch the original.)
|
||||
* @return EntityBody
|
||||
*/
|
||||
function fetchPhotoContent(Photo $photo, $thumbnail = null);
|
||||
|
||||
/**
|
||||
* Gets the name of this album source.
|
||||
* @return string
|
||||
*/
|
||||
function getName();
|
||||
|
||||
/**
|
||||
* Gets the absolute path to the given photo file.
|
||||
* @param Photo $photo Photo to get the path to.
|
||||
* @param string $thumbnail Thumbnail to get the image to.
|
||||
* @return string
|
||||
*/
|
||||
function getPathToPhoto(Photo $photo, $thumbnail = null);
|
||||
|
||||
/**
|
||||
* Gets the absolute URL to the given photo file.
|
||||
* @param Photo $photo Photo to get the URL to.
|
||||
@ -47,20 +48,12 @@ interface IAlbumSource
|
||||
|
||||
/**
|
||||
* Saves a generated thumbnail to its permanent location.
|
||||
* @param Photo $photo Photo the thumbnail relates to.
|
||||
* @param string $thumbnailInfo Information about the thumbnail.
|
||||
* @param string $tempFilename Filename containing the thumbnail.
|
||||
* @param Photo $photo Photo the image relates to.
|
||||
* @param string $tempFilename Filename containing the image.
|
||||
* @param string $thumbnail Name of the thumbnail (or null for the original.)
|
||||
* @return mixed
|
||||
*/
|
||||
function saveThumbnail(Photo $photo, $thumbnailInfo, $tempFilename);
|
||||
|
||||
/**
|
||||
* Saves an uploaded file to the container and returns the filename.
|
||||
* @param File $uploadedFile The photo uploaded
|
||||
* @param string $overrideFilename Specific file name to use, or null to randomly generate one.
|
||||
* @return File
|
||||
*/
|
||||
function saveUploadedPhoto(File $uploadedFile, $overrideFilename = null);
|
||||
function saveThumbnail(Photo $photo, $tempFilename, $thumbnail = null);
|
||||
|
||||
/**
|
||||
* @param Album $album
|
||||
|
@ -6,6 +6,7 @@ use App\Album;
|
||||
use App\Helpers\MiscHelper;
|
||||
use App\Photo;
|
||||
use App\Services\PhotoService;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
|
||||
/**
|
||||
@ -24,12 +25,33 @@ class LocalFilesystemSource extends AlbumSourceBase implements IAlbumSource
|
||||
|
||||
public function deleteThumbnail(Photo $photo, $thumbnail = null)
|
||||
{
|
||||
return @unlink($this->getPathToPhoto($photo, $thumbnail));
|
||||
return @unlink(
|
||||
join(DIRECTORY_SEPARATOR, [
|
||||
$this->getPathToAlbum(),
|
||||
is_null($thumbnail) ? $this->getOriginalsFolder() : $thumbnail,
|
||||
$photo->storage_file_name
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function getOriginalsFolder()
|
||||
/**
|
||||
* Fetches the contents of a thumbnail for a photo.
|
||||
* @param Photo $photo Photo to fetch the thumbnail for.
|
||||
* @param string $thumbnail Thumbnail to fetch (or null to fetch the original.)
|
||||
* @return EntityBody
|
||||
*/
|
||||
public function fetchPhotoContent(Photo $photo, $thumbnail = null)
|
||||
{
|
||||
return '_originals';
|
||||
$fh = fopen(
|
||||
join(DIRECTORY_SEPARATOR, [
|
||||
$this->getPathToAlbum(),
|
||||
is_null($thumbnail) ? $this->getOriginalsFolder() : $thumbnail,
|
||||
$photo->storage_file_name
|
||||
]),
|
||||
'r+'
|
||||
);
|
||||
|
||||
return EntityBody::factory($fh);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
@ -37,16 +59,6 @@ class LocalFilesystemSource extends AlbumSourceBase implements IAlbumSource
|
||||
return 'global.album_sources.filesystem';
|
||||
}
|
||||
|
||||
public function getPathToPhoto(Photo $photo, $thumbnail = null)
|
||||
{
|
||||
if (is_null($thumbnail))
|
||||
{
|
||||
$thumbnail = $this->getOriginalsFolder();
|
||||
}
|
||||
|
||||
return sprintf('%s/%s/%s', $this->getPathToAlbum(), $thumbnail, $photo->storage_file_name);
|
||||
}
|
||||
|
||||
public function getUrlToPhoto(Photo $photo, $thumbnail = null)
|
||||
{
|
||||
$photoUrl = route('downloadPhoto', [
|
||||
@ -62,33 +74,21 @@ class LocalFilesystemSource extends AlbumSourceBase implements IAlbumSource
|
||||
return $photoUrl;
|
||||
}
|
||||
|
||||
public function saveThumbnail(Photo $photo, $thumbnailInfo, $tempFilename)
|
||||
public function saveThumbnail(Photo $photo, $tempFilename, $thumbnail = null)
|
||||
{
|
||||
$fileInfo = new File($tempFilename);
|
||||
$fileInfo->move(sprintf('%s/%s', $this->getPathToAlbum(), $thumbnailInfo['name']), $photo->storage_file_name);
|
||||
$fileInfo->move(
|
||||
join(DIRECTORY_SEPARATOR, [
|
||||
$this->getPathToAlbum(),
|
||||
is_null($thumbnail) ? $this->getOriginalsFolder() : $thumbnail
|
||||
]),
|
||||
$photo->storage_file_name
|
||||
);
|
||||
}
|
||||
|
||||
public function saveUploadedPhoto(File $uploadedFile, $overrideFilename = null)
|
||||
private function getOriginalsFolder()
|
||||
{
|
||||
$tempFilename = sprintf(
|
||||
'%s/%s/%s',
|
||||
$this->getPathToAlbum(),
|
||||
$this->getOriginalsFolder(),
|
||||
is_null($overrideFilename) ? MiscHelper::randomString(20) : basename($overrideFilename)
|
||||
);
|
||||
|
||||
// Only add an extension if an override filename was not given, assume this is present
|
||||
if (is_null($overrideFilename))
|
||||
{
|
||||
$extension = $uploadedFile->guessExtension();
|
||||
if (!is_null($extension))
|
||||
{
|
||||
$tempFilename .= '.' . $extension;
|
||||
}
|
||||
}
|
||||
|
||||
$uploadedFile->move(dirname($tempFilename), basename($tempFilename));
|
||||
return new File($tempFilename);
|
||||
return '_originals';
|
||||
}
|
||||
|
||||
private function getPathToAlbum()
|
||||
|
156
app/AlbumSources/OpenStackSource.php
Normal file
156
app/AlbumSources/OpenStackSource.php
Normal file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace App\AlbumSources;
|
||||
use App\Photo;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Guzzle\Http\Exception\ClientErrorResponseException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use OpenCloud\ObjectStore\Exception\ObjectNotFoundException;
|
||||
use OpenCloud\OpenStack;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
|
||||
/**
|
||||
* Driver for managing files on the local filesystem.
|
||||
* @package App\AlbumSources
|
||||
*/
|
||||
class OpenStackSource extends AlbumSourceBase implements IAlbumSource
|
||||
{
|
||||
/**
|
||||
* Deletes an entire album's media contents.
|
||||
* @return void
|
||||
*/
|
||||
public function deleteAlbumContents()
|
||||
{
|
||||
// Because all photos live in a single container, there is nothing "global" to delete for the entire album
|
||||
// The delete routine will have already removed all photos
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a thumbnail file for a photo.
|
||||
* @param Photo $photo Photo to delete the thumbnail from.
|
||||
* @param string $thumbnail Thumbnail to delete (or null to delete the original.)
|
||||
* @return void
|
||||
*/
|
||||
public function deleteThumbnail(Photo $photo, $thumbnail = null)
|
||||
{
|
||||
$photoPath = $this->getPathToPhoto($photo, $thumbnail);
|
||||
|
||||
try
|
||||
{
|
||||
$this->getContainer()->deleteObject($photoPath);
|
||||
}
|
||||
catch (ClientErrorResponseException $ex)
|
||||
{
|
||||
// Don't worry if the file no longer exists
|
||||
Log::warning('Failed deleting image from OpenStack.', ['error' => $ex->getMessage(), 'path' => $photoPath]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the contents of a thumbnail for a photo.
|
||||
* @param Photo $photo Photo to fetch the thumbnail for.
|
||||
* @param string $thumbnail Thumbnail to fetch (or null to fetch the original.)
|
||||
* @return EntityBody
|
||||
*/
|
||||
public function fetchPhotoContent(Photo $photo, $thumbnail = null)
|
||||
{
|
||||
$object = $this->getContainer()->getObject($this->getPathToPhoto($photo, $thumbnail));
|
||||
|
||||
return $object->getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this album source.
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'global.album_sources.openstack';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the absolute URL to the given photo file.
|
||||
* @param Photo $photo Photo to get the URL to.
|
||||
* @param string $thumbnail Thumbnail to get the image to.
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlToPhoto(Photo $photo, $thumbnail = null)
|
||||
{
|
||||
$cdnUrl = $this->configuration->cdn_url;
|
||||
if (strlen($cdnUrl) > 0)
|
||||
{
|
||||
if (substr($cdnUrl, strlen($cdnUrl) - 1, 1) == '/')
|
||||
{
|
||||
$cdnUrl = substr($cdnUrl, 0, strlen($cdnUrl) - 1);
|
||||
}
|
||||
|
||||
return sprintf('%s/%s', $cdnUrl, $this->getPathToPhoto($photo, $thumbnail));
|
||||
}
|
||||
|
||||
// Not using a CDN - use the standard download controller
|
||||
$photoUrl = route('downloadPhoto', [
|
||||
'albumUrlAlias' => $this->album->url_alias,
|
||||
'photoFilename' => $photo->storage_file_name
|
||||
]);
|
||||
|
||||
if (!is_null($thumbnail))
|
||||
{
|
||||
$photoUrl .= sprintf('?t=%s', urlencode($thumbnail));
|
||||
}
|
||||
|
||||
return $photoUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a generated thumbnail to its permanent location.
|
||||
* @param Photo $photo Photo the image relates to.
|
||||
* @param string $tempFilename Filename containing the image.
|
||||
* @param string $thumbnail Name of the thumbnail (or null for the original.)
|
||||
* @return mixed
|
||||
*/
|
||||
public function saveThumbnail(Photo $photo, $tempFilename, $thumbnail = null)
|
||||
{
|
||||
$photoPath = $this->getPathToPhoto($photo, $thumbnail);
|
||||
|
||||
$container = $this->getContainer();
|
||||
$container->uploadObject($photoPath, fopen($tempFilename, 'r+'));
|
||||
}
|
||||
|
||||
protected function getClient()
|
||||
{
|
||||
return new OpenStack($this->configuration->auth_url, [
|
||||
'username' => $this->configuration->username,
|
||||
'password' => decrypt($this->configuration->password),
|
||||
'tenantName' => $this->configuration->tenant_name,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getContainer()
|
||||
{
|
||||
return $this->getStorageService()->getContainer($this->configuration->container_name);
|
||||
}
|
||||
|
||||
protected function getStorageService()
|
||||
{
|
||||
return $this->getClient()->objectStoreService(
|
||||
$this->configuration->service_name,
|
||||
$this->configuration->service_region,
|
||||
'publicURL'
|
||||
);
|
||||
}
|
||||
|
||||
private function getOriginalsFolder()
|
||||
{
|
||||
return '_originals';
|
||||
}
|
||||
|
||||
private function getPathToPhoto(Photo $photo, $thumbnail = null)
|
||||
{
|
||||
return sprintf(
|
||||
'%s/%s/%s',
|
||||
$this->album->url_alias,
|
||||
is_null($thumbnail) ? $this->getOriginalsFolder() : $thumbnail,
|
||||
$photo->storage_file_name
|
||||
);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ namespace App\Helpers;
|
||||
use App\Album;
|
||||
use App\AlbumSources\IAlbumSource;
|
||||
use App\AlbumSources\LocalFilesystemSource;
|
||||
use App\AlbumSources\OpenStackSource;
|
||||
use App\Configuration;
|
||||
|
||||
class ConfigHelper
|
||||
@ -29,7 +30,8 @@ class ConfigHelper
|
||||
$results = [];
|
||||
|
||||
$classes = [
|
||||
LocalFilesystemSource::class
|
||||
LocalFilesystemSource::class,
|
||||
OpenStackSource::class
|
||||
];
|
||||
foreach ($classes as $class)
|
||||
{
|
||||
|
48
app/Helpers/FileHelper.php
Normal file
48
app/Helpers/FileHelper.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Http\File;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
|
||||
class FileHelper
|
||||
{
|
||||
public static function getQueuePath($queueUid)
|
||||
{
|
||||
$path = join(DIRECTORY_SEPARATOR, [
|
||||
dirname(dirname(__DIR__)),
|
||||
'storage',
|
||||
'app',
|
||||
'analysis-queue',
|
||||
str_replace(['.', '/', '\\'], '', $queueUid)
|
||||
]);
|
||||
|
||||
if (!file_exists($path))
|
||||
{
|
||||
mkdir($path, 0755, true);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
public static function saveUploadedFile(UploadedFile $uploadedFile, $destinationPath, $overrideFilename = null)
|
||||
{
|
||||
$tempFilename = join(DIRECTORY_SEPARATOR, [
|
||||
$destinationPath,
|
||||
is_null($overrideFilename) ? MiscHelper::randomString(20) : basename($overrideFilename)
|
||||
]);
|
||||
|
||||
// Only add an extension if an override filename was not given, assume this is present
|
||||
if (is_null($overrideFilename))
|
||||
{
|
||||
$extension = $uploadedFile->guessExtension();
|
||||
if (!is_null($extension))
|
||||
{
|
||||
$tempFilename .= '.' . $extension;
|
||||
}
|
||||
}
|
||||
|
||||
$uploadedFile->move(dirname($tempFilename), basename($tempFilename));
|
||||
return new File($tempFilename);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ namespace app\Http\Controllers\Admin;
|
||||
use App\Album;
|
||||
use App\Facade\Theme;
|
||||
use App\Facade\UserConfig;
|
||||
use App\Helpers\FileHelper;
|
||||
use App\Helpers\MiscHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests;
|
||||
@ -26,7 +27,7 @@ class AlbumController extends Controller
|
||||
View::share('is_admin', true);
|
||||
}
|
||||
|
||||
public function analyse($id)
|
||||
public function analyse($id, $queue_token)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
|
||||
@ -36,7 +37,7 @@ class AlbumController extends Controller
|
||||
->orderBy('created_at')
|
||||
->get();
|
||||
|
||||
return Theme::render('admin.analyse_album', ['album' => $album, 'photos' => $photos]);
|
||||
return Theme::render('admin.analyse_album', ['album' => $album, 'photos' => $photos, 'queue_token' => $queue_token]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,6 +185,7 @@ class AlbumController extends Controller
|
||||
'max_post_limit' => $postLimit,
|
||||
'max_post_limit_bulk' => $fileUploadOrPostLowerLimit,
|
||||
'photos' => $photos,
|
||||
'queue_token' => MiscHelper::randomString(),
|
||||
'success' => $request->session()->get('success'),
|
||||
'warning' => $request->session()->get('warning')
|
||||
]);
|
||||
|
@ -96,7 +96,7 @@ class DefaultController extends Controller
|
||||
}
|
||||
|
||||
$config->value = $request->request->get($key);
|
||||
if (in_array($key, $passwordKeys))
|
||||
if (in_array($key, $passwordKeys) && strlen($config->value) > 0)
|
||||
{
|
||||
$config->value = encrypt($config->value);
|
||||
}
|
||||
|
@ -6,8 +6,10 @@ use App\Album;
|
||||
use App\AlbumSources\IAlbumSource;
|
||||
use App\Facade\Image;
|
||||
use App\Facade\Theme;
|
||||
use App\Helpers\FileHelper;
|
||||
use App\Helpers\ImageHelper;
|
||||
use App\Helpers\MiscHelper;
|
||||
use App\Http\Requests\UpdatePhotosBulkRequest;
|
||||
use App\Photo;
|
||||
use App\Services\PhotoService;
|
||||
use App\Upload;
|
||||
@ -30,7 +32,7 @@ class PhotoController extends Controller
|
||||
View::share('is_admin', true);
|
||||
}
|
||||
|
||||
public function analyse($photoId)
|
||||
public function analyse($photoId, $queue_token)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
|
||||
@ -47,7 +49,7 @@ class PhotoController extends Controller
|
||||
try
|
||||
{
|
||||
$photoService = new PhotoService($photo);
|
||||
$photoService->analyse();
|
||||
$photoService->analyse($queue_token);
|
||||
|
||||
$result['is_successful'] = true;
|
||||
}
|
||||
@ -111,7 +113,8 @@ class PhotoController extends Controller
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
|
||||
settype($direction, 'boolean');
|
||||
settype($horizontal, 'boolean');
|
||||
settype($vertical, 'boolean');
|
||||
|
||||
$photo = Photo::where('id', intval($photoId))->first();
|
||||
if (is_null($photo))
|
||||
@ -222,6 +225,15 @@ class PhotoController extends Controller
|
||||
$album = $this->loadAlbum($request->get('album_id'));
|
||||
$isSuccessful = false;
|
||||
|
||||
// Create the folder to hold the analysis results if not already present
|
||||
$queueUid = $request->get('queue_token');
|
||||
if (strlen($queueUid) == 0)
|
||||
{
|
||||
throw new \Exception('No queue_token value was provided!');
|
||||
}
|
||||
|
||||
$queueFolder = FileHelper::getQueuePath($queueUid);
|
||||
|
||||
foreach ($photoFiles as $photoFile)
|
||||
{
|
||||
$photoFile = UploadedFile::createFromBase($photoFile);
|
||||
@ -232,7 +244,7 @@ class PhotoController extends Controller
|
||||
else
|
||||
{
|
||||
/** @var File $savedFile */
|
||||
$savedFile = $album->getAlbumSource()->saveUploadedPhoto($photoFile);
|
||||
$savedFile = FileHelper::saveUploadedFile($photoFile, $queueFolder);
|
||||
|
||||
$photo = new Photo();
|
||||
$photo->album_id = $album->id;
|
||||
@ -256,7 +268,8 @@ class PhotoController extends Controller
|
||||
else
|
||||
{
|
||||
return redirect(route('albums.analyse', [
|
||||
'id' => $album->id
|
||||
'id' => $album->id,
|
||||
'queue_token' => $queueUid
|
||||
]));
|
||||
}
|
||||
}
|
||||
@ -276,9 +289,14 @@ class PhotoController extends Controller
|
||||
return redirect(route('albums.show', ['id' => $album->id]));
|
||||
}
|
||||
|
||||
// Create a temporary folder to hold the extracted files
|
||||
$tempFolder = sprintf('%s/btw_upload_%s', env('TEMP_FOLDER', '/tmp'), MiscHelper::randomString());
|
||||
mkdir($tempFolder);
|
||||
// Create the folder to hold the analysis results if not already present
|
||||
$queueUid = $request->get('queue_token');
|
||||
if (strlen($queueUid) == 0)
|
||||
{
|
||||
throw new \Exception('No queue_token value was provided!');
|
||||
}
|
||||
|
||||
$queueFolder = FileHelper::getQueuePath($queueUid);
|
||||
|
||||
$mimeType = strtolower($archiveFile->getMimeType());
|
||||
switch ($mimeType)
|
||||
@ -286,7 +304,7 @@ class PhotoController extends Controller
|
||||
case 'application/zip':
|
||||
$zip = new \ZipArchive();
|
||||
$zip->open($archiveFile->getPathname());
|
||||
$zip->extractTo($tempFolder);
|
||||
$zip->extractTo($queueFolder);
|
||||
$zip->close();
|
||||
break;
|
||||
|
||||
@ -295,7 +313,7 @@ class PhotoController extends Controller
|
||||
return redirect(route('albums.show', ['id' => $album->id]));
|
||||
}
|
||||
|
||||
$di = new \RecursiveDirectoryIterator($tempFolder, \RecursiveDirectoryIterator::SKIP_DOTS);
|
||||
$di = new \RecursiveDirectoryIterator($queueFolder, \RecursiveDirectoryIterator::SKIP_DOTS);
|
||||
$recursive = new \RecursiveIteratorIterator($di);
|
||||
|
||||
/** @var \SplFileInfo $fileInfo */
|
||||
@ -336,10 +354,11 @@ class PhotoController extends Controller
|
||||
$photo->save();
|
||||
}
|
||||
|
||||
@rmdir($tempFolder);
|
||||
@rmdir($queueFolder);
|
||||
|
||||
return redirect(route('albums.analyse', [
|
||||
'id' => $album->id
|
||||
'id' => $album->id,
|
||||
'queue_token' => $queueUid
|
||||
]));
|
||||
}
|
||||
|
||||
@ -377,7 +396,7 @@ class PhotoController extends Controller
|
||||
//
|
||||
}
|
||||
|
||||
public function updateBulk(Request $request, $albumId)
|
||||
public function updateBulk(UpdatePhotosBulkRequest $request, $albumId)
|
||||
{
|
||||
$this->authorize('admin-access');
|
||||
|
||||
@ -390,9 +409,7 @@ class PhotoController extends Controller
|
||||
return null;
|
||||
}
|
||||
|
||||
$numberChanged = 0;
|
||||
|
||||
if ($request->has('bulk-apply'))
|
||||
if ($request->has('bulk-action'))
|
||||
{
|
||||
$numberChanged = $this->applyBulkActions($request, $album);
|
||||
}
|
||||
@ -428,6 +445,7 @@ class PhotoController extends Controller
|
||||
}
|
||||
|
||||
$photoService = new PhotoService($photo);
|
||||
$doNotSave = false;
|
||||
switch (strtolower($action))
|
||||
{
|
||||
case 'change_album':
|
||||
@ -449,6 +467,7 @@ class PhotoController extends Controller
|
||||
|
||||
case 'delete':
|
||||
$photoService->delete();
|
||||
$doNotSave = true;
|
||||
break;
|
||||
|
||||
case 'flip_both':
|
||||
@ -476,7 +495,10 @@ class PhotoController extends Controller
|
||||
break;
|
||||
}
|
||||
|
||||
$photo->save();
|
||||
if (!$doNotSave)
|
||||
{
|
||||
$photo->save();
|
||||
}
|
||||
|
||||
$numberChanged++;
|
||||
}
|
||||
|
@ -68,10 +68,33 @@ class StorageController extends Controller
|
||||
$this->authorize('admin-access');
|
||||
|
||||
$storage = new Storage();
|
||||
$storage->fill($request->only(['name', 'source', 'location']));
|
||||
$storage->fill($request->only([
|
||||
'name',
|
||||
'source',
|
||||
'location',
|
||||
'auth_url',
|
||||
'tenant_name',
|
||||
'username',
|
||||
'password',
|
||||
'service_name',
|
||||
'service_region',
|
||||
'container_name',
|
||||
'cdn_url'
|
||||
]));
|
||||
$storage->is_active = true;
|
||||
$storage->is_default = (strtolower($request->get('is_default')) == 'on');
|
||||
$storage->is_internal = false;
|
||||
|
||||
if ($storage->source != 'LocalFilesystemSource' && isset($storage->location))
|
||||
{
|
||||
unset($storage->location);
|
||||
}
|
||||
|
||||
if (isset($storage->password) && !empty($storage->password))
|
||||
{
|
||||
$storage->password = encrypt($storage->password);
|
||||
}
|
||||
|
||||
$storage->save();
|
||||
|
||||
if ($storage->is_default)
|
||||
@ -142,6 +165,11 @@ class StorageController extends Controller
|
||||
App::abort(404);
|
||||
}
|
||||
|
||||
if (isset($storage->password) && strlen($storage->password) > 0)
|
||||
{
|
||||
$storage->password = decrypt($storage->password);
|
||||
}
|
||||
|
||||
return Theme::render('admin.edit_storage', ['storage' => $storage]);
|
||||
}
|
||||
|
||||
@ -162,7 +190,17 @@ class StorageController extends Controller
|
||||
App::abort(404);
|
||||
}
|
||||
|
||||
$storage->fill($request->only(['name']));
|
||||
$storage->fill($request->only([
|
||||
'name',
|
||||
'auth_url',
|
||||
'tenant_name',
|
||||
'username',
|
||||
'password',
|
||||
'service_name',
|
||||
'service_region',
|
||||
'container_name',
|
||||
'cdn_url'
|
||||
]));
|
||||
$storage->is_active = (strtolower($request->get('is_active')) == 'on');
|
||||
$storage->is_default = (strtolower($request->get('is_default')) == 'on');
|
||||
|
||||
@ -171,6 +209,11 @@ class StorageController extends Controller
|
||||
$storage->is_default = false;
|
||||
}
|
||||
|
||||
if (isset($storage->password) && !empty($storage->password))
|
||||
{
|
||||
$storage->password = encrypt($storage->password);
|
||||
}
|
||||
|
||||
$storage->save();
|
||||
|
||||
if ($storage->is_default)
|
||||
|
@ -11,6 +11,7 @@ use app\Http\Controllers\Admin\AlbumController;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Middleware\VerifyCsrfToken;
|
||||
use App\Photo;
|
||||
use Guzzle\Http\Mimetypes;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@ -53,10 +54,23 @@ class PhotoController extends Controller
|
||||
$thumbnail = $request->get('t');
|
||||
if (is_null($thumbnail))
|
||||
{
|
||||
Gate::forUser($this->getUser())->authorize('photo.download_original', $photo);
|
||||
$this->authorizeForUser($this->getUser(), 'photo.download_original', $photo);
|
||||
}
|
||||
|
||||
return response()->file($album->getAlbumSource()->getPathToPhoto($photo, $thumbnail));
|
||||
$photoStream = $album->getAlbumSource()->fetchPhotoContent($photo, $thumbnail);
|
||||
$mimeType = Mimetypes::getInstance()->fromFilename($photo->storage_file_name);
|
||||
|
||||
return response()->stream(
|
||||
function() use ($photoStream)
|
||||
{
|
||||
echo $photoStream;
|
||||
},
|
||||
200,
|
||||
[
|
||||
'Content-Length' => $photoStream->getContentLength(),
|
||||
'Content-Type' => $mimeType
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function show(Request $request, $albumUrlAlias, $photoFilename)
|
||||
|
@ -24,6 +24,8 @@ class StoreStorageRequest extends FormRequest
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$result = [];
|
||||
|
||||
switch ($this->method())
|
||||
{
|
||||
case 'POST':
|
||||
@ -32,21 +34,49 @@ class StoreStorageRequest extends FormRequest
|
||||
'source' => 'required|max:255',
|
||||
];
|
||||
|
||||
if ($this->get('source') == 'LocalFilesystemSource')
|
||||
switch ($this->get('source'))
|
||||
{
|
||||
$result['location'] = 'sometimes|required|is_dir|dir_empty|is_writeable';
|
||||
}
|
||||
case 'LocalFilesystemSource':
|
||||
$result['location'] = 'sometimes|required|is_dir|dir_empty|is_writeable';
|
||||
break;
|
||||
|
||||
return $result;
|
||||
case 'OpenStackSource':
|
||||
$result['auth_url'] = 'sometimes|required';
|
||||
$result['tenant_name'] = 'sometimes|required';
|
||||
$result['username'] = 'sometimes|required';
|
||||
$result['password'] = 'sometimes|required';
|
||||
$result['service_name'] = 'sometimes|required';
|
||||
$result['service_region'] = 'sometimes|required';
|
||||
$result['container_name'] = 'sometimes|required';
|
||||
$result['cdn_url'] = 'sometimes|url';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PATCH':
|
||||
case 'PUT':
|
||||
$storageId = intval($this->segment(3));
|
||||
|
||||
return [
|
||||
$storage = Storage::find($storageId);
|
||||
$result = [
|
||||
'name' => 'required|max:255|unique:storages,name,' . $storageId
|
||||
];
|
||||
|
||||
switch ($storage->source)
|
||||
{
|
||||
case 'OpenStackSource':
|
||||
$result['auth_url'] = 'sometimes|required';
|
||||
$result['tenant_name'] = 'sometimes|required';
|
||||
$result['username'] = 'sometimes|required';
|
||||
$result['password'] = 'sometimes|required';
|
||||
$result['service_name'] = 'sometimes|required';
|
||||
$result['service_region'] = 'sometimes|required';
|
||||
$result['container_name'] = 'sometimes|required';
|
||||
$result['cdn_url'] = 'sometimes|url';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ namespace App\Services;
|
||||
|
||||
use App\Album;
|
||||
use App\AlbumSources\IAlbumSource;
|
||||
use App\Helpers\FileHelper;
|
||||
use App\Helpers\ImageHelper;
|
||||
use App\Helpers\ThemeHelper;
|
||||
use App\Photo;
|
||||
@ -48,13 +49,12 @@ class PhotoService
|
||||
$this->themeHelper = new ThemeHelper();
|
||||
}
|
||||
|
||||
public function analyse()
|
||||
public function analyse($queueToken)
|
||||
{
|
||||
/** @var Album $album */
|
||||
$album = $this->photo->album;
|
||||
$albumSource = $album->getAlbumSource();
|
||||
|
||||
$photoFile = $albumSource->getPathToPhoto($this->photo);
|
||||
$photoFile = join(DIRECTORY_SEPARATOR, [
|
||||
FileHelper::getQueuePath($queueToken),
|
||||
$this->photo->storage_file_name
|
||||
]);
|
||||
|
||||
$imageInfo = null;
|
||||
$originalPhotoResource = $this->imageHelper->openImage($photoFile, $imageInfo);
|
||||
@ -116,6 +116,9 @@ class PhotoService
|
||||
$this->photo->is_analysed = true;
|
||||
$this->photo->save();
|
||||
|
||||
// Save the original
|
||||
$this->albumSource->saveThumbnail($this->photo, $photoFile);
|
||||
|
||||
$this->regenerateThumbnails($originalPhotoResource);
|
||||
}
|
||||
|
||||
@ -125,11 +128,11 @@ class PhotoService
|
||||
$currentSource = $this->photo->album->getAlbumSource();
|
||||
$newSource = $newAlbum->getAlbumSource();
|
||||
|
||||
// Get the current photo's path
|
||||
$file = new File($currentSource->getPathToPhoto($this->photo));
|
||||
// First export the original photo from the storage provider
|
||||
$photoPath = $this->downloadToTemporaryFolder();
|
||||
|
||||
// Save to the new album
|
||||
$newSource->saveUploadedPhoto($file, $this->photo->storage_file_name);
|
||||
$newSource->saveThumbnail($this->photo, $photoPath);
|
||||
|
||||
// Delete the original
|
||||
$this->delete();
|
||||
@ -166,25 +169,39 @@ class PhotoService
|
||||
|
||||
public function flip($horizontal, $vertical)
|
||||
{
|
||||
// First export the original photo from the storage provider
|
||||
$photoPath = $this->downloadToTemporaryFolder();
|
||||
|
||||
$imageInfo = array();
|
||||
$photoPath = $this->albumSource->getPathToPhoto($this->photo);
|
||||
$originalPhotoImage = $this->imageHelper->openImage($photoPath, $imageInfo);
|
||||
if ($this->imageHelper->flipImage($originalPhotoImage, boolval($horizontal), boolval($vertical)))
|
||||
{
|
||||
$this->imageHelper->saveImage($originalPhotoImage, $photoPath, $imageInfo);
|
||||
|
||||
// Update and save the original image back to the storage provider
|
||||
$this->albumSource->saveThumbnail($this->photo, $photoPath);
|
||||
|
||||
// Re-create the thumbnails
|
||||
$this->regenerateThumbnails($originalPhotoImage);
|
||||
|
||||
$this->photo->save();
|
||||
}
|
||||
|
||||
// Remove the temp file
|
||||
@unlink($photoPath);
|
||||
}
|
||||
|
||||
public function regenerateThumbnails($originalPhotoResource = null)
|
||||
{
|
||||
$photoPath = null;
|
||||
|
||||
if (is_null($originalPhotoResource))
|
||||
{
|
||||
// First export the original photo from the storage provider
|
||||
$photoPath = $this->downloadToTemporaryFolder();
|
||||
|
||||
$imageInfo = null;
|
||||
$originalPhotoResource = $this->imageHelper->openImage($this->albumSource->getPathToPhoto($this->photo), $imageInfo);
|
||||
$originalPhotoResource = $this->imageHelper->openImage($photoPath, $imageInfo);
|
||||
}
|
||||
|
||||
// Generate and save thumbnails
|
||||
@ -195,18 +212,30 @@ class PhotoService
|
||||
foreach ($thumbnailsRequired as $thumbnail)
|
||||
{
|
||||
$generatedThumbnailPath = $this->imageHelper->generateThumbnail($originalPhotoResource, $this->photo, $thumbnail);
|
||||
$this->albumSource->saveThumbnail($this->photo, $thumbnail, $generatedThumbnailPath);
|
||||
$this->albumSource->saveThumbnail($this->photo, $generatedThumbnailPath, $thumbnail['name']);
|
||||
}
|
||||
|
||||
if (is_null($originalPhotoResource) && !is_null($photoPath))
|
||||
{
|
||||
// Remove the temp file
|
||||
@unlink($photoPath);
|
||||
}
|
||||
}
|
||||
|
||||
public function rotate($angle)
|
||||
{
|
||||
$imageInfo = array();
|
||||
$photoPath = $this->albumSource->getPathToPhoto($this->photo);
|
||||
|
||||
// First export the photo from the storage provider
|
||||
$photoPath = $this->downloadToTemporaryFolder();
|
||||
|
||||
$originalPhotoImage = $this->imageHelper->openImage($photoPath, $imageInfo);
|
||||
$originalPhotoImage = $this->imageHelper->rotateImage($originalPhotoImage, intval($angle));
|
||||
$this->imageHelper->saveImage($originalPhotoImage, $photoPath, $imageInfo);
|
||||
|
||||
// Update and save the original image back to the storage provider
|
||||
$this->albumSource->saveThumbnail($this->photo, $photoPath);
|
||||
|
||||
if ($angle == 90 || $angle == 270)
|
||||
{
|
||||
$width = $this->photo->width;
|
||||
@ -217,6 +246,27 @@ class PhotoService
|
||||
$this->regenerateThumbnails($originalPhotoImage);
|
||||
|
||||
$this->photo->save();
|
||||
|
||||
// Remove the temp file
|
||||
@unlink($photoPath);
|
||||
}
|
||||
|
||||
private function downloadToTemporaryFolder()
|
||||
{
|
||||
$photoPath = tempnam(sys_get_temp_dir(), 'BlueTwilight_');
|
||||
$photoHandle = fopen($photoPath, 'w');
|
||||
|
||||
$stream = $this->albumSource->fetchPhotoContent($this->photo);
|
||||
$stream->rewind();
|
||||
while (!$stream->feof())
|
||||
{
|
||||
fwrite($photoHandle, $stream->read(4096));
|
||||
}
|
||||
fflush($photoHandle);
|
||||
fclose($photoHandle);
|
||||
$stream->close();
|
||||
|
||||
return $photoPath;
|
||||
}
|
||||
|
||||
private function metadataCameraMake(array $exifData)
|
||||
|
@ -15,7 +15,20 @@ class Storage extends Model
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name', 'source', 'is_default', 'location', 'is_internal', 'is_active'
|
||||
'name',
|
||||
'source',
|
||||
'is_default',
|
||||
'location',
|
||||
'is_internal',
|
||||
'is_active',
|
||||
'auth_url',
|
||||
'tenant_name',
|
||||
'username',
|
||||
'password',
|
||||
'service_name',
|
||||
'service_region',
|
||||
'container_name',
|
||||
'cdn_url'
|
||||
];
|
||||
|
||||
public function albums()
|
||||
|
@ -7,7 +7,9 @@
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"laravel/framework": "5.3.*",
|
||||
"laravelcollective/html": "5.3.*"
|
||||
"laravelcollective/html": "5.3.*",
|
||||
"rackspace/php-opencloud": "^1.16",
|
||||
"doctrine/dbal": "^2.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"fzaninotto/faker": "~1.4",
|
||||
|
583
composer.lock
generated
583
composer.lock
generated
@ -4,8 +4,8 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "c3e85190a6742649a1f169529151e61a",
|
||||
"content-hash": "d5b24ed9a8a6b89d2dd2f6f3b8049a0e",
|
||||
"hash": "a5bcf947cf94af4452c3bbb308f3231c",
|
||||
"content-hash": "8da0234bc3f5e6de745254c161031630",
|
||||
"packages": [
|
||||
{
|
||||
"name": "classpreloader/classpreloader",
|
||||
@ -94,6 +94,354 @@
|
||||
"description": "implementation of xdg base directory specification for php",
|
||||
"time": "2014-10-24 07:27:01"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
"version": "v1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/annotations.git",
|
||||
"reference": "30e07cf03edc3cd3ef579d0dd4dd8c58250799a5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/annotations/zipball/30e07cf03edc3cd3ef579d0dd4dd8c58250799a5",
|
||||
"reference": "30e07cf03edc3cd3ef579d0dd4dd8c58250799a5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/lexer": "1.*",
|
||||
"php": "^5.6 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/cache": "1.*",
|
||||
"phpunit/phpunit": "^5.6.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Docblock Annotations Parser",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"annotations",
|
||||
"docblock",
|
||||
"parser"
|
||||
],
|
||||
"time": "2016-10-24 11:45:47"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/cache",
|
||||
"version": "v1.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/cache.git",
|
||||
"reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/f8af318d14bdb0eff0336795b428b547bd39ccb6",
|
||||
"reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "~5.5|~7.0"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/common": ">2.2,<2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.8|~5.0",
|
||||
"predis/predis": "~1.0",
|
||||
"satooshi/php-coveralls": "~0.6"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.6.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Caching library offering an object-oriented API for many cache backends",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching"
|
||||
],
|
||||
"time": "2015-12-31 16:37:02"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/collections",
|
||||
"version": "v1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/collections.git",
|
||||
"reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
|
||||
"reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Doctrine\\Common\\Collections\\": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Collections Abstraction library",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"array",
|
||||
"collections",
|
||||
"iterator"
|
||||
],
|
||||
"time": "2015-04-14 22:21:58"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/common",
|
||||
"version": "v2.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/common.git",
|
||||
"reference": "a579557bc689580c19fee4e27487a67fe60defc0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/common/zipball/a579557bc689580c19fee4e27487a67fe60defc0",
|
||||
"reference": "a579557bc689580c19fee4e27487a67fe60defc0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/annotations": "1.*",
|
||||
"doctrine/cache": "1.*",
|
||||
"doctrine/collections": "1.*",
|
||||
"doctrine/inflector": "1.*",
|
||||
"doctrine/lexer": "1.*",
|
||||
"php": "~5.5|~7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.8|~5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\": "lib/Doctrine/Common"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Common Library for Doctrine projects",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"annotations",
|
||||
"collections",
|
||||
"eventmanager",
|
||||
"persistence",
|
||||
"spl"
|
||||
],
|
||||
"time": "2015-12-25 13:18:31"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/dbal",
|
||||
"version": "v2.5.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/dbal.git",
|
||||
"reference": "9f8c05cd5225a320d56d4bfdb4772f10d045a0c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/dbal/zipball/9f8c05cd5225a320d56d4bfdb4772f10d045a0c9",
|
||||
"reference": "9f8c05cd5225a320d56d4bfdb4772f10d045a0c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/common": ">=2.4,<2.7-dev",
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*",
|
||||
"symfony/console": "2.*||^3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "For helpful console commands such as SQL execution and import of files."
|
||||
},
|
||||
"bin": [
|
||||
"bin/doctrine-dbal"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.5.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Doctrine\\DBAL\\": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Database Abstraction Layer",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"database",
|
||||
"dbal",
|
||||
"persistence",
|
||||
"queryobject"
|
||||
],
|
||||
"time": "2016-09-09 19:13:33"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/inflector",
|
||||
"version": "v1.1.0",
|
||||
@ -161,6 +509,153 @@
|
||||
],
|
||||
"time": "2015-11-06 14:35:42"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/lexer",
|
||||
"version": "v1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/lexer.git",
|
||||
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
|
||||
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Doctrine\\Common\\Lexer\\": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"lexer",
|
||||
"parser"
|
||||
],
|
||||
"time": "2014-09-09 13:34:57"
|
||||
},
|
||||
{
|
||||
"name": "guzzle/guzzle",
|
||||
"version": "v3.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
|
||||
"reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"php": ">=5.3.3",
|
||||
"symfony/event-dispatcher": ">=2.1"
|
||||
},
|
||||
"replace": {
|
||||
"guzzle/batch": "self.version",
|
||||
"guzzle/cache": "self.version",
|
||||
"guzzle/common": "self.version",
|
||||
"guzzle/http": "self.version",
|
||||
"guzzle/inflection": "self.version",
|
||||
"guzzle/iterator": "self.version",
|
||||
"guzzle/log": "self.version",
|
||||
"guzzle/parser": "self.version",
|
||||
"guzzle/plugin": "self.version",
|
||||
"guzzle/plugin-async": "self.version",
|
||||
"guzzle/plugin-backoff": "self.version",
|
||||
"guzzle/plugin-cache": "self.version",
|
||||
"guzzle/plugin-cookie": "self.version",
|
||||
"guzzle/plugin-curlauth": "self.version",
|
||||
"guzzle/plugin-error-response": "self.version",
|
||||
"guzzle/plugin-history": "self.version",
|
||||
"guzzle/plugin-log": "self.version",
|
||||
"guzzle/plugin-md5": "self.version",
|
||||
"guzzle/plugin-mock": "self.version",
|
||||
"guzzle/plugin-oauth": "self.version",
|
||||
"guzzle/service": "self.version",
|
||||
"guzzle/stream": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/cache": "*",
|
||||
"monolog/monolog": "1.*",
|
||||
"phpunit/phpunit": "3.7.*",
|
||||
"psr/log": "1.0.*",
|
||||
"symfony/class-loader": "*",
|
||||
"zendframework/zend-cache": "<2.3",
|
||||
"zendframework/zend-log": "<2.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.8-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Guzzle": "src/",
|
||||
"Guzzle\\Tests": "tests/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "Guzzle Community",
|
||||
"homepage": "https://github.com/guzzle/guzzle/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"client",
|
||||
"curl",
|
||||
"framework",
|
||||
"http",
|
||||
"http client",
|
||||
"rest",
|
||||
"web service"
|
||||
],
|
||||
"abandoned": "guzzlehttp/guzzle",
|
||||
"time": "2014-01-28 22:29:15"
|
||||
},
|
||||
{
|
||||
"name": "jakub-onderka/php-console-color",
|
||||
"version": "0.1",
|
||||
@ -571,6 +1066,33 @@
|
||||
],
|
||||
"time": "2016-08-10 08:55:11"
|
||||
},
|
||||
{
|
||||
"name": "mikemccabe/json-patch-php",
|
||||
"version": "0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mikemccabe/json-patch-php.git",
|
||||
"reference": "b3af30a6aec7f6467c773cd49b2d974a70f7c0d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mikemccabe/json-patch-php/zipball/b3af30a6aec7f6467c773cd49b2d974a70f7c0d4",
|
||||
"reference": "b3af30a6aec7f6467c773cd49b2d974a70f7c0d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"mikemccabe\\JsonPatch\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0"
|
||||
],
|
||||
"description": "Produce and apply json-patch objects",
|
||||
"time": "2015-01-05 21:19:54"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "1.21.0",
|
||||
@ -958,6 +1480,63 @@
|
||||
],
|
||||
"time": "2016-03-09 05:03:14"
|
||||
},
|
||||
{
|
||||
"name": "rackspace/php-opencloud",
|
||||
"version": "v1.16.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rackspace/php-opencloud.git",
|
||||
"reference": "d6b71feed7f9e7a4b52e0240a79f06473ba69c8c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rackspace/php-opencloud/zipball/d6b71feed7f9e7a4b52e0240a79f06473ba69c8c",
|
||||
"reference": "d6b71feed7f9e7a4b52e0240a79f06473ba69c8c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzle/guzzle": "~3.8",
|
||||
"mikemccabe/json-patch-php": "~0.1",
|
||||
"php": ">=5.4",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"apigen/apigen": "~4.0",
|
||||
"fabpot/php-cs-fixer": "1.0.*@dev",
|
||||
"jakub-onderka/php-parallel-lint": "0.*",
|
||||
"phpspec/prophecy": "~1.4",
|
||||
"phpunit/phpunit": "4.3.*",
|
||||
"satooshi/php-coveralls": "0.6.*@dev"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"OpenCloud": [
|
||||
"lib/"
|
||||
]
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jamie Hannaford",
|
||||
"email": "jamie.hannaford@rackspace.com",
|
||||
"homepage": "https://github.com/jamiehannaford"
|
||||
}
|
||||
],
|
||||
"description": "PHP SDK for Rackspace/OpenStack APIs",
|
||||
"keywords": [
|
||||
"Openstack",
|
||||
"nova",
|
||||
"opencloud",
|
||||
"rackspace",
|
||||
"swift"
|
||||
],
|
||||
"time": "2016-01-29 10:34:57"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "3.5.1",
|
||||
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddStorageOpenstackColumns extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('storages', function (Blueprint $table) {
|
||||
$table->string('auth_url')->nullable();
|
||||
$table->string('tenant_name')->nullable();
|
||||
$table->string('username')->nullable();
|
||||
$table->string('password')->nullable();
|
||||
$table->string('service_name')->nullable();
|
||||
$table->string('service_region')->nullable();
|
||||
$table->string('container_name')->nullable();
|
||||
$table->string('location')->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('storages', function (Blueprint $table) {
|
||||
$table->string('location')->change();
|
||||
$table->dropColumn('container_name');
|
||||
$table->dropColumn('service_region');
|
||||
$table->dropColumn('service_name');
|
||||
$table->dropColumn('password');
|
||||
$table->dropColumn('username');
|
||||
$table->dropColumn('tenant_name');
|
||||
$table->dropColumn('auth_url');
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddCdnUrlStorageColumn extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('storages', function (Blueprint $table) {
|
||||
$table->string('cdn_url')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('storages', function (Blueprint $table) {
|
||||
$table->dropColumn('cdn_url');
|
||||
});
|
||||
}
|
||||
}
|
@ -93,10 +93,16 @@ function EditPhotosViewModel(album_id, language, urls) {
|
||||
self.albums = ko.observableArray();
|
||||
self.bulkModifyMethod = ko.observable();
|
||||
self.photoIDs = ko.observableArray();
|
||||
self.isSubmitting = false;
|
||||
|
||||
/* Called when the Apply button on the "bulk apply selected actions" form is clicked */
|
||||
self.bulkModifySelected = function()
|
||||
{
|
||||
if (self.isSubmitting)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var bulk_form = $('form#bulk-modify-form');
|
||||
|
||||
if (self.bulkModifyMethod() == 'change_album')
|
||||
@ -104,8 +110,11 @@ function EditPhotosViewModel(album_id, language, urls) {
|
||||
// Prompt for the new album to move to
|
||||
self.promptForNewAlbum(function(dialog) {
|
||||
var album_id = $('select', dialog).val();
|
||||
$('input[name="new-album-id"]', form).val(album_id);
|
||||
bulk_form.submit();
|
||||
$('input[name="new-album-id"]', bulk_form).val(album_id);
|
||||
|
||||
self.isSubmitting = true;
|
||||
$('button[name="bulk-apply"]', bulk_form).click();
|
||||
_bt_showLoadingModal();
|
||||
});
|
||||
|
||||
return false;
|
||||
@ -125,7 +134,9 @@ function EditPhotosViewModel(album_id, language, urls) {
|
||||
label: language.action_delete,
|
||||
className: "btn-danger",
|
||||
callback: function() {
|
||||
bulk_form.submit();
|
||||
self.isSubmitting = true;
|
||||
$('button[name="bulk-apply"]', bulk_form).click();
|
||||
_bt_showLoadingModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -151,6 +162,7 @@ function EditPhotosViewModel(album_id, language, urls) {
|
||||
{
|
||||
window.location.reload();
|
||||
});
|
||||
_bt_showLoadingModal();
|
||||
});
|
||||
|
||||
return false;
|
||||
@ -434,11 +446,12 @@ function StorageLocationsViewModel() {
|
||||
/**
|
||||
* This model is used by admin/show_album.blade.php to handle photo uploads.
|
||||
* @param album_id ID of the album the photos are being uploaded to
|
||||
* @param queue_token Unique token of the upload queue to save the photos to
|
||||
* @param language Array containing language strings
|
||||
* @param urls Array containing URLs
|
||||
* @constructor
|
||||
*/
|
||||
function UploadPhotosViewModel(album_id, language, urls) {
|
||||
function UploadPhotosViewModel(album_id, queue_token, language, urls) {
|
||||
var self = this;
|
||||
|
||||
self.currentStatus = ko.observable('');
|
||||
@ -510,6 +523,7 @@ function UploadPhotosViewModel(album_id, language, urls) {
|
||||
self.uploadFile = function uploadImageFile(formObject, imageFile) {
|
||||
var formData = new FormData();
|
||||
formData.append('album_id', album_id);
|
||||
formData.append('queue_token', queue_token);
|
||||
formData.append('photo[]', imageFile, imageFile.name);
|
||||
|
||||
$.ajax(
|
||||
|
@ -30,8 +30,15 @@ return [
|
||||
'settings_restrict_originals_download' => 'Restrict access to original images',
|
||||
'settings_restrict_originals_download_help' => 'With this option enabled, only the photo\'s owner can download the original high-resolution images.',
|
||||
'storage_active_label' => 'Location is active. Uncheck to prevent creating new albums in this location.',
|
||||
'storage_auth_url_label' => 'Authentication URL:',
|
||||
'storage_cdn_url_label' => 'Public CDN URL (if supported and enabled):',
|
||||
'storage_container_name_label' => 'Container name:',
|
||||
'storage_driver_label' => 'Storage driver:',
|
||||
'storage_location_label' => 'Physical location:',
|
||||
'storage_service_name_label' => 'Service name:',
|
||||
'storage_service_region_label' => 'Region:',
|
||||
'storage_tenant_name_label' => 'Tenant:',
|
||||
'username_label' => 'Username:',
|
||||
'upload_action' => 'Upload',
|
||||
'save_action' => 'Save Changes'
|
||||
];
|
@ -1,12 +1,14 @@
|
||||
<?php
|
||||
return [
|
||||
'album_sources' => [
|
||||
'filesystem' => 'Local filesystem'
|
||||
'filesystem' => 'Local filesystem',
|
||||
'openstack' => 'OpenStack cloud storage'
|
||||
],
|
||||
'app_name' => 'Blue Twilight',
|
||||
'copyright' => '© :years :link_startAndy Heathershaw:link_end',
|
||||
'licensed_to' => 'Licensed to :name (:number)',
|
||||
'version_number' => 'Version :version',
|
||||
'please_wait' => 'Please wait...',
|
||||
'post_max_exceeded' => 'Your upload exceeded the maximum size the web server is configured to allow. Please check the value of the "post_max_size" parameter in php.ini.',
|
||||
'powered_by' => 'Powered by :link_startBlue Twilight:link_end - the self-hosted photo gallery software.',
|
||||
'units' => [
|
||||
|
@ -115,5 +115,6 @@ return [
|
||||
// Added by Andy H. for custom validators
|
||||
'dir_empty' => 'The path must be an empty folder.',
|
||||
'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.',
|
||||
'photo_name_required' => 'The name field is required.'
|
||||
];
|
||||
|
@ -56,65 +56,10 @@
|
||||
viewModel.imagesToAnalyse.push(new AnalyseImageViewModel({
|
||||
'id': '{{ $photo->id }}',
|
||||
'name': '{!! addslashes($photo->name) !!}',
|
||||
'url': '{{ route('photos.analyse', ['id' => $photo->id]) }}'
|
||||
'url': '{{ route('photos.analyse', ['id' => $photo->id, 'queue_token' => $queue_token]) }}'
|
||||
}));
|
||||
@endforeach
|
||||
|
||||
ko.applyBindings(viewModel);
|
||||
|
||||
/*
|
||||
|
||||
$(document).ready(function() {
|
||||
number_total = $('#file-list p').length;
|
||||
|
||||
if (number_total == 0) {
|
||||
$('#status-panel').hide();
|
||||
$('#complete-panel').show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#file-list p').each(function (index, element) {
|
||||
var photo_id = $(element).data('photo-id');
|
||||
var url = '{{ route('photos.analyse', ['id' => 0]) }}';
|
||||
url = url.replace(/0$/, photo_id);
|
||||
|
||||
$.ajax(
|
||||
url,
|
||||
{
|
||||
complete: function () {
|
||||
redrawProgressBar();
|
||||
|
||||
if (number_successful + number_error >= number_total) {
|
||||
$('#status-panel').hide();
|
||||
$('#complete-panel').show();
|
||||
}
|
||||
},
|
||||
dataType: 'json',
|
||||
error: function (xhr, textStatus, errorThrown) {
|
||||
$('i', '#file-list p[data-photo-id=' + photo_id + ']')
|
||||
.addClass('text-danger')
|
||||
.addClass('fa-times');
|
||||
number_error++;
|
||||
},
|
||||
method: 'POST',
|
||||
success: function (data) {
|
||||
if (data.is_successful) {
|
||||
$('i', '#file-list p[data-photo-id=' + photo_id + ']')
|
||||
.addClass('text-success')
|
||||
.addClass('fa-check');
|
||||
number_successful++;
|
||||
}
|
||||
else {
|
||||
$('i', '#file-list p[data-photo-id=' + photo_id + ']')
|
||||
.addClass('text-danger')
|
||||
.addClass('fa-times');
|
||||
number_error++;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
});*/
|
||||
</script>
|
||||
@endpush
|
@ -23,20 +23,16 @@
|
||||
<p>@lang('admin.create_album_intro2')</p>
|
||||
<hr/>
|
||||
|
||||
@if (count($errors) > 0)
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $form_error)
|
||||
<li>{{ $form_error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{!! Form::open(['route' => 'albums.store', 'method' => 'POST']) !!}
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('name', trans('forms.name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('name', old('name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -52,6 +52,111 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="local-filesystem" data-bind="visible: selectedLocation() == 'OpenStackSource'">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('auth_url') ? ' has-error' : '' }}">
|
||||
{!! Form::label('auth_url', trans('forms.storage_auth_url_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('auth_url', old('auth_url'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('auth_url'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('auth_url') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('tenant_name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('tenant_name', trans('forms.storage_tenant_name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('tenant_name', old('tenant_name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('tenant_name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('tenant_name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('username') ? ' has-error' : '' }}">
|
||||
{!! Form::label('username', trans('forms.username_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('username', old('username'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('username'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('username') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
{!! Form::label('password', trans('forms.password_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('password', old('password'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('service_name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('service_name', trans('forms.storage_service_name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('service_name', old('service_name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('service_name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('service_name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('service_region') ? ' has-error' : '' }}">
|
||||
{!! Form::label('service_region', trans('forms.storage_service_region_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('service_region', old('service_region'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('service_region'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('service_region') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('container_name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('container_name', trans('forms.storage_container_name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('container_name', old('container_name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('container_name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('container_name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('cdn_url') ? ' has-error' : '' }}">
|
||||
{!! Form::label('cdn_url', trans('forms.storage_cdn_url_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('cdn_url', old('cdn_url'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('cdn_url'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('cdn_url') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
|
@ -22,45 +22,59 @@
|
||||
<p>@lang('admin.create_user_intro')</p>
|
||||
<hr/>
|
||||
|
||||
@if (count($errors) > 0)
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $form_error)
|
||||
<li>{{ $form_error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{!! Form::open(['route' => 'user.store', 'method' => 'POST']) !!}
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('name', trans('forms.name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('name', old('name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
{!! Form::label('email', trans('forms.email_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('email', old('email'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('email'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
{!! Form::label('password', trans('forms.password_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::password('password', ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">
|
||||
{!! Form::label('password_confirmation', trans('forms.password_confirm_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::password('password_confirmation', ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('password_confirmation'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password_confirmation') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -24,20 +24,16 @@
|
||||
<p>@lang('admin.edit_album_intro2', ['album_name' => $album->name])</p>
|
||||
<hr/>
|
||||
|
||||
@if (count($errors) > 0)
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{!! Form::model($album, ['route' => ['albums.update', $album->id], 'method' => 'PUT']) !!}
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('name', trans('forms.name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('name', old('name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -48,6 +48,112 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@if ($storage->source == 'OpenStackSource')
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('auth_url') ? ' has-error' : '' }}">
|
||||
{!! Form::label('auth_url', trans('forms.storage_auth_url_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('auth_url', old('auth_url'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('auth_url'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('auth_url') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('tenant_name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('tenant_name', trans('forms.storage_tenant_name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('tenant_name', old('tenant_name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('tenant_name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('tenant_name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('username') ? ' has-error' : '' }}">
|
||||
{!! Form::label('username', trans('forms.username_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('username', old('username'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('username'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('username') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
{!! Form::label('password', trans('forms.password_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('password', old('password'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('service_name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('service_name', trans('forms.storage_service_name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('service_name', old('service_name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('service_name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('service_name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group{{ $errors->has('service_region') ? ' has-error' : '' }}">
|
||||
{!! Form::label('service_region', trans('forms.storage_service_region_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('service_region', old('service_region'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('service_region'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('service_region') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('container_name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('container_name', trans('forms.storage_container_name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('container_name', old('container_name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('container_name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('container_name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('cdn_url') ? ' has-error' : '' }}">
|
||||
{!! Form::label('cdn_url', trans('forms.storage_cdn_url_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('cdn_url', old('cdn_url'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('cdn_url'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('cdn_url') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ route('storage.index') }}" class="btn btn-default">@lang('forms.cancel_action')</a>
|
||||
{!! Form::submit(trans('forms.save_action'), ['class' => 'btn btn-success']) !!}
|
||||
|
@ -22,45 +22,59 @@
|
||||
<p>@lang('admin.edit_user_intro')</p>
|
||||
<hr/>
|
||||
|
||||
@if (count($errors) > 0)
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $form_error)
|
||||
<li>{{ $form_error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{!! Form::model($user, ['route' => ['user.update', $user->id], 'method' => 'PUT']) !!}
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
|
||||
{!! Form::label('name', trans('forms.name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('name', old('name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
{!! Form::label('email', trans('forms.email_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('email', old('email'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('email'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
{!! Form::label('password', trans('forms.password_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::password('password', ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">
|
||||
{!! Form::label('password_confirmation', trans('forms.password_confirm_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::password('password_confirmation', ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('password_confirmation'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password_confirmation') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -36,7 +36,9 @@
|
||||
{{ $storage->name }}
|
||||
@if ($storage->is_default) <i class="fa fa-fw fa-check text-success"></i>@endif
|
||||
@if (!$storage->is_active) <i class="fa fa-fw fa-minus-circle text-danger"></i>@endif
|
||||
</span><br/>{{ $storage->location }}
|
||||
</span><br/>
|
||||
@if ($storage->source == 'LocalFilesystemSource'){{ $storage->location }}@endif
|
||||
@if ($storage->source == 'OpenStackSource'){{ $storage->container_name }} - {{ $storage->service_name }}, {{ $storage->service_region }}@endif
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<a href="{{ route('storage.edit', ['id' => $storage->id]) }}" class="btn btn-default">@lang('forms.edit_action')</a>
|
||||
|
@ -89,6 +89,7 @@
|
||||
<div class="col-sm-5" style="margin-bottom: 20px;">
|
||||
{!! Form::open(['route' => 'photos.store', 'method' => 'POST', 'files' => true, 'id' => 'single-upload-form']) !!}
|
||||
{!! Form::hidden('album_id', $album->id) !!}
|
||||
{!! Form::hidden('queue_token', $queue_token) !!}
|
||||
|
||||
<div class="form-group">
|
||||
{!! Form::file('photo[]', ['class' => 'control-label', 'multiple' => 'multiple', 'id' => 'single-upload-files']) !!}
|
||||
@ -120,7 +121,7 @@
|
||||
</p>
|
||||
<p data-bind="visible: imagesUploaded() > 0">
|
||||
@lang('admin.upload_file_failed_continue')<br /><br/>
|
||||
<a href="{{ route('albums.analyse', ['id' => $album->id]) }}" class="btn btn-primary">@lang('forms.continue_action')</a>
|
||||
<a href="{{ route('albums.analyse', ['id' => $album->id, 'queue_token' => $queue_token]) }}" class="btn btn-primary">@lang('forms.continue_action')</a>
|
||||
</p>
|
||||
|
||||
<ul data-bind="foreach: statusMessages">
|
||||
@ -141,6 +142,7 @@
|
||||
|
||||
{!! Form::open(['route' => 'photos.storeBulk', 'method' => 'POST', 'files' => true, 'id' => 'bulk-upload-form']) !!}
|
||||
{!! Form::hidden('album_id', $album->id) !!}
|
||||
{!! Form::hidden('queue_token', $queue_token) !!}
|
||||
|
||||
<div class="form-group">
|
||||
{!! Form::file('archive', ['class' => 'control-label']) !!}
|
||||
@ -159,9 +161,15 @@
|
||||
<h4><i class="fa fa-fw fa-info"></i> @lang('admin.album_basic_info_heading')</h4>
|
||||
<p>@lang('admin.album_basic_info_intro')</p>
|
||||
|
||||
<div class="form-group" style="margin-top: 20px;">
|
||||
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}" style="margin-top: 20px;">
|
||||
{!! Form::label('name', trans('forms.name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text('name', old('name'), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has('name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@ -244,14 +252,14 @@
|
||||
language.upload_status = '{!! addslashes(trans('admin.upload_file_status_progress')) !!}';
|
||||
|
||||
var urls = [];
|
||||
urls.analyse = '{{ route('albums.analyse', ['id' => $album->id]) }}';
|
||||
urls.analyse = '{{ route('albums.analyse', ['id' => $album->id, 'queue_token' => $queue_token]) }}';
|
||||
urls.delete_photo = '{{ route('photos.destroy', ['id' => 0]) }}';
|
||||
urls.flip_photo = '{{ route('photos.flip', ['id' => 0, 'horizontal' => -1, 'vertical' => -2]) }}';
|
||||
urls.move_photo = '{{ route('photos.move', ['photoId' => 0]) }}';
|
||||
urls.regenerate_thumbnails = '{{ route('photos.regenerateThumbnails', ['photoId' => 0]) }}';
|
||||
urls.rotate_photo = '{{ route('photos.rotate', ['id' => 0, 'angle' => 1]) }}';
|
||||
|
||||
var viewModel = new UploadPhotosViewModel('{{ $album->id }}', language, urls);
|
||||
var viewModel = new UploadPhotosViewModel('{{ $album->id }}', '{{ $queue_token }}', language, urls);
|
||||
var editViewModel = new EditPhotosViewModel('{{ $album->id }}', language, urls);
|
||||
|
||||
// Populate the list of albums in the view model
|
||||
|
@ -78,6 +78,14 @@
|
||||
<script src="themes/base/js/knockout.min.js?v={{ urlencode(config('app.version')) }}"></script>
|
||||
<script src="themes/base/js/app.js?v={{ urlencode(config('app.version')) }}"></script>
|
||||
<script type="text/javascript">
|
||||
function _bt_showLoadingModal() {
|
||||
bootbox.dialog({
|
||||
closeButton: false,
|
||||
message: '<center><img src="{{ asset('ripple.svg') }}"/></center>',
|
||||
title: '@lang('global.please_wait')'
|
||||
});
|
||||
}
|
||||
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
|
@ -41,9 +41,16 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-10">
|
||||
<div class="form-group">
|
||||
@php($validation_field_name = ('photo.' . $photo->id . '.name'))
|
||||
<div class="form-group{{ $errors->has($validation_field_name) ? ' has-error' : '' }}">
|
||||
{!! Form::label($field_prefix . '[name]', trans('forms.name_label'), ['class' => 'control-label']) !!}
|
||||
{!! Form::text($field_prefix . '[name]', old('name', $photo->name), ['class' => 'form-control']) !!}
|
||||
|
||||
@if ($errors->has($validation_field_name))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first($validation_field_name) }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -21,12 +21,12 @@ Route::group(['prefix' => 'admin'], function () {
|
||||
Route::get('settings', 'Admin\DefaultController@settings')->name('admin.settings');
|
||||
|
||||
// Album management
|
||||
Route::get('albums/{id}/analyse', 'Admin\AlbumController@analyse')->name('albums.analyse');
|
||||
Route::get('albums/{id}/analyse/{queue_token}', 'Admin\AlbumController@analyse')->name('albums.analyse');
|
||||
Route::get('albums/{id}/delete', 'Admin\AlbumController@delete')->name('albums.delete');
|
||||
Route::resource('albums', 'Admin\AlbumController');
|
||||
|
||||
// Photo management
|
||||
Route::post('photos/analyse/{id}', 'Admin\PhotoController@analyse')->name('photos.analyse');
|
||||
Route::post('photos/analyse/{id}/{queue_token}', 'Admin\PhotoController@analyse')->name('photos.analyse');
|
||||
Route::post('photos/flip/{photoId}/{horizontal}/{vertical}', 'Admin\PhotoController@flip')->name('photos.flip');
|
||||
Route::post('photos/move/{photoId}', 'Admin\PhotoController@move')->name('photos.move');
|
||||
Route::post('photos/regenerate-thumbnails/{photoId}', 'Admin\PhotoController@regenerateThumbnails')->name('photos.regenerateThumbnails');
|
||||
|
Loading…
Reference in New Issue
Block a user