Created solution for JS translations
Also tidied up existing components and JS
This commit is contained in:
parent
05316c90ba
commit
c9700e38e2
26 changed files with 371 additions and 267 deletions
|
@ -117,7 +117,7 @@ class AttachmentController extends Controller
|
|||
}
|
||||
|
||||
$attachment = $this->attachmentService->updateFile($attachment, $request->all());
|
||||
return $this->jsonSuccess($attachment, trans('entities.attachments_updated_success'));
|
||||
return response()->json($attachment);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -117,17 +117,6 @@ 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
|
||||
|
|
|
@ -43,4 +43,39 @@ class HomeController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a js representation of the current translations
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function getTranslations() {
|
||||
$locale = trans()->getLocale();
|
||||
$cacheKey = 'GLOBAL_TRANSLATIONS_' . $locale;
|
||||
if (cache()->has($cacheKey) && config('app.env') !== 'development') {
|
||||
$resp = cache($cacheKey);
|
||||
} else {
|
||||
$translations = [
|
||||
// Get only translations which might be used in JS
|
||||
'common' => trans('common'),
|
||||
'components' => trans('components'),
|
||||
'entities' => trans('entities'),
|
||||
'errors' => trans('errors')
|
||||
];
|
||||
if ($locale !== 'en') {
|
||||
$enTrans = [
|
||||
'common' => trans('common', [], null, 'en'),
|
||||
'components' => trans('components', [], null, 'en'),
|
||||
'entities' => trans('entities', [], null, 'en'),
|
||||
'errors' => trans('errors', [], null, 'en')
|
||||
];
|
||||
$translations = array_replace_recursive($enTrans, $translations);
|
||||
}
|
||||
$resp = 'window.translations = ' . json_encode($translations);
|
||||
cache()->put($cacheKey, $resp, 120);
|
||||
}
|
||||
|
||||
return response($resp, 200, [
|
||||
'Content-Type' => 'application/javascript'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ export default function (ngApp, events) {
|
|||
$scope.$apply(() => {
|
||||
$scope.images.unshift(data);
|
||||
});
|
||||
events.emit('success', 'Image uploaded');
|
||||
events.emit('success', trans('components.image_upload_success'));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -151,10 +151,9 @@ export default function (ngApp, events) {
|
|||
if ($scope.searching) components['term'] = $scope.searchTerm;
|
||||
|
||||
|
||||
let urlQueryString = Object.keys(components).map((key) => {
|
||||
url += Object.keys(components).map((key) => {
|
||||
return key + '=' + encodeURIComponent(components[key]);
|
||||
}).join('&');
|
||||
url += urlQueryString;
|
||||
|
||||
$http.get(url).then((response) => {
|
||||
$scope.images = $scope.images.concat(response.data.images);
|
||||
|
@ -209,7 +208,7 @@ export default function (ngApp, events) {
|
|||
event.preventDefault();
|
||||
let url = window.baseUrl('/images/update/' + $scope.selectedImage.id);
|
||||
$http.put(url, this.selectedImage).then(response => {
|
||||
events.emit('success', 'Image details updated');
|
||||
events.emit('success', trans('components.image_update_success'));
|
||||
}, (response) => {
|
||||
if (response.status === 422) {
|
||||
let errors = response.data;
|
||||
|
@ -238,7 +237,7 @@ export default function (ngApp, events) {
|
|||
$http.delete(url).then((response) => {
|
||||
$scope.images.splice($scope.images.indexOf($scope.selectedImage), 1);
|
||||
$scope.selectedImage = false;
|
||||
events.emit('success', 'Image successfully deleted');
|
||||
events.emit('success', trans('components.image_delete_success'));
|
||||
}, (response) => {
|
||||
// Pages failure
|
||||
if (response.status === 400) {
|
||||
|
@ -309,9 +308,9 @@ export default function (ngApp, events) {
|
|||
|
||||
// Set initial header draft text
|
||||
if ($scope.isUpdateDraft || $scope.isNewPageDraft) {
|
||||
$scope.draftText = 'Editing Draft'
|
||||
$scope.draftText = trans('entities.pages_editing_draft');
|
||||
} else {
|
||||
$scope.draftText = 'Editing Page'
|
||||
$scope.draftText = trans('entities.pages_editing_page');
|
||||
}
|
||||
|
||||
let autoSave = false;
|
||||
|
@ -388,7 +387,7 @@ export default function (ngApp, events) {
|
|||
lastSave = Date.now();
|
||||
}, errorRes => {
|
||||
if (draftErroring) return;
|
||||
events.emit('error', 'Failed to save draft. Ensure you have internet connection before saving this page.')
|
||||
events.emit('error', trans('errors.page_draft_autosave_fail'));
|
||||
draftErroring = true;
|
||||
});
|
||||
}
|
||||
|
@ -421,7 +420,7 @@ export default function (ngApp, events) {
|
|||
let url = window.baseUrl('/ajax/page/' + pageId);
|
||||
$http.get(url).then((responseData) => {
|
||||
if (autoSave) $interval.cancel(autoSave);
|
||||
$scope.draftText = 'Editing Page';
|
||||
$scope.draftText = trans('entities.pages_editing_page');
|
||||
$scope.isUpdateDraft = false;
|
||||
$scope.$broadcast('html-update', responseData.data.html);
|
||||
$scope.$broadcast('markdown-update', responseData.data.markdown || responseData.data.html);
|
||||
|
@ -429,7 +428,7 @@ export default function (ngApp, events) {
|
|||
$timeout(() => {
|
||||
startAutoSave();
|
||||
}, 1000);
|
||||
events.emit('success', 'Draft discarded, The editor has been updated with the current page content');
|
||||
events.emit('success', trans('entities.pages_draft_discarded'));
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -594,7 +593,7 @@ export default function (ngApp, events) {
|
|||
$scope.$apply(() => {
|
||||
$scope.files.push(data);
|
||||
});
|
||||
events.emit('success', 'File uploaded');
|
||||
events.emit('success', trans('entities.attachments_file_uploaded'));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -612,7 +611,7 @@ export default function (ngApp, events) {
|
|||
data.link = '';
|
||||
}
|
||||
});
|
||||
events.emit('success', 'File updated');
|
||||
events.emit('success', trans('entities.attachments_file_updated'));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -638,7 +637,7 @@ export default function (ngApp, events) {
|
|||
file.uploaded_to = pageId;
|
||||
$http.post(window.baseUrl('/attachments/link'), file).then(resp => {
|
||||
$scope.files.push(resp.data);
|
||||
events.emit('success', 'Link attached');
|
||||
events.emit('success', trans('entities.attachments_link_attached'));
|
||||
$scope.file = getCleanFile();
|
||||
}, checkError('link'));
|
||||
};
|
||||
|
@ -672,7 +671,7 @@ export default function (ngApp, events) {
|
|||
$scope.editFile.link = '';
|
||||
}
|
||||
$scope.editFile = false;
|
||||
events.emit('success', resp.headers('message-success'));
|
||||
events.emit('success', trans('entities.attachments_updated_success'));
|
||||
}, checkError('edit'));
|
||||
};
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ export default function (ngApp, events) {
|
|||
$(file.previewElement).find('[data-dz-errormessage]').text(message);
|
||||
}
|
||||
|
||||
if (xhr.status === 413) setMessage('The server does not allow uploads of this size. Please try a smaller file.');
|
||||
if (xhr.status === 413) setMessage(trans('errors.server_upload_limit'));
|
||||
if (errorMessage.file) setMessage(errorMessage.file[0]);
|
||||
|
||||
});
|
||||
|
@ -261,15 +261,21 @@ export default function (ngApp, events) {
|
|||
link: function (scope, element, attrs) {
|
||||
|
||||
// Elements
|
||||
const input = element.find('[markdown-input] textarea').first();
|
||||
const display = element.find('.markdown-display').first();
|
||||
const insertImage = element.find('button[data-action="insertImage"]');
|
||||
const insertEntityLink = element.find('button[data-action="insertEntityLink"]')
|
||||
const $input = element.find('[markdown-input] textarea').first();
|
||||
const $display = element.find('.markdown-display').first();
|
||||
const $insertImage = element.find('button[data-action="insertImage"]');
|
||||
const $insertEntityLink = element.find('button[data-action="insertEntityLink"]');
|
||||
|
||||
// Prevent markdown display link click redirect
|
||||
$display.on('click', 'a', function(event) {
|
||||
event.preventDefault();
|
||||
window.open(this.getAttribute('href'));
|
||||
});
|
||||
|
||||
let currentCaretPos = 0;
|
||||
|
||||
input.blur(event => {
|
||||
currentCaretPos = input[0].selectionStart;
|
||||
$input.blur(event => {
|
||||
currentCaretPos = $input[0].selectionStart;
|
||||
});
|
||||
|
||||
// Scroll sync
|
||||
|
@ -279,10 +285,10 @@ export default function (ngApp, events) {
|
|||
displayHeight;
|
||||
|
||||
function setScrollHeights() {
|
||||
inputScrollHeight = input[0].scrollHeight;
|
||||
inputHeight = input.height();
|
||||
displayScrollHeight = display[0].scrollHeight;
|
||||
displayHeight = display.height();
|
||||
inputScrollHeight = $input[0].scrollHeight;
|
||||
inputHeight = $input.height();
|
||||
displayScrollHeight = $display[0].scrollHeight;
|
||||
displayHeight = $display.height();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
|
@ -291,29 +297,29 @@ export default function (ngApp, events) {
|
|||
window.addEventListener('resize', setScrollHeights);
|
||||
let scrollDebounceTime = 800;
|
||||
let lastScroll = 0;
|
||||
input.on('scroll', event => {
|
||||
$input.on('scroll', event => {
|
||||
let now = Date.now();
|
||||
if (now - lastScroll > scrollDebounceTime) {
|
||||
setScrollHeights()
|
||||
}
|
||||
let scrollPercent = (input.scrollTop() / (inputScrollHeight - inputHeight));
|
||||
let scrollPercent = ($input.scrollTop() / (inputScrollHeight - inputHeight));
|
||||
let displayScrollY = (displayScrollHeight - displayHeight) * scrollPercent;
|
||||
display.scrollTop(displayScrollY);
|
||||
$display.scrollTop(displayScrollY);
|
||||
lastScroll = now;
|
||||
});
|
||||
|
||||
// Editor key-presses
|
||||
input.keydown(event => {
|
||||
$input.keydown(event => {
|
||||
// Insert image shortcut
|
||||
if (event.which === 73 && event.ctrlKey && event.shiftKey) {
|
||||
event.preventDefault();
|
||||
let caretPos = input[0].selectionStart;
|
||||
let currentContent = input.val();
|
||||
let caretPos = $input[0].selectionStart;
|
||||
let currentContent = $input.val();
|
||||
const mdImageText = "![](http://)";
|
||||
input.val(currentContent.substring(0, caretPos) + mdImageText + currentContent.substring(caretPos));
|
||||
input.focus();
|
||||
input[0].selectionStart = caretPos + ("![](".length);
|
||||
input[0].selectionEnd = caretPos + ('![](http://'.length);
|
||||
$input.val(currentContent.substring(0, caretPos) + mdImageText + currentContent.substring(caretPos));
|
||||
$input.focus();
|
||||
$input[0].selectionStart = caretPos + ("![](".length);
|
||||
$input[0].selectionEnd = caretPos + ('![](http://'.length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -328,35 +334,35 @@ export default function (ngApp, events) {
|
|||
});
|
||||
|
||||
// Insert image from image manager
|
||||
insertImage.click(event => {
|
||||
$insertImage.click(event => {
|
||||
window.ImageManager.showExternal(image => {
|
||||
let caretPos = currentCaretPos;
|
||||
let currentContent = input.val();
|
||||
let currentContent = $input.val();
|
||||
let mdImageText = "![" + image.name + "](" + image.thumbs.display + ")";
|
||||
input.val(currentContent.substring(0, caretPos) + mdImageText + currentContent.substring(caretPos));
|
||||
input.change();
|
||||
$input.val(currentContent.substring(0, caretPos) + mdImageText + currentContent.substring(caretPos));
|
||||
$input.change();
|
||||
});
|
||||
});
|
||||
|
||||
function showLinkSelector() {
|
||||
window.showEntityLinkSelector((entity) => {
|
||||
let selectionStart = currentCaretPos;
|
||||
let selectionEnd = input[0].selectionEnd;
|
||||
let selectionEnd = $input[0].selectionEnd;
|
||||
let textSelected = (selectionEnd !== selectionStart);
|
||||
let currentContent = input.val();
|
||||
let currentContent = $input.val();
|
||||
|
||||
if (textSelected) {
|
||||
let selectedText = currentContent.substring(selectionStart, selectionEnd);
|
||||
let linkText = `[${selectedText}](${entity.link})`;
|
||||
input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionEnd));
|
||||
$input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionEnd));
|
||||
} else {
|
||||
let linkText = ` [${entity.name}](${entity.link}) `;
|
||||
input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionStart))
|
||||
$input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionStart))
|
||||
}
|
||||
input.change();
|
||||
$input.change();
|
||||
});
|
||||
}
|
||||
insertEntityLink.click(showLinkSelector);
|
||||
$insertEntityLink.click(showLinkSelector);
|
||||
|
||||
// Upload and insert image on paste
|
||||
function editorPaste(e) {
|
||||
|
@ -369,7 +375,7 @@ export default function (ngApp, events) {
|
|||
}
|
||||
}
|
||||
|
||||
input.on('paste', editorPaste);
|
||||
$input.on('paste', editorPaste);
|
||||
|
||||
// Handle image drop, Uploads images to BookStack.
|
||||
function handleImageDrop(event) {
|
||||
|
@ -381,7 +387,7 @@ export default function (ngApp, events) {
|
|||
}
|
||||
}
|
||||
|
||||
input.on('drop', handleImageDrop);
|
||||
$input.on('drop', handleImageDrop);
|
||||
|
||||
// Handle image upload and add image into markdown content
|
||||
function uploadImage(file) {
|
||||
|
@ -399,17 +405,17 @@ export default function (ngApp, events) {
|
|||
|
||||
// Insert image into markdown
|
||||
let id = "image-" + Math.random().toString(16).slice(2);
|
||||
let selectStart = input[0].selectionStart;
|
||||
let selectEnd = input[0].selectionEnd;
|
||||
let content = input[0].value;
|
||||
let selectStart = $input[0].selectionStart;
|
||||
let selectEnd = $input[0].selectionEnd;
|
||||
let content = $input[0].value;
|
||||
let selectText = content.substring(selectStart, selectEnd);
|
||||
let placeholderImage = window.baseUrl(`/loading.gif#upload${id}`);
|
||||
let innerContent = ((selectEnd > selectStart) ? `![${selectText}]` : '![]') + `(${placeholderImage})`;
|
||||
input[0].value = content.substring(0, selectStart) + innerContent + content.substring(selectEnd);
|
||||
$input[0].value = content.substring(0, selectStart) + innerContent + content.substring(selectEnd);
|
||||
|
||||
input.focus();
|
||||
input[0].selectionStart = selectStart;
|
||||
input[0].selectionEnd = selectStart;
|
||||
$input.focus();
|
||||
$input[0].selectionStart = selectStart;
|
||||
$input[0].selectionEnd = selectStart;
|
||||
|
||||
let remoteFilename = "image-" + Date.now() + "." + ext;
|
||||
formData.append('file', file, remoteFilename);
|
||||
|
@ -417,20 +423,20 @@ export default function (ngApp, events) {
|
|||
|
||||
xhr.open('POST', window.baseUrl('/images/gallery/upload'));
|
||||
xhr.onload = function () {
|
||||
let selectStart = input[0].selectionStart;
|
||||
let selectStart = $input[0].selectionStart;
|
||||
if (xhr.status === 200 || xhr.status === 201) {
|
||||
let result = JSON.parse(xhr.responseText);
|
||||
input[0].value = input[0].value.replace(placeholderImage, result.thumbs.display);
|
||||
input.change();
|
||||
$input[0].value = $input[0].value.replace(placeholderImage, result.thumbs.display);
|
||||
$input.change();
|
||||
} else {
|
||||
console.log('An error occurred uploading the image');
|
||||
console.log(trans('errors.image_upload_error'));
|
||||
console.log(xhr.responseText);
|
||||
input[0].value = input[0].value.replace(innerContent, '');
|
||||
input.change();
|
||||
$input[0].value = $input[0].value.replace(innerContent, '');
|
||||
$input.change();
|
||||
}
|
||||
input.focus();
|
||||
input[0].selectionStart = selectStart;
|
||||
input[0].selectionEnd = selectStart;
|
||||
$input.focus();
|
||||
$input[0].selectionStart = selectStart;
|
||||
$input[0].selectionEnd = selectStart;
|
||||
};
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
@ -568,8 +574,7 @@ export default function (ngApp, events) {
|
|||
}
|
||||
// Enter or tab key
|
||||
else if ((event.keyCode === 13 || event.keyCode === 9) && !event.shiftKey) {
|
||||
let text = suggestionElems[active].textContent;
|
||||
currentInput[0].value = text;
|
||||
currentInput[0].value = suggestionElems[active].textContent;
|
||||
currentInput.focus();
|
||||
$suggestionBox.hide();
|
||||
isShowing = false;
|
||||
|
@ -665,7 +670,7 @@ export default function (ngApp, events) {
|
|||
|
||||
ngApp.directive('entityLinkSelector', [function($http) {
|
||||
return {
|
||||
restict: 'A',
|
||||
restrict: 'A',
|
||||
link: function(scope, element, attrs) {
|
||||
|
||||
const selectButton = element.find('.entity-link-selector-confirm');
|
||||
|
|
|
@ -17,6 +17,12 @@ window.baseUrl = function(path) {
|
|||
|
||||
let ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']);
|
||||
|
||||
// Translation setup
|
||||
// Creates a global function with name 'trans' to be used in the same way as Laravel's translation system
|
||||
import Translations from "./translations"
|
||||
let translator = new Translations(window.translations);
|
||||
window.trans = translator.get.bind(translator);
|
||||
|
||||
// Global Event System
|
||||
class EventManager {
|
||||
constructor() {
|
||||
|
@ -70,150 +76,83 @@ jQuery.expr[":"].contains = $.expr.createPseudo(function (arg) {
|
|||
});
|
||||
|
||||
// Global jQuery Elements
|
||||
$(function () {
|
||||
|
||||
let notifications = $('.notification');
|
||||
let successNotification = notifications.filter('.pos');
|
||||
let errorNotification = notifications.filter('.neg');
|
||||
let warningNotification = notifications.filter('.warning');
|
||||
// Notification Events
|
||||
window.Events.listen('success', function (text) {
|
||||
successNotification.hide();
|
||||
successNotification.find('span').text(text);
|
||||
setTimeout(() => {
|
||||
successNotification.show();
|
||||
}, 1);
|
||||
});
|
||||
window.Events.listen('warning', function (text) {
|
||||
warningNotification.find('span').text(text);
|
||||
warningNotification.show();
|
||||
});
|
||||
window.Events.listen('error', function (text) {
|
||||
errorNotification.find('span').text(text);
|
||||
errorNotification.show();
|
||||
});
|
||||
|
||||
// Notification hiding
|
||||
notifications.click(function () {
|
||||
$(this).fadeOut(100);
|
||||
});
|
||||
|
||||
// Chapter page list toggles
|
||||
$('.chapter-toggle').click(function (e) {
|
||||
e.preventDefault();
|
||||
$(this).toggleClass('open');
|
||||
$(this).closest('.chapter').find('.inset-list').slideToggle(180);
|
||||
});
|
||||
|
||||
// Back to top button
|
||||
$('#back-to-top').click(function() {
|
||||
$('#header').smoothScrollTo();
|
||||
});
|
||||
let scrollTopShowing = false;
|
||||
let scrollTop = document.getElementById('back-to-top');
|
||||
let scrollTopBreakpoint = 1200;
|
||||
window.addEventListener('scroll', function() {
|
||||
let scrollTopPos = document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||
if (!scrollTopShowing && scrollTopPos > scrollTopBreakpoint) {
|
||||
scrollTop.style.display = 'block';
|
||||
scrollTopShowing = true;
|
||||
setTimeout(() => {
|
||||
scrollTop.style.opacity = 0.4;
|
||||
}, 1);
|
||||
} else if (scrollTopShowing && scrollTopPos < scrollTopBreakpoint) {
|
||||
scrollTop.style.opacity = 0;
|
||||
scrollTopShowing = false;
|
||||
setTimeout(() => {
|
||||
scrollTop.style.display = 'none';
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
|
||||
// Common jQuery actions
|
||||
$('[data-action="expand-entity-list-details"]').click(function() {
|
||||
$('.entity-list.compact').find('p').not('.empty-text').slideToggle(240);
|
||||
});
|
||||
|
||||
// Popup close
|
||||
$('.popup-close').click(function() {
|
||||
$(this).closest('.overlay').fadeOut(240);
|
||||
});
|
||||
$('.overlay').click(function(event) {
|
||||
if (!$(event.target).hasClass('overlay')) return;
|
||||
$(this).fadeOut(240);
|
||||
});
|
||||
|
||||
// Prevent markdown display link click redirect
|
||||
$('.markdown-display').on('click', 'a', function(event) {
|
||||
event.preventDefault();
|
||||
window.open($(this).attr('href'));
|
||||
});
|
||||
|
||||
// Toggle Switches
|
||||
let $switches = $('[toggle-switch]');
|
||||
if ($switches.length > 0) {
|
||||
$switches.click(event => {
|
||||
let $switch = $(event.target);
|
||||
let input = $switch.find('input').first()[0];
|
||||
let checked = input.value !== 'true';
|
||||
input.value = checked ? 'true' : 'false';
|
||||
$switch.toggleClass('active', checked);
|
||||
});
|
||||
}
|
||||
|
||||
// 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
|
||||
|| navigator.userAgent.indexOf('Safari') !== -1){
|
||||
$('body').addClass('flexbox-support');
|
||||
}
|
||||
|
||||
let notifications = $('.notification');
|
||||
let successNotification = notifications.filter('.pos');
|
||||
let errorNotification = notifications.filter('.neg');
|
||||
let warningNotification = notifications.filter('.warning');
|
||||
// Notification Events
|
||||
window.Events.listen('success', function (text) {
|
||||
successNotification.hide();
|
||||
successNotification.find('span').text(text);
|
||||
setTimeout(() => {
|
||||
successNotification.show();
|
||||
}, 1);
|
||||
});
|
||||
window.Events.listen('warning', function (text) {
|
||||
warningNotification.find('span').text(text);
|
||||
warningNotification.show();
|
||||
});
|
||||
window.Events.listen('error', function (text) {
|
||||
errorNotification.find('span').text(text);
|
||||
errorNotification.show();
|
||||
});
|
||||
|
||||
// Notification hiding
|
||||
notifications.click(function () {
|
||||
$(this).fadeOut(100);
|
||||
});
|
||||
|
||||
// Chapter page list toggles
|
||||
$('.chapter-toggle').click(function (e) {
|
||||
e.preventDefault();
|
||||
$(this).toggleClass('open');
|
||||
$(this).closest('.chapter').find('.inset-list').slideToggle(180);
|
||||
});
|
||||
|
||||
// Back to top button
|
||||
$('#back-to-top').click(function() {
|
||||
$('#header').smoothScrollTo();
|
||||
});
|
||||
let scrollTopShowing = false;
|
||||
let scrollTop = document.getElementById('back-to-top');
|
||||
let scrollTopBreakpoint = 1200;
|
||||
window.addEventListener('scroll', function() {
|
||||
let scrollTopPos = document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||
if (!scrollTopShowing && scrollTopPos > scrollTopBreakpoint) {
|
||||
scrollTop.style.display = 'block';
|
||||
scrollTopShowing = true;
|
||||
setTimeout(() => {
|
||||
scrollTop.style.opacity = 0.4;
|
||||
}, 1);
|
||||
} else if (scrollTopShowing && scrollTopPos < scrollTopBreakpoint) {
|
||||
scrollTop.style.opacity = 0;
|
||||
scrollTopShowing = false;
|
||||
setTimeout(() => {
|
||||
scrollTop.style.display = 'none';
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
|
||||
// Common jQuery actions
|
||||
$('[data-action="expand-entity-list-details"]').click(function() {
|
||||
$('.entity-list.compact').find('p').not('.empty-text').slideToggle(240);
|
||||
});
|
||||
|
||||
// Popup close
|
||||
$('.popup-close').click(function() {
|
||||
$(this).closest('.overlay').fadeOut(240);
|
||||
});
|
||||
$('.overlay').click(function(event) {
|
||||
if (!$(event.target).hasClass('overlay')) return;
|
||||
$(this).fadeOut(240);
|
||||
});
|
||||
|
||||
// Detect IE for css
|
||||
if(navigator.userAgent.indexOf('MSIE')!==-1
|
||||
|| navigator.appVersion.indexOf('Trident/') > 0
|
||||
|| navigator.userAgent.indexOf('Safari') !== -1){
|
||||
$('body').addClass('flexbox-support');
|
||||
}
|
||||
|
||||
// Page specific items
|
||||
import "./pages/page-show";
|
||||
|
|
47
resources/assets/js/translations.js
Normal file
47
resources/assets/js/translations.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Translation Manager
|
||||
* Handles the JavaScript side of translating strings
|
||||
* in a way which fits with Laravel.
|
||||
*/
|
||||
class Translator {
|
||||
|
||||
/**
|
||||
* Create an instance, Passing in the required translations
|
||||
* @param translations
|
||||
*/
|
||||
constructor(translations) {
|
||||
this.store = translations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a translation, Same format as laravel's 'trans' helper
|
||||
* @param key
|
||||
* @param replacements
|
||||
* @returns {*}
|
||||
*/
|
||||
get(key, replacements) {
|
||||
let splitKey = key.split('.');
|
||||
let value = splitKey.reduce((a, b) => {
|
||||
return a != undefined ? a[b] : a;
|
||||
}, this.store);
|
||||
|
||||
if (value === undefined) {
|
||||
console.log(`Translation with key "${key}" does not exist`);
|
||||
value = key;
|
||||
}
|
||||
|
||||
if (replacements === undefined) return value;
|
||||
|
||||
let replaceMatches = value.match(/:([\S]+)/g);
|
||||
if (replaceMatches === null) return value;
|
||||
replaceMatches.forEach(match => {
|
||||
let key = match.substring(1);
|
||||
if (typeof replacements[key] === 'undefined') return;
|
||||
value = value.replace(match, replacements[key]);
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Translator
|
|
@ -35,6 +35,12 @@ table.table {
|
|||
tr:hover {
|
||||
background-color: #EEE;
|
||||
}
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
table.no-style {
|
||||
|
|
|
@ -16,7 +16,7 @@ return [
|
|||
'app_name_desc' => 'Dieser Name wird im Header und E-Mails angezeigt.',
|
||||
'app_name_header' => 'Anwendungsname im Header anzeigen?',
|
||||
'app_public_viewing' => 'Öffentliche Ansicht erlauben?',
|
||||
'app_secure_images' => 'Erh&oml;hte Sicherheit für Bilduploads aktivieren?',
|
||||
'app_secure_images' => 'Erhöhte Sicherheit für Bilduploads aktivieren?',
|
||||
'app_secure_images_desc' => 'Aus Leistungsgründen sind alle Bilder öffentlich sichtbar. Diese Option fügt zufällige, schwer zu eratene, Zeichenketten vor die Bild-URLs hinzu. Stellen sie sicher, dass Verzeichnindexes deaktiviert sind, um einen einfachen Zugrif zu verhindern.',
|
||||
'app_editor' => 'Seiteneditor',
|
||||
'app_editor_desc' => 'Wählen sie den Editor aus, der von allen Benutzern genutzt werden soll, um Seiten zu editieren.',
|
||||
|
|
|
@ -4,18 +4,21 @@ return [
|
|||
/**
|
||||
* Image Manager
|
||||
*/
|
||||
'imagem_select' => 'Image Select',
|
||||
'imagem_all' => 'All',
|
||||
'imagem_all_title' => 'View all images',
|
||||
'imagem_book_title' => 'View images uploaded to this book',
|
||||
'imagem_page_title' => 'View images uploaded to this page',
|
||||
'imagem_search_hint' => 'Search by image name',
|
||||
'imagem_uploaded' => 'Uploaded :uploadedDate',
|
||||
'imagem_load_more' => 'Load More',
|
||||
'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',
|
||||
'image_select' => 'Image Select',
|
||||
'image_all' => 'All',
|
||||
'image_all_title' => 'View all images',
|
||||
'image_book_title' => 'View images uploaded to this book',
|
||||
'image_page_title' => 'View images uploaded to this page',
|
||||
'image_search_hint' => 'Search by image name',
|
||||
'image_uploaded' => 'Uploaded :uploadedDate',
|
||||
'image_load_more' => 'Load More',
|
||||
'image_image_name' => 'Image Name',
|
||||
'image_delete_confirm' => 'This image is used in the pages below, Click delete again to confirm you want to delete this image.',
|
||||
'image_select_image' => 'Select Image',
|
||||
'image_dropzone' => 'Drop images or click here to upload',
|
||||
'images_deleted' => 'Images Deleted',
|
||||
'image_preview' => 'Image Preview',
|
||||
'image_upload_success' => 'Image uploaded successfully',
|
||||
'image_update_success' => 'Image details successfully updated',
|
||||
'image_delete_success' => 'Image successfully deleted'
|
||||
];
|
|
@ -129,6 +129,8 @@ return [
|
|||
'pages_edit_toggle_header' => 'Toggle header',
|
||||
'pages_edit_save_draft' => 'Save Draft',
|
||||
'pages_edit_draft' => 'Edit Page Draft',
|
||||
'pages_editing_draft' => 'Editing Draft',
|
||||
'pages_editing_page' => 'Editing Page',
|
||||
'pages_edit_draft_save_at' => 'Draft saved at ',
|
||||
'pages_edit_delete_draft' => 'Delete Draft',
|
||||
'pages_edit_discard_draft' => 'Discard Draft',
|
||||
|
@ -175,6 +177,7 @@ return [
|
|||
'time_b' => 'in the last :minCount minutes',
|
||||
'message' => ':start :time. Take care not to overwrite each other\'s updates!',
|
||||
],
|
||||
'pages_draft_discarded' => 'Draft discarded, The editor has been updated with the current page content',
|
||||
|
||||
/**
|
||||
* Editor sidebar
|
||||
|
@ -207,6 +210,9 @@ return [
|
|||
'attachments_order_updated' => 'Attachment order updated',
|
||||
'attachments_updated_success' => 'Attachment details updated',
|
||||
'attachments_deleted' => 'Attachment deleted',
|
||||
'attachments_file_uploaded' => 'File successfully uploaded',
|
||||
'attachments_file_updated' => 'File successfully updated',
|
||||
'attachments_link_attached' => 'Link successfully attached to page',
|
||||
|
||||
/**
|
||||
* Profile View
|
||||
|
|
|
@ -33,10 +33,15 @@ return [
|
|||
'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.',
|
||||
'cannot_get_image_from_url' => 'Cannot get image from :url',
|
||||
'cannot_create_thumbs' => 'The server cannot create thumbnails. Please check you have the GD PHP extension installed.',
|
||||
'server_upload_limit' => 'The server does not allow uploads of this size. Please try a smaller file size.',
|
||||
'image_upload_error' => 'An error occurred uploading the image',
|
||||
|
||||
// Attachments
|
||||
'attachment_page_mismatch' => 'Page mismatch during attachment update',
|
||||
|
||||
// Pages
|
||||
'page_draft_autosave_fail' => 'Failed to save draft. Ensure you have internet connection before saving this page',
|
||||
|
||||
// Entities
|
||||
'entity_not_found' => 'Entity not found',
|
||||
'book_not_found' => 'Book not found',
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<!-- Scripts -->
|
||||
<script src="{{ baseUrl('/libs/jquery/jquery.min.js?version=2.1.4') }}"></script>
|
||||
<script src="{{ baseUrl('/libs/jquery/jquery-ui.min.js?version=1.11.4') }}"></script>
|
||||
<script src="{{ baseUrl('/translations.js') }}"></script>
|
||||
|
||||
@yield('head')
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
{!! csrf_field() !!}
|
||||
<input type="hidden" name="_method" value="PUT">
|
||||
|
||||
@include('partials/entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book'])
|
||||
@include('components.entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book'])
|
||||
|
||||
<a href="{{ $chapter->getUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
|
||||
<button type="submit" class="button pos">{{ trans('entities.chapters_move') }}</button>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="popup-title">{{ trans('entities.entity_select') }}</div>
|
||||
<button type="button" class="corner-button neg button popup-close">x</button>
|
||||
</div>
|
||||
@include('partials/entity-selector', ['name' => 'entity-selector'])
|
||||
@include('components.entity-selector', ['name' => 'entity-selector'])
|
||||
<div class="popup-footer">
|
||||
<button type="button" disabled="true" class="button entity-link-selector-confirm pos corner-button">{{ trans('common.select') }}</button>
|
||||
</div>
|
|
@ -2,7 +2,7 @@
|
|||
<div entity-selector class="entity-selector {{$selectorSize or ''}}" entity-types="{{ $entityTypes or 'book,chapter,page' }}">
|
||||
<input type="hidden" entity-selector-input name="{{$name}}" value="">
|
||||
<input type="text" placeholder="{{ trans('common.search') }}" ng-model="search" ng-model-options="{debounce: 200}" ng-change="searchEntities()">
|
||||
<div class="text-center loading" ng-show="loading">@include('partials/loading-icon')</div>
|
||||
<div class="text-center loading" ng-show="loading">@include('partials.loading-icon')</div>
|
||||
<div ng-show="!loading" ng-bind-html="entityResults"></div>
|
||||
</div>
|
||||
</div>
|
|
@ -3,7 +3,7 @@
|
|||
<div class="popup-body" ng-click="$event.stopPropagation()">
|
||||
|
||||
<div class="popup-header primary-background">
|
||||
<div class="popup-title">{{ trans('components.imagem_select') }}</div>
|
||||
<div class="popup-title">{{ trans('components.image_select') }}</div>
|
||||
<button class="popup-close neg corner-button button">x</button>
|
||||
</div>
|
||||
|
||||
|
@ -12,14 +12,14 @@
|
|||
<div class="image-manager-content">
|
||||
<div ng-if="imageType === 'gallery'" class="container">
|
||||
<div class="image-manager-header row faded-small nav-tabs">
|
||||
<div class="col-xs-4 tab-item" title="{{ trans('components.imagem_all_title') }}" ng-class="{selected: (view=='all')}" ng-click="setView('all')"><i class="zmdi zmdi-collection-image"></i> {{ trans('components.imagem_all') }}</div>
|
||||
<div class="col-xs-4 tab-item" title="{{ trans('components.imagem_book_title') }}" ng-class="{selected: (view=='book')}" ng-click="setView('book')"><i class="zmdi zmdi-book text-book"></i> {{ trans('entities.book') }}</div>
|
||||
<div class="col-xs-4 tab-item" title="{{ trans('components.imagem_page_title') }}" ng-class="{selected: (view=='page')}" ng-click="setView('page')"><i class="zmdi zmdi-file-text text-page"></i> {{ trans('entities.page') }}</div>
|
||||
<div class="col-xs-4 tab-item" title="{{ trans('components.image_all_title') }}" ng-class="{selected: (view=='all')}" ng-click="setView('all')"><i class="zmdi zmdi-collection-image"></i> {{ trans('components.image_all') }}</div>
|
||||
<div class="col-xs-4 tab-item" title="{{ trans('components.image_book_title') }}" ng-class="{selected: (view=='book')}" ng-click="setView('book')"><i class="zmdi zmdi-book text-book"></i> {{ trans('entities.book') }}</div>
|
||||
<div class="col-xs-4 tab-item" title="{{ trans('components.image_page_title') }}" ng-class="{selected: (view=='page')}" ng-click="setView('page')"><i class="zmdi zmdi-file-text text-page"></i> {{ trans('entities.page') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="view === 'all'" >
|
||||
<form ng-submit="searchImages()" class="contained-search-box">
|
||||
<input type="text" placeholder="{{ trans('components.imagem_search_hint') }}" ng-model="searchTerm">
|
||||
<input type="text" placeholder="{{ trans('components.image_search_hint') }}" ng-model="searchTerm">
|
||||
<button ng-class="{active: searching}" title="{{ trans('common.search_clear') }}" type="button" ng-click="cancelSearch()" class="text-button cancel"><i class="zmdi zmdi-close-circle-o"></i></button>
|
||||
<button title="{{ trans('common.search') }}" class="text-button" type="submit"><i class="zmdi zmdi-search"></i></button>
|
||||
</form>
|
||||
|
@ -31,11 +31,11 @@
|
|||
<img ng-src="@{{image.thumbs.gallery}}" ng-attr-alt="@{{image.title}}" ng-attr-title="@{{image.name}}">
|
||||
<div class="image-meta">
|
||||
<span class="name" ng-bind="image.name"></span>
|
||||
<span class="date">{{ trans('components.imagem_uploaded', ['uploadedDate' => "{{ getDate(image.created_at) }" . "}"]) }}</span>
|
||||
<span class="date">{{ trans('components.image_uploaded', ['uploadedDate' => "{{ getDate(image.created_at) }" . "}"]) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="load-more" ng-show="hasMore" ng-click="fetchData()">{{ trans('components.imagem_load_more') }}</div>
|
||||
<div class="load-more" ng-show="hasMore" ng-click="fetchData()">{{ trans('components.image_load_more') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -51,14 +51,14 @@
|
|||
</a>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">{{ trans('components.imagem_image_name') }}</label>
|
||||
<label for="name">{{ trans('components.image_image_name') }}</label>
|
||||
<input type="text" id="name" name="name" ng-model="selectedImage.name">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div ng-show="dependantPages">
|
||||
<p class="text-neg text-small">
|
||||
{{ trans('components.imagem_delete_confirm') }}
|
||||
{{ trans('components.image_delete_confirm') }}
|
||||
</p>
|
||||
<ul class="text-neg">
|
||||
<li ng-repeat="page in dependantPages">
|
||||
|
@ -72,13 +72,13 @@
|
|||
<button class="button icon neg"><i class="zmdi zmdi-delete"></i></button>
|
||||
</form>
|
||||
<button class="button pos anim fadeIn float right" ng-show="selectedImage" ng-click="selectButtonClick()">
|
||||
<i class="zmdi zmdi-square-right"></i>{{ trans('components.imagem_select_image') }}
|
||||
<i class="zmdi zmdi-square-right"></i>{{ trans('components.image_select_image') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<drop-zone message="{{ trans('components.imagem_dropzone') }}" upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
|
||||
<drop-zone message="{{ trans('components.image_dropzone') }}" upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
|
||||
|
||||
|
||||
</div>
|
|
@ -1,10 +1,10 @@
|
|||
<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 class="image-picker" image-picker="{{$name}}" 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>
|
||||
<button class="button" type="button" data-action="show-image-manager">{{ trans('components.image_select_image') }}</button>
|
||||
<br>
|
||||
<button class="text-button" data-action="reset-image" type="button">{{ trans('common.reset') }}</button>
|
||||
|
||||
|
@ -13,5 +13,54 @@
|
|||
<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>
|
||||
<input type="hidden" name="{{$name}}" id="{{$name}}" value="{{ isset($currentId) && ($currentId !== '' && $currentId !== false) ? $currentId : $currentImage}}">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
|
||||
var picker = document.querySelector('[image-picker="{{$name}}"]');
|
||||
picker.addEventListener('click', function(event) {
|
||||
if (event.target.nodeName.toLowerCase() !== 'button') return;
|
||||
var button = event.target;
|
||||
var action = button.getAttribute('data-action');
|
||||
var resize = picker.getAttribute('data-resize-height') && picker.getAttribute('data-resize-width');
|
||||
var usingIds = picker.getAttribute('data-current-id') !== '';
|
||||
var resizeCrop = picker.getAttribute('data-resize-crop') !== '';
|
||||
var imageElem = picker.querySelector('img');
|
||||
var 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;
|
||||
}
|
||||
var 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');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
</script>
|
|
@ -1,4 +1,15 @@
|
|||
<div toggle-switch class="toggle-switch @if($value) active @endif">
|
||||
<div toggle-switch="{{$name}}" class="toggle-switch @if($value) active @endif">
|
||||
<input type="hidden" name="{{$name}}" value="{{$value?'true':'false'}}"/>
|
||||
<div class="switch-handle"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
var toggle = document.querySelector('[toggle-switch="{{$name}}"]');
|
||||
var toggleInput = toggle.querySelector('input');
|
||||
toggle.onclick = function(event) {
|
||||
var checked = toggleInput.value !== 'true';
|
||||
toggleInput.value = checked ? 'true' : 'false';
|
||||
checked ? toggle.classList.add('active') : toggle.classList.remove('active');
|
||||
};
|
||||
})()
|
||||
</script>
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
</div>
|
||||
|
||||
@include('partials/image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id])
|
||||
@include('partials/entity-selector-popup')
|
||||
@include('components.image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id])
|
||||
@include('components.entity-selector-popup')
|
||||
|
||||
@stop
|
|
@ -19,7 +19,7 @@
|
|||
{!! csrf_field() !!}
|
||||
<input type="hidden" name="_method" value="PUT">
|
||||
|
||||
@include('partials/entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book,chapter'])
|
||||
@include('components.entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book,chapter'])
|
||||
|
||||
<a href="{{ $page->getUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
|
||||
<button type="submit" class="button pos">{{ trans('entities.pages_move') }}</button>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<style>
|
||||
<style id="custom-styles" data-color="{{ setting('app-color') }}" data-color-light="{{ setting('app-color-light') }}">
|
||||
header, #back-to-top, .primary-background {
|
||||
background-color: {{ setting('app-color') }} !important;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
'defaultImage' => baseUrl('/logo.png'),
|
||||
'currentImage' => setting('app-logo'),
|
||||
'name' => 'setting-app-logo',
|
||||
'imageClass' => 'logo-image'
|
||||
'imageClass' => 'logo-image',
|
||||
'currentId' => false
|
||||
])
|
||||
|
||||
</div>
|
||||
|
@ -125,7 +126,7 @@
|
|||
|
||||
</div>
|
||||
|
||||
@include('partials/image-manager', ['imageType' => 'system'])
|
||||
@include('components.image-manager', ['imageType' => 'system'])
|
||||
|
||||
@stop
|
||||
|
||||
|
@ -142,10 +143,16 @@
|
|||
var isEmpty = $.trim($elm.val()).length === 0;
|
||||
if (!isEmpty) $elm.val(hexVal);
|
||||
$('#setting-app-color-light').val(isEmpty ? '' : rgbLightVal);
|
||||
// Set page elements to provide preview
|
||||
$('#header, .image-picker .button').attr('style', 'background-color:'+ hexVal+'!important;');
|
||||
$('.faded-small').css('background-color', rgbLightVal);
|
||||
$('.setting-nav a.selected').css('border-bottom-color', hexVal + '!important');
|
||||
|
||||
var customStyles = document.getElementById('custom-styles');
|
||||
var oldColor = customStyles.getAttribute('data-color');
|
||||
var oldColorLight = customStyles.getAttribute('data-color-light');
|
||||
|
||||
customStyles.innerHTML = customStyles.innerHTML.split(oldColor).join(hexVal);
|
||||
customStyles.innerHTML = customStyles.innerHTML.split(oldColorLight).join(rgbLightVal);
|
||||
|
||||
customStyles.setAttribute('data-color', hexVal);
|
||||
customStyles.setAttribute('data-color-light', rgbLightVal);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -20,13 +20,13 @@
|
|||
<tr>
|
||||
<th>{{ trans('settings.role_name') }}</th>
|
||||
<th></th>
|
||||
<th class="text-right">{{ trans('settings.users') }}</th>
|
||||
<th class="text-center">{{ trans('settings.users') }}</th>
|
||||
</tr>
|
||||
@foreach($roles as $role)
|
||||
<tr>
|
||||
<td><a href="{{ baseUrl("/settings/roles/{$role->id}") }}">{{ $role->display_name }}</a></td>
|
||||
<td>{{ $role->description }}</td>
|
||||
<td class="text-right">{{ $role->users->count() }}</td>
|
||||
<td class="text-center">{{ $role->users->count() }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</table>
|
||||
|
|
|
@ -85,5 +85,5 @@
|
|||
</div>
|
||||
|
||||
<p class="margin-top large"><br></p>
|
||||
@include('partials/image-manager', ['imageType' => 'user'])
|
||||
@include('components.image-manager', ['imageType' => 'user'])
|
||||
@stop
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
Route::get('/translations.js', 'HomeController@getTranslations');
|
||||
|
||||
// Authenticated routes...
|
||||
Route::group(['middleware' => 'auth'], function () {
|
||||
|
||||
|
|
Loading…
Reference in a new issue