mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
parent
fbccc6824a
commit
9f95cbcbfb
@ -71,13 +71,18 @@ class ImageController extends Controller
|
||||
*/
|
||||
public function getAll($page = 0)
|
||||
{
|
||||
$pageSize = 25;
|
||||
$pageSize = 13;
|
||||
$images = DB::table('images')->orderBy('created_at', 'desc')
|
||||
->skip($page*$pageSize)->take($pageSize)->get();
|
||||
foreach($images as $image) {
|
||||
$image->thumbnail = $this->getThumbnail($image, 150, 150);
|
||||
}
|
||||
return response()->json($images);
|
||||
$hasMore = count(DB::table('images')->orderBy('created_at', 'desc')
|
||||
->skip(($page+1)*$pageSize)->take($pageSize)->get()) > 0;
|
||||
return response()->json([
|
||||
'images' => $images,
|
||||
'hasMore' => $hasMore
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,18 +98,24 @@ class ImageController extends Controller
|
||||
array_splice($explodedPath, 3, 0, ['thumbs-' . $width . '-' . $height]);
|
||||
$thumbPath = implode('/', $explodedPath);
|
||||
$thumbFilePath = storage_path() . $thumbPath;
|
||||
|
||||
// Return the thumbnail url path if already exists
|
||||
if(file_exists($thumbFilePath)) {
|
||||
return $thumbPath;
|
||||
}
|
||||
|
||||
//dd($thumbFilePath);
|
||||
// Otherwise create the thumbnail
|
||||
$thumb = ImageTool::make(storage_path() . $image->url);
|
||||
$thumb->fit($width, $height);
|
||||
|
||||
// Create thumbnail folder if it does not exist
|
||||
if(!file_exists(dirname($thumbFilePath))) {
|
||||
mkdir(dirname($thumbFilePath), 0775, true);
|
||||
}
|
||||
|
||||
//Save Thumbnail
|
||||
$thumb->save($thumbFilePath);
|
||||
return $thumbFilePath;
|
||||
return $thumbPath;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,6 +141,7 @@ class ImageController extends Controller
|
||||
$this->image->created_by = Auth::user()->id;
|
||||
$this->image->updated_by = Auth::user()->id;
|
||||
$this->image->save();
|
||||
$this->image->thumbnail = $this->getThumbnail($this->image, 150, 150);
|
||||
return response()->json($this->image);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,19 @@
|
||||
|
||||
// Dropzone config
|
||||
Dropzone.options.imageUploadDropzone = {
|
||||
uploadMultiple: false,
|
||||
previewsContainer: '.image-manager-display .uploads',
|
||||
init: function() {
|
||||
this.on('success', function(event, image) {
|
||||
$('.image-manager-display .uploads').empty();
|
||||
var newImage = $('<img />').attr('data-image-id', image.id);
|
||||
newImage.attr('title', image.name).attr('src', image.thumbnail);
|
||||
newImage.data('imageData', image);
|
||||
$('.image-manager-display .uploads').after(newImage);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
||||
var isInit = false;
|
||||
@ -6,6 +21,9 @@
|
||||
var overlay;
|
||||
var display;
|
||||
var imageIndexUrl = '/images/all';
|
||||
var pageIndex = 0;
|
||||
var hasMore = true;
|
||||
var isGettingImages = true;
|
||||
|
||||
var ImageManager = {};
|
||||
var action = false;
|
||||
@ -22,23 +40,48 @@
|
||||
};
|
||||
|
||||
ImageManager.init = function(selector) {
|
||||
console.log('cat');
|
||||
elem = $(selector);
|
||||
overlay = elem.closest('.overlay');
|
||||
display = elem.find('.image-manager-display').first()
|
||||
|
||||
display = elem.find('.image-manager-display').first();
|
||||
var uploads = display.find('.uploads');
|
||||
var images = display.find('images');
|
||||
var loadMore = display.find('.load-more');
|
||||
// Get recent images and show
|
||||
$.getJSON(imageIndexUrl, showImages);
|
||||
function showImages(images) {
|
||||
function showImages(data) {
|
||||
var images = data.images;
|
||||
hasMore = data.hasMore;
|
||||
pageIndex++;
|
||||
isGettingImages = false;
|
||||
for(var i = 0; i < images.length; i++) {
|
||||
var image = images[i];
|
||||
var newImage = $('<img />').attr('data-image-id', image.id);
|
||||
newImage.attr('title', image.name).attr('src', image.thumbnail);
|
||||
display.append(newImage);
|
||||
loadMore.before(newImage);
|
||||
newImage.data('imageData', image);
|
||||
}
|
||||
if(hasMore) loadMore.show();
|
||||
}
|
||||
|
||||
loadMore.click(function() {
|
||||
loadMore.hide();
|
||||
if(isGettingImages === false) {
|
||||
isGettingImages = true;
|
||||
$.getJSON(imageIndexUrl + '/' + pageIndex, showImages);
|
||||
}
|
||||
});
|
||||
|
||||
// Image grabbing on scroll
|
||||
display.on('scroll', function() {
|
||||
var displayBottom = display.scrollTop() + display.height();
|
||||
var elemTop = loadMore.offset().top;
|
||||
if(elemTop < displayBottom && hasMore && isGettingImages === false) {
|
||||
isGettingImages = true;
|
||||
loadMore.hide();
|
||||
$.getJSON(imageIndexUrl + '/' + pageIndex, showImages);
|
||||
}
|
||||
});
|
||||
|
||||
elem.on('dblclick', '.image-manager-display img', function() {
|
||||
var imageElem = $(this);
|
||||
var imageData = imageElem.data('imageData');
|
||||
@ -55,7 +98,7 @@
|
||||
// Set up dropzone
|
||||
elem.find('.image-manager-dropzone').first().dropzone({
|
||||
uploadMultiple: false
|
||||
})
|
||||
});
|
||||
|
||||
isInit = true;
|
||||
};
|
||||
|
324
resources/assets/sass/image-manager.scss
Normal file
324
resources/assets/sass/image-manager.scss
Normal file
@ -0,0 +1,324 @@
|
||||
#image-manager {
|
||||
background-color: #EEE;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
margin: 2% 5%;
|
||||
//border: 2px solid $primary;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.3);
|
||||
overflow: hidden;
|
||||
.image-manager-display img {
|
||||
border-radius: 0;
|
||||
float: left;
|
||||
margin: 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
#image-manager .dropzone {
|
||||
display: table;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 300px;
|
||||
width: 480px;
|
||||
height: 60px;
|
||||
border: 4px dashed $primary;
|
||||
text-align: center;
|
||||
z-index: 900;
|
||||
.dz-message {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
color: $primary;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
* {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
.image-manager-left {
|
||||
background-color: #FFF;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
position: relative;
|
||||
.image-manager-display-wrap {
|
||||
height: 100%;
|
||||
padding-top: 87px;
|
||||
position: absolute;
|
||||
top: 0;width: 100%;
|
||||
}
|
||||
.image-manager-display {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.image-manager-header {
|
||||
z-index: 50;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
#image-manager .load-more {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
display: none;
|
||||
float: left;
|
||||
text-align: center;
|
||||
background-color: #888;
|
||||
margin: 1px;
|
||||
color: #FFF;
|
||||
line-height: 140px;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.image-manager-title {
|
||||
font-size: 2em;
|
||||
text-align: left;
|
||||
margin: 0 $-m;
|
||||
padding: $-xl $-m;
|
||||
color: #666;
|
||||
border-bottom: 1px solid #DDD;
|
||||
}
|
||||
|
||||
.image-manager-dropzone {
|
||||
background-color: lighten($primary, 40%);
|
||||
height: 25%;
|
||||
text-align: center;
|
||||
font-size: 2em;
|
||||
line-height: 2em;
|
||||
padding-top: $-xl*1.2;
|
||||
color: #666;
|
||||
border-top: 2px solid $primary;
|
||||
}
|
||||
|
||||
// Dropzone
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright (c) 2012 Matias Meno <m@tias.me>
|
||||
*/
|
||||
|
||||
@keyframes passing-through {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(40px); }
|
||||
30%, 70% {
|
||||
opacity: 1;
|
||||
transform: translateY(0px); }
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(-40px); } }
|
||||
|
||||
@keyframes slide-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(40px); }
|
||||
30% {
|
||||
opacity: 1;
|
||||
transform: translateY(0px); } }
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
-webkit-transform: scale(1);
|
||||
-moz-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
-o-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
10% {
|
||||
-webkit-transform: scale(1.1);
|
||||
-moz-transform: scale(1.1);
|
||||
-ms-transform: scale(1.1);
|
||||
-o-transform: scale(1.1);
|
||||
transform: scale(1.1); }
|
||||
20% {
|
||||
-webkit-transform: scale(1);
|
||||
-moz-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
-o-transform: scale(1);
|
||||
transform: scale(1); } }
|
||||
.dropzone, .dropzone * {
|
||||
box-sizing: border-box; }
|
||||
|
||||
.dropzone {
|
||||
background: white;
|
||||
padding: 20px 20px; }
|
||||
.dropzone.dz-clickable {
|
||||
cursor: pointer; }
|
||||
.dropzone.dz-clickable * {
|
||||
cursor: default; }
|
||||
.dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
|
||||
cursor: pointer; }
|
||||
.dropzone.dz-started .dz-message {
|
||||
display: none; }
|
||||
.dropzone.dz-drag-hover {
|
||||
border-style: solid; }
|
||||
.dropzone.dz-drag-hover .dz-message {
|
||||
opacity: 0.5; }
|
||||
.dropzone .dz-message {
|
||||
text-align: center;
|
||||
margin: 2em 0; }
|
||||
.dz-preview {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin: 16px;
|
||||
min-height: 100px; }
|
||||
.dz-preview:hover {
|
||||
z-index: 1000; }
|
||||
.dz-preview:hover .dz-details {
|
||||
opacity: 1; }
|
||||
.dz-preview.dz-file-preview .dz-image {
|
||||
border-radius: 4px;
|
||||
background: #999;
|
||||
background: linear-gradient(to bottom, #eee, #ddd); }
|
||||
.dz-preview.dz-file-preview .dz-details {
|
||||
opacity: 1; }
|
||||
.dz-preview.dz-image-preview {
|
||||
background: white; }
|
||||
.dz-preview.dz-image-preview .dz-details {
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
-ms-transition: opacity 0.2s linear;
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear; }
|
||||
.dz-preview .dz-remove {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
border: none; }
|
||||
.dz-preview .dz-remove:hover {
|
||||
text-decoration: underline; }
|
||||
.dz-preview:hover .dz-details {
|
||||
opacity: 1; }
|
||||
.dz-preview .dz-details {
|
||||
z-index: 20;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
font-size: 13px;
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
padding: 2em 1em;
|
||||
text-align: center;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
line-height: 150%; }
|
||||
.dz-preview .dz-details .dz-size {
|
||||
margin-bottom: 1em;
|
||||
font-size: 16px; }
|
||||
.dz-preview .dz-details .dz-filename {
|
||||
white-space: nowrap; }
|
||||
.dz-preview .dz-details .dz-filename:hover span {
|
||||
border: 1px solid rgba(200, 200, 200, 0.8);
|
||||
background-color: rgba(255, 255, 255, 0.8); }
|
||||
.dz-preview .dz-details .dz-filename:not(:hover) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; }
|
||||
.dz-preview .dz-details .dz-filename:not(:hover) span {
|
||||
border: 1px solid transparent; }
|
||||
.dz-preview .dz-details .dz-filename span, .dz-preview .dz-details .dz-size span {
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
padding: 0 0.4em;
|
||||
border-radius: 3px; }
|
||||
.dz-preview:hover .dz-image img {
|
||||
-webkit-transform: scale(1.05, 1.05);
|
||||
-moz-transform: scale(1.05, 1.05);
|
||||
-ms-transform: scale(1.05, 1.05);
|
||||
-o-transform: scale(1.05, 1.05);
|
||||
transform: scale(1.05, 1.05);
|
||||
-webkit-filter: blur(8px);
|
||||
filter: blur(8px); }
|
||||
.dz-preview .dz-image {
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
position: relative;
|
||||
display: block;
|
||||
z-index: 10; }
|
||||
.dz-preview .dz-image img {
|
||||
display: block; }
|
||||
.dz-preview.dz-success .dz-success-mark {
|
||||
animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); }
|
||||
.dz-preview.dz-error .dz-error-mark {
|
||||
opacity: 1;
|
||||
animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); }
|
||||
.dz-preview .dz-success-mark, .dz-preview .dz-error-mark {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
z-index: 500;
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -27px;
|
||||
margin-top: -27px; }
|
||||
.dz-preview .dz-success-mark svg, .dz-preview .dz-error-mark svg {
|
||||
display: block;
|
||||
width: 54px;
|
||||
height: 54px; }
|
||||
.dz-preview.dz-processing .dz-progress {
|
||||
opacity: 1;
|
||||
transition: all 0.2s linear; }
|
||||
.dz-preview.dz-complete .dz-progress {
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s ease-in; }
|
||||
.dz-preview:not(.dz-processing) .dz-progress {
|
||||
animation: pulse 6s ease infinite; }
|
||||
.dz-preview .dz-progress {
|
||||
opacity: 1;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
height: 16px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-top: -8px;
|
||||
width: 80px;
|
||||
margin-left: -40px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
-webkit-transform: scale(1);
|
||||
border-radius: 8px;
|
||||
overflow: hidden; }
|
||||
.dz-preview .dz-progress .dz-upload {
|
||||
background: #333;
|
||||
background: linear-gradient(to bottom, #666, #444);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 0;
|
||||
transition: width 300ms ease-in-out; }
|
||||
.dz-preview.dz-error .dz-error-message {
|
||||
display: block; }
|
||||
.dz-preview.dz-error:hover .dz-error-message {
|
||||
opacity: 1;
|
||||
pointer-events: auto; }
|
||||
.dz-preview .dz-error-message {
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
position: absolute;
|
||||
display: block;
|
||||
display: none;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
top: 130px;
|
||||
left: -10px;
|
||||
width: 140px;
|
||||
background: #be2626;
|
||||
background: linear-gradient(to bottom, #be2626, #a92222);
|
||||
padding: 0.5em 1.2em;
|
||||
color: white; }
|
||||
.dz-preview .dz-error-message:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 64px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #be2626; }
|
@ -9,6 +9,7 @@
|
||||
@import "forms";
|
||||
@import "tables";
|
||||
@import "tinymce";
|
||||
@import "image-manager";
|
||||
|
||||
header {
|
||||
display: block;
|
||||
@ -192,57 +193,6 @@ ul.menu {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
#image-manager {
|
||||
background-color: #EEE;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
margin: 2% 5%;
|
||||
//border: 2px solid $primary;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.3);
|
||||
overflow: hidden;
|
||||
.image-manager-display img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
display: inline-block;
|
||||
margin: $-s 0 0 $-s;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.image-manager-left {
|
||||
background-color: #FFF;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
.image-manager-display {
|
||||
height: 75%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
.image-manager-title {
|
||||
font-size: 2em;
|
||||
text-align: left;
|
||||
margin: 0 $-m;
|
||||
padding: $-xl $-m;
|
||||
color: #666;
|
||||
border-bottom: 1px solid #DDD;
|
||||
}
|
||||
|
||||
.image-manager-dropzone {
|
||||
background-color: lighten($primary, 40%);
|
||||
height: 25%;
|
||||
text-align: center;
|
||||
font-size: 2em;
|
||||
line-height: 2em;
|
||||
padding-top: $-xl*1.2;
|
||||
color: #666;
|
||||
border-top: 2px solid $primary;
|
||||
}
|
||||
|
||||
// Link hooks & popovers
|
||||
a.link-hook {
|
||||
|
@ -1,15 +1,23 @@
|
||||
<section class="overlay" style="display:none;">
|
||||
{{--<section class="overlay">--}}
|
||||
<div id="image-manager">
|
||||
<div class="image-manager-left">
|
||||
<div class="image-manager-header">
|
||||
<button type="button" class="button neg float right" data-action="close">Close</button>
|
||||
<div class="image-manager-title">Image Library</div>
|
||||
</div>
|
||||
<div class="image-manager-display-wrap">
|
||||
<div class="image-manager-display">
|
||||
<div class="uploads"></div>
|
||||
<div class="images">
|
||||
<div class="load-more">Load More</div>
|
||||
</div>
|
||||
<form action="/upload/image" class="image-manager-dropzone">
|
||||
{{ csrf_field() }}
|
||||
Drag images or click here to upload
|
||||
</div>
|
||||
</div>
|
||||
<form action="/upload/image"
|
||||
class="dropzone"
|
||||
id="image-upload-dropzone">
|
||||
{!! csrf_field() !!}
|
||||
</form>
|
||||
</div>
|
||||
{{--<div class="sidebar">--}}
|
||||
|
Loading…
Reference in New Issue
Block a user