mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-08-25 11:45:58 +00:00
converted image picker to blade-based component
Also updated some other JS translations
This commit is contained in:
parent
242dc21876
commit
05316c90ba
@ -117,7 +117,7 @@ class AttachmentController extends Controller
|
||||
}
|
||||
|
||||
$attachment = $this->attachmentService->updateFile($attachment, $request->all());
|
||||
return $attachment;
|
||||
return $this->jsonSuccess($attachment, trans('entities.attachments_updated_success'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,6 +117,17 @@ abstract class Controller extends BaseController
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a json respons with a message attached as a header.
|
||||
* @param $data
|
||||
* @param string $successMessage
|
||||
* @return $this
|
||||
*/
|
||||
protected function jsonSuccess($data, $successMessage = "")
|
||||
{
|
||||
return response()->json($data)->header('message-success', $successMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send back a json error message.
|
||||
* @param string $messageText
|
||||
|
@ -6,6 +6,7 @@
|
||||
return [
|
||||
|
||||
'app-name' => 'BookStack',
|
||||
'app-logo' => '',
|
||||
'app-name-header' => true,
|
||||
'app-editor' => 'wysiwyg',
|
||||
'app-color' => '#0288D1',
|
||||
|
@ -576,7 +576,7 @@ export default function (ngApp, events) {
|
||||
* Get files for the current page from the server.
|
||||
*/
|
||||
function getFiles() {
|
||||
let url = window.baseUrl(`/attachments/get/page/${pageId}`)
|
||||
let url = window.baseUrl(`/attachments/get/page/${pageId}`);
|
||||
$http.get(url).then(resp => {
|
||||
$scope.files = resp.data;
|
||||
currentOrder = resp.data.map(file => {return file.id}).join(':');
|
||||
@ -672,7 +672,7 @@ export default function (ngApp, events) {
|
||||
$scope.editFile.link = '';
|
||||
}
|
||||
$scope.editFile = false;
|
||||
events.emit('success', 'Attachment details updated');
|
||||
events.emit('success', resp.headers('message-success'));
|
||||
}, checkError('edit'));
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,7 @@ export default function (ngApp, events) {
|
||||
});
|
||||
|
||||
/**
|
||||
* Sub form component to allow inner-form sections to act like thier own forms.
|
||||
* Sub form component to allow inner-form sections to act like their own forms.
|
||||
*/
|
||||
ngApp.directive('subForm', function() {
|
||||
return {
|
||||
@ -50,96 +50,13 @@ export default function (ngApp, events) {
|
||||
element.find('button[type="submit"]').click(submitEvent);
|
||||
|
||||
function submitEvent(e) {
|
||||
e.preventDefault()
|
||||
e.preventDefault();
|
||||
if (attrs.subForm) scope.$eval(attrs.subForm);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Image Picker
|
||||
* Is a simple front-end interface that connects to an ImageManager if present.
|
||||
*/
|
||||
ngApp.directive('imagePicker', ['$http', 'imageManagerService', function ($http, imageManagerService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: `
|
||||
<div class="image-picker">
|
||||
<div>
|
||||
<img ng-if="image && image !== 'none'" ng-src="{{image}}" ng-class="{{imageClass}}" alt="Image Preview">
|
||||
<img ng-if="image === '' && defaultImage" ng-src="{{defaultImage}}" ng-class="{{imageClass}}" alt="Image Preview">
|
||||
</div>
|
||||
<button class="button" type="button" ng-click="showImageManager()">Select Image</button>
|
||||
<br>
|
||||
|
||||
<button class="text-button" ng-click="reset()" type="button">Reset</button>
|
||||
<span ng-show="showRemove" class="sep">|</span>
|
||||
<button ng-show="showRemove" class="text-button neg" ng-click="remove()" type="button">Remove</button>
|
||||
|
||||
<input type="hidden" ng-attr-name="{{name}}" ng-attr-id="{{name}}" ng-attr-value="{{value}}">
|
||||
</div>
|
||||
`,
|
||||
scope: {
|
||||
name: '@',
|
||||
resizeHeight: '@',
|
||||
resizeWidth: '@',
|
||||
resizeCrop: '@',
|
||||
showRemove: '=',
|
||||
currentImage: '@',
|
||||
currentId: '@',
|
||||
defaultImage: '@',
|
||||
imageClass: '@'
|
||||
},
|
||||
link: function (scope, element, attrs) {
|
||||
let usingIds = typeof scope.currentId !== 'undefined' || scope.currentId === 'false';
|
||||
scope.image = scope.currentImage;
|
||||
scope.value = scope.currentImage || '';
|
||||
if (usingIds) scope.value = scope.currentId;
|
||||
|
||||
function setImage(imageModel, imageUrl) {
|
||||
scope.image = imageUrl;
|
||||
scope.value = usingIds ? imageModel.id : imageUrl;
|
||||
}
|
||||
|
||||
scope.reset = function () {
|
||||
setImage({id: 0}, scope.defaultImage);
|
||||
};
|
||||
|
||||
scope.remove = function () {
|
||||
scope.image = 'none';
|
||||
scope.value = 'none';
|
||||
};
|
||||
|
||||
scope.showImageManager = function () {
|
||||
imageManagerService.show((image) => {
|
||||
scope.updateImageFromModel(image);
|
||||
});
|
||||
};
|
||||
|
||||
scope.updateImageFromModel = function (model) {
|
||||
let isResized = scope.resizeWidth && scope.resizeHeight;
|
||||
|
||||
if (!isResized) {
|
||||
scope.$apply(() => {
|
||||
setImage(model, model.url);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let cropped = scope.resizeCrop ? 'true' : 'false';
|
||||
let requestString = '/images/thumb/' + model.id + '/' + scope.resizeWidth + '/' + scope.resizeHeight + '/' + cropped;
|
||||
requestString = window.baseUrl(requestString);
|
||||
$http.get(requestString).then((response) => {
|
||||
setImage(model, response.data.url);
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
/**
|
||||
* DropZone
|
||||
* Used for uploading images
|
||||
@ -149,16 +66,17 @@ export default function (ngApp, events) {
|
||||
restrict: 'E',
|
||||
template: `
|
||||
<div class="dropzone-container">
|
||||
<div class="dz-message">Drop files or click here to upload</div>
|
||||
<div class="dz-message">{{message}}</div>
|
||||
</div>
|
||||
`,
|
||||
scope: {
|
||||
uploadUrl: '@',
|
||||
eventSuccess: '=',
|
||||
eventError: '=',
|
||||
uploadedTo: '@'
|
||||
uploadedTo: '@',
|
||||
},
|
||||
link: function (scope, element, attrs) {
|
||||
scope.message = attrs.message;
|
||||
if (attrs.placeholder) element[0].querySelector('.dz-message').textContent = attrs.placeholder;
|
||||
let dropZone = new DropZone(element[0].querySelector('.dropzone-container'), {
|
||||
url: scope.uploadUrl,
|
||||
|
@ -161,6 +161,51 @@ $(function () {
|
||||
});
|
||||
}
|
||||
|
||||
// Image pickers
|
||||
$('.image-picker').on('click', 'button', event => {
|
||||
let button = event.target;
|
||||
let picker = $(button).closest('.image-picker')[0];
|
||||
let action = button.getAttribute('data-action');
|
||||
let resize = picker.getAttribute('data-resize-height') && picker.getAttribute('data-resize-width');
|
||||
let usingIds = picker.getAttribute('data-current-id') !== '';
|
||||
let resizeCrop = picker.getAttribute('data-resize-crop') !== '';
|
||||
let imageElem = picker.querySelector('img');
|
||||
let input = picker.querySelector('input');
|
||||
|
||||
function setImage(image) {
|
||||
|
||||
if (image === 'none') {
|
||||
imageElem.src = picker.getAttribute('data-default-image');
|
||||
imageElem.classList.add('none');
|
||||
input.value = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
imageElem.src = image.url;
|
||||
input.value = usingIds ? image.id : image.url;
|
||||
imageElem.classList.remove('none');
|
||||
}
|
||||
|
||||
if (action === 'show-image-manager') {
|
||||
window.ImageManager.showExternal((image) => {
|
||||
if (!resize) {
|
||||
setImage(image);
|
||||
return;
|
||||
}
|
||||
let requestString = '/images/thumb/' + image.id + '/' + picker.getAttribute('data-resize-width') + '/' + picker.getAttribute('data-resize-height') + '/' + (resizeCrop ? 'true' : 'false');
|
||||
$.get(window.baseUrl(requestString), resp => {
|
||||
image.url = resp.url;
|
||||
setImage(image);
|
||||
});
|
||||
});
|
||||
} else if (action === 'reset-image') {
|
||||
setImage({id: 0, url: picker.getAttribute('data-default-image')});
|
||||
} else if (action === 'remove-image') {
|
||||
setImage('none');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Detect IE for css
|
||||
if(navigator.userAgent.indexOf('MSIE')!==-1
|
||||
|| navigator.appVersion.indexOf('Trident/') > 0
|
||||
|
@ -465,4 +465,8 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
||||
border-bottom-width: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.image-picker .none {
|
||||
display: none;
|
||||
}
|
@ -31,6 +31,8 @@ return [
|
||||
'delete' => 'Delete',
|
||||
'search' => 'Search',
|
||||
'search_clear' => 'Clear Search',
|
||||
'reset' => 'Reset',
|
||||
'remove' => 'Remove',
|
||||
|
||||
|
||||
/**
|
||||
|
@ -15,5 +15,7 @@ return [
|
||||
'imagem_image_name' => 'Image Name',
|
||||
'imagem_delete_confirm' => 'This image is used in the pages below, Click delete again to confirm you want to delete this image.',
|
||||
'imagem_select_image' => 'Select Image',
|
||||
'imagem_dropzone' => 'Drop images or click here to upload',
|
||||
'images_deleted' => 'Images Deleted',
|
||||
'image_preview' => 'Image Preview',
|
||||
];
|
@ -193,6 +193,7 @@ return [
|
||||
'attachments_link' => 'Attach Link',
|
||||
'attachments_set_link' => 'Set Link',
|
||||
'attachments_delete_confirm' => 'Click delete again to confirm you want to delete this attachment.',
|
||||
'attachments_dropzone' => 'Drop files or click here to attach a file',
|
||||
'attachments_no_files' => 'No files have been uploaded',
|
||||
'attachments_explain_link' => 'You can attach a link if you\'d prefer not to upload a file. This can be a link to another page or a link to a file in the cloud.',
|
||||
'attachments_link_name' => 'Link Name',
|
||||
@ -204,6 +205,7 @@ return [
|
||||
'attachments_edit_file_name' => 'File Name',
|
||||
'attachments_edit_drop_upload' => 'Drop files or click here to upload and overwrite',
|
||||
'attachments_order_updated' => 'Attachment order updated',
|
||||
'attachments_updated_success' => 'Attachment details updated',
|
||||
'attachments_deleted' => 'Attachment deleted',
|
||||
|
||||
/**
|
||||
|
17
resources/views/components/image-picker.blade.php
Normal file
17
resources/views/components/image-picker.blade.php
Normal file
@ -0,0 +1,17 @@
|
||||
<div class="image-picker" data-default-image="{{ $defaultImage }}" data-resize-height="{{ $resizeHeight }}" data-resize-width="{{ $resizeWidth }}" data-current-id="{{ $currentId or '' }}" data-resize-crop="{{ $resizeCrop or '' }}">
|
||||
|
||||
<div>
|
||||
<img @if($currentImage && $currentImage !== 'none') src="{{$currentImage}}" @else src="{{$defaultImage}}" @endif class="{{$imageClass}} @if($currentImage=== 'none') none @endif" alt="{{ trans('components.image_preview') }}">
|
||||
</div>
|
||||
|
||||
<button class="button" type="button" data-action="show-image-manager">{{ trans('components.imagem_select_image') }}</button>
|
||||
<br>
|
||||
<button class="text-button" data-action="reset-image" type="button">{{ trans('common.reset') }}</button>
|
||||
|
||||
@if ($showRemove)
|
||||
<span class="sep">|</span>
|
||||
<button class="text-button neg" data-action="remove-image" type="button">{{ trans('common.remove') }}</button>
|
||||
@endif
|
||||
|
||||
<input type="hidden" name="{{$name}}" id="{{$name}}" value="{{$currentId or $currentImage or ''}}">
|
||||
</div>
|
@ -75,7 +75,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<div tab-content="file">
|
||||
<drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
|
||||
<drop-zone message="{{ trans('entities.attachments_dropzone') }}" upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
|
||||
</div>
|
||||
<div tab-content="link" sub-form="attachLinkSubmit(file)">
|
||||
<p class="muted small">{{ trans('entities.attachments_explain_link') }}</p>
|
||||
@ -123,8 +123,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="button" ng-click="cancelEdit()">{{ trans('entities.back') }}</button>
|
||||
<button type="submit" class="button pos">{{ trans('entities.save') }}</button>
|
||||
<button type="button" class="button" ng-click="cancelEdit()">{{ trans('common.back') }}</button>
|
||||
<button type="submit" class="button pos">{{ trans('common.save') }}</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -78,7 +78,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
<drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
|
||||
<drop-zone message="{{ trans('components.imagem_dropzone') }}" upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
<h1>{{ trans('settings.settings') }}</h1>
|
||||
|
||||
<form action="{{ baseUrl("/settings") }}" method="POST" ng-cloak>
|
||||
<form action="{{ baseUrl("/settings") }}" method="POST">
|
||||
{!! csrf_field() !!}
|
||||
|
||||
<h3>{{ trans('settings.app_settings') }}</h3>
|
||||
@ -48,7 +48,17 @@
|
||||
<div class="form-group" id="logo-control">
|
||||
<label for="setting-app-logo">{{ trans('settings.app_logo') }}</label>
|
||||
<p class="small">{!! trans('settings.app_logo_desc') !!}</p>
|
||||
<image-picker resize-height="43" show-remove="true" resize-width="200" current-image="{{ setting('app-logo', '') }}" default-image="{{ baseUrl('/logo.png') }}" name="setting-app-logo" image-class="logo-image"></image-picker>
|
||||
|
||||
@include('components.image-picker', [
|
||||
'resizeHeight' => '43',
|
||||
'resizeWidth' => '200',
|
||||
'showRemove' => true,
|
||||
'defaultImage' => baseUrl('/logo.png'),
|
||||
'currentImage' => setting('app-logo'),
|
||||
'name' => 'setting-app-logo',
|
||||
'imageClass' => 'logo-image'
|
||||
])
|
||||
|
||||
</div>
|
||||
<div class="form-group" id="color-control">
|
||||
<label for="setting-app-color">{{ trans('settings.app_primary_color') }}</label>
|
||||
|
@ -31,7 +31,18 @@
|
||||
<div class="form-group" id="logo-control">
|
||||
<label for="user-avatar">{{ trans('settings.users_avatar') }}</label>
|
||||
<p class="small">{{ trans('settings.users_avatar_desc') }}</p>
|
||||
<image-picker resize-height="512" resize-width="512" current-image="{{ $user->getAvatar(80) }}" current-id="{{ $user->image_id }}" default-image="{{ baseUrl("/user_avatar.png") }}" name="image_id" show-remove="false" image-class="['avatar' ,'large']"></image-picker>
|
||||
|
||||
@include('components.image-picker', [
|
||||
'resizeHeight' => '512',
|
||||
'resizeWidth' => '512',
|
||||
'showRemove' => false,
|
||||
'defaultImage' => baseUrl('/user_avatar.png'),
|
||||
'currentImage' => $user->getAvatar(80),
|
||||
'currentId' => $user->image_id,
|
||||
'name' => 'image_id',
|
||||
'imageClass' => 'avatar large'
|
||||
])
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user