}
$attachment = $this->attachmentService->updateFile($attachment, $request->all());
- return $attachment;
+ return $this->jsonSuccess($attachment, trans('entities.attachments_updated_success'));
}
/**
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
return [
'app-name' => 'BookStack',
+ 'app-logo' => '',
'app-name-header' => true,
'app-editor' => 'wysiwyg',
'app-color' => '#0288D1',
* 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(':');
$scope.editFile.link = '';
}
$scope.editFile = false;
- events.emit('success', 'Attachment details updated');
+ events.emit('success', resp.headers('message-success'));
}, checkError('edit'));
};
});
/**
- * 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 {
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
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,
});
}
+ // 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
border-bottom-width: 3px;
}
}
+}
+
+.image-picker .none {
+ display: none;
}
\ No newline at end of file
'delete' => 'Delete',
'search' => 'Search',
'search_clear' => 'Clear Search',
+ 'reset' => 'Reset',
+ 'remove' => 'Remove',
/**
'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',
];
\ No newline at end of file
'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',
'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',
/**
--- /dev/null
+<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>
\ No newline at end of file
</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>
</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>
</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>
<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>
<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>
<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>