Update media resizer
This commit is contained in:
parent
c8ee7f1514
commit
acf891f47a
53
Plugin.php
53
Plugin.php
|
@ -4,16 +4,11 @@ use Aweos\Resizer\Classes\CacheManager;
|
||||||
use Aweos\Resizer\Classes\FileObserver;
|
use Aweos\Resizer\Classes\FileObserver;
|
||||||
use Aweos\Resizer\Classes\ImageResizer;
|
use Aweos\Resizer\Classes\ImageResizer;
|
||||||
use Aweos\Resizer\Classes\ResizeJob;
|
use Aweos\Resizer\Classes\ResizeJob;
|
||||||
use Aweos\Resizer\Classes\TagGenerator;
|
|
||||||
use Aweos\Resizer\Console\ClearOld;
|
|
||||||
use Aweos\Resizer\Console\ResizeMake;
|
use Aweos\Resizer\Console\ResizeMake;
|
||||||
use Aweos\Resizer\Console\ResizePurge;
|
use Aweos\Resizer\Console\ResizePurge;
|
||||||
use Aweos\Resizer\FormWidgets\Responsiveimage;
|
use Aweos\Resizer\Lib\MediaPath;
|
||||||
use Aweos\Resizer\Models\Setting;
|
|
||||||
use Event;
|
use Event;
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Queue;
|
use Queue;
|
||||||
use Storage;
|
|
||||||
use System\Classes\MediaLibrary;
|
use System\Classes\MediaLibrary;
|
||||||
use System\Classes\PluginBase;
|
use System\Classes\PluginBase;
|
||||||
use System\Models\File;
|
use System\Models\File;
|
||||||
|
@ -47,7 +42,6 @@ class Plugin extends PluginBase
|
||||||
{
|
{
|
||||||
$this->registerConsoleCommand('resizer.resizemake', ResizeMake::class);
|
$this->registerConsoleCommand('resizer.resizemake', ResizeMake::class);
|
||||||
$this->registerConsoleCommand('resizer.resizepurge', ResizePurge::class);
|
$this->registerConsoleCommand('resizer.resizepurge', ResizePurge::class);
|
||||||
$this->registerConsoleCommand('resizer.clearold', ClearOld::class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,22 +60,22 @@ class Plugin extends PluginBase
|
||||||
});
|
});
|
||||||
|
|
||||||
Event::listen('media.file.upload', function($widget, $filePath, $uploadedFile) {
|
Event::listen('media.file.upload', function($widget, $filePath, $uploadedFile) {
|
||||||
if (app(FileObserver::class)->shouldProcessFile($filePath)) {
|
if ((new MediaPath($filePath))->shouldProcess()) {
|
||||||
Queue::push(ResizeJob::class, [$filePath]);
|
Queue::push(ResizeJob::class, [$filePath]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Event::listen('media.file.delete', function($widget, $filePath) {
|
Event::listen('media.file.delete', function($widget, $filePath) {
|
||||||
app(FileObserver::class)->delete($filePath);
|
app(FileObserver::class)->delete(new MediaPath($filePath));
|
||||||
app(CacheManager::class)->delete($filePath);
|
app(CacheManager::class)->delete(new MediaPath($filePath));
|
||||||
});
|
});
|
||||||
|
|
||||||
Event::listen('media.file.move', function($widget, $old, $new) {
|
Event::listen('media.file.move', function($widget, $old, $new) {
|
||||||
app(FileObserver::class)->rename($old, $new);
|
app(FileObserver::class)->rename(new MediaPath($old), new MediaPath($new));
|
||||||
app(CacheManager::class)->delete($old);
|
app(CacheManager::class)->delete(new MediaPath($old));
|
||||||
});
|
});
|
||||||
Event::listen('media.file.rename', function($widget, $old, $new) {
|
Event::listen('media.file.rename', function($widget, $old, $new) {
|
||||||
app(FileObserver::class)->rename($old, $new);
|
app(FileObserver::class)->rename(new MediaPath($old), new MediaPath($new));
|
||||||
app(CacheManager::class)->delete($old);
|
app(CacheManager::class)->delete(new MediaPath($old));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,34 +97,13 @@ class Plugin extends PluginBase
|
||||||
public function registerMarkupTags() {
|
public function registerMarkupTags() {
|
||||||
return [
|
return [
|
||||||
'filters' => [
|
'filters' => [
|
||||||
'resize' => fn ($media, $size = 'original', $sizes = null) => app(CacheManager::class)->get($media, $size, $sizes)
|
'resize' => fn ($media, $size = 'original', $sizes = null) => app(CacheManager::class)->get(
|
||||||
|
new MediaPath($media),
|
||||||
|
$size,
|
||||||
|
$sizes,
|
||||||
|
)
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function breakpointsToSizes($breakpoints) {
|
|
||||||
$s = [];
|
|
||||||
|
|
||||||
foreach ($breakpoints as $size => $bp) {
|
|
||||||
if ($size === 'max') { continue; }
|
|
||||||
|
|
||||||
$s[] = '(max-width: '.$size.'px) '.$bp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists('max', $breakpoints)) {
|
|
||||||
$s[] = $breakpoints['max'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'sizes="'.implode(', ', $s).'"';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function registerSchedule($schedule) {
|
|
||||||
$schedule->command('resize:make')->dailyAt('01:00');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function registerFormWidgets() {
|
|
||||||
return [
|
|
||||||
Responsiveimage::class => 'responsiveimage'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,47 +2,51 @@
|
||||||
|
|
||||||
namespace Aweos\Resizer\Classes;
|
namespace Aweos\Resizer\Classes;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Lib\MediaPath;
|
||||||
use Cache;
|
use Cache;
|
||||||
|
|
||||||
class CacheManager
|
class CacheManager
|
||||||
{
|
{
|
||||||
|
|
||||||
public FileObserver $fileObserver;
|
public TagGenerator $tagGenerator;
|
||||||
public TagGenerator $tag;
|
private string $tagAll = 'resizer';
|
||||||
|
|
||||||
public function __construct(FileObserver $fileObserver, TagGenerator $tag)
|
public function __construct(TagGenerator $tagGenerator)
|
||||||
{
|
{
|
||||||
$this->tag = $tag;
|
$this->tagGenerator = $tagGenerator;
|
||||||
$this->fileObserver = $fileObserver;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(string $path, string $size, ?string $sizes): string
|
public function get(MediaPath $path, string $size, ?string $sizes): string
|
||||||
{
|
{
|
||||||
return Cache::tags($this->getTag($path, $sizes))
|
return Cache::tags($this->pathTag($path, $size))->rememberForever(
|
||||||
->rememberForever($this->cacheKey($path, $size), fn () => $this->tag->generate($path, $size, $sizes));
|
$this->cacheKey($path, $size),
|
||||||
|
fn () => $this->tagGenerator->generate($path, $size, $sizes)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete(string $path): void
|
public function delete(MediaPath $path): void
|
||||||
{
|
{
|
||||||
$path = $this->fileObserver->normalizePath($path);
|
Cache::tags([$this->singlePathTag($path)])->flush();
|
||||||
Cache::tags("resizer.$path")->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getTag(string $path): array
|
|
||||||
{
|
|
||||||
return ['resizer', "resizer.{$this->fileObserver->normalizePath($path)}"];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function cacheKey(string $path, string $size): string
|
|
||||||
{
|
|
||||||
$normalPath = $this->fileObserver->normalizePath($path);
|
|
||||||
|
|
||||||
return "resizer.{$size}.{$normalPath}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function flush(): void
|
public function flush(): void
|
||||||
{
|
{
|
||||||
Cache::tags('resizer')->flush();
|
Cache::tags([$this->tagAll])->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function cacheKey(MediaPath $path, string $size): string
|
||||||
|
{
|
||||||
|
return "resizer.{$size}.{$path->normal()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private function pathTag(MediaPath $path, string $size): array
|
||||||
|
{
|
||||||
|
return [$this->tagAll, $this->singlePathTag($path)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function singlePathTag(MediaPath $path): string
|
||||||
|
{
|
||||||
|
return "resizer.{$path->normal()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Aweos\Resizer\Classes;
|
|
||||||
|
|
||||||
use Storage;
|
|
||||||
use Aweos\Resizer\Models\Setting;
|
|
||||||
use October\Rain\Database\Attach\Resizer;
|
|
||||||
use Aweos\Resizer\Models\Attachment;
|
|
||||||
|
|
||||||
class CompressJob {
|
|
||||||
|
|
||||||
public $attachment_id;
|
|
||||||
public $maxFilesize = 1920;
|
|
||||||
public $disk = 'uploads';
|
|
||||||
public $fullPath;
|
|
||||||
public $crop;
|
|
||||||
public $sizes;
|
|
||||||
|
|
||||||
public function fire($job, $data) {
|
|
||||||
$this->attachment_id = $data['attachment_id'];
|
|
||||||
$this->attachment = Attachment::find($this->attachment_id);
|
|
||||||
|
|
||||||
if (!$this->shouldResize()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->crop = $data['crop'];
|
|
||||||
|
|
||||||
$this->sizes = Setting::get('srcx');
|
|
||||||
|
|
||||||
Storage::disk($this->disk)->makeDirectory('cropped');
|
|
||||||
|
|
||||||
$this->fullPath = Storage::disk($this->disk)->path($this->attachment->source->path);
|
|
||||||
|
|
||||||
$this->crop();
|
|
||||||
$this->createVersions();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function crop() {
|
|
||||||
if ($this->crop === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$r = Resizer::open($this->fullPath);
|
|
||||||
$r->crop(floor($this->crop['x']), floor($this->crop['y']), floor($this->crop['w']), floor($this->crop['h']));
|
|
||||||
$r->save($this->fullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createVersions()
|
|
||||||
{
|
|
||||||
[ $width, $height ] = getimagesize($this->fullPath);
|
|
||||||
|
|
||||||
Storage::disk($this->disk)->makeDirectory($this->attachment->path);
|
|
||||||
|
|
||||||
if ($width > $this->maxFilesize) {
|
|
||||||
$r = Resizer::open($this->fullPath);
|
|
||||||
$r->resize($this->maxFilesize, 0);
|
|
||||||
$r->save($this->fullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
$r = Resizer::open($this->fullPath);
|
|
||||||
$r->save(Storage::disk($this->disk)->path($this->attachment->getVersionPath('full')));
|
|
||||||
|
|
||||||
[ $width, $height ] = getimagesize($this->fullPath);
|
|
||||||
|
|
||||||
foreach ($this->sizes as $w) {
|
|
||||||
if ($width < $w) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$r = Resizer::open($this->fullPath);
|
|
||||||
$r->resize($w, 0);
|
|
||||||
$r->save(Storage::disk($this->disk)->path($this->attachment->getVersionPath($w)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getStrategy() {
|
|
||||||
return app($this->strategy);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function shouldResize() {
|
|
||||||
return $this->attachment->source->isCroppable();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -2,68 +2,30 @@
|
||||||
|
|
||||||
namespace Aweos\Resizer\Classes;
|
namespace Aweos\Resizer\Classes;
|
||||||
|
|
||||||
use Aweos\Resizer\Models\Setting;
|
use Aweos\Resizer\Lib\MediaPath;
|
||||||
use Storage;
|
use Storage;
|
||||||
|
|
||||||
class FileObserver
|
class FileObserver
|
||||||
{
|
{
|
||||||
|
|
||||||
public function versionsPath(string $mediaPath): string
|
public function delete(MediaPath $path): void
|
||||||
{
|
{
|
||||||
return "uploads/public/c/{$this->normalizePath($mediaPath)}";
|
foreach ($path->versions() as $version) {
|
||||||
|
Storage::delete($version->get('path'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function normalizePath(string $path): string
|
if (empty(Storage::files($path->versionsDirPath()))) {
|
||||||
|
Storage::deleteDirectory($path->versionsDirPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rename(MediaPath $old, MediaPath $new): void
|
||||||
{
|
{
|
||||||
return preg_replace('|^/*|', '', $path);
|
foreach ($old->versions() as $version) {
|
||||||
}
|
Storage::move(
|
||||||
|
$version->get('path'),
|
||||||
public function fullMediaPath(string $path): string
|
$new->versionsDirPath().'/'.$new->filename().$version->get('size').$version->get('ext')
|
||||||
{
|
);
|
||||||
return "media/{$this->normalizePath($path)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function shouldProcessFile($file): bool
|
|
||||||
{
|
|
||||||
return collect(Setting::get('folders'))->pluck('folder')->first(
|
|
||||||
fn ($folder) => starts_with($file, $folder.'/')
|
|
||||||
) !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function delete($path): void
|
|
||||||
{
|
|
||||||
$dir = pathinfo($path, PATHINFO_DIRNAME);
|
|
||||||
$base = $dir.'/'.pathinfo($path, PATHINFO_FILENAME);
|
|
||||||
|
|
||||||
Storage::delete("uploads/public/c{$path}");
|
|
||||||
|
|
||||||
collect(Storage::files("uploads/public/c{$dir}"))->filter(
|
|
||||||
fn ($file) => preg_match('|'.preg_quote("uploads/public/c{$base}", '|').'-[0-9]+x[0-9]+\.[a-zA-Z]+$|', $file)
|
|
||||||
)->each(function ($path) {
|
|
||||||
Storage::delete($path);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (empty(Storage::allFiles("uploads/public/c{$dir}"))) {
|
|
||||||
Storage::deleteDirectory("uploads/public/c{$dir}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rename(string $old, string $new): void
|
|
||||||
{
|
|
||||||
$dir = pathinfo($old, PATHINFO_DIRNAME);
|
|
||||||
$base = pathinfo($old, PATHINFO_FILENAME);
|
|
||||||
$newBase = pathinfo($new, PATHINFO_FILENAME);
|
|
||||||
$newDir = pathinfo($new, PATHINFO_DIRNAME);
|
|
||||||
|
|
||||||
foreach (Storage::files("uploads/public/c{$dir}") as $file) {
|
|
||||||
if (!preg_match_all('|'.preg_quote("uploads/public/c{$dir}/{$base}", '|').'(-[0-9]+x[0-9]+)?(\.[a-zA-Z]+)$|', $file, $matches)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$size = $matches[1][0];
|
|
||||||
$ext = $matches[2][0];
|
|
||||||
|
|
||||||
Storage::move($file, "uploads/public/c{$newDir}/{$newBase}{$size}{$ext}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Aweos\Resizer\Classes;
|
namespace Aweos\Resizer\Classes;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Lib\MediaPath;
|
||||||
use Aweos\Resizer\Models\Setting;
|
use Aweos\Resizer\Models\Setting;
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
use Illuminate\Filesystem\FilesystemAdapter;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
@ -16,6 +17,7 @@ class ImageResizer
|
||||||
private FilesystemAdapter $disk;
|
private FilesystemAdapter $disk;
|
||||||
private string $uploadDir;
|
private string $uploadDir;
|
||||||
private MediaLibrary $media;
|
private MediaLibrary $media;
|
||||||
|
private MediaPath $file;
|
||||||
|
|
||||||
public function __construct(FilesystemAdapter $disk, string $uploadDir, MediaLibrary $media)
|
public function __construct(FilesystemAdapter $disk, string $uploadDir, MediaLibrary $media)
|
||||||
{
|
{
|
||||||
|
@ -24,29 +26,19 @@ class ImageResizer
|
||||||
$this->media = $media;
|
$this->media = $media;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generate(string $file): void
|
public function generate(MediaPath $file): void
|
||||||
{
|
{
|
||||||
$this->source = app(FileObserver::class)->normalizePath($file);
|
$this->file = $file;
|
||||||
if (Storage::mimeType(app(FileObserver::class)->fullMediaPath($file)) !== 'image/jpeg') {
|
$this->disk->put($this->file->versionsPath(), $this->file->get());
|
||||||
return;
|
|
||||||
}
|
if ($this->file->compressor()->shouldGenerateVersions()) {
|
||||||
$this->copyOriginalImage();
|
|
||||||
$this->generateVersions();
|
$this->generateVersions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function copyOriginalImage()
|
|
||||||
{
|
|
||||||
$this->disk->put($this->destinationFilename(), $this->media->get($this->source));
|
|
||||||
}
|
|
||||||
|
|
||||||
private function destinationFilename(): string
|
|
||||||
{
|
|
||||||
return $this->uploadDir.$this->source;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function dimensions(): Collection
|
private function dimensions(): Collection
|
||||||
{
|
{
|
||||||
[$width, $height] = getimagesize(Storage::path($this->destinationFilename()));
|
[$width, $height] = getimagesize($this->file->root());
|
||||||
|
|
||||||
return collect(compact('width', 'height'));
|
return collect(compact('width', 'height'));
|
||||||
}
|
}
|
||||||
|
@ -85,24 +77,21 @@ class ImageResizer
|
||||||
{
|
{
|
||||||
foreach ($this->possibleSizes() as $size) {
|
foreach ($this->possibleSizes() as $size) {
|
||||||
$temp = microtime().'.jpg';
|
$temp = microtime().'.jpg';
|
||||||
$this->disk->copy($this->destinationFilename(), $temp);
|
|
||||||
$fullOriginalPath = $this->disk->path($this->destinationFilename());
|
|
||||||
$pathinfo = collect(pathinfo($this->destinationFilename()));
|
|
||||||
|
|
||||||
$r = app(ImageManager::class)->make($this->disk->path($temp))
|
$r = app(ImageManager::class)->make($this->file->root())
|
||||||
->fit($size->get('width'), $size->get('height'), fn ($constraint) => $constraint->upsize())
|
->fit($size->get('width'), $size->get('height'), fn ($constraint) => $constraint->upsize())
|
||||||
->save($this->disk->path($temp));
|
->save($this->disk->path($temp));
|
||||||
list($destWidth, $destHeight) = getimagesize($this->disk->path($temp));
|
list($destWidth, $destHeight) = getimagesize($this->disk->path($temp));
|
||||||
|
|
||||||
$versionFilename = $pathinfo->get('dirname').
|
$versionFilename = $this->file->versionsDirPath().
|
||||||
'/'.
|
'/'.
|
||||||
$pathinfo->get('filename').
|
$this->file->filename().
|
||||||
'-'.
|
'-'.
|
||||||
$destWidth.
|
$destWidth.
|
||||||
'x'.
|
'x'.
|
||||||
$destHeight.
|
$destHeight.
|
||||||
'.'.
|
'.'.
|
||||||
$pathinfo->get('extension');
|
$this->file->extension();
|
||||||
|
|
||||||
if ($this->disk->exists($versionFilename)) {
|
if ($this->disk->exists($versionFilename)) {
|
||||||
$this->disk->delete($versionFilename);
|
$this->disk->delete($versionFilename);
|
||||||
|
@ -110,6 +99,10 @@ class ImageResizer
|
||||||
|
|
||||||
$this->disk->move($temp, $versionFilename);
|
$this->disk->move($temp, $versionFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($this->file->versions() as $version) {
|
||||||
|
$this->file->compressor()->make($this->disk->path($version->get('path')));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
namespace Aweos\Resizer\Classes;
|
namespace Aweos\Resizer\Classes;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Lib\MediaPath;
|
||||||
|
|
||||||
class ResizeJob
|
class ResizeJob
|
||||||
{
|
{
|
||||||
|
|
||||||
public function fire($job, $params)
|
public function fire($job, $params)
|
||||||
{
|
{
|
||||||
list($file) = $params;
|
list($file) = $params;
|
||||||
app(ImageResizer::class)->generate($file);
|
app(ImageResizer::class)->generate(new MediaPath($file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
namespace Aweos\Resizer\Classes;
|
namespace Aweos\Resizer\Classes;
|
||||||
|
|
||||||
use Aweos\Resizer\Models\Attachment;
|
use Aweos\Resizer\Compressors\CompressorNotFoundException;
|
||||||
|
use Aweos\Resizer\Compressors\Factory as CompressorFactory;
|
||||||
|
use Aweos\Resizer\Lib\MediaPath;
|
||||||
use Aweos\Resizer\Models\Setting;
|
use Aweos\Resizer\Models\Setting;
|
||||||
use Cache;
|
use Cache;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
@ -14,9 +16,11 @@ class TagGenerator {
|
||||||
public MediaLibrary $media;
|
public MediaLibrary $media;
|
||||||
public array $breakpoints;
|
public array $breakpoints;
|
||||||
public $path;
|
public $path;
|
||||||
|
private CompressorFactory $compressorFactory;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct(CompressorFactory $compressorFactory)
|
||||||
{
|
{
|
||||||
|
$this->compressorFactory = $compressorFactory;
|
||||||
$this->media = MediaLibrary::instance();
|
$this->media = MediaLibrary::instance();
|
||||||
$this->breakpoints = Setting::get('breakpoints');
|
$this->breakpoints = Setting::get('breakpoints');
|
||||||
ksort($this->breakpoints);
|
ksort($this->breakpoints);
|
||||||
|
@ -32,34 +36,24 @@ class TagGenerator {
|
||||||
|
|
||||||
public function possibleFiles(string $ratio): ?Collection
|
public function possibleFiles(string $ratio): ?Collection
|
||||||
{
|
{
|
||||||
if (Storage::mimeType(app(FileObserver::class)->fullMediaPath($this->path)) !== 'image/jpeg') {
|
$filename = $this->path->filename();
|
||||||
return null;
|
$basePath = $this->path->versionsDirPath();
|
||||||
}
|
[$originalWidth, $originalHeight] = getimagesize($this->path->root());
|
||||||
|
|
||||||
$filename = pathinfo($this->path, PATHINFO_FILENAME);
|
|
||||||
$basePath = app(FileObserver::class)->versionsPath(pathinfo($this->path, PATHINFO_DIRNAME));
|
|
||||||
[$originalWidth, $originalHeight] = getimagesize(Storage::path(app(FileObserver::class)->fullMediaPath($this->path)));
|
|
||||||
$aspectRatio = $ratio === 'original'
|
$aspectRatio = $ratio === 'original'
|
||||||
? $originalWidth / $originalHeight
|
? $originalWidth / $originalHeight
|
||||||
: $this->size($ratio)[0] / $this->size($ratio)[1];
|
: $this->size($ratio)[0] / $this->size($ratio)[1];
|
||||||
|
|
||||||
$result = collect([]);
|
$result = collect([]);
|
||||||
|
|
||||||
foreach (Storage::files($basePath) as $file) {
|
foreach ($this->path->versions() as $version) {
|
||||||
if (!preg_match('|'.preg_quote($basePath.'/'.$filename, '|').'-([0-9]+x[0-9]+)\.([a-zA-Z]+)$|', $file, $matches)) {
|
if ($version->get('width') / ($version->get('height')+1) > $aspectRatio || $version->get('width') / ($version->get('height')-1) < $aspectRatio) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$width = explode('x', $matches[1])[0];
|
|
||||||
$height = explode('x', $matches[1])[1];
|
|
||||||
if ($width / ($height+1) > $aspectRatio || $width / ($height-1) < $aspectRatio) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result->push(collect([
|
$result->push(collect([
|
||||||
'url' => Storage::url($file),
|
'url' => $version->get('url'),
|
||||||
'width' => $width,
|
'width' => $version->get('width'),
|
||||||
'height' => $height,
|
'height' => $version->get('height'),
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,13 +62,22 @@ class TagGenerator {
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generate(string $path, ?string $ratio = 'original', $sizes = null): string
|
public function generate(MediaPath $path, ?string $ratio = 'original', $sizes = null): string
|
||||||
{
|
{
|
||||||
$this->path = $path;
|
$this->path = $path;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!$path->compressor()->shouldGenerateVersions()) {
|
||||||
|
return $this->fallback();
|
||||||
|
}
|
||||||
|
} catch (CompressorNotFoundException $e) {
|
||||||
|
return $this->fallback();
|
||||||
|
}
|
||||||
|
|
||||||
$files = $this->possibleFiles($ratio);
|
$files = $this->possibleFiles($ratio);
|
||||||
|
|
||||||
if ($files === null) {
|
if ($files === null) {
|
||||||
return 'src="'.$this->media->findFiles($path)[0]->publicUrl.'"';
|
return $this->fallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
$sizes = $this->parseSizes($files, $sizes);
|
$sizes = $this->parseSizes($files, $sizes);
|
||||||
|
@ -115,4 +118,9 @@ class TagGenerator {
|
||||||
return "(min-width: {$components[0]}px) {$components[1]}";
|
return "(min-width: {$components[0]}px) {$components[1]}";
|
||||||
})->push($minSize);
|
})->push($minSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function fallback(): string
|
||||||
|
{
|
||||||
|
return 'src="'.$this->path->publicUrl().'"';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Aweos\Resizer\Classes;
|
|
||||||
|
|
||||||
use Queue;
|
|
||||||
use Storage;
|
|
||||||
use Aweos\Resizer\Models\SourceFile;
|
|
||||||
use Aweos\Resizer\Models\Attachment;
|
|
||||||
|
|
||||||
class UploadStorage {
|
|
||||||
|
|
||||||
public $disk = 'uploads';
|
|
||||||
public $file;
|
|
||||||
public $data;
|
|
||||||
public $strategy = FirstLetterStrategy::class;
|
|
||||||
|
|
||||||
public function storeFileFromUpload($uploadedFile, $data) {
|
|
||||||
$this->file = $uploadedFile;
|
|
||||||
$this->data = $data;
|
|
||||||
|
|
||||||
$sourceFile = new SourceFile([
|
|
||||||
'basename' => pathinfo($this->file->getClientOriginalName(), PATHINFO_FILENAME),
|
|
||||||
'extension' => $this->file->getClientOriginalExtension(),
|
|
||||||
'tags' => [],
|
|
||||||
'aspect_ratio' => $this->data['aspectRatio'],
|
|
||||||
'min_width' => $this->data['minWidth']
|
|
||||||
]);
|
|
||||||
$sourceFile->slugAttributes();
|
|
||||||
|
|
||||||
$uploadedFile->storeAs('', $sourceFile->path, $this->disk);
|
|
||||||
$sourceFile->save();
|
|
||||||
|
|
||||||
return $this->storeAttachment($sourceFile, [
|
|
||||||
'title' => $this->data['title'],
|
|
||||||
'description' => $this->data['description'] ?? '',
|
|
||||||
'crop' => $this->data['crop']
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function storeAttachment($sourceFile, $data) {
|
|
||||||
$attachment = $sourceFile->attachments()->create([
|
|
||||||
'title' => $data['title'],
|
|
||||||
'description' => $data['description']
|
|
||||||
]);
|
|
||||||
|
|
||||||
Queue::push(CompressJob::class, [
|
|
||||||
'attachment_id' => $attachment->id,
|
|
||||||
'crop' => $data['crop']
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $attachment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFileData($id) {
|
|
||||||
$attachment = Attachment::find($id);
|
|
||||||
|
|
||||||
return $attachment ? [
|
|
||||||
'url' => $this->storage()->url($attachment->source->path),
|
|
||||||
'type' => $this->storage()->mimeType($attachment->source->path),
|
|
||||||
'size' => $this->storage()->size($attachment->source->path),
|
|
||||||
'name' => $attachment->slug,
|
|
||||||
'id' => $id
|
|
||||||
] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function removeAttachment($id) {
|
|
||||||
$attachment = Attachment::find($id);
|
|
||||||
|
|
||||||
collect(Storage::disk($this->disk)->files($attachment->path))->filter(function($file) use ($attachment) {
|
|
||||||
return preg_match($attachment->versionRegex, $file);
|
|
||||||
})->each(function($file) {
|
|
||||||
Storage::disk($this->disk)->delete($file);
|
|
||||||
});
|
|
||||||
|
|
||||||
$attachment->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function storage() {
|
|
||||||
return Storage::disk($this->disk);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function originalExtension() {
|
|
||||||
return $this->file->getClientOriginalExtension();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getStrategy() {
|
|
||||||
return app($this->strategy);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -10,5 +10,10 @@
|
||||||
"name": "Werbeagentur AWEOS",
|
"name": "Werbeagentur AWEOS",
|
||||||
"email": "philipp@aweos.de"
|
"email": "philipp@aweos.de"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Aweos\\Resizer\\Compilers\\": "./compilers"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Compressors;
|
||||||
|
|
||||||
|
abstract class Compressor
|
||||||
|
{
|
||||||
|
|
||||||
|
abstract function make(string $path): array;
|
||||||
|
|
||||||
|
public function tmpPath(): string
|
||||||
|
{
|
||||||
|
return "/tmp/".str_slug(microtime());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Compressors;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class CompressorNotFoundException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Compressors;
|
||||||
|
|
||||||
|
class DefaultCompressor extends Compressor {
|
||||||
|
|
||||||
|
public function make(string $path): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldGenerateVersions(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Compressors;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Lib\MediaPath;
|
||||||
|
|
||||||
|
class Factory
|
||||||
|
{
|
||||||
|
|
||||||
|
private string $default = DefaultCompressor::class;
|
||||||
|
|
||||||
|
public array $types = [
|
||||||
|
'image/jpeg' => JpgCompressor::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function fromMedia(string $mediaPath): Compressor
|
||||||
|
{
|
||||||
|
return $this->resolve(new MediaPath($mediaPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resolve(MediaPath $path): Compressor
|
||||||
|
{
|
||||||
|
$mime = mime_content_type($path->root());
|
||||||
|
$compiler = $this->resolveType($mime);
|
||||||
|
|
||||||
|
if (is_null($compiler)) {
|
||||||
|
return new $this->default($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new $compiler($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveType(string $type): ?string
|
||||||
|
{
|
||||||
|
return collect($this->types)->get($type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Compressors;
|
||||||
|
|
||||||
|
class JpgCompressor extends Compressor {
|
||||||
|
|
||||||
|
public function make(string $path): array
|
||||||
|
{
|
||||||
|
$output = "/tmp/".str_slug(microtime());
|
||||||
|
$mimetype = mime_content_type($path);
|
||||||
|
|
||||||
|
system('imagemin '.escapeshellarg($path).' --plugin=jpegtran --plugin=mozjpeg --plugin.mozjpeg.quality=70 > '.escapeshellarg($output));
|
||||||
|
system("mv ".escapeshellarg($output)." ".escapeshellarg($path));
|
||||||
|
|
||||||
|
return [
|
||||||
|
$path => [$path],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldGenerateVersions(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,63 +0,0 @@
|
||||||
<?php namespace Aweos\Resizer\Console;
|
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
|
||||||
|
|
||||||
class ClearOld extends Command
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var string The console command name.
|
|
||||||
*/
|
|
||||||
protected $name = 'resizer:clearold';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string The console command description.
|
|
||||||
*/
|
|
||||||
protected $description = 'No description provided yet...';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the console command.
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
foreach (\Aweos\Base\Models\OfferKitchen::get() as $k) {
|
|
||||||
$newImages = collect($k->images)->map(function($image) {
|
|
||||||
if (!strpos($image['image'], 'cropped-images')) {
|
|
||||||
return $image;
|
|
||||||
}
|
|
||||||
|
|
||||||
$n = preg_replace('/-(\d+-){4}\d+/', '', $image['image']);
|
|
||||||
$n = str_replace('cropped-images/', '', $n);
|
|
||||||
|
|
||||||
if (!\Storage::has('media'.$n)) {
|
|
||||||
return $image;
|
|
||||||
}
|
|
||||||
|
|
||||||
$image['image'] = $n;
|
|
||||||
return $image;
|
|
||||||
});
|
|
||||||
|
|
||||||
$k->update(['images' => $newImages]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the console command arguments.
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getArguments()
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the console command options.
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getOptions()
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,7 @@
|
||||||
<?php namespace Aweos\Resizer\Console;
|
<?php namespace Aweos\Resizer\Console;
|
||||||
|
|
||||||
use Storage;
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use System\Classes\MediaLibrary;
|
use Storage;
|
||||||
use Aweos\Resizer\Models\Setting;
|
|
||||||
use October\Rain\Database\Attach\Resizer;
|
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
|
||||||
|
|
||||||
class ResizePurge extends Command
|
class ResizePurge extends Command
|
||||||
{
|
{
|
||||||
|
@ -26,25 +21,7 @@ class ResizePurge extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$folders = Setting::get('folders');
|
Storage::deleteDirectory('uploads/public/c');
|
||||||
$sizes = Setting::get('srcx');
|
|
||||||
|
|
||||||
foreach($folders as $folder) {
|
|
||||||
$f = '/'.rtrim(ltrim($folder['folder'], '/'), '/');
|
|
||||||
$this->start($f, $sizes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function start($f, $sizes) {
|
|
||||||
$l = MediaLibrary::instance();
|
|
||||||
|
|
||||||
$folders = array_filter(\Storage::allDirectories('media/'.$f), function($item) use ($f) {
|
|
||||||
return pathinfo($item, PATHINFO_FILENAME) == 'c';
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach ($folders as $folder) {
|
|
||||||
\Storage::deleteDirectory($folder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,183 +0,0 @@
|
||||||
<?php namespace Aweos\Resizer\FormWidgets;
|
|
||||||
|
|
||||||
use Db;
|
|
||||||
use Input;
|
|
||||||
use Request;
|
|
||||||
use Response;
|
|
||||||
use Validator;
|
|
||||||
use Backend\Widgets\Form;
|
|
||||||
use Backend\Classes\FormField;
|
|
||||||
use Backend\Classes\FormWidgetBase;
|
|
||||||
use October\Rain\Filesystem\Definitions as FileDefinitions;
|
|
||||||
use ApplicationException;
|
|
||||||
use ValidationException;
|
|
||||||
use Exception;
|
|
||||||
use Aweos\Resizer\Traits\ResponsiveSaver;
|
|
||||||
use Aweos\Resizer\Traits\ResponsiveWidget;
|
|
||||||
use Aweos\Resizer\Classes\UploadStorage;
|
|
||||||
use Aweos\Resizer\Models\SourceFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File upload field
|
|
||||||
* Renders a form file uploader field.
|
|
||||||
*
|
|
||||||
* Supported options:
|
|
||||||
* - mode: image-single, image-multi, file-single, file-multi
|
|
||||||
* - upload-label: Add file
|
|
||||||
* - empty-label: No file uploaded
|
|
||||||
*
|
|
||||||
* @package october\backend
|
|
||||||
* @author Alexey Bobkov, Samuel Georges
|
|
||||||
*/
|
|
||||||
class Responsiveimage extends FormWidgetBase
|
|
||||||
{
|
|
||||||
|
|
||||||
public $minWidth;
|
|
||||||
|
|
||||||
public $aspectRatio;
|
|
||||||
|
|
||||||
protected $defaultAlias = 'responsiveimage';
|
|
||||||
|
|
||||||
protected $configFormWidget;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function init()
|
|
||||||
{
|
|
||||||
$this->fillFromConfig([
|
|
||||||
'minWidth',
|
|
||||||
'aspectRatio'
|
|
||||||
]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
if ($this->formField->disabled) {
|
|
||||||
$this->previewMode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//$this->getConfigFormWidget();
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function render()
|
|
||||||
{
|
|
||||||
$this->prepareVars();
|
|
||||||
return $this->makePartial('responsiveimage');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares the view data
|
|
||||||
*/
|
|
||||||
protected function prepareVars()
|
|
||||||
{
|
|
||||||
$this->vars['aspectRatio'] = $this->aspectRatio
|
|
||||||
? $this->vueParam(explode(' / ', $this->aspectRatio))
|
|
||||||
: 'null';
|
|
||||||
$this->vars['minWidth'] = $this->minWidth ?: '0';
|
|
||||||
$this->vars['name'] = $this->formField->getName();
|
|
||||||
$this->vars['value'] = is_numeric($this->getLoadValue()) ? $this->getLoadValue() : 'null';
|
|
||||||
$this->vars['meta'] = is_numeric($this->getLoadValue())
|
|
||||||
? $this->vueParam(app(UploadStorage::class)->getFileData($this->getLoadValue()))
|
|
||||||
: 'null';
|
|
||||||
$this->vars['model'] = $this->model;
|
|
||||||
$this->vars['croppableTypes'] = $this->vueParam(SourceFile::$croppableTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function vueParam($config) {
|
|
||||||
return str_replace('"', "'", json_encode($config));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
protected function loadAssets()
|
|
||||||
{
|
|
||||||
$this->addCss('css/responsiveimage.build.css', 'core');
|
|
||||||
$this->addJs('js/responsiveimage.build.js', 'core');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function getSaveValue($value)
|
|
||||||
{
|
|
||||||
return is_numeric($value) ? $value : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLoadValue() {
|
|
||||||
return is_numeric(parent::getLoadValue()) ? parent::getLoadValue() : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload handler for the server-side processing of uploaded files
|
|
||||||
*/
|
|
||||||
public function onUpload()
|
|
||||||
{
|
|
||||||
if (!Input::hasFile('file_data')) {
|
|
||||||
throw new ApplicationException('File missing from request');
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = json_decode(Input::get('extraData'), true);
|
|
||||||
$uploadedFile = Input::file('file_data');
|
|
||||||
|
|
||||||
if (!$uploadedFile->isValid()) {
|
|
||||||
throw new ApplicationException('File is not valid');
|
|
||||||
}
|
|
||||||
|
|
||||||
$attachment = app(UploadStorage::class)->storeFileFromUpload($uploadedFile, $data);
|
|
||||||
|
|
||||||
return Response::make($attachment->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onDelete() {
|
|
||||||
app(UploadStorage::class)->removeAttachment(Input::get('file_id'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onOpenDatabase() {
|
|
||||||
$files = (new SourceFile)->newQuery();
|
|
||||||
|
|
||||||
if ($aspectRatio = Input::get('databasePopup.crop.aspectRatio', null)) {
|
|
||||||
$files->where('aspect_ratio', json_encode($aspectRatio));
|
|
||||||
}
|
|
||||||
if ($minWidth = Input::get('databasePopup.crop.minWidth', null)) {
|
|
||||||
$files->where('min_width', '>=', $minWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->makePartial('database', [
|
|
||||||
'images' => $files->get()
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onSelectDatabase() {
|
|
||||||
$v = Validator::make(Input::get(), [
|
|
||||||
'image' => 'required|exists:responsive_source_files,id',
|
|
||||||
'title' => 'required'
|
|
||||||
], [
|
|
||||||
'image.required' => 'Bitte ein Bild auswählen',
|
|
||||||
'title.required' => 'Bitte einen Titel angeben'
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($v->fails()) {
|
|
||||||
throw new ValidationException($v);
|
|
||||||
}
|
|
||||||
|
|
||||||
$attachment = app(UploadStorage::class)->storeAttachment(SourceFile::find(Input::get('image')), [
|
|
||||||
'title' => Input::get('title', ''),
|
|
||||||
'description' => Input::get('description', ''),
|
|
||||||
'crop' => null
|
|
||||||
]);
|
|
||||||
|
|
||||||
return Response::json([
|
|
||||||
'id' => $attachment->id,
|
|
||||||
'url' => $attachment->url,
|
|
||||||
'name' => $attachment->slug,
|
|
||||||
'type' => $attachment->source->type,
|
|
||||||
'size' => $attachment->source->size
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,253 +0,0 @@
|
||||||
.field-responsiveimage .upload-object {-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:relative;outline:none;overflow:hidden;display:inline-block;vertical-align:top}
|
|
||||||
.field-responsiveimage .upload-object img {width:100%;height:100%}
|
|
||||||
.field-responsiveimage .upload-object .icon-container {display:table;opacity:.6}
|
|
||||||
.field-responsiveimage .upload-object .icon-container i {color:#95a5a6;display:inline-block}
|
|
||||||
.field-responsiveimage .upload-object .icon-container div {display:table-cell;text-align:center;vertical-align:middle}
|
|
||||||
.field-responsiveimage .upload-object .icon-container.image >div.icon-wrapper {display:none}
|
|
||||||
.field-responsiveimage .upload-object h4 {font-size:13px;color:#2A3E51;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:150%;margin:15px 0 5px 0;padding-right:0;-webkit-transition:padding 0.1s;transition:padding 0.1s;position:relative}
|
|
||||||
.field-responsiveimage .upload-object h4 a {position:absolute;right:0;top:0;display:none;font-weight:400}
|
|
||||||
.field-responsiveimage .upload-object p.size {font-size:12px;color:#95a5a6}
|
|
||||||
.field-responsiveimage .upload-object p.size strong {font-weight:400}
|
|
||||||
.field-responsiveimage .upload-object .meta .drag-handle {position:absolute;bottom:0;right:0;cursor:move;display:block}
|
|
||||||
.field-responsiveimage .upload-object .info h4 a,
|
|
||||||
.field-responsiveimage .upload-object .meta a.upload-remove-button,
|
|
||||||
.field-responsiveimage .upload-object .meta a.drag-handle {color:#2b3e50;display:none;font-size:13px;text-decoration:none}
|
|
||||||
.field-responsiveimage .upload-object .icon-container {position:relative}
|
|
||||||
.field-responsiveimage .upload-object .icon-container:after {background-image:url('../../../../../../../modules/system/assets/ui/images/loader-transparent.svg');position:absolute;content:' ';width:40px;height:40px;left:50%;top:50%;margin-top:-20px;margin-left:-20px;display:block;background-size:40px 40px;background-position:50% 50%;-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}
|
|
||||||
.field-responsiveimage .upload-object.is-success .icon-container {opacity:1}
|
|
||||||
.field-responsiveimage .upload-object.is-success .icon-container:after {opacity:0;-webkit-transition:opacity 0.3s ease;transition:opacity 0.3s ease}
|
|
||||||
.field-responsiveimage .upload-object.is-error .icon-container:after {content:"";background:none;font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;content:"\f071";-webkit-animation:none;animation:none;font-size:40px;color:#ab2a1c;margin-top:-20px;margin-left:-20px;text-shadow:2px 2px 0 #fff}
|
|
||||||
.field-responsiveimage .upload-object.is-loading .icon-container {opacity:.6}
|
|
||||||
.field-responsiveimage .upload-object.is-loading .icon-container:after {opacity:1;-webkit-transition:opacity 0.3s ease;transition:opacity 0.3s ease}
|
|
||||||
.field-responsiveimage .upload-object.is-success {cursor:pointer}
|
|
||||||
.field-responsiveimage .upload-object.is-success .progress-bar {opacity:0;-webkit-transition:opacity 0.3s ease;transition:opacity 0.3s ease}
|
|
||||||
.field-responsiveimage .upload-object.is-success:hover h4 a,
|
|
||||||
.field-responsiveimage .upload-object.is-success:hover .meta .upload-remove-button,
|
|
||||||
.field-responsiveimage .upload-object.is-success:hover .meta .drag-handle {display:block}
|
|
||||||
.field-responsiveimage .upload-object.is-error {cursor:pointer}
|
|
||||||
.field-responsiveimage .upload-object.is-error .icon-container {opacity:1}
|
|
||||||
.field-responsiveimage .upload-object.is-error .icon-container >img,
|
|
||||||
.field-responsiveimage .upload-object.is-error .icon-container >i {opacity:.5}
|
|
||||||
.field-responsiveimage .upload-object.is-error .info h4 {color:#ab2a1c}
|
|
||||||
.field-responsiveimage .upload-object.is-error .info h4 a {display:none}
|
|
||||||
.field-responsiveimage .upload-object.is-error .meta {display:none}
|
|
||||||
.field-responsiveimage.is-sortable {position:relative}
|
|
||||||
.field-responsiveimage.is-sortable .upload-placeholder {position:relative;border:1px dotted #e0e0e0 !important}
|
|
||||||
.field-responsiveimage.is-sortable .upload-object.dragged {position:absolute;opacity:0.5;filter:alpha(opacity=50);z-index:2000}
|
|
||||||
.field-responsiveimage.is-sortable .upload-object.dragged .uploader-toolbar {display:none}
|
|
||||||
.field-responsiveimage.is-preview .upload-button,
|
|
||||||
.field-responsiveimage.is-preview .upload-remove-button,
|
|
||||||
.field-responsiveimage.is-preview .meta a.drag-handle {display:none !important}
|
|
||||||
@media (max-width:1024px) {.field-responsiveimage .upload-object.is-success h4 a,.field-responsiveimage .upload-object.is-success .meta .upload-remove-button,.field-responsiveimage .upload-object.is-success .meta .drag-handle {display:block !important }}
|
|
||||||
.fileupload-config-form .fileupload-url-button {padding-left:0}
|
|
||||||
.fileupload-config-form .fileupload-url-button >i {color:#666}
|
|
||||||
.fileupload-config-form .file-upload-modal-image-header {background-color:#FEFEFE;background-image:-webkit-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-webkit-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:-moz-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-moz-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:-o-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-o-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:-ms-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-ms-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);-webkit-background-size:20px 20px;-moz-background-size:20px 20px;background-size:20px 20px;background-position:0 0,10px 10px}
|
|
||||||
.fileupload-config-form .file-upload-modal-image-header,
|
|
||||||
.fileupload-config-form .file-upload-modal-image-header img {border-top-right-radius:2px;border-top-left-radius:2px}
|
|
||||||
.fileupload-config-form .file-upload-modal-image-header .close {position:absolute;top:20px;right:20px;background:#BDC3C7;opacity:.7;height:24px;width:22px}
|
|
||||||
.fileupload-config-form .file-upload-modal-image-header .close:hover,
|
|
||||||
.fileupload-config-form .file-upload-modal-image-header .close:focus {opacity:.9}
|
|
||||||
.fileupload-config-form .file-upload-modal-image-header + .modal-body {padding-top:20px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button,
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object {margin:0 10px 10px 0}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button {display:block;border:2px dashed #BDC3C7;background-clip:content-box;background-color:#F9F9F9;position:relative;outline:none;float:left;width:76px;height:76px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button .upload-button-icon {position:absolute;width:22px;height:22px;top:50%;left:50%;margin-top:-11px;margin-left:-11px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button .upload-button-icon:before {text-align:center;display:block;font-size:22px;height:22px;width:22px;line-height:22px;color:#BDC3C7}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button .upload-button-icon.large-icon {width:34px;height:34px;top:50%;left:50%;margin-top:-17px;margin-left:-17px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button .upload-button-icon.large-icon:before {font-size:34px;height:24px;width:24px;line-height:24px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button:hover {border:2px dashed #1F99DC}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button:hover .upload-button-icon:before {color:#1F99DC}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button:focus {border:2px dashed #1F99DC}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-button:focus .upload-button-icon:before {color:#1F99DC}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-files-container {margin-left:90px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object {background:#fff;border:1px solid #ecf0f1;width:260px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .progress-bar {display:block;width:100%;overflow:hidden;height:5px;background-color:#f5f5f5;border-radius:3px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);position:absolute;bottom:10px;left:0}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .progress-bar .upload-progress {float:left;width:0%;height:100%;line-height:5px;color:#fff;background-color:#5fb6f5;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:width 0.6s ease;transition:width 0.6s ease}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .icon-container {border-right:1px solid #f6f8f9;float:left;display:inline-block;overflow:hidden;width:75px;height:75px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .icon-container i {font-size:35px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .icon-container.image img {border-bottom-left-radius:3px;border-top-left-radius:3px;width:auto}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .info {margin-left:90px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .info h4 {padding-right:15px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .info h4 a {right:15px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .meta {position:absolute;bottom:0;left:0;right:0;margin:0 15px 0 90px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object .meta a.drag-handle {bottom:15px}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object.upload-placeholder {height:75px;background-color:transparent}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object.upload-placeholder:after {opacity:0}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object:hover {background:#4da7e8 !important}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object:hover i,
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object:hover p.size {color:#ecf0f1}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object:hover h4 {color:white}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object:hover .icon-container {border-right-color:#4da7e8 !important}
|
|
||||||
.field-responsiveimage.style-image-multi .upload-object:hover h4 {padding-right:35px}
|
|
||||||
.field-responsiveimage.style-image-multi.is-preview .upload-files-container {margin-left:0}
|
|
||||||
.form-sidebar .field-responsiveimage.style-image-multi .upload-files-container {margin-left:0}
|
|
||||||
.form-sidebar .field-responsiveimage.style-image-multi .upload-button {width:100%}
|
|
||||||
@media (max-width:1280px) {.field-responsiveimage.style-image-multi .upload-object {width:230px }}
|
|
||||||
@media (max-width:1024px) {.field-responsiveimage.style-image-multi .upload-button {width:100% }.field-responsiveimage.style-image-multi .upload-files-container {margin-left:0 }.field-responsiveimage.style-image-multi .upload-object {margin-right:0;display:block;width:auto }}
|
|
||||||
.field-responsiveimage.style-image-single.is-populated .upload-button {display:none}
|
|
||||||
.field-responsiveimage.style-image-single .upload-button {display:block;border:2px dashed #BDC3C7;background-clip:content-box;background-color:#F9F9F9;position:relative;outline:none;min-height:100px;min-width:100px}
|
|
||||||
.field-responsiveimage.style-image-single .upload-button .upload-button-icon {position:absolute;width:22px;height:22px;top:50%;left:50%;margin-top:-11px;margin-left:-11px}
|
|
||||||
.field-responsiveimage.style-image-single .upload-button .upload-button-icon:before {text-align:center;display:block;font-size:22px;height:22px;width:22px;line-height:22px;color:#BDC3C7}
|
|
||||||
.field-responsiveimage.style-image-single .upload-button .upload-button-icon.large-icon {width:34px;height:34px;top:50%;left:50%;margin-top:-17px;margin-left:-17px}
|
|
||||||
.field-responsiveimage.style-image-single .upload-button .upload-button-icon.large-icon:before {font-size:34px;height:24px;width:24px;line-height:24px}
|
|
||||||
.field-responsiveimage.style-image-single .upload-button:hover {border:2px dashed #1F99DC}
|
|
||||||
.field-responsiveimage.style-image-single .upload-button:hover .upload-button-icon:before {color:#1F99DC}
|
|
||||||
.field-responsiveimage.style-image-single .upload-button:focus {border:2px dashed #1F99DC}
|
|
||||||
.field-responsiveimage.style-image-single .upload-button:focus .upload-button-icon:before {color:#1F99DC}
|
|
||||||
.field-responsiveimage.style-image-single .upload-object {padding-bottom:66px}
|
|
||||||
.field-responsiveimage.style-image-single .upload-object .icon-container {border:1px solid #f6f8f9;background:rgba(255,255,255,0.5)}
|
|
||||||
.field-responsiveimage.style-image-single .upload-object .icon-container.image img {-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;display:block;max-width:100%;height:auto;min-height:100px;min-width:100px}
|
|
||||||
.field-responsiveimage.style-image-single .upload-object .progress-bar {display:block;width:100%;overflow:hidden;height:5px;background-color:#f5f5f5;border-radius:3px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);position:absolute;bottom:10px;left:0}
|
|
||||||
.field-responsiveimage.style-image-single .upload-object .progress-bar .upload-progress {float:left;width:0%;height:100%;line-height:5px;color:#fff;background-color:#5fb6f5;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:width 0.6s ease;transition:width 0.6s ease}
|
|
||||||
.field-responsiveimage.style-image-single .upload-object .info {position:absolute;left:0;right:0;bottom:0;height:66px}
|
|
||||||
.field-responsiveimage.style-image-single .upload-object .meta {position:absolute;bottom:65px;left:0;right:0;margin:0 15px}
|
|
||||||
.field-responsiveimage.style-image-single .upload-object:hover h4 {padding-right:20px}
|
|
||||||
@media (max-width:1024px) {.field-responsiveimage.style-image-single .upload-object h4 {padding-right:20px !important }}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-button {margin-bottom:10px}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-files-container {border:1px solid #eee;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;border-bottom:none;display:none}
|
|
||||||
.field-responsiveimage.style-file-multi.is-populated .upload-files-container {display:block}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object {display:block;width:100%;border-bottom:1px solid #eee;padding-left:10px}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object:nth-child(even) {background-color:#f5f5f5}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .icon-container {position:absolute;top:0;left:10px;width:15px;padding:11px 7px}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .icon-container i {line-height:150%;font-size:15px}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .icon-container img {display:none}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .info {margin-left:35px;margin-right:15%}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .info h4,
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .info p {margin:0;padding:11px 0;font-size:12px;font-weight:normal;line-height:150%;color:#666}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .info h4 {padding-right:15px}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .info h4 a {padding:10px 0;right:15px}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .info p.size {position:absolute;top:0;right:0;width:15%;display:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .progress-bar {display:block;width:100%;overflow:hidden;height:5px;background-color:#f5f5f5;border-radius:3px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);position:absolute;top:18px;left:0}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .progress-bar .upload-progress {float:left;width:0%;height:100%;line-height:5px;color:#fff;background-color:#5fb6f5;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:width 0.6s ease;transition:width 0.6s ease}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .meta {position:absolute;top:0;right:0;margin-right:15px;width:15%}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .meta a.drag-handle {top:-2px;bottom:auto;line-height:150%;padding:10px 0}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object .icon-container:after {width:20px;height:20px;margin-top:-10px;margin-left:-10px;background-size:20px 20px}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object.is-error .icon-container:after {font-size:20px}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object.is-success .info p.size {display:block}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object.upload-placeholder {height:35px;background-color:transparent}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object.upload-placeholder:after {opacity:0}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object:hover {background:#4da7e8 !important}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object:hover i,
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object:hover p.size {color:#ecf0f1}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object:hover h4 {color:white}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object:hover .icon-container {border-right-color:#4da7e8 !important}
|
|
||||||
.field-responsiveimage.style-file-multi .upload-object:hover h4 {padding-right:35px}
|
|
||||||
@media (max-width:1199px) {.field-responsiveimage.style-file-multi .info {margin-right:20% !important }.field-responsiveimage.style-file-multi .info p.size {width:20% !important }.field-responsiveimage.style-file-multi .meta {width:20% !important }}
|
|
||||||
@media (max-width:991px) {.field-responsiveimage.style-file-multi .upload-object h4 {padding-right:35px !important }.field-responsiveimage.style-file-multi .info {margin-right:25% !important }.field-responsiveimage.style-file-multi .info p.size {width:25% !important;padding-right:35px !important }.field-responsiveimage.style-file-multi .meta {width:25% !important }}
|
|
||||||
.field-responsiveimage.style-file-single {background-color:#fff;border:1px solid #d1d6d9;overflow:hidden;position:relative;padding-right:30px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(209,214,217,0.25),0 1px 0 rgba(255,255,255,.5);box-shadow:inset 0 1px 0 rgba(209,214,217,0.25),0 1px 0 rgba(255,255,255,.5)}
|
|
||||||
.field-responsiveimage.style-file-single .upload-button {position:absolute;top:50%;margin-top:-44px;height:88px;background:transparent;right:-2px;color:#595959}
|
|
||||||
.field-responsiveimage.style-file-single .upload-button i {font-size:14px}
|
|
||||||
.field-responsiveimage.style-file-single .upload-button:hover {color:#333}
|
|
||||||
.field-responsiveimage.style-file-single .upload-empty-message {padding:8px 0 8px 11px;font-size:14px}
|
|
||||||
.field-responsiveimage.style-file-single.is-populated .upload-empty-message {display:none}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object {display:block;width:100%;padding:7px 0 9px 0}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .icon-container {position:absolute;top:0;left:0;width:15px;padding:0 5px;margin:8px 0 0 7px;text-align:center}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .icon-container i {line-height:150%;font-size:15px}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .icon-container img {display:none}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .info {margin-left:34px;margin-right:15%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .info h4,
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .info p {display:inline;margin:0;padding:0;font-size:13px;line-height:150%;color:#666}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .info p.size {font-weight:normal}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .info p.size:before {content:" - "}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .progress-bar {display:block;width:100%;overflow:hidden;height:5px;background-color:#f5f5f5;border-radius:3px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);position:absolute;top:50%;margin-top:-2px;right:5px}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .progress-bar .upload-progress {float:left;width:0%;height:100%;line-height:5px;color:#fff;background-color:#5fb6f5;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:width 0.6s ease;transition:width 0.6s ease}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .meta {position:absolute;top:50%;margin-top:-44px;height:88px;right:0;width:15%}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .meta .upload-remove-button {position:absolute;top:50%;right:0;height:20px;margin-top:-10px;margin-right:10px;z-index:100}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object .icon-container:after {width:20px;height:20px;margin-top:-10px;margin-left:-10px;background-size:20px 20px}
|
|
||||||
.field-responsiveimage.style-file-single .upload-object.is-error .icon-container:after {font-size:20px}
|
|
||||||
|
|
||||||
.responsiveimage-jcrop-body {
|
|
||||||
div[data-jcrop].no-jcrop img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.field-responsiveimage {
|
|
||||||
.vue-dropzone {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.upload-wrapper {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
grid-gap: 1.5rem;
|
|
||||||
}
|
|
||||||
.preview-container {
|
|
||||||
display: grid;
|
|
||||||
grid-gap: 0.5rem;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
||||||
.cdz-preview {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
background: white;
|
|
||||||
border: 1px solid rgba(0,0,0,0.2);
|
|
||||||
[data-dz-remove] {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 2rem;
|
|
||||||
height: 2rem;
|
|
||||||
color: #333;
|
|
||||||
fill: currentColor;
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
}
|
|
||||||
div.details {
|
|
||||||
padding: 1rem;
|
|
||||||
flex: 1 0 0;
|
|
||||||
min-width: 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
flex-direction: column;
|
|
||||||
& > div {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
width: 15rem !important;
|
|
||||||
height: 10rem !important;
|
|
||||||
object-fit: cover !important;
|
|
||||||
}
|
|
||||||
div.cdz-progress {
|
|
||||||
position: absolute;
|
|
||||||
height: 5px;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
.dz-upload {
|
|
||||||
transition: width 0.2s;
|
|
||||||
background: hsl(200.9, 78.6%, 45.9%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.responsive-database-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
||||||
grid-gap: 1.5rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
label {
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
cursor: pointer;
|
|
||||||
input {
|
|
||||||
visibility: hidden;
|
|
||||||
z-index: -999;
|
|
||||||
position: absolute;
|
|
||||||
& + img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
input:checked + img {
|
|
||||||
box-shadow: 3px 3px 1px hsl(200.9, 78.6%, 45.9%),
|
|
||||||
-3px 3px 1px hsl(200.9, 78.6%, 45.9%),
|
|
||||||
3px -3px 1px hsl(200.9, 78.6%, 45.9%),
|
|
||||||
-3px -3px 1px hsl(200.9, 78.6%, 45.9%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,413 +0,0 @@
|
||||||
.uploader-object-active() {
|
|
||||||
background: @fileupload-object-active-bg !important;
|
|
||||||
|
|
||||||
i, p.size {
|
|
||||||
color: #ecf0f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
border-right-color: @fileupload-object-active-bg !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploader-progress-bar() {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
height: @fileupload-progress-bar-height;
|
|
||||||
background-color: @fileupload-progress-bar-bg;
|
|
||||||
border-radius: @border-radius-base;
|
|
||||||
.box-shadow(inset 0 1px 2px rgba(0,0,0,.1));
|
|
||||||
|
|
||||||
.upload-progress {
|
|
||||||
float: left;
|
|
||||||
width: 0%;
|
|
||||||
height: 100%;
|
|
||||||
line-height: @fileupload-progress-bar-height;
|
|
||||||
color: @fileupload-progress-bar-color;
|
|
||||||
background-color: #5fb6f5;
|
|
||||||
.box-shadow(none);
|
|
||||||
.transition(width .6s ease);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploader-block-button() {
|
|
||||||
display: block;
|
|
||||||
border: 2px dashed #BDC3C7;
|
|
||||||
background-clip: content-box;
|
|
||||||
background-color: #F9F9F9;
|
|
||||||
position: relative;
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
.upload-button-icon {
|
|
||||||
position: absolute;
|
|
||||||
width: 22px;
|
|
||||||
height: 22px;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
margin-top: -11px;
|
|
||||||
margin-left: -11px;
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
text-align: center;
|
|
||||||
display: block;
|
|
||||||
font-size: 22px;
|
|
||||||
height: 22px;
|
|
||||||
width: 22px;
|
|
||||||
line-height: 22px;
|
|
||||||
color: #BDC3C7;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.large-icon {
|
|
||||||
width: 34px;
|
|
||||||
height: 34px;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
margin-top: -17px;
|
|
||||||
margin-left: -17px;
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
font-size: 34px;
|
|
||||||
height: 24px;
|
|
||||||
width: 24px;
|
|
||||||
line-height: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border: 2px dashed #1F99DC;
|
|
||||||
|
|
||||||
.upload-button-icon:before {
|
|
||||||
color: #1F99DC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border: 2px dashed #1F99DC;
|
|
||||||
|
|
||||||
.upload-button-icon:before {
|
|
||||||
color: #1F99DC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploader-small-loader() {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
margin-top: -10px;
|
|
||||||
margin-left: -10px;
|
|
||||||
background-size: 20px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploader-vertical-align() {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -44px;
|
|
||||||
height: 88px;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Shared
|
|
||||||
//
|
|
||||||
|
|
||||||
.field-fileupload {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Uploaded item
|
|
||||||
//
|
|
||||||
|
|
||||||
.upload-object {
|
|
||||||
|
|
||||||
.border-radius(3px);
|
|
||||||
position: relative;
|
|
||||||
outline: none;
|
|
||||||
overflow: hidden;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
display: table;
|
|
||||||
opacity: .6;
|
|
||||||
|
|
||||||
i {
|
|
||||||
color: #95a5a6;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
div {
|
|
||||||
display: table-cell;
|
|
||||||
text-align: center;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container.image {
|
|
||||||
> div.icon-wrapper {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: 13px;
|
|
||||||
color: #2A3E51;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
line-height: 150%;
|
|
||||||
margin: 15px 0 5px 0;
|
|
||||||
padding-right: 0;
|
|
||||||
.transition(padding 0.1s);
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
a {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
display: none;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.size {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #95a5a6;
|
|
||||||
strong { font-weight: 400; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
.drag-handle {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
cursor: move;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.info h4 a,
|
|
||||||
.meta a.upload-remove-button,
|
|
||||||
.meta a.drag-handle {
|
|
||||||
color: #2b3e50;
|
|
||||||
display: none;
|
|
||||||
font-size: 13px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Loading State
|
|
||||||
//
|
|
||||||
|
|
||||||
.upload-object {
|
|
||||||
.icon-container {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container:after {
|
|
||||||
background-image: url('../../../../../system/assets/ui/images/loader-transparent.svg');
|
|
||||||
position: absolute;
|
|
||||||
content: ' ';
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -20px;
|
|
||||||
margin-left: -20px;
|
|
||||||
display: block;
|
|
||||||
background-size: 40px 40px;
|
|
||||||
background-position: 50% 50%;
|
|
||||||
.animation(spin 1s linear infinite);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-success {
|
|
||||||
.icon-container {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.icon-container:after {
|
|
||||||
opacity: 0;
|
|
||||||
.transition(opacity .3s ease);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replaces the loader with an error symbol
|
|
||||||
&.is-error {
|
|
||||||
.icon-container:after {
|
|
||||||
content: "";
|
|
||||||
background: none;
|
|
||||||
.icon(@exclamation-triangle);
|
|
||||||
.animation(none);
|
|
||||||
font-size: 40px;
|
|
||||||
color: #ab2a1c;
|
|
||||||
margin-top: -20px;
|
|
||||||
margin-left: -20px;
|
|
||||||
text-shadow: 2px 2px 0 #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-loading {
|
|
||||||
.icon-container {
|
|
||||||
opacity: .6;
|
|
||||||
}
|
|
||||||
.icon-container:after {
|
|
||||||
opacity: 1;
|
|
||||||
.transition(opacity .3s ease);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Success state
|
|
||||||
//
|
|
||||||
|
|
||||||
.upload-object.is-success {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
.progress-bar {
|
|
||||||
opacity: 0;
|
|
||||||
.transition(opacity .3s ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
h4 a,
|
|
||||||
.meta .upload-remove-button,
|
|
||||||
.meta .drag-handle { display: block; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Error State
|
|
||||||
//
|
|
||||||
|
|
||||||
.upload-object.is-error {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
opacity: 1;
|
|
||||||
> img, > i {
|
|
||||||
opacity: .5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.info h4 {
|
|
||||||
color: #ab2a1c;
|
|
||||||
a {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Sortable
|
|
||||||
//
|
|
||||||
|
|
||||||
&.is-sortable {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.upload-placeholder {
|
|
||||||
position: relative;
|
|
||||||
border: 1px dotted #e0e0e0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-object.dragged {
|
|
||||||
position: absolute;
|
|
||||||
.opacity(.5);
|
|
||||||
z-index: 2000;
|
|
||||||
.uploader-toolbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Preview mode
|
|
||||||
//
|
|
||||||
|
|
||||||
&.is-preview {
|
|
||||||
.upload-button,
|
|
||||||
.upload-remove-button,
|
|
||||||
.meta a.drag-handle {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Media
|
|
||||||
//
|
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
|
||||||
.field-fileupload {
|
|
||||||
.upload-object.is-success {
|
|
||||||
h4 a,
|
|
||||||
.meta .upload-remove-button,
|
|
||||||
.meta .drag-handle { display: block !important; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Config form
|
|
||||||
//
|
|
||||||
|
|
||||||
.fileupload-config-form {
|
|
||||||
.fileupload-url-button{
|
|
||||||
padding-left: 0;
|
|
||||||
> i {
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-upload-modal-image-header {
|
|
||||||
// Photoshop transparent background
|
|
||||||
// Based on: http://lea.verou.me/css3patterns/#checkerboard
|
|
||||||
background-color: #FEFEFE;
|
|
||||||
background-image: -webkit-linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB), -webkit-linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB);
|
|
||||||
background-image: -moz-linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB), -moz-linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB);
|
|
||||||
background-image: -o-linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB), -o-linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB);
|
|
||||||
background-image: -ms-linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB), -ms-linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB);
|
|
||||||
background-image: linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB), linear-gradient(45deg, #CBCBCB 25%, transparent 25%, transparent 75%, #CBCBCB 75%, #CBCBCB);
|
|
||||||
-webkit-background-size: 20px 20px;
|
|
||||||
-moz-background-size: 20px 20px;
|
|
||||||
background-size: 20px 20px;
|
|
||||||
background-position: 0 0, 10px 10px;
|
|
||||||
|
|
||||||
|
|
||||||
&, img {
|
|
||||||
.border-top-radius(2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.close {
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
right: 20px;
|
|
||||||
background: #BDC3C7;
|
|
||||||
opacity: .7;
|
|
||||||
height: 24px;
|
|
||||||
width: 22px;
|
|
||||||
|
|
||||||
&:hover, &:focus {
|
|
||||||
opacity: .9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-upload-modal-image-header + .modal-body {
|
|
||||||
padding-top: @padding-standard;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,176 +0,0 @@
|
||||||
//
|
|
||||||
// Multi File
|
|
||||||
//
|
|
||||||
|
|
||||||
.field-fileupload.style-file-multi {
|
|
||||||
.upload-button {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-files-container {
|
|
||||||
border: 1px solid @fileupload-list-border-color;
|
|
||||||
.border-radius(3px);
|
|
||||||
border-bottom: none;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-populated .upload-files-container {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-object {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
border-bottom: 1px solid @fileupload-list-border-color;
|
|
||||||
padding-left: 10px;
|
|
||||||
|
|
||||||
&:nth-child(even) {
|
|
||||||
background-color: @fileupload-list-accent-bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 10px;
|
|
||||||
width: 15px;
|
|
||||||
padding: 11px 7px;
|
|
||||||
|
|
||||||
i {
|
|
||||||
line-height: 150%;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
img { display: none; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
margin-left: 35px;
|
|
||||||
margin-right: 15%;
|
|
||||||
|
|
||||||
h4, p {
|
|
||||||
margin: 0;
|
|
||||||
padding: 11px 0;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: normal;
|
|
||||||
line-height: 150%;
|
|
||||||
color: #666666;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
padding-right: 15px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
padding: 10px 0;
|
|
||||||
right: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.size {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 15%;
|
|
||||||
display: none;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-bar {
|
|
||||||
.uploader-progress-bar();
|
|
||||||
position: absolute;
|
|
||||||
top: 18px;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
margin-right: 15px;
|
|
||||||
width: 15%;
|
|
||||||
|
|
||||||
a.drag-handle {
|
|
||||||
top: -2px;
|
|
||||||
bottom: auto;
|
|
||||||
line-height: 150%;
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container:after {
|
|
||||||
.uploader-small-loader();
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-error .icon-container:after {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Success
|
|
||||||
//
|
|
||||||
|
|
||||||
&.is-success {
|
|
||||||
.info p.size { display: block; }
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Sorting
|
|
||||||
//
|
|
||||||
|
|
||||||
&.upload-placeholder {
|
|
||||||
height: 35px;
|
|
||||||
background-color: transparent;
|
|
||||||
&:after { opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Hover
|
|
||||||
//
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.uploader-object-active();
|
|
||||||
h4 { padding-right: 35px; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Media
|
|
||||||
//
|
|
||||||
|
|
||||||
@media (max-width: @screen-md-max) {
|
|
||||||
.field-fileupload.style-file-multi {
|
|
||||||
.info {
|
|
||||||
margin-right: 20% !important;
|
|
||||||
p.size {
|
|
||||||
width: 20% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
width: 20% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: @screen-sm-max) {
|
|
||||||
.field-fileupload.style-file-multi {
|
|
||||||
.upload-object {
|
|
||||||
h4 { padding-right: 35px !important; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
margin-right: 25% !important;
|
|
||||||
p.size {
|
|
||||||
width: 25% !important;
|
|
||||||
padding-right: 35px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
width: 25% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
//
|
|
||||||
// Single File
|
|
||||||
//
|
|
||||||
|
|
||||||
.field-fileupload.style-file-single {
|
|
||||||
background-color: @color-form-field-bg;
|
|
||||||
border: 1px solid @color-form-field-border;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
padding-right: 30px;
|
|
||||||
border-radius: 3px;
|
|
||||||
.box-shadow(@input-box-shadow);
|
|
||||||
|
|
||||||
.upload-button {
|
|
||||||
.uploader-vertical-align();
|
|
||||||
background: transparent;
|
|
||||||
right: -2px;
|
|
||||||
|
|
||||||
color: lighten(@color-form-field-recordfinder-btn, 15%);
|
|
||||||
|
|
||||||
i {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: @color-form-field-recordfinder-btn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-empty-message {
|
|
||||||
padding: 8px 0 8px 11px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-populated {
|
|
||||||
.upload-empty-message {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-object {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
padding: 7px 0 9px 0;
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 15px;
|
|
||||||
padding: 0 5px;
|
|
||||||
margin: 8px 0 0 7px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
i {
|
|
||||||
line-height: 150%;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
img { display: none; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
margin-left: 34px;
|
|
||||||
margin-right: 15%;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
|
|
||||||
h4, p {
|
|
||||||
display: inline;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 150%;
|
|
||||||
color: #666666;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.size {
|
|
||||||
font-weight: normal;
|
|
||||||
&:before {
|
|
||||||
content: " - ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-bar {
|
|
||||||
.uploader-progress-bar();
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -2px;
|
|
||||||
right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
.uploader-vertical-align();
|
|
||||||
right: 0;
|
|
||||||
width: 15%;
|
|
||||||
.upload-remove-button {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 0;
|
|
||||||
height: 20px;
|
|
||||||
margin-top: -10px;
|
|
||||||
margin-right: 10px;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container:after {
|
|
||||||
.uploader-small-loader();
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-error .icon-container:after {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,134 +0,0 @@
|
||||||
//
|
|
||||||
// Multi Image
|
|
||||||
//
|
|
||||||
|
|
||||||
.field-fileupload.style-image-multi {
|
|
||||||
.upload-button,
|
|
||||||
.upload-object {
|
|
||||||
margin: 0 10px 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-button {
|
|
||||||
.uploader-block-button();
|
|
||||||
float: left;
|
|
||||||
width: 76px;
|
|
||||||
height: 76px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-files-container {
|
|
||||||
margin-left: 90px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-object {
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #ecf0f1;
|
|
||||||
width: 260px;
|
|
||||||
|
|
||||||
.progress-bar {
|
|
||||||
.uploader-progress-bar();
|
|
||||||
position: absolute;
|
|
||||||
bottom: 10px;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
border-right: 1px solid #f6f8f9;
|
|
||||||
float: left;
|
|
||||||
display: inline-block;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 75px;
|
|
||||||
height: 75px;
|
|
||||||
|
|
||||||
i {
|
|
||||||
font-size: 35px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.image img {
|
|
||||||
.border-left-radius(3px);
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
margin-left: 90px;
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
padding-right: 15px;
|
|
||||||
a {
|
|
||||||
right: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: 0 15px 0 90px;
|
|
||||||
|
|
||||||
a.drag-handle {
|
|
||||||
bottom: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.upload-placeholder {
|
|
||||||
height: 75px;
|
|
||||||
background-color: transparent;
|
|
||||||
&:after { opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.uploader-object-active();
|
|
||||||
h4 { padding-right: 35px; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-preview {
|
|
||||||
.upload-files-container {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// On Sidebar
|
|
||||||
//
|
|
||||||
|
|
||||||
.form-sidebar .field-fileupload.style-image-multi .upload-files-container {
|
|
||||||
margin-left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-sidebar .field-fileupload.style-image-multi .upload-button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Media
|
|
||||||
//
|
|
||||||
|
|
||||||
@media (max-width: 1280px) {
|
|
||||||
.field-fileupload.style-image-multi {
|
|
||||||
.upload-object {
|
|
||||||
width: 230px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
|
||||||
.field-fileupload.style-image-multi {
|
|
||||||
.upload-button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-files-container {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-object {
|
|
||||||
margin-right: 0;
|
|
||||||
display: block;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
//
|
|
||||||
// Single Image
|
|
||||||
//
|
|
||||||
|
|
||||||
.field-fileupload.style-image-single {
|
|
||||||
&.is-populated {
|
|
||||||
.upload-button {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-button {
|
|
||||||
.uploader-block-button();
|
|
||||||
min-height: 100px;
|
|
||||||
min-width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-object {
|
|
||||||
padding-bottom: 66px;
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
border: 1px solid #f6f8f9;
|
|
||||||
background: rgba(255,255,255,.5);
|
|
||||||
|
|
||||||
&.image img {
|
|
||||||
.border-radius(3px);
|
|
||||||
.img-responsive();
|
|
||||||
|
|
||||||
// This is needed when the image is very large and
|
|
||||||
// being processed by dropzone on the client-side
|
|
||||||
// the image has no height or width.
|
|
||||||
min-height: 100px;
|
|
||||||
min-width: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-bar {
|
|
||||||
.uploader-progress-bar();
|
|
||||||
position: absolute;
|
|
||||||
bottom: 10px;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
height: 66px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 65px;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: 0 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
h4 { padding-right: 20px; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Media
|
|
||||||
//
|
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
|
||||||
.field-fileupload.style-image-single {
|
|
||||||
.upload-object {
|
|
||||||
h4 { padding-right: 20px !important; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
@import "../../../../assets/less/core/boot.less";
|
|
||||||
|
|
||||||
@fileupload-progress-bar-height: 5px;
|
|
||||||
@fileupload-progress-bar-color: #fff;
|
|
||||||
@fileupload-progress-bar-bg: #f5f5f5;
|
|
||||||
@fileupload-inactive-icon: #808b93;
|
|
||||||
@fileupload-object-active-bg: #4da7e8;
|
|
||||||
@fileupload-list-accent-bg: #f5f5f5;
|
|
||||||
@fileupload-list-border-color: #eeeeee;
|
|
||||||
|
|
||||||
@import "fileupload.base.less";
|
|
||||||
@import "fileupload.imagemulti.less";
|
|
||||||
@import "fileupload.imagesingle.less";
|
|
||||||
@import "fileupload.filemulti.less";
|
|
||||||
@import "fileupload.filesingle.less";
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"name": "assets",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "webpack.mix.js",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "npm run development",
|
|
||||||
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
|
||||||
"watch": "npm run development -- --watch",
|
|
||||||
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
|
|
||||||
"prod": "npm run production",
|
|
||||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"cross-env": "^7.0.2",
|
|
||||||
"laravel-mix": "^5.0.7",
|
|
||||||
"postcss-nested": "^4.0.0",
|
|
||||||
"vue": "^2.6.12",
|
|
||||||
"vue2-dropzone": "^3.6.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"vue-template-compiler": "^2.6.12"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,186 +0,0 @@
|
||||||
<template>
|
|
||||||
<div
|
|
||||||
class="field-responsiveimage style-image-single"
|
|
||||||
data-control="responsiveimage"
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- Add New Image -->
|
|
||||||
<div class="upload-wrapper" v-show="addVisible">
|
|
||||||
<a href="javascript:;" class="upload-button" ref="addQueueTrigger">
|
|
||||||
<span class="upload-button-icon oc-icon-upload"></span>
|
|
||||||
</a>
|
|
||||||
<a href="javascript:;" @click="openDatabase" class="upload-button">
|
|
||||||
<span class="upload-button-icon oc-icon-database"></span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<vue-dropzone @vdropzone-mounted="onMount" @vdropzone-removed-file="onRemove" @vdropzone-success="onUploadSuccess" @vdropzone-sending="onSend" @vdropzone-thumbnail="onAdd" v-if="loaded" ref="dropzone" :id="id" :options="dropzoneOptions"></vue-dropzone>
|
|
||||||
|
|
||||||
<div class="preview-container" ref="previewsContainer"></div>
|
|
||||||
|
|
||||||
<input type="hidden" :name="name" :value="asString">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import vueDropzone from 'vue2-dropzone';
|
|
||||||
import popup from './popup.mixin.js';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
mixins: [ popup ],
|
|
||||||
|
|
||||||
data: function() {
|
|
||||||
return {
|
|
||||||
extraData: {},
|
|
||||||
addVisible: true,
|
|
||||||
content: {
|
|
||||||
sections: [],
|
|
||||||
placeholders: {
|
|
||||||
header: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
loaded: false,
|
|
||||||
content: []
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
components: { vueDropzone },
|
|
||||||
props: {
|
|
||||||
meta: {},
|
|
||||||
cropOptions: {},
|
|
||||||
name: {
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
default: function() { return null; }
|
|
||||||
},
|
|
||||||
formid: {},
|
|
||||||
handlers: {}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
id() {
|
|
||||||
return Math.random().toString(36).substring(7);
|
|
||||||
},
|
|
||||||
asString() {
|
|
||||||
return this.content;
|
|
||||||
},
|
|
||||||
formData() {
|
|
||||||
return $(this.$el).closest('form').serializeArray();
|
|
||||||
},
|
|
||||||
dropzoneOptions() {
|
|
||||||
return {
|
|
||||||
paramName: 'file_data',
|
|
||||||
autoProcessQueue: false,
|
|
||||||
url: window.location,
|
|
||||||
clickable: this.$refs.addQueueTrigger,
|
|
||||||
previewsContainer: this.$refs.previewsContainer,
|
|
||||||
headers: {
|
|
||||||
'X-OCTOBER-REQUEST-HANDLER': this.handlers.onUpload,
|
|
||||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
|
||||||
},
|
|
||||||
previewTemplate: `
|
|
||||||
<div class="cdz-preview">
|
|
||||||
<a href="#" data-dz-remove>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z"/></svg>
|
|
||||||
</a>
|
|
||||||
<img data-dz-thumbnail />
|
|
||||||
<div class="details">
|
|
||||||
<div><span data-dz-name></span></div>
|
|
||||||
<div data-dz-size></div>
|
|
||||||
</div>
|
|
||||||
<div class="cdz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
|
|
||||||
</div>`
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onUploadSuccess(file, response) {
|
|
||||||
this.content = response;
|
|
||||||
},
|
|
||||||
onAdd(file) {
|
|
||||||
if(file.manuallyAdded === true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.width < this.cropOptions.minWidth) {
|
|
||||||
$.oc.flashMsg({
|
|
||||||
text: `Dieses Bild ist zu klein. Bitte wähle ein Bild mit mindestens ${this.cropOptions.minWidth} Pixel Breite.`,
|
|
||||||
class: 'error'
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$refs.dropzone.removeFile(file);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.addVisible = false;
|
|
||||||
|
|
||||||
this.showPopup(file).then((ret) => {
|
|
||||||
this.extraData[file.name] = ret;
|
|
||||||
this.$refs.dropzone.processQueue();
|
|
||||||
}).catch((err) => {
|
|
||||||
this.$refs.dropzone.removeFile(file);
|
|
||||||
this.addVisible = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
openDatabase(e) {
|
|
||||||
var _cls = this;
|
|
||||||
|
|
||||||
var data = {
|
|
||||||
file_id: this.value,
|
|
||||||
crop: this.cropOptions
|
|
||||||
};
|
|
||||||
|
|
||||||
$(e.target).popup({ handler: this.handlers.onOpenDatabase, size: 'giant', extraData: { databasePopup: data } }).on('complete.oc.popup', function(e) {
|
|
||||||
$(e.relatedTarget).on('ajaxSuccess', 'form', function(event, context, data) {
|
|
||||||
_cls.content = data.id;
|
|
||||||
_cls.addVisible = false;
|
|
||||||
var file = { size: data.size, name: data.name, type: data.type };
|
|
||||||
_cls.$refs.dropzone.manuallyAddFile(file, data.url);
|
|
||||||
|
|
||||||
$(e.relatedTarget).popup('hide');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onSend(file, xhr, formData) {
|
|
||||||
formData.append('extraData', JSON.stringify({
|
|
||||||
...this.extraData[file.name],
|
|
||||||
...this.cropOptions
|
|
||||||
}));
|
|
||||||
this.formData.forEach((v) => {
|
|
||||||
formData.append(v.name, v.value);
|
|
||||||
});
|
|
||||||
Object.keys(this.cropOptions).forEach((v) => {
|
|
||||||
formData.append(v, this.cropOptions[v]);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onMount() {
|
|
||||||
if (!this.value) { return; }
|
|
||||||
this.addVisible = false;
|
|
||||||
var file = { size: this.meta.size, name: this.meta.name, type: this.meta.type };
|
|
||||||
this.$refs.dropzone.manuallyAddFile(file, this.meta.url);
|
|
||||||
},
|
|
||||||
onRemove(file, error, xhr) {
|
|
||||||
var _cls = this;
|
|
||||||
|
|
||||||
$(this.$el).request(this.handlers.onDelete, {
|
|
||||||
data: { file_id: this.content },
|
|
||||||
success: function(data) {
|
|
||||||
_cls.addVisible = true;
|
|
||||||
_cls.content = '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.loaded = true;
|
|
||||||
this.content = this.value;
|
|
||||||
var self = this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
import Vue from 'vue';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
+function ($) { "use strict";
|
|
||||||
var Base = $.oc.foundation.base,
|
|
||||||
BaseProto = Base.prototype
|
|
||||||
|
|
||||||
var Responsiveimage = function (element, options) {
|
|
||||||
this.$el = $(element)
|
|
||||||
this.$form = $(element).closest('form');
|
|
||||||
this.options = options || {}
|
|
||||||
|
|
||||||
$.oc.foundation.controlUtils.markDisposable(element)
|
|
||||||
Base.call(this)
|
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
Responsiveimage.prototype = Object.create(BaseProto)
|
|
||||||
Responsiveimage.prototype.constructor = Responsiveimage
|
|
||||||
|
|
||||||
Responsiveimage.prototype.init = function() {
|
|
||||||
this.$app = new Vue({
|
|
||||||
el: this.$el.children('div').get(0),
|
|
||||||
components: { App }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Responsiveimage.DEFAULTS = {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// PLUGIN DEFINITION
|
|
||||||
// ============================
|
|
||||||
|
|
||||||
var old = $.fn.responsiveimage
|
|
||||||
|
|
||||||
$.fn.responsiveimage = function (option) {
|
|
||||||
return this.each(function () {
|
|
||||||
var $this = $(this)
|
|
||||||
var data = $this.data('oc.responsiveimage')
|
|
||||||
var options = $.extend({}, Responsiveimage.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
|
||||||
if (!data) $this.data('oc.responsiveimage', (data = new Responsiveimage(this, options)))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.responsiveimage.Constructor = Responsiveimage
|
|
||||||
|
|
||||||
$.fn.responsiveimage.noConflict = function () {
|
|
||||||
$.fn.responsiveimage = old
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).render(function (){
|
|
||||||
$('[data-responsiveimage]').responsiveimage()
|
|
||||||
})
|
|
||||||
|
|
||||||
}(window.jQuery);
|
|
|
@ -1,125 +0,0 @@
|
||||||
export default {
|
|
||||||
|
|
||||||
data: function() {
|
|
||||||
return {
|
|
||||||
popup: null,
|
|
||||||
jcrop: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
onChangeCrop() {
|
|
||||||
this.popup.values.crop = this.jcrop.tellSelect();
|
|
||||||
},
|
|
||||||
showPopup(file, cro) {
|
|
||||||
var _cls = this;
|
|
||||||
this.popup = {
|
|
||||||
file: file,
|
|
||||||
values: { crop: null }
|
|
||||||
};
|
|
||||||
|
|
||||||
$('body').append(this.popupContent(file));
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var $popup = $(`#${this.popupId}`);
|
|
||||||
$popup.modal({ backdrop: false });
|
|
||||||
|
|
||||||
$popup.one('shown.bs.modal', function() {
|
|
||||||
var $cropContainer = $popup.find('[data-jcrop]');
|
|
||||||
|
|
||||||
var imageElement = new Image();
|
|
||||||
imageElement.src = file.dataURL;
|
|
||||||
$cropContainer.append(imageElement);
|
|
||||||
|
|
||||||
if (_cls.useJcrop) {
|
|
||||||
var jcropOptions = {
|
|
||||||
shade: true,
|
|
||||||
boxWidth: $cropContainer.width(),
|
|
||||||
onChange: _cls.onChangeCrop,
|
|
||||||
aspectRatio: _cls.realAspectRatio,
|
|
||||||
minSize: [_cls.cropOptions.minWidth, 0]
|
|
||||||
};
|
|
||||||
|
|
||||||
_cls.jcrop = $.Jcrop($popup.find('[data-jcrop] img').get(0), jcropOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
$popup.on('change', '[name=title]', (e) => { _cls.popup.values.title = e.target.value });
|
|
||||||
$popup.on('change', '[name=description]', (e) => { _cls.popup.values.description = e.target.value });
|
|
||||||
});
|
|
||||||
|
|
||||||
$popup.off('click', '[data-resolve]').on('click', '[data-resolve]', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (!_cls.popup.values.title) {
|
|
||||||
$.oc.flashMsg({ text: 'Bitte einen Titel angeben.', class: 'error' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_cls.aspectRatio && !_cls.popup.values.crop) {
|
|
||||||
$.oc.flashMsg({ text: 'Bitte das Bild beschneiden', class: 'error' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$popup.modal('hide');
|
|
||||||
|
|
||||||
resolve(_cls.popup.values);
|
|
||||||
});
|
|
||||||
|
|
||||||
$popup.off('hidden.bs.modal').one('hidden.bs.modal', () => {
|
|
||||||
$popup.remove();
|
|
||||||
|
|
||||||
reject(null);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
popupContent(file) {
|
|
||||||
var decoration = this.jcropContainerDecoration(file);
|
|
||||||
return `<div class="control-popup modal fade" id="${this.popupId}">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<form>
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
||||||
<h4 class="modal-title">Bild konfigurieren</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body responsiveimage-jcrop-body">
|
|
||||||
<div data-jcrop ${decoration}></div>
|
|
||||||
<p style="margin-top: 2rem;">Füge dem Anhang einen Titel und eine Beschreibung hinzu.</p>
|
|
||||||
<div class="form-group text-field span-full">
|
|
||||||
<input type="text" name="title" value="" placeholder="Titel" class="form-control" autocomplete="off" maxlength="255">
|
|
||||||
</div>
|
|
||||||
<div class="form-group textarea-field span-full">
|
|
||||||
<textarea name="description" class="form-control field-textarea size-tiny" placeholder="Beschreibung"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal" data-reject>Abbrechen</button>
|
|
||||||
<button type="submit" class="btn btn-primary" data-resolve>Änderungen übernehmen</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
},
|
|
||||||
useJcrop(file) {
|
|
||||||
return this.cropOptions.types.some(type => type == file.type);
|
|
||||||
},
|
|
||||||
jcropContainerDecoration(file) {
|
|
||||||
return this.useJcrop(file) ? '' : 'class="no-jcrop"';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
realAspectRatio() {
|
|
||||||
return this.cropOptions.aspectRatio
|
|
||||||
? this.cropOptions.aspectRatio[0] / this.cropOptions.aspectRatio[1]
|
|
||||||
: null;
|
|
||||||
},
|
|
||||||
popupId() {
|
|
||||||
return `subform-popup-${this.formid}`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,27 +0,0 @@
|
||||||
let mix = require('laravel-mix');
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Mix Asset Management
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Mix provides a clean, fluent API for defining some Webpack build steps
|
|
||||||
| for your Laravel application. By default, we are compiling the Sass
|
|
||||||
| file for your application, as well as bundling up your JS files.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
mix.config.resourceRoot = '..';
|
|
||||||
|
|
||||||
mix.options({
|
|
||||||
hmrOptions: {
|
|
||||||
host: 'dpsgkoeln.test',
|
|
||||||
port: 8080
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
mix.js('src/main.js', 'js/responsiveimage.build.js')
|
|
||||||
.postCss('css/main.css', 'css/responsiveimage.build.css', [
|
|
||||||
require('postcss-nested')
|
|
||||||
])
|
|
||||||
.sourceMaps();
|
|
|
@ -1,47 +0,0 @@
|
||||||
<div class="fileupload-config-form">
|
|
||||||
<?= Form::open() ?>
|
|
||||||
<input type="hidden" name="file_id" value="<?= $file->id ?>" />
|
|
||||||
<input type="hidden" name="manage_id" value="<?= $relationManageId ?>" />
|
|
||||||
<input type="hidden" name="_relation_field" value="<?= $relationField ?>" />
|
|
||||||
|
|
||||||
<?php if (starts_with($displayMode, 'image')): ?>
|
|
||||||
<div class="file-upload-modal-image-header">
|
|
||||||
<button type="button" class="close" data-dismiss="popup">×</button>
|
|
||||||
<img
|
|
||||||
src="<?= $file->thumbUrl ?>"
|
|
||||||
class="img-responsive center-block"
|
|
||||||
alt=""
|
|
||||||
title="<?= e(trans('backend::lang.fileupload.attachment')) ?>: <?= e($file->file_name) ?>"
|
|
||||||
style="<?= $cssDimensions ?>" />
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="popup">×</button>
|
|
||||||
<h4 class="modal-title"><?= e(trans('backend::lang.fileupload.attachment')) ?>: <?= $file->file_name ?></h4>
|
|
||||||
</div>
|
|
||||||
<?php endif ?>
|
|
||||||
<div class="modal-body">
|
|
||||||
<p><?= e(trans('backend::lang.fileupload.help')) ?></p>
|
|
||||||
|
|
||||||
<?= $this->getConfigFormWidget()->render(); ?>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<a href="<?= $file->pathUrl ?>" class="pull-left btn btn-link fileupload-url-button" target="_blank">
|
|
||||||
<i class="oc-icon-link"></i><?= e(trans('backend::lang.fileupload.attachment_url')) ?>
|
|
||||||
</a>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
class="btn btn-primary"
|
|
||||||
data-request="<?= $this->getEventHandler('onSaveAttachmentConfig') ?>"
|
|
||||||
data-popup-load-indicator>
|
|
||||||
<?= e(trans('backend::lang.form.save')) ?>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-default"
|
|
||||||
data-dismiss="popup">
|
|
||||||
<?= e(trans('backend::lang.form.cancel')) ?>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<?= Form::close() ?>
|
|
||||||
</div>
|
|
|
@ -1,30 +0,0 @@
|
||||||
<form data-request="<?= $this->getEventHandler('onSelectDatabase') ?>">
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
||||||
<h4 class="modal-title">Bild aus Datenbank einfügen</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<p>Wähle hier ein Bild aus</p>
|
|
||||||
|
|
||||||
<div class="responsive-database-grid">
|
|
||||||
<?php foreach ($images as $file): ?>
|
|
||||||
<label for="responsive-image-<?= $file->id ?>">
|
|
||||||
<input type="radio" name="image" id="responsive-image-<?= $file->id ?>" value="<?= $file->id ?>" data-select>
|
|
||||||
<img src="<?= $file->url ?>">
|
|
||||||
</label>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group textarea-field span-full">
|
|
||||||
<textarea name="title" class="form-control field-textarea size-tiny" placeholder="Titel"></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group textarea-field span-full">
|
|
||||||
<textarea name="description" class="form-control field-textarea size-tiny" placeholder="Beschreibung"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Abbrechen</button>
|
|
||||||
<button type="submit" class="btn btn-primary">Bild wählen</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
|
@ -1,73 +0,0 @@
|
||||||
<div
|
|
||||||
id="<?= $this->getId() ?>"
|
|
||||||
class="field-fileupload style-file-multi is-sortable is-multi <?= count($fileList) ? 'is-populated' : '' ?> <?= $this->previewMode ? 'is-preview' : '' ?>"
|
|
||||||
data-control="fileupload"
|
|
||||||
data-upload-handler="<?= $this->getEventHandler('onUpload') ?>"
|
|
||||||
data-template="#<?= $this->getId('template') ?>"
|
|
||||||
data-error-template="#<?= $this->getId('errorTemplate') ?>"
|
|
||||||
data-sort-handler="<?= $this->getEventHandler('onSortAttachments') ?>"
|
|
||||||
data-unique-id="<?= $this->getId() ?>"
|
|
||||||
data-max-filesize="<?= $maxFilesize ?>"
|
|
||||||
<?php if ($useCaption): ?>data-config-handler="<?= $this->getEventHandler('onLoadAttachmentConfig') ?>"<?php endif ?>
|
|
||||||
<?php if ($acceptedFileTypes): ?>data-file-types="<?= $acceptedFileTypes ?>"<?php endif ?>
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- Upload Button -->
|
|
||||||
<button type="button" class="btn btn-sm btn-secondary oc-icon-upload upload-button">
|
|
||||||
<?= $prompt ?>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Existing files -->
|
|
||||||
<div class="upload-files-container">
|
|
||||||
<?php foreach ($fileList as $file): ?>
|
|
||||||
<div class="upload-object is-success" data-id="<?= $file->id ?>" data-path="<?= $file->pathUrl ?>">
|
|
||||||
<div class="icon-container">
|
|
||||||
<i class="icon-file"></i>
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<h4 class="filename">
|
|
||||||
<span data-dz-name><?= e($file->title ?: $file->file_name) ?></span>
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
class="upload-remove-button"
|
|
||||||
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
|
|
||||||
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
|
|
||||||
data-request-data="file_id: <?= $file->id ?>"
|
|
||||||
><i class="icon-times"></i></a>
|
|
||||||
</h4>
|
|
||||||
<p class="size"><?= e($file->sizeToString()) ?></p>
|
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<a href="javascript:;" class="drag-handle"><i class="icon-bars"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Template for new files -->
|
|
||||||
<script type="text/template" id="<?= $this->getId('template') ?>">
|
|
||||||
<div class="upload-object dz-preview dz-file-preview">
|
|
||||||
<div class="icon-container">
|
|
||||||
<i class="icon-file"></i>
|
|
||||||
<img data-dz-thumbnail alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<h4 class="filename">
|
|
||||||
<span data-dz-name></span>
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
class="upload-remove-button"
|
|
||||||
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
|
|
||||||
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
|
|
||||||
><i class="icon-times"></i></a>
|
|
||||||
</h4>
|
|
||||||
<p class="size" data-dz-size></p>
|
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<a href="javascript:;" class="drag-handle"><i class="icon-bars"></i></a>
|
|
||||||
<div class="progress-bar"><span class="upload-progress" data-dz-uploadprogress></span></div>
|
|
||||||
<div class="error-message"><span data-dz-errormessage></span></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
|
|
@ -1,76 +0,0 @@
|
||||||
<div
|
|
||||||
id="<?= $this->getId() ?>"
|
|
||||||
class="field-fileupload style-file-single <?= $singleFile ? 'is-populated' : '' ?> <?= $this->previewMode ? 'is-preview' : '' ?>"
|
|
||||||
data-control="fileupload"
|
|
||||||
data-upload-handler="<?= $this->getEventHandler('onUpload') ?>"
|
|
||||||
data-template="#<?= $this->getId('template') ?>"
|
|
||||||
data-error-template="#<?= $this->getId('errorTemplate') ?>"
|
|
||||||
data-unique-id="<?= $this->getId() ?>"
|
|
||||||
data-max-filesize="<?= $maxFilesize ?>"
|
|
||||||
<?php if ($useCaption): ?>data-config-handler="<?= $this->getEventHandler('onLoadAttachmentConfig') ?>"<?php endif ?>
|
|
||||||
<?php if ($acceptedFileTypes): ?>data-file-types="<?= $acceptedFileTypes ?>"<?php endif ?>
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- Upload Button -->
|
|
||||||
<button type="button" class="btn btn-default upload-button">
|
|
||||||
<i class="icon-upload"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Existing file -->
|
|
||||||
<div class="upload-files-container">
|
|
||||||
<?php if ($singleFile): ?>
|
|
||||||
<div class="upload-object is-success" data-id="<?= $singleFile->id ?>" data-path="<?= $singleFile->pathUrl ?>">
|
|
||||||
<div class="icon-container">
|
|
||||||
<i class="icon-file"></i>
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<h4 class="filename">
|
|
||||||
<span data-dz-name><?= e($singleFile->title ?: $singleFile->file_name) ?></span>
|
|
||||||
</h4>
|
|
||||||
<p class="size"><?= e($singleFile->sizeToString()) ?></p>
|
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
class="upload-remove-button"
|
|
||||||
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
|
|
||||||
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
|
|
||||||
data-request-data="file_id: <?= $singleFile->id ?>"
|
|
||||||
><i class="icon-times"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Empty message -->
|
|
||||||
<div class="upload-empty-message">
|
|
||||||
<span class="text-muted"><?= $prompt ?></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Template for new file -->
|
|
||||||
<script type="text/template" id="<?= $this->getId('template') ?>">
|
|
||||||
<div class="upload-object dz-preview dz-file-preview">
|
|
||||||
<div class="icon-container">
|
|
||||||
<i class="icon-file"></i>
|
|
||||||
<img data-dz-thumbnail alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<h4 class="filename">
|
|
||||||
<span data-dz-name></span>
|
|
||||||
</h4>
|
|
||||||
<p class="size" data-dz-size></p>
|
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
class="upload-remove-button"
|
|
||||||
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
|
|
||||||
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
|
|
||||||
><i class="icon-times"></i></a>
|
|
||||||
<div class="progress-bar"><span class="upload-progress" data-dz-uploadprogress></span></div>
|
|
||||||
<div class="error-message"><span data-dz-errormessage></span></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
|
|
@ -1,72 +0,0 @@
|
||||||
<div
|
|
||||||
id="<?= $this->getId() ?>"
|
|
||||||
class="field-fileupload style-image-multi is-sortable is-multi <?= count($fileList) ? 'is-populated' : '' ?> <?= $this->previewMode ? 'is-preview' : '' ?>"
|
|
||||||
data-control="fileupload"
|
|
||||||
data-upload-handler="<?= $this->getEventHandler('onUpload') ?>"
|
|
||||||
data-template="#<?= $this->getId('template') ?>"
|
|
||||||
data-error-template="#<?= $this->getId('errorTemplate') ?>"
|
|
||||||
data-sort-handler="<?= $this->getEventHandler('onSortAttachments') ?>"
|
|
||||||
data-unique-id="<?= $this->getId() ?>"
|
|
||||||
data-max-filesize="<?= $maxFilesize ?>"
|
|
||||||
<?php if ($useCaption): ?>data-config-handler="<?= $this->getEventHandler('onLoadAttachmentConfig') ?>"<?php endif ?>
|
|
||||||
<?php if ($acceptedFileTypes): ?>data-file-types="<?= $acceptedFileTypes ?>"<?php endif ?>
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- Upload Button -->
|
|
||||||
<a href="javascript:;" class="upload-button">
|
|
||||||
<span class="upload-button-icon oc-<?= $emptyIcon ?>"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Existing files -->
|
|
||||||
<div class="upload-files-container">
|
|
||||||
<?php foreach ($fileList as $file): ?>
|
|
||||||
<div class="upload-object is-success" data-id="<?= $file->id ?>" data-path="<?= $file->pathUrl ?>">
|
|
||||||
<div class="icon-container image">
|
|
||||||
<img src="<?= $file->thumbUrl ?>" alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<h4 class="filename">
|
|
||||||
<span data-dz-name><?= e($file->title ?: $file->file_name) ?></span>
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
class="upload-remove-button"
|
|
||||||
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
|
|
||||||
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
|
|
||||||
data-request-data="file_id: <?= $file->id ?>"
|
|
||||||
><i class="icon-times"></i></a>
|
|
||||||
</h4>
|
|
||||||
<p class="size"><?= e($file->sizeToString()) ?></p>
|
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<a href="javascript:;" class="drag-handle"><i class="icon-bars"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Template for new files -->
|
|
||||||
<script type="text/template" id="<?= $this->getId('template') ?>">
|
|
||||||
<div class="upload-object dz-preview dz-file-preview">
|
|
||||||
<div class="icon-container image">
|
|
||||||
<img data-dz-thumbnail alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<h4 class="filename">
|
|
||||||
<span data-dz-name></span>
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
class="upload-remove-button"
|
|
||||||
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
|
|
||||||
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
|
|
||||||
><i class="icon-times"></i></a>
|
|
||||||
</h4>
|
|
||||||
<p class="size" data-dz-size></p>
|
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<a href="javascript:;" class="drag-handle"><i class="icon-bars"></i></a>
|
|
||||||
<div class="progress-bar"><span class="upload-progress" data-dz-uploadprogress></span></div>
|
|
||||||
<div class="error-message"><span data-dz-errormessage></span></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
|
|
@ -1,74 +0,0 @@
|
||||||
<div
|
|
||||||
id="<?= $this->getId() ?>"
|
|
||||||
class="field-fileupload style-image-single <?= $singleFile ? 'is-populated' : '' ?> <?= $this->previewMode ? 'is-preview' : '' ?>"
|
|
||||||
data-control="fileupload"
|
|
||||||
data-upload-handler="<?= $this->getEventHandler('onUpload') ?>"
|
|
||||||
data-template="#<?= $this->getId('template') ?>"
|
|
||||||
data-error-template="#<?= $this->getId('errorTemplate') ?>"
|
|
||||||
data-unique-id="<?= $this->getId() ?>"
|
|
||||||
data-thumbnail-width="<?= $imageWidth ?: '0' ?>"
|
|
||||||
data-thumbnail-height="<?= $imageHeight ?: '0' ?>"
|
|
||||||
data-max-filesize="<?= $maxFilesize ?>"
|
|
||||||
<?php if ($useCaption): ?>data-config-handler="<?= $this->getEventHandler('onLoadAttachmentConfig') ?>"<?php endif ?>
|
|
||||||
<?php if ($acceptedFileTypes): ?>data-file-types="<?= $acceptedFileTypes ?>"<?php endif ?>
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- Add New Image -->
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
style="<?= $cssBlockDimensions ?>"
|
|
||||||
class="upload-button">
|
|
||||||
<span class="upload-button-icon oc-<?= $emptyIcon ?> <?= $imageWidth > 100 ? 'large-icon' : '' ?>"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Existing file -->
|
|
||||||
<div class="upload-files-container">
|
|
||||||
<?php if ($singleFile): ?>
|
|
||||||
<div class="upload-object is-success" data-id="<?= $singleFile->id ?>" data-path="<?= $singleFile->pathUrl ?>">
|
|
||||||
<div class="icon-container image">
|
|
||||||
<img src="<?= $singleFile->thumbUrl ?>" alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<h4 class="filename">
|
|
||||||
<span data-dz-name><?= e($singleFile->title ?: $singleFile->file_name) ?></span>
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
class="upload-remove-button"
|
|
||||||
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
|
|
||||||
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
|
|
||||||
data-request-data="file_id: <?= $singleFile->id ?>"
|
|
||||||
><i class="icon-times"></i></a>
|
|
||||||
</h4>
|
|
||||||
<p class="size"><?= e($singleFile->sizeToString()) ?></p>
|
|
||||||
</div>
|
|
||||||
<div class="meta"></div>
|
|
||||||
</div>
|
|
||||||
<?php endif ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Template for new file -->
|
|
||||||
<script type="text/template" id="<?= $this->getId('template') ?>">
|
|
||||||
<div class="upload-object dz-preview dz-file-preview">
|
|
||||||
<div class="icon-container image">
|
|
||||||
<img data-dz-thumbnail style="<?= $cssDimensions ?>" alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<h4 class="filename">
|
|
||||||
<span data-dz-name></span>
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
class="upload-remove-button"
|
|
||||||
data-request="<?= $this->getEventHandler('onRemoveAttachment') ?>"
|
|
||||||
data-request-confirm="<?= e(trans('backend::lang.fileupload.remove_confirm')) ?>"
|
|
||||||
><i class="icon-times"></i></a>
|
|
||||||
</h4>
|
|
||||||
<p class="size" data-dz-size></p>
|
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<div class="progress-bar"><span class="upload-progress" data-dz-uploadprogress></span></div>
|
|
||||||
<div class="error-message"><span data-dz-errormessage></span></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?php if ($this->previewMode && !$fileList->count()): ?>
|
|
||||||
<div class="form-control">
|
|
||||||
<?= $value ?>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div data-responsiveimage>
|
|
||||||
<div>
|
|
||||||
<app formid="<?php echo $this->getId(); ?>" name="<?= $name ?>" :handlers="{
|
|
||||||
onUpload: '<?= $this->getEventHandler('onUpload') ?>',
|
|
||||||
onOpenDatabase: '<?= $this->getEventHandler('onOpenDatabase') ?>',
|
|
||||||
onDelete: '<?= $this->getEventHandler('onDelete') ?>'
|
|
||||||
}"
|
|
||||||
:crop-options="{
|
|
||||||
aspectRatio: <?= $aspectRatio ?>,
|
|
||||||
minWidth: <?= $minWidth ?>,
|
|
||||||
types: <?= $croppableTypes; ?>
|
|
||||||
}"
|
|
||||||
:value="<?= $value; ?>"
|
|
||||||
:meta="<?= $meta; ?>"
|
|
||||||
></app>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php endif ?>
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Lib;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Compressors\Compressor;
|
||||||
|
use Aweos\Resizer\Compressors\Factory as CompressorFactory;
|
||||||
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Media\Classes\MediaLibrary;
|
||||||
|
use Storage;
|
||||||
|
|
||||||
|
class MediaPath
|
||||||
|
{
|
||||||
|
|
||||||
|
private string $path;
|
||||||
|
|
||||||
|
public function __construct(string $path)
|
||||||
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function root(): string
|
||||||
|
{
|
||||||
|
return Storage::path($this->storagePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function storagePath(): string
|
||||||
|
{
|
||||||
|
return "media/{$this->normal()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function normal(): string
|
||||||
|
{
|
||||||
|
return preg_replace('|^/*|', '', $this->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compressor(): Compressor
|
||||||
|
{
|
||||||
|
return app(CompressorFactory::class)->resolve($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filename(): string
|
||||||
|
{
|
||||||
|
return pathinfo($this->path, PATHINFO_FILENAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function extension(): string
|
||||||
|
{
|
||||||
|
return pathinfo($this->path, PATHINFO_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function versionsPath(): string
|
||||||
|
{
|
||||||
|
return "uploads/public/c/{$this->normal()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function versionsDirPath(): string
|
||||||
|
{
|
||||||
|
return pathinfo("uploads/public/c/{$this->normal()}", PATHINFO_DIRNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function publicUrl(): string
|
||||||
|
{
|
||||||
|
return MediaLibrary::instance()->findFiles($this->path)[0]->publicUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(): string
|
||||||
|
{
|
||||||
|
return MediaLibrary::instance()->get($this->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldProcess(): bool
|
||||||
|
{
|
||||||
|
return collect(Setting::get('folders'))->pluck('folder')->first(
|
||||||
|
fn ($folder) => starts_with('/'.$this->normal(), $folder.'/')
|
||||||
|
) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function versions(): Collection
|
||||||
|
{
|
||||||
|
$return = collect([]);
|
||||||
|
|
||||||
|
foreach (Storage::files($this->versionsDirPath()) as $file) {
|
||||||
|
if (!preg_match_all('|('.preg_quote($this->filename(), '|').')(-[0-9]+x[0-9]+)?(\.[a-zA-Z]+)$|', $file, $matches)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($matches[2][0]) {
|
||||||
|
[$width, $height] = explode('x', substr($matches[2][0], 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = $this->versionsDirPath().'/'.$matches[0][0];
|
||||||
|
|
||||||
|
$return->push(collect([
|
||||||
|
'path' => $path,
|
||||||
|
'url' => Storage::url($path),
|
||||||
|
'filename' => $matches[0][0],
|
||||||
|
'base' => $matches[1][0],
|
||||||
|
'size' => $matches[2][0],
|
||||||
|
'ext' => $matches[3][0],
|
||||||
|
'width' => $width ?? null,
|
||||||
|
'height' => $height ?? null,
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,73 +0,0 @@
|
||||||
<?php namespace Aweos\Resizer\Models;
|
|
||||||
|
|
||||||
use Model;
|
|
||||||
use Storage;
|
|
||||||
use Cache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setting Model
|
|
||||||
*/
|
|
||||||
class Attachment extends Model
|
|
||||||
{
|
|
||||||
use \October\Rain\Database\Traits\Sluggable;
|
|
||||||
|
|
||||||
protected $slugs = ['slug' => 'title'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string The database table used by the model.
|
|
||||||
*/
|
|
||||||
public $table = 'responsive_attachments';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array Guarded fields
|
|
||||||
*/
|
|
||||||
protected $guarded = ['*'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array Fillable fields
|
|
||||||
*/
|
|
||||||
protected $fillable = ['id', 'file_id', 'title', 'slug', 'description'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array Relations
|
|
||||||
*/
|
|
||||||
public $hasOne = [];
|
|
||||||
public $hasMany = [];
|
|
||||||
public $belongsTo = [
|
|
||||||
'source' => [SourceFile::class, 'key' => 'file_id']
|
|
||||||
];
|
|
||||||
public $belongsToMany = [];
|
|
||||||
public $morphTo = [];
|
|
||||||
public $morphOne = [];
|
|
||||||
public $morphMany = [];
|
|
||||||
public $attachOne = [];
|
|
||||||
public $attachMany = [];
|
|
||||||
|
|
||||||
public function getFilenameAttribute() {
|
|
||||||
return $this->slug.'.'.$this->source->extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPathAttribute() {
|
|
||||||
return strtolower($this->slug[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVersionPath($w) {
|
|
||||||
return $this->path.'/'.$this->slug.'-'.$w.'.'.$this->source->extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVersionRegexAttribute() {
|
|
||||||
$path = preg_quote($this->path, '/');
|
|
||||||
$ext = preg_quote($this->source->extension, '/');
|
|
||||||
$name = preg_quote($this->slug, '/');
|
|
||||||
|
|
||||||
return "/^{$path}\/{$name}(-[0-9]+)?(-full)?\.{$ext}$/";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUrlAttribute() {
|
|
||||||
return Storage::disk('uploads')->url($this->source->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function beforeDelete() {
|
|
||||||
Cache::forget('responsive-image-'.$this->id);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
<?php namespace Aweos\Resizer\Models;
|
|
||||||
|
|
||||||
use Model;
|
|
||||||
use Storage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setting Model
|
|
||||||
*/
|
|
||||||
class SourceFile extends Model
|
|
||||||
{
|
|
||||||
use \October\Rain\Database\Traits\Sluggable;
|
|
||||||
|
|
||||||
protected $slugs = ['slug' => 'basename'];
|
|
||||||
|
|
||||||
public static $croppableTypes = [ 'image/jpeg', 'image/gif', 'image/png', 'image/webp' ];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string The database table used by the model.
|
|
||||||
*/
|
|
||||||
public $table = 'responsive_source_files';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array Guarded fields
|
|
||||||
*/
|
|
||||||
protected $guarded = ['*'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array Fillable fields
|
|
||||||
*/
|
|
||||||
protected $fillable = ['id', 'basename', 'extension', 'tags', 'slug', 'aspect_ratio', 'min_width'];
|
|
||||||
|
|
||||||
public $jsonable = ['tags', 'aspect_ratio'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array Relations
|
|
||||||
*/
|
|
||||||
public $hasOne = [];
|
|
||||||
public $hasMany = [
|
|
||||||
'attachments' => [Attachment::class, 'key' => 'file_id']
|
|
||||||
];
|
|
||||||
public $belongsTo = [];
|
|
||||||
public $belongsToMany = [];
|
|
||||||
public $morphTo = [];
|
|
||||||
public $morphOne = [];
|
|
||||||
public $morphMany = [];
|
|
||||||
public $attachOne = [];
|
|
||||||
public $attachMany = [];
|
|
||||||
|
|
||||||
public function getPathAttribute() {
|
|
||||||
return 'source/'.$this->slug.'.'.$this->extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUrlAttribute() {
|
|
||||||
return Storage::disk('uploads')->url($this->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTypeAttribute() {
|
|
||||||
return Storage::disk('uploads')->mimeType($this->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSizeAttribute() {
|
|
||||||
return Storage::disk('uploads')->size($this->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isCroppable(): bool {
|
|
||||||
return in_array($this->type, static::$croppableTypes);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
namespace Aweos\Resizer\Tests\MediaTest;
|
namespace Aweos\Resizer\Tests\MediaTest;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Classes\CacheManager;
|
||||||
use Aweos\Resizer\Classes\TagGenerator;
|
use Aweos\Resizer\Classes\TagGenerator;
|
||||||
|
use Aweos\Resizer\Lib\MediaPath;
|
||||||
use Aweos\Resizer\Models\Setting;
|
use Aweos\Resizer\Models\Setting;
|
||||||
use Aweos\Resizer\Tests\TestCase;
|
use Aweos\Resizer\Tests\TestCase;
|
||||||
use Cache;
|
use Cache;
|
||||||
|
@ -32,7 +34,7 @@ class ImageTagTest extends TestCase
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'width="500" height="500" sizes="(max-width: 100px) 100px, (max-width: 200px) 200px, (max-width: 500px) 500px" srcset="/storage/uploads/public/c/pages/test-100x100.jpg 100w, /storage/uploads/public/c/pages/test-200x200.jpg 200w, /storage/uploads/public/c/pages/test-500x500.jpg 500w" src="/storage/uploads/public/c/pages/test-500x500.jpg"',
|
'width="500" height="500" sizes="(max-width: 100px) 100px, (max-width: 200px) 200px, (max-width: 500px) 500px" srcset="/storage/uploads/public/c/pages/test-100x100.jpg 100w, /storage/uploads/public/c/pages/test-200x200.jpg 200w, /storage/uploads/public/c/pages/test-500x500.jpg 500w" src="/storage/uploads/public/c/pages/test-500x500.jpg"',
|
||||||
app(Twig::class)->parse('{{"pages/test.jpg" | resize}}'),
|
app(CacheManager::class)->get(new MediaPath('pages/test.jpg'), 'original', null),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
<?php namespace Aweos\Resizer\Traits;
|
|
||||||
|
|
||||||
use Str;
|
|
||||||
use Backend\Classes\FormField;
|
|
||||||
use October\Rain\Halcyon\Model as HalcyonModel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements special logic for processing form data, typically from from postback, and
|
|
||||||
* filling the model attributes and attributes of any related models. This is a
|
|
||||||
* customized, safer and simplified version of `$model->push()`.
|
|
||||||
*
|
|
||||||
* @package october\backend
|
|
||||||
* @author Alexey Bobkov, Samuel Georges
|
|
||||||
*/
|
|
||||||
trait ResponsiveSaver
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var array List of prepared models that require saving.
|
|
||||||
*/
|
|
||||||
protected $modelsToSave = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a model and fills it with data from a multidimensional array.
|
|
||||||
* If an attribute is found to be a relationship, that relationship
|
|
||||||
* is also filled.
|
|
||||||
*
|
|
||||||
* $modelsToSave = $this->prepareModelsToSave($model, [...]);
|
|
||||||
*
|
|
||||||
* foreach ($modelsToSave as $modelToSave) {
|
|
||||||
* $modelToSave->save();
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @param \October\Rain\Database\Model $model Model to fill.
|
|
||||||
* @param array $saveData Attribute values to fill model.
|
|
||||||
* @return array The collection of models to save.
|
|
||||||
*/
|
|
||||||
protected function prepareModelsToSave($model, $saveData)
|
|
||||||
{
|
|
||||||
$this->modelsToSave = [];
|
|
||||||
$this->setModelAttributes($model, $saveData);
|
|
||||||
$this->modelsToSave = array_reverse($this->modelsToSave);
|
|
||||||
return $this->modelsToSave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a data collection to a model attributes, relations are also set.
|
|
||||||
*
|
|
||||||
* @param \October\Rain\Database\Model $model Model to fill.
|
|
||||||
* @param array $saveData Attribute values to fill model.
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function setModelAttributes($model, $saveData)
|
|
||||||
{
|
|
||||||
$this->modelsToSave[] = $model;
|
|
||||||
|
|
||||||
if (!is_array($saveData)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($model instanceof HalcyonModel) {
|
|
||||||
$model->fill($saveData);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$attributesToPurge = [];
|
|
||||||
$singularTypes = ['belongsTo', 'hasOne', 'morphTo', 'morphOne'];
|
|
||||||
|
|
||||||
foreach ($saveData as $attribute => $value) {
|
|
||||||
$isNested = $attribute == 'pivot' || (
|
|
||||||
$model->hasRelation($attribute) &&
|
|
||||||
in_array($model->getRelationType($attribute), $singularTypes)
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($isNested && is_array($value)) {
|
|
||||||
$this->setModelAttributes($model->{$attribute}, $value);
|
|
||||||
}
|
|
||||||
elseif ($value !== FormField::NO_SAVE_DATA) {
|
|
||||||
if (Str::startsWith($attribute, '_')) {
|
|
||||||
$attributesToPurge[] = $attribute;
|
|
||||||
}
|
|
||||||
$model->{$attribute} = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($attributesToPurge) {
|
|
||||||
$this->deferPurgedSaveAttributes($model, $attributesToPurge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes an array of attributes from the model. If the model implements
|
|
||||||
* the Purgeable trait, this is preferred over the internal logic.
|
|
||||||
*
|
|
||||||
* @param \October\Rain\Database\Model $model Model to adjust.
|
|
||||||
* @param array $attributesToPurge Attribute values to remove from the model.
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function deferPurgedSaveAttributes($model, $attributesToPurge)
|
|
||||||
{
|
|
||||||
if (!is_array($attributesToPurge)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compatibility with Purgeable trait:
|
|
||||||
* This will give the ability to restore purged attributes
|
|
||||||
* and make them available again if necessary.
|
|
||||||
*/
|
|
||||||
if (method_exists($model, 'getPurgeableAttributes')) {
|
|
||||||
$model->addPurgeable($attributesToPurge);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$model->bindEventOnce('model.saveInternal', function () use ($model, $attributesToPurge) {
|
|
||||||
foreach ($attributesToPurge as $attribute) {
|
|
||||||
unset($model->attributes[$attribute]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
<?php namespace Aweos\Resizer\Traits;
|
|
||||||
|
|
||||||
use Lang;
|
|
||||||
use ApplicationException;
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Form Model Widget Trait
|
|
||||||
*
|
|
||||||
* Special logic for for form widgets that use a database stored model.
|
|
||||||
*
|
|
||||||
* @package october\backend
|
|
||||||
* @author Alexey Bobkov, Samuel Georges
|
|
||||||
*/
|
|
||||||
|
|
||||||
trait ResponsiveWidget
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the final model and attribute name of
|
|
||||||
* a nested HTML array attribute.
|
|
||||||
* Eg: list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
|
|
||||||
* @param string $attribute.
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function resolveModelAttribute($attribute)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return $this->formField->resolveModelAttribute($this->model, $attribute);
|
|
||||||
}
|
|
||||||
catch (Exception $ex) {
|
|
||||||
throw new ApplicationException(Lang::get('backend::lang.model.missing_relation', [
|
|
||||||
'class' => get_class($this->model),
|
|
||||||
'relation' => $attribute
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the model of a relation type,
|
|
||||||
* supports nesting via HTML array.
|
|
||||||
* @return Relation
|
|
||||||
*/
|
|
||||||
protected function getRelationModel()
|
|
||||||
{
|
|
||||||
list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
|
|
||||||
|
|
||||||
if (!$model) {
|
|
||||||
throw new ApplicationException(Lang::get('backend::lang.model.missing_relation', [
|
|
||||||
'class' => get_class($this->model),
|
|
||||||
'relation' => $this->valueFrom
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$model->hasRelation($attribute)) {
|
|
||||||
throw new ApplicationException(Lang::get('backend::lang.model.missing_relation', [
|
|
||||||
'class' => get_class($model),
|
|
||||||
'relation' => $attribute
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $model->makeRelation($attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value as a relation object from the model,
|
|
||||||
* supports nesting via HTML array.
|
|
||||||
* @return Relation
|
|
||||||
*/
|
|
||||||
protected function getRelationObject()
|
|
||||||
{
|
|
||||||
list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
|
|
||||||
|
|
||||||
if (!$model) {
|
|
||||||
throw new ApplicationException(Lang::get('backend::lang.model.missing_relation', [
|
|
||||||
'class' => get_class($this->model),
|
|
||||||
'relation' => $this->valueFrom
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$model->hasRelation($attribute)) {
|
|
||||||
throw new ApplicationException(Lang::get('backend::lang.model.missing_relation', [
|
|
||||||
'class' => get_class($model),
|
|
||||||
'relation' => $attribute
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $model->{$attribute}();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value as a relation type from the model,
|
|
||||||
* supports nesting via HTML array.
|
|
||||||
* @return Relation
|
|
||||||
*/
|
|
||||||
protected function getRelationType()
|
|
||||||
{
|
|
||||||
list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
|
|
||||||
return $model->getRelationType($attribute);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php namespace Aweos\Resizer\Updates;
|
|
||||||
|
|
||||||
use Schema;
|
|
||||||
use October\Rain\Database\Schema\Blueprint;
|
|
||||||
use October\Rain\Database\Updates\Migration;
|
|
||||||
|
|
||||||
class CreateResponsiveFilesTable extends Migration
|
|
||||||
{
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('responsive_source_files', function(Blueprint $table) {
|
|
||||||
$table->engine = 'InnoDB';
|
|
||||||
$table->increments('id');
|
|
||||||
$table->string('basename');
|
|
||||||
$table->string('slug');
|
|
||||||
$table->string('extension');
|
|
||||||
$table->json('tags');
|
|
||||||
$table->string('aspect_ratio')->nullable();
|
|
||||||
$table->integer('min_width')->nullable();
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::create('responsive_attachments', function(Blueprint $table) {
|
|
||||||
$table->engine = 'InnoDB';
|
|
||||||
$table->increments('id');
|
|
||||||
$table->integer('file_id')->unsigned();
|
|
||||||
$table->string('title');
|
|
||||||
$table->string('slug');
|
|
||||||
$table->string('description')->nullable();
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('aweos_resizer_settings');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,2 @@
|
||||||
1.0.1: First version of resizer
|
1.0.1: First version of resizer
|
||||||
1.0.2:
|
- create_settings_table.php
|
||||||
- Create attachments
|
|
||||||
- create_file_attachments_table.php
|
|
||||||
|
|
Loading…
Reference in New Issue