From 82967821499fd87fb4cf2c24667b5b856ea9498e Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 7 Feb 2016 10:14:11 +0000 Subject: [PATCH] Updated image controller styling and added preview option The notification system was also updated so it can be used from JavaScript events such as image manager uploads. Closes #25 --- resources/assets/js/controllers.js | 73 +++++++++++++++---- resources/assets/js/directives.js | 2 +- resources/assets/js/global.js | 49 +++++++++++-- resources/assets/js/pages/page-form.js | 7 +- resources/assets/js/services.js | 2 +- resources/assets/sass/_image-manager.scss | 36 ++++++++- .../views/partials/image-manager.blade.php | 23 +++--- .../views/partials/notifications.blade.php | 17 ++--- 8 files changed, 164 insertions(+), 45 deletions(-) diff --git a/resources/assets/js/controllers.js b/resources/assets/js/controllers.js index 5d8990754..76def6abd 100644 --- a/resources/assets/js/controllers.js +++ b/resources/assets/js/controllers.js @@ -1,6 +1,6 @@ "use strict"; -module.exports = function (ngApp) { +module.exports = function (ngApp, events) { ngApp.controller('ImageManagerController', ['$scope', '$attrs', '$http', '$timeout', 'imageManagerService', function ($scope, $attrs, $http, $timeout, imageManagerService) { @@ -17,21 +17,40 @@ module.exports = function (ngApp) { var dataLoaded = false; var callback = false; + /** + * Simple returns the appropriate upload url depending on the image type set. + * @returns {string} + */ $scope.getUploadUrl = function () { return '/images/' + $scope.imageType + '/upload'; }; + /** + * Runs on image upload, Adds an image to local list of images + * and shows a success message to the user. + * @param file + * @param data + */ $scope.uploadSuccess = function (file, data) { $scope.$apply(() => { $scope.images.unshift(data); }); + events.emit('success', 'Image uploaded'); }; + /** + * Runs the callback and hides the image manager. + * @param returnData + */ function callbackAndHide(returnData) { if (callback) callback(returnData); $scope.showing = false; } + /** + * Image select action. Checks if a double-click was fired. + * @param image + */ $scope.imageSelect = function (image) { var dblClickTime = 300; var currentTime = Date.now(); @@ -48,10 +67,19 @@ module.exports = function (ngApp) { previousClickTime = currentTime; }; + /** + * Action that runs when the 'Select image' button is clicked. + * Runs the callback and hides the image manager. + */ $scope.selectButtonClick = function () { callbackAndHide($scope.selectedImage); }; + /** + * Show the image manager. + * Takes a callback to execute later on. + * @param doneCallback + */ function show(doneCallback) { callback = doneCallback; $scope.showing = true; @@ -62,6 +90,8 @@ module.exports = function (ngApp) { } } + // Connects up the image manger so it can be used externally + // such as from TinyMCE. imageManagerService.show = show; imageManagerService.showExternal = function (doneCallback) { $scope.$apply(() => { @@ -70,10 +100,16 @@ module.exports = function (ngApp) { }; window.ImageManager = imageManagerService; + /** + * Hide the image manager + */ $scope.hide = function () { $scope.showing = false; }; + /** + * Fetch the list image data from the server. + */ function fetchData() { var url = '/images/' + $scope.imageType + '/all/' + page; $http.get(url).then((response) => { @@ -82,28 +118,33 @@ module.exports = function (ngApp) { page++; }); } + $scope.fetchData = fetchData; + /** + * Save the details of an image. + * @param event + */ $scope.saveImageDetails = function (event) { event.preventDefault(); var url = '/images/update/' + $scope.selectedImage.id; $http.put(url, this.selectedImage).then((response) => { - $scope.imageUpdateSuccess = true; - $timeout(() => { - $scope.imageUpdateSuccess = false; - }, 3000); + events.emit('success', 'Image details updated'); }, (response) => { var errors = response.data; var message = ''; Object.keys(errors).forEach((key) => { message += errors[key].join('\n'); }); - $scope.imageUpdateFailure = message; - $timeout(() => { - $scope.imageUpdateFailure = false; - }, 5000); + events.emit('error', message); }); }; + /** + * Delete an image from system and notify of success. + * Checks if it should force delete when an image + * has dependant pages. + * @param event + */ $scope.deleteImage = function (event) { event.preventDefault(); var force = $scope.dependantPages !== false; @@ -112,10 +153,7 @@ module.exports = function (ngApp) { $http.delete(url).then((response) => { $scope.images.splice($scope.images.indexOf($scope.selectedImage), 1); $scope.selectedImage = false; - $scope.imageDeleteSuccess = true; - $timeout(() => { - $scope.imageDeleteSuccess = false; - }, 3000); + events.emit('success', 'Image successfully deleted'); }, (response) => { // Pages failure if (response.status === 400) { @@ -124,6 +162,15 @@ module.exports = function (ngApp) { }); }; + /** + * Simple date creator used to properly format dates. + * @param stringDate + * @returns {Date} + */ + $scope.getDate = function(stringDate) { + return new Date(stringDate); + }; + }]); diff --git a/resources/assets/js/directives.js b/resources/assets/js/directives.js index 6ccfcf855..60abde6e9 100644 --- a/resources/assets/js/directives.js +++ b/resources/assets/js/directives.js @@ -5,7 +5,7 @@ var toggleSwitchTemplate = require('./components/toggle-switch.html'); var imagePickerTemplate = require('./components/image-picker.html'); var dropZoneTemplate = require('./components/drop-zone.html'); -module.exports = function (ngApp) { +module.exports = function (ngApp, events) { /** * Toggle Switches diff --git a/resources/assets/js/global.js b/resources/assets/js/global.js index 5b0b6f9f0..00c5f13c2 100644 --- a/resources/assets/js/global.js +++ b/resources/assets/js/global.js @@ -1,4 +1,4 @@ - +"use strict"; // AngularJS - Create application and load components var angular = require('angular'); @@ -7,9 +7,31 @@ var ngAnimate = require('angular-animate'); var ngSanitize = require('angular-sanitize'); var ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize']); -var services = require('./services')(ngApp); -var directives = require('./directives')(ngApp); -var controllers = require('./controllers')(ngApp); + + +// Global Event System +var Events = { + listeners: {}, + emit: function (eventName, eventData) { + if (typeof this.listeners[eventName] === 'undefined') return this; + var eventsToStart = this.listeners[eventName]; + for (let i = 0; i < eventsToStart.length; i++) { + var event = eventsToStart[i]; + event(eventData); + } + return this; + }, + listen: function (eventName, callback) { + if (typeof this.listeners[eventName] === 'undefined') this.listeners[eventName] = []; + this.listeners[eventName].push(callback); + return this; + } +}; +window.Events = Events; + +var services = require('./services')(ngApp, Events); +var directives = require('./directives')(ngApp, Events); +var controllers = require('./controllers')(ngApp, Events); //Global jQuery Config & Extensions @@ -32,8 +54,25 @@ $.expr[":"].contains = $.expr.createPseudo(function (arg) { // Global jQuery Elements $(function () { + + var notifications = $('.notification'); + var successNotification = notifications.filter('.pos'); + var errorNotification = notifications.filter('.neg'); + // Notification Events + window.Events.listen('success', function (text) { + successNotification.hide(); + successNotification.find('span').text(text); + setTimeout(() => { + successNotification.show(); + }, 1); + }); + window.Events.listen('error', function (text) { + errorNotification.find('span').text(text); + errorNotification.show(); + }); + // Notification hiding - $('.notification').click(function () { + notifications.click(function () { $(this).fadeOut(100); }); diff --git a/resources/assets/js/pages/page-form.js b/resources/assets/js/pages/page-form.js index 756a9211b..290b7c653 100644 --- a/resources/assets/js/pages/page-form.js +++ b/resources/assets/js/pages/page-form.js @@ -8,7 +8,6 @@ module.exports = { statusbar: false, menubar: false, paste_data_images: false, - //height: 700, extended_valid_elements: 'pre[*]', automatic_uploads: false, valid_children: "-div[p|pre|h1|h2|h3|h4|h5|h6|blockquote]", @@ -31,7 +30,7 @@ module.exports = { alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-right'}, }, file_browser_callback: function (field_name, url, type, win) { - ImageManager.show(function (image) { + window.ImageManager.showExternal(function (image) { win.document.getElementById(field_name).value = image.url; if ("createEvent" in document) { var evt = document.createEvent("HTMLEvents"); @@ -40,6 +39,10 @@ module.exports = { } else { win.document.getElementById(field_name).fireEvent("onchange"); } + var html = ''; + html += '' + image.name + ''; + html += ''; + win.tinyMCE.activeEditor.execCommand('mceInsertContent', false, html); }); }, paste_preprocess: function (plugin, args) { diff --git a/resources/assets/js/services.js b/resources/assets/js/services.js index 684a68450..cd2759c54 100644 --- a/resources/assets/js/services.js +++ b/resources/assets/js/services.js @@ -1,6 +1,6 @@ "use strict"; -module.exports = function(ngApp) { +module.exports = function(ngApp, events) { ngApp.factory('imageManagerService', function() { return { diff --git a/resources/assets/sass/_image-manager.scss b/resources/assets/sass/_image-manager.scss index babbad0c1..8b18d24f3 100644 --- a/resources/assets/sass/_image-manager.scss +++ b/resources/assets/sass/_image-manager.scss @@ -21,7 +21,6 @@ border-radius: 4px; box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.3); overflow: hidden; - max-width: 1340px; position: fixed; top: 0; bottom: 0; @@ -44,18 +43,49 @@ right: 0; } -.image-manager-list img { +.image-manager-list .image { display: block; + position: relative; border-radius: 0; float: left; margin: 0; cursor: pointer; width: (100%/6); height: auto; - border: 1px solid #FFF; + border: 1px solid #DDD; + box-shadow: 0 0 0 0 rgba(0, 0, 0, 0); transition: all cubic-bezier(.4, 0, 1, 1) 160ms; + overflow: hidden; &.selected { transform: scale3d(0.92, 0.92, 0.92); + border: 1px solid #444; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2); + } + img { + width: 100%; + max-width: 100%; + display: block; + } + .image-meta { + position: absolute; + width: 100%; + bottom: 0; + left: 0; + color: #EEE; + background-color: rgba(0, 0, 0, 0.4); + font-size: 10px; + padding: 3px 4px; + span { + display: block; + } + } + @include smaller-than($xl) { + width: (100%/4); + } + @include smaller-than($m) { + .image-meta { + display: none; + } } } diff --git a/resources/views/partials/image-manager.blade.php b/resources/views/partials/image-manager.blade.php index 6dc528d23..bf7bf445c 100644 --- a/resources/views/partials/image-manager.blade.php +++ b/resources/views/partials/image-manager.blade.php @@ -5,11 +5,14 @@
- +
+ +
+ + Uploaded @{{ getDate(image.created_at) | date:'mediumDate' }} +
+
Load More
@@ -19,18 +22,20 @@

Images

-

+
+ + + +
-

Image name updated

-

@@ -53,8 +58,6 @@
-

Image deleted

-