mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Image uploads now quicker, and image sized reduced with links to originals
This commit is contained in:
parent
6c4b4e1cf9
commit
8ea75b0fdf
@ -39,27 +39,40 @@ class ImageController extends Controller
|
||||
$images = $this->image->orderBy('created_at', 'desc')
|
||||
->skip($page * $pageSize)->take($pageSize)->get();
|
||||
foreach ($images as $image) {
|
||||
$image->thumbnail = $this->getThumbnail($image, 150, 150);
|
||||
$this->loadSizes($image);
|
||||
}
|
||||
$hasMore = $this->image->orderBy('created_at', 'desc')
|
||||
->skip(($page + 1) * $pageSize)->take($pageSize)->count() > 0;
|
||||
return response()->json([
|
||||
'images' => $images,
|
||||
'images' => $images,
|
||||
'hasMore' => $hasMore
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the standard thumbnail sizes for an image.
|
||||
* @param Image $image
|
||||
*/
|
||||
private function loadSizes(Image $image)
|
||||
{
|
||||
$image->thumbnail = $this->getThumbnail($image, 150, 150);
|
||||
$image->display = $this->getThumbnail($image, 840, 0, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the thumbnail for an image.
|
||||
* @param $image
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* If $keepRatio is true only the width will be used.
|
||||
* @param $image
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param bool $keepRatio
|
||||
* @return string
|
||||
*/
|
||||
public function getThumbnail($image, $width = 220, $height = 220)
|
||||
public function getThumbnail($image, $width = 220, $height = 220, $keepRatio = false)
|
||||
{
|
||||
$explodedPath = explode('/', $image->url);
|
||||
array_splice($explodedPath, 4, 0, ['thumbs-' . $width . '-' . $height]);
|
||||
$dirPrefix = $keepRatio ? 'scaled-' : 'thumbs-';
|
||||
array_splice($explodedPath, 4, 0, [$dirPrefix . $width . '-' . $height]);
|
||||
$thumbPath = implode('/', $explodedPath);
|
||||
$thumbFilePath = public_path() . $thumbPath;
|
||||
|
||||
@ -70,7 +83,14 @@ class ImageController extends Controller
|
||||
|
||||
// Otherwise create the thumbnail
|
||||
$thumb = ImageTool::make(public_path() . $image->url);
|
||||
$thumb->fit($width, $height);
|
||||
if($keepRatio) {
|
||||
$thumb->resize($width, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
});
|
||||
} else {
|
||||
$thumb->fit($width, $height);
|
||||
}
|
||||
|
||||
// Create thumbnail folder if it does not exist
|
||||
if (!file_exists(dirname($thumbFilePath))) {
|
||||
@ -107,7 +127,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);
|
||||
$this->loadSizes($this->image);
|
||||
return response()->json($this->image);
|
||||
}
|
||||
|
||||
@ -126,6 +146,7 @@ class ImageController extends Controller
|
||||
$image = $this->image->findOrFail($imageId);
|
||||
$image->fill($request->all());
|
||||
$image->save();
|
||||
$this->loadSizes($image);
|
||||
return response()->json($this->image);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"tinymce-dist": "~4.2.1",
|
||||
"tinymce-dist": "~4.2.6",
|
||||
"bootstrap": "~3.3.5",
|
||||
"jquery-sortable": "~0.9.13",
|
||||
"material-design-iconic-font": "~2.1.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="image-manager">
|
||||
<div class="overlay" v-el="overlay" v-on="click: overlayClick" >
|
||||
<div class="overlay" v-el="overlay" v-on="click: overlayClick">
|
||||
<div class="image-manager-body">
|
||||
<div class="image-manager-content">
|
||||
<div class="image-manager-list">
|
||||
@ -32,7 +32,8 @@
|
||||
<hr class="even">
|
||||
<div v-show="dependantPages">
|
||||
<p class="text-neg text-small">
|
||||
This image is used in the pages below, Click delete again to confirm you want to delete this image.
|
||||
This image is used in the pages below, Click delete again to confirm you want to delete
|
||||
this image.
|
||||
</p>
|
||||
<ul class="text-neg">
|
||||
<li v-repeat="page: dependantPages">
|
||||
@ -46,7 +47,9 @@
|
||||
</form>
|
||||
</div>
|
||||
<div class="image-manager-bottom">
|
||||
<button class="button pos anim fadeIn" v-show="selectedImage" v-on="click:selectButtonClick"><i class="zmdi zmdi-square-right"></i>Select Image</button>
|
||||
<button class="button pos anim fadeIn" v-show="selectedImage" v-on="click:selectButtonClick"><i
|
||||
class="zmdi zmdi-square-right"></i>Select Image
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -59,7 +62,7 @@
|
||||
var Dropzone = require('dropzone');
|
||||
|
||||
module.exports = {
|
||||
data: function(){
|
||||
data: function () {
|
||||
return {
|
||||
images: [],
|
||||
hasMore: false,
|
||||
@ -68,13 +71,12 @@
|
||||
selectedImage: false,
|
||||
dependantPages: false,
|
||||
deleteForm: {},
|
||||
token: document.querySelector('meta[name=token]').getAttribute('content')
|
||||
token: document.querySelector('meta[name=token]').getAttribute('content'),
|
||||
dataLoaded: false
|
||||
}
|
||||
},
|
||||
|
||||
created: function () {
|
||||
// Get initial images
|
||||
this.fetchData(this.page);
|
||||
window.ImageManager = this;
|
||||
},
|
||||
|
||||
@ -139,6 +141,11 @@
|
||||
show: function (callback) {
|
||||
this.callback = callback;
|
||||
this.$$.overlay.style.display = 'block';
|
||||
// Get initial images if they have not yet been loaded in.
|
||||
if (!this.dataLoaded) {
|
||||
this.fetchData(this.page);
|
||||
this.dataLoaded = true;
|
||||
}
|
||||
},
|
||||
|
||||
overlayClick: function (e) {
|
||||
@ -178,9 +185,9 @@
|
||||
_this.images.splice(_this.images.indexOf(_this.selectedImage), 1);
|
||||
_this.selectedImage = false;
|
||||
$(_this.$$.imageTitle).showSuccess('Image Deleted');
|
||||
}).fail(function(jqXHR, textStatus) {
|
||||
}).fail(function (jqXHR, textStatus) {
|
||||
// Pages failure
|
||||
if(jqXHR.status === 400) {
|
||||
if (jqXHR.status === 400) {
|
||||
_this.dependantPages = jqXHR.responseJSON;
|
||||
}
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ module.exports = {
|
||||
automatic_uploads: false,
|
||||
valid_children: "-div[p|pre|h1|h2|h3|h4|h5|h6|blockquote]",
|
||||
plugins: "image table textcolor paste link imagetools fullscreen code hr",
|
||||
toolbar: "undo redo | styleselect | bold italic underline strikethrough superscript subscript | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image link hr | removeformat code fullscreen",
|
||||
toolbar: "undo redo | styleselect | bold italic underline strikethrough superscript subscript | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image-insert link hr | removeformat code fullscreen",
|
||||
content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}",
|
||||
style_formats: [
|
||||
{title: "Header 1", format: "h1"},
|
||||
@ -51,6 +51,62 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
setup: function(editor) {
|
||||
|
||||
( function() {
|
||||
var wrap;
|
||||
|
||||
function hasTextContent( node ) {
|
||||
return node && !! ( node.textContent || node.innerText );
|
||||
}
|
||||
|
||||
editor.on( 'dragstart', function() {
|
||||
var node = editor.selection.getNode();
|
||||
|
||||
if ( node.nodeName === 'IMG' ) {
|
||||
wrap = editor.dom.getParent( node, '.mceTemp' );
|
||||
|
||||
if ( ! wrap && node.parentNode.nodeName === 'A' && ! hasTextContent( node.parentNode ) ) {
|
||||
wrap = node.parentNode;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
editor.on( 'drop', function( event ) {
|
||||
var dom = editor.dom,
|
||||
rng = tinymce.dom.RangeUtils.getCaretRangeFromPoint( event.clientX, event.clientY, editor.getDoc() );
|
||||
|
||||
// Don't allow anything to be dropped in a captioned image.
|
||||
if ( dom.getParent( rng.startContainer, '.mceTemp' ) ) {
|
||||
event.preventDefault();
|
||||
} else if ( wrap ) {
|
||||
event.preventDefault();
|
||||
|
||||
editor.undoManager.transact( function() {
|
||||
editor.selection.setRng( rng );
|
||||
editor.selection.setNode( wrap );
|
||||
dom.remove( wrap );
|
||||
} );
|
||||
}
|
||||
|
||||
wrap = null;
|
||||
} );
|
||||
} )();
|
||||
|
||||
// Image picker button
|
||||
editor.addButton('image-insert', {
|
||||
title: 'My title',
|
||||
icon: 'image',
|
||||
tooltip: 'Insert an image',
|
||||
onclick: function() {
|
||||
ImageManager.show(function(image) {
|
||||
var html = '<p><a href="'+image.url+'" target="_blank">';
|
||||
html += '<img src="'+image.display+'" alt="'+image.name+'">';
|
||||
html += '</a></p>';
|
||||
console.log(image);
|
||||
editor.execCommand('mceInsertContent', false, html);
|
||||
});
|
||||
}
|
||||
});
|
||||
// Paste image-uploads
|
||||
editor.on('paste', function(e) {
|
||||
if(e.clipboardData) {
|
||||
|
Loading…
Reference in New Issue
Block a user