Showing
24 changed files
with
452 additions
and
440 deletions
| ... | @@ -21,6 +21,6 @@ elixir.extend('queryVersion', function(inputFiles) { | ... | @@ -21,6 +21,6 @@ elixir.extend('queryVersion', function(inputFiles) { |
| 21 | elixir(function(mix) { | 21 | elixir(function(mix) { |
| 22 | mix.sass('styles.scss') | 22 | mix.sass('styles.scss') |
| 23 | .sass('print-styles.scss') | 23 | .sass('print-styles.scss') |
| 24 | - .browserify(['jquery-extensions.js', 'global.js'], 'public/js/common.js') | 24 | + .browserify('global.js', 'public/js/common.js') |
| 25 | .queryVersion(['css/styles.css', 'css/print-styles.css', 'js/common.js']); | 25 | .queryVersion(['css/styles.css', 'css/print-styles.css', 'js/common.js']); |
| 26 | }); | 26 | }); | ... | ... |
| 1 | { | 1 | { |
| 2 | "private": true, | 2 | "private": true, |
| 3 | "devDependencies": { | 3 | "devDependencies": { |
| 4 | - "gulp": "^3.9.0", | 4 | + "gulp": "^3.9.0" |
| 5 | - "insert-css": "^0.2.0" | ||
| 6 | }, | 5 | }, |
| 7 | "dependencies": { | 6 | "dependencies": { |
| 8 | "angular": "^1.5.0-rc.0", | 7 | "angular": "^1.5.0-rc.0", |
| 8 | + "angular-animate": "^1.5.0-rc.0", | ||
| 9 | "angular-resource": "^1.5.0-rc.0", | 9 | "angular-resource": "^1.5.0-rc.0", |
| 10 | + "angular-sanitize": "^1.5.0-rc.0", | ||
| 10 | "babel-runtime": "^5.8.29", | 11 | "babel-runtime": "^5.8.29", |
| 11 | "bootstrap-sass": "^3.0.0", | 12 | "bootstrap-sass": "^3.0.0", |
| 12 | "dropzone": "^4.0.1", | 13 | "dropzone": "^4.0.1", |
| 13 | "laravel-elixir": "^3.4.0", | 14 | "laravel-elixir": "^3.4.0", |
| 14 | - "vue": "^1.0.13", | ||
| 15 | - "vue-hot-reload-api": "^1.2.1", | ||
| 16 | - "vue-resource": "^0.5.1", | ||
| 17 | - "vueify": "^5.0.1", | ||
| 18 | - "vueify-insert-css": "^1.0.0", | ||
| 19 | "zeroclipboard": "^2.2.0" | 15 | "zeroclipboard": "^2.2.0" |
| 20 | } | 16 | } |
| 21 | } | 17 | } | ... | ... |
| 1 | -<template> | ||
| 2 | - <div id="image-manager"> | ||
| 3 | - <div class="overlay" v-el:overlay @click="overlayClick"> | ||
| 4 | - <div class="image-manager-body"> | ||
| 5 | - <div class="image-manager-content"> | ||
| 6 | - <div class="image-manager-list"> | ||
| 7 | - <div v-for="image in images"> | ||
| 8 | - <img class="anim fadeIn" | ||
| 9 | - :class="{selected: (image==selectedImage)}" | ||
| 10 | - :src="image.thumbs.gallery" :alt="image.title" :title="image.name" | ||
| 11 | - @click="imageClick(image)" | ||
| 12 | - :style="{animationDelay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'}"> | ||
| 13 | - </div> | ||
| 14 | - <div class="load-more" v-show="hasMore" @click="fetchData">Load More</div> | ||
| 15 | - </div> | ||
| 16 | - </div> | ||
| 17 | - <button class="neg button image-manager-close" @click="hide">x</button> | ||
| 18 | - <div class="image-manager-sidebar"> | ||
| 19 | - <h2 v-el:image-title>Images</h2> | ||
| 20 | - <hr class="even"> | ||
| 21 | - <div class="dropzone-container" v-el:drop-zone> | ||
| 22 | - <div class="dz-message">Drop files or click here to upload</div> | ||
| 23 | - </div> | ||
| 24 | - <div class="image-manager-details anim fadeIn" v-show="selectedImage"> | ||
| 25 | - <hr class="even"> | ||
| 26 | - <form @submit="saveImageDetails" v-el:image-form> | ||
| 27 | - <div class="form-group"> | ||
| 28 | - <label for="name">Image Name</label> | ||
| 29 | - <input type="text" id="name" name="name" v-model="selectedImage.name"> | ||
| 30 | - </div> | ||
| 31 | - </form> | ||
| 32 | - <hr class="even"> | ||
| 33 | - <div v-show="dependantPages"> | ||
| 34 | - <p class="text-neg text-small"> | ||
| 35 | - This image is used in the pages below, Click delete again to confirm you want to delete | ||
| 36 | - this image. | ||
| 37 | - </p> | ||
| 38 | - <ul class="text-neg"> | ||
| 39 | - <li v-for="page in dependantPages"> | ||
| 40 | - <a :href="page.url" target="_blank" class="text-neg">{{ page.name }}</a> | ||
| 41 | - </li> | ||
| 42 | - </ul> | ||
| 43 | - </div> | ||
| 44 | - | ||
| 45 | - <form @submit="deleteImage" v-el:image-delete-form> | ||
| 46 | - <button class="button neg"><i class="zmdi zmdi-delete"></i>Delete Image</button> | ||
| 47 | - </form> | ||
| 48 | - </div> | ||
| 49 | - <div class="image-manager-bottom"> | ||
| 50 | - <button class="button pos anim fadeIn" v-show="selectedImage" @click="selectButtonClick"><i | ||
| 51 | - class="zmdi zmdi-square-right"></i>Select Image | ||
| 52 | - </button> | ||
| 53 | - </div> | ||
| 54 | - </div> | ||
| 55 | - </div> | ||
| 56 | - </div> | ||
| 57 | - </div> | ||
| 58 | -</template> | ||
| 59 | - | ||
| 60 | -<script> | ||
| 61 | - | ||
| 62 | - var Dropzone = require('dropzone'); | ||
| 63 | - | ||
| 64 | - module.exports = { | ||
| 65 | - data: function () { | ||
| 66 | - return { | ||
| 67 | - images: [], | ||
| 68 | - hasMore: false, | ||
| 69 | - page: 0, | ||
| 70 | - cClickTime: 0, | ||
| 71 | - selectedImage: false, | ||
| 72 | - dependantPages: false, | ||
| 73 | - deleteForm: {}, | ||
| 74 | - token: document.querySelector('meta[name=token]').getAttribute('content'), | ||
| 75 | - dataLoaded: false | ||
| 76 | - } | ||
| 77 | - }, | ||
| 78 | - | ||
| 79 | - props: { | ||
| 80 | - imageType: { | ||
| 81 | - type: String, | ||
| 82 | - required: true | ||
| 83 | - } | ||
| 84 | - }, | ||
| 85 | - | ||
| 86 | - created: function () { | ||
| 87 | - window.ImageManager = this; | ||
| 88 | - }, | ||
| 89 | - | ||
| 90 | - ready: function () { | ||
| 91 | - // Create dropzone | ||
| 92 | - this.setupDropZone(); | ||
| 93 | - }, | ||
| 94 | - | ||
| 95 | - methods: { | ||
| 96 | - fetchData: function () { | ||
| 97 | - var url = '/images/' + this.imageType + '/all/' + this.page; | ||
| 98 | - this.$http.get(url).then((response) => { | ||
| 99 | - this.images = this.images.concat(response.data.images); | ||
| 100 | - this.hasMore = response.data.hasMore; | ||
| 101 | - this.page++; | ||
| 102 | - }); | ||
| 103 | - }, | ||
| 104 | - | ||
| 105 | - setupDropZone: function () { | ||
| 106 | - var _this = this; | ||
| 107 | - var dropZone = new Dropzone(_this.$els.dropZone, { | ||
| 108 | - url: '/images/' + _this.imageType + '/upload', | ||
| 109 | - init: function () { | ||
| 110 | - var dz = this; | ||
| 111 | - dz.on("sending", function (file, xhr, data) { | ||
| 112 | - data.append("_token", _this.token); | ||
| 113 | - }); | ||
| 114 | - dz.on("success", function (file, data) { | ||
| 115 | - _this.images.unshift(data); | ||
| 116 | - $(file.previewElement).fadeOut(400, function () { | ||
| 117 | - dz.removeFile(file); | ||
| 118 | - }); | ||
| 119 | - }); | ||
| 120 | - dz.on('error', function (file, errorMessage, xhr) { | ||
| 121 | - if (errorMessage.file) { | ||
| 122 | - $(file.previewElement).find('[data-dz-errormessage]').text(errorMessage.file[0]); | ||
| 123 | - } | ||
| 124 | - console.log(errorMessage); | ||
| 125 | - }); | ||
| 126 | - } | ||
| 127 | - }); | ||
| 128 | - }, | ||
| 129 | - | ||
| 130 | - returnCallback: function (image) { | ||
| 131 | - this.callback(image); | ||
| 132 | - }, | ||
| 133 | - | ||
| 134 | - imageClick: function (image) { | ||
| 135 | - var dblClickTime = 380; | ||
| 136 | - var cTime = (new Date()).getTime(); | ||
| 137 | - var timeDiff = cTime - this.cClickTime; | ||
| 138 | - if (this.cClickTime !== 0 && timeDiff < dblClickTime && this.selectedImage === image) { | ||
| 139 | - // DoubleClick | ||
| 140 | - if (this.callback) { | ||
| 141 | - this.returnCallback(image); | ||
| 142 | - } | ||
| 143 | - this.hide(); | ||
| 144 | - } else { | ||
| 145 | - this.selectedImage = (this.selectedImage === image) ? false : image; | ||
| 146 | - this.dependantPages = false; | ||
| 147 | - } | ||
| 148 | - this.cClickTime = cTime; | ||
| 149 | - }, | ||
| 150 | - | ||
| 151 | - selectButtonClick: function () { | ||
| 152 | - if (this.callback) this.returnCallback(this.selectedImage); | ||
| 153 | - this.hide(); | ||
| 154 | - }, | ||
| 155 | - | ||
| 156 | - show: function (callback) { | ||
| 157 | - this.callback = callback; | ||
| 158 | - this.$els.overlay.style.display = 'block'; | ||
| 159 | - // Get initial images if they have not yet been loaded in. | ||
| 160 | - if (!this.dataLoaded) { | ||
| 161 | - this.fetchData(this.page); | ||
| 162 | - this.dataLoaded = true; | ||
| 163 | - } | ||
| 164 | - }, | ||
| 165 | - | ||
| 166 | - overlayClick: function (e) { | ||
| 167 | - if (e.target.className === 'overlay') { | ||
| 168 | - this.hide(); | ||
| 169 | - } | ||
| 170 | - }, | ||
| 171 | - | ||
| 172 | - hide: function () { | ||
| 173 | - this.$els.overlay.style.display = 'none'; | ||
| 174 | - }, | ||
| 175 | - | ||
| 176 | - saveImageDetails: function (e) { | ||
| 177 | - e.preventDefault(); | ||
| 178 | - this.selectedImage._token = this.token; | ||
| 179 | - var form = $(this.$els.imageForm); | ||
| 180 | - var url = '/images/update/' + this.selectedImage.id; | ||
| 181 | - this.$http.put(url, this.selectedImage).then((response) => { | ||
| 182 | - form.showSuccess('Image name updated'); | ||
| 183 | - }, (response) => { | ||
| 184 | - form.showFailure(response.data); | ||
| 185 | - }); | ||
| 186 | - }, | ||
| 187 | - | ||
| 188 | - deleteImage: function (e) { | ||
| 189 | - e.preventDefault(); | ||
| 190 | - var _this = this; | ||
| 191 | - _this.deleteForm.force = _this.dependantPages !== false; | ||
| 192 | - _this.deleteForm._token = _this.token; | ||
| 193 | - var url = '/images/' + _this.selectedImage.id; | ||
| 194 | - this.$http.delete(url, this.deleteForm).then((response) => { | ||
| 195 | - this.images.splice(this.images.indexOf(this.selectedImage), 1); | ||
| 196 | - this.selectedImage = false; | ||
| 197 | - $(this.$els.imageTitle).showSuccess('Image Deleted'); | ||
| 198 | - }, (response) => { | ||
| 199 | - // Pages failure | ||
| 200 | - if (response.status === 400) { | ||
| 201 | - _this.dependantPages = response.data; | ||
| 202 | - } | ||
| 203 | - }); | ||
| 204 | - } | ||
| 205 | - | ||
| 206 | - } | ||
| 207 | - | ||
| 208 | - }; | ||
| 209 | -</script> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | + | ||
| 2 | +<div class="image-picker"> | ||
| 3 | + <div> | ||
| 4 | + <img ng-if="image && image !== 'none'" ng-src="{{image}}" ng-class="{{imageClass}}" alt="Image Preview"> | ||
| 5 | + <img ng-if="image === '' && defaultImage" ng-src="{{defaultImage}}" ng-class="{{imageClass}}" alt="Image Preview"> | ||
| 6 | + </div> | ||
| 7 | + <button class="button" type="button" ng-click="showImageManager()">Select Image</button> | ||
| 8 | + <br> | ||
| 9 | + | ||
| 10 | + <button class="text-button" ng-click="reset()" type="button">Reset</button> | ||
| 11 | + <span ng-show="showRemove" class="sep">|</span> | ||
| 12 | + <button ng-show="showRemove" class="text-button neg" ng-click="remove()" type="button">Remove</button> | ||
| 13 | + | ||
| 14 | + <input type="hidden" ng-attr-name="{{name}}" ng-attr-id="{{name}}" ng-attr-value="{{value}}"> | ||
| 15 | +</div> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | - | ||
| 2 | -<template> | ||
| 3 | - <div class="image-picker"> | ||
| 4 | - <div> | ||
| 5 | - <img v-if="image && image !== 'none'" :src="image" :class="imageClass" alt="Image Preview"> | ||
| 6 | - <img v-if="image === '' && defaultImage" :src="defaultImage" :class="imageClass" alt="Image Preview"> | ||
| 7 | - </div> | ||
| 8 | - <button class="button" type="button" @click="showImageManager">Select Image</button> | ||
| 9 | - <br> | ||
| 10 | - <button class="text-button" @click="reset" type="button">Reset</button> <span v-show="showRemove" class="sep">|</span> <button v-show="showRemove" class="text-button neg" @click="remove" type="button">Remove</button> | ||
| 11 | - <input type="hidden" :name="name" :id="name" v-model="value"> | ||
| 12 | - </div> | ||
| 13 | -</template> | ||
| 14 | - | ||
| 15 | -<script> | ||
| 16 | - module.exports = { | ||
| 17 | - props: { | ||
| 18 | - currentImage: { | ||
| 19 | - required: true, | ||
| 20 | - type: String | ||
| 21 | - }, | ||
| 22 | - currentId: { | ||
| 23 | - required: false, | ||
| 24 | - default: 'false', | ||
| 25 | - type: String | ||
| 26 | - }, | ||
| 27 | - name: { | ||
| 28 | - required: true, | ||
| 29 | - type: String | ||
| 30 | - }, | ||
| 31 | - defaultImage: { | ||
| 32 | - required: true, | ||
| 33 | - type: String | ||
| 34 | - }, | ||
| 35 | - imageClass: { | ||
| 36 | - required: true, | ||
| 37 | - type: String | ||
| 38 | - }, | ||
| 39 | - resizeWidth: { | ||
| 40 | - type: String | ||
| 41 | - }, | ||
| 42 | - resizeHeight: { | ||
| 43 | - type: String | ||
| 44 | - }, | ||
| 45 | - resizeCrop: { | ||
| 46 | - type: Boolean | ||
| 47 | - }, | ||
| 48 | - showRemove: { | ||
| 49 | - type: Boolean, | ||
| 50 | - default: 'true' | ||
| 51 | - } | ||
| 52 | - }, | ||
| 53 | - data: function() { | ||
| 54 | - return { | ||
| 55 | - image: this.currentImage, | ||
| 56 | - value: false | ||
| 57 | - } | ||
| 58 | - }, | ||
| 59 | - compiled: function() { | ||
| 60 | - this.value = this.currentId === 'false' ? this.currentImage : this.currentId; | ||
| 61 | - }, | ||
| 62 | - methods: { | ||
| 63 | - setCurrentValue: function(imageModel, imageUrl) { | ||
| 64 | - this.image = imageUrl; | ||
| 65 | - this.value = this.currentId === 'false' ? imageUrl : imageModel.id; | ||
| 66 | - }, | ||
| 67 | - showImageManager: function(e) { | ||
| 68 | - ImageManager.show((image) => { | ||
| 69 | - this.updateImageFromModel(image); | ||
| 70 | - }); | ||
| 71 | - }, | ||
| 72 | - reset: function() { | ||
| 73 | - this.setCurrentValue({id: 0}, this.defaultImage); | ||
| 74 | - }, | ||
| 75 | - remove: function() { | ||
| 76 | - this.image = 'none'; | ||
| 77 | - this.value = 'none'; | ||
| 78 | - }, | ||
| 79 | - updateImageFromModel: function(model) { | ||
| 80 | - var isResized = this.resizeWidth && this.resizeHeight; | ||
| 81 | - | ||
| 82 | - if (!isResized) { | ||
| 83 | - this.setCurrentValue(model, model.url); | ||
| 84 | - return; | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - var cropped = this.resizeCrop ? 'true' : 'false'; | ||
| 88 | - var requestString = '/images/thumb/' + model.id + '/' + this.resizeWidth + '/' + this.resizeHeight + '/' + cropped; | ||
| 89 | - this.$http.get(requestString).then((response) => { | ||
| 90 | - this.setCurrentValue(model, response.data.url); | ||
| 91 | - }); | ||
| 92 | - } | ||
| 93 | - } | ||
| 94 | - }; | ||
| 95 | -</script> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
resources/assets/js/controllers.js
0 → 100644
| 1 | +"use strict"; | ||
| 2 | + | ||
| 3 | +module.exports = function(ngApp) { | ||
| 4 | + | ||
| 5 | + ngApp.controller('ImageManagerController', ['$scope', '$attrs', '$http', '$timeout','imageManagerService', | ||
| 6 | + function($scope, $attrs, $http, $timeout, imageManagerService) { | ||
| 7 | + $scope.images = []; | ||
| 8 | + $scope.imageType = $attrs.imageType; | ||
| 9 | + $scope.selectedImage = false; | ||
| 10 | + $scope.dependantPages = false; | ||
| 11 | + $scope.showing = false; | ||
| 12 | + $scope.hasMore = false; | ||
| 13 | + $scope.imageUpdateSuccess = false; | ||
| 14 | + $scope.imageDeleteSuccess = false; | ||
| 15 | + var page = 0; | ||
| 16 | + var previousClickTime = 0; | ||
| 17 | + var dataLoaded = false; | ||
| 18 | + var callback = false; | ||
| 19 | + | ||
| 20 | + $scope.getUploadUrl = function() { | ||
| 21 | + return '/images/' + $scope.imageType + '/upload'; | ||
| 22 | + }; | ||
| 23 | + | ||
| 24 | + $scope.uploadSuccess = function(file, data) { | ||
| 25 | + $scope.$apply(() => { | ||
| 26 | + $scope.images.unshift(data); | ||
| 27 | + }); | ||
| 28 | + }; | ||
| 29 | + | ||
| 30 | + function callbackAndHide(returnData) { | ||
| 31 | + if (callback) callback(returnData); | ||
| 32 | + $scope.showing = false; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + $scope.imageSelect = function (image) { | ||
| 36 | + var dblClickTime = 300; | ||
| 37 | + var currentTime = Date.now(); | ||
| 38 | + var timeDiff = currentTime - previousClickTime; | ||
| 39 | + | ||
| 40 | + if (timeDiff < dblClickTime) { | ||
| 41 | + // If double click | ||
| 42 | + callbackAndHide(image); | ||
| 43 | + } else { | ||
| 44 | + // If single | ||
| 45 | + $scope.selectedImage = image; | ||
| 46 | + $scope.dependantPages = false; | ||
| 47 | + } | ||
| 48 | + previousClickTime = currentTime; | ||
| 49 | + }; | ||
| 50 | + | ||
| 51 | + $scope.selectButtonClick = function() { | ||
| 52 | + callbackAndHide($scope.selectedImage); | ||
| 53 | + }; | ||
| 54 | + | ||
| 55 | + function show(doneCallback) { | ||
| 56 | + callback = doneCallback; | ||
| 57 | + $scope.showing = true; | ||
| 58 | + // Get initial images if they have not yet been loaded in. | ||
| 59 | + if (!dataLoaded) { | ||
| 60 | + fetchData(); | ||
| 61 | + dataLoaded = true; | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + imageManagerService.show = show; | ||
| 66 | + imageManagerService.showExternal = function(doneCallback) { | ||
| 67 | + $scope.$apply(() => { | ||
| 68 | + show(doneCallback); | ||
| 69 | + }); | ||
| 70 | + }; | ||
| 71 | + window.ImageManager = imageManagerService; | ||
| 72 | + | ||
| 73 | + $scope.hide = function() { | ||
| 74 | + $scope.showing = false; | ||
| 75 | + }; | ||
| 76 | + | ||
| 77 | + function fetchData() { | ||
| 78 | + var url = '/images/' + $scope.imageType + '/all/' + page; | ||
| 79 | + $http.get(url).then((response) => { | ||
| 80 | + $scope.images = $scope.images.concat(response.data.images); | ||
| 81 | + $scope.hasMore = response.data.hasMore; | ||
| 82 | + page++; | ||
| 83 | + }); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + $scope.saveImageDetails = function(event) { | ||
| 87 | + event.preventDefault(); | ||
| 88 | + var url = '/images/update/' + $scope.selectedImage.id; | ||
| 89 | + $http.put(url, this.selectedImage).then((response) => { | ||
| 90 | + $scope.imageUpdateSuccess = true; | ||
| 91 | + $timeout(() => { | ||
| 92 | + $scope.imageUpdateSuccess = false; | ||
| 93 | + }, 3000); | ||
| 94 | + }, (response) => { | ||
| 95 | + var errors = response.data; | ||
| 96 | + var message = ''; | ||
| 97 | + Object.keys(errors).forEach((key) => { | ||
| 98 | + message += errors[key].join('\n'); | ||
| 99 | + }); | ||
| 100 | + $scope.imageUpdateFailure = message; | ||
| 101 | + $timeout(() => { | ||
| 102 | + $scope.imageUpdateFailure = false; | ||
| 103 | + }, 5000); | ||
| 104 | + }); | ||
| 105 | + }; | ||
| 106 | + | ||
| 107 | + $scope.deleteImage = function(event) { | ||
| 108 | + event.preventDefault(); | ||
| 109 | + var force = $scope.dependantPages !== false; | ||
| 110 | + var url = '/images/' + $scope.selectedImage.id; | ||
| 111 | + if (force) url += '?force=true'; | ||
| 112 | + $http.delete(url).then((response) => { | ||
| 113 | + $scope.images.splice($scope.images.indexOf($scope.selectedImage), 1); | ||
| 114 | + $scope.selectedImage = false; | ||
| 115 | + $scope.imageDeleteSuccess = true; | ||
| 116 | + $timeout(() => { | ||
| 117 | + $scope.imageDeleteSuccess = false; | ||
| 118 | + }, 3000); | ||
| 119 | + }, (response) => { | ||
| 120 | + // Pages failure | ||
| 121 | + if (response.status === 400) { | ||
| 122 | + $scope.dependantPages = response.data; | ||
| 123 | + } | ||
| 124 | + }); | ||
| 125 | + }; | ||
| 126 | + | ||
| 127 | + }]); | ||
| 128 | + | ||
| 129 | + | ||
| 130 | + ngApp.controller('BookShowController', ['$scope', '$http', '$attrs', function($scope, $http, $attrs) { | ||
| 131 | + $scope.searching = false; | ||
| 132 | + $scope.searchTerm = ''; | ||
| 133 | + $scope.searchResults = ''; | ||
| 134 | + | ||
| 135 | + $scope.searchBook = function (e) { | ||
| 136 | + e.preventDefault(); | ||
| 137 | + var term = $scope.searchTerm; | ||
| 138 | + if (term.length == 0) return; | ||
| 139 | + $scope.searching = true; | ||
| 140 | + $scope.searchResults = ''; | ||
| 141 | + var searchUrl = '/search/book/' + $attrs.bookId; | ||
| 142 | + searchUrl += '?term=' + encodeURIComponent(term); | ||
| 143 | + $http.get(searchUrl).then((response) => { | ||
| 144 | + $scope.searchResults = response.data; | ||
| 145 | + }); | ||
| 146 | + }; | ||
| 147 | + | ||
| 148 | + $scope.checkSearchForm = function () { | ||
| 149 | + if ($scope.searchTerm.length < 1) { | ||
| 150 | + $scope.searching = false; | ||
| 151 | + } | ||
| 152 | + }; | ||
| 153 | + | ||
| 154 | + $scope.clearSearch = function() { | ||
| 155 | + $scope.searching = false; | ||
| 156 | + $scope.searchTerm = ''; | ||
| 157 | + }; | ||
| 158 | + | ||
| 159 | + }]); | ||
| 160 | + | ||
| 161 | + | ||
| 162 | +}; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +"use strict"; | ||
| 2 | +var DropZone = require('dropzone'); | ||
| 1 | 3 | ||
| 2 | var toggleSwitchTemplate = require('./components/toggle-switch.html'); | 4 | var toggleSwitchTemplate = require('./components/toggle-switch.html'); |
| 5 | +var imagePickerTemplate = require('./components/image-picker.html'); | ||
| 6 | +var dropZoneTemplate = require('./components/drop-zone.html'); | ||
| 3 | 7 | ||
| 4 | module.exports = function(ngApp) { | 8 | module.exports = function(ngApp) { |
| 5 | 9 | ||
| 6 | /** | 10 | /** |
| 7 | * Toggle Switches | 11 | * Toggle Switches |
| 8 | - * Have basic on/off functionality. | 12 | + * Has basic on/off functionality. |
| 9 | * Use string values of 'true' & 'false' to dictate the current state. | 13 | * Use string values of 'true' & 'false' to dictate the current state. |
| 10 | */ | 14 | */ |
| 11 | ngApp.directive('toggleSwitch', function() { | 15 | ngApp.directive('toggleSwitch', function() { |
| ... | @@ -29,4 +33,127 @@ module.exports = function(ngApp) { | ... | @@ -29,4 +33,127 @@ module.exports = function(ngApp) { |
| 29 | }); | 33 | }); |
| 30 | 34 | ||
| 31 | 35 | ||
| 36 | + /** | ||
| 37 | + * Image Picker | ||
| 38 | + * Is a simple front-end interface that connects to an ImageManager if present. | ||
| 39 | + */ | ||
| 40 | + ngApp.directive('imagePicker', ['$http', 'imageManagerService', function($http, imageManagerService) { | ||
| 41 | + return { | ||
| 42 | + restrict: 'E', | ||
| 43 | + template: imagePickerTemplate, | ||
| 44 | + scope: { | ||
| 45 | + name: '@', | ||
| 46 | + resizeHeight: '@', | ||
| 47 | + resizeWidth: '@', | ||
| 48 | + resizeCrop: '@', | ||
| 49 | + showRemove: '=', | ||
| 50 | + currentImage: '@', | ||
| 51 | + currentId: '@', | ||
| 52 | + defaultImage: '@', | ||
| 53 | + imageClass: '@' | ||
| 54 | + }, | ||
| 55 | + link: function(scope, element, attrs) { | ||
| 56 | + var usingIds = typeof scope.currentId !== 'undefined' || scope.currentId === 'false'; | ||
| 57 | + scope.image = scope.currentImage; | ||
| 58 | + scope.value = scope.currentImage || ''; | ||
| 59 | + | ||
| 60 | + function setImage(imageModel, imageUrl) { | ||
| 61 | + scope.image = imageUrl; | ||
| 62 | + scope.value = usingIds ? imageModel.id : imageUrl; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + scope.reset = function() { | ||
| 66 | + setImage({id: 0}, scope.defaultImage); | ||
| 67 | + }; | ||
| 68 | + | ||
| 69 | + scope.remove = function() { | ||
| 70 | + scope.image = 'none'; | ||
| 71 | + scope.value = 'none'; | ||
| 72 | + }; | ||
| 73 | + | ||
| 74 | + scope.showImageManager = function() { | ||
| 75 | + imageManagerService.show((image) => { | ||
| 76 | + scope.updateImageFromModel(image); | ||
| 77 | + }); | ||
| 78 | + }; | ||
| 79 | + | ||
| 80 | + scope.updateImageFromModel = function(model) { | ||
| 81 | + var isResized = scope.resizeWidth && scope.resizeHeight; | ||
| 82 | + | ||
| 83 | + if (!isResized) { | ||
| 84 | + scope.$apply(() => { | ||
| 85 | + setImage(model, model.url); | ||
| 86 | + }); | ||
| 87 | + return; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + var cropped = scope.resizeCrop ? 'true' : 'false'; | ||
| 91 | + var requestString = '/images/thumb/' + model.id + '/' + scope.resizeWidth + '/' + scope.resizeHeight + '/' + cropped; | ||
| 92 | + $http.get(requestString).then((response) => { | ||
| 93 | + setImage(model, response.data.url); | ||
| 94 | + }); | ||
| 95 | + }; | ||
| 96 | + | ||
| 97 | + } | ||
| 98 | + }; | ||
| 99 | + }]); | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * DropZone | ||
| 103 | + * Used for uploading images | ||
| 104 | + */ | ||
| 105 | + ngApp.directive('dropZone', [function() { | ||
| 106 | + return { | ||
| 107 | + restrict: 'E', | ||
| 108 | + template: dropZoneTemplate, | ||
| 109 | + scope: { | ||
| 110 | + uploadUrl: '@', | ||
| 111 | + eventSuccess: '=', | ||
| 112 | + eventError: '=' | ||
| 113 | + }, | ||
| 114 | + link: function(scope, element, attrs) { | ||
| 115 | + var dropZone = new DropZone(element[0].querySelector('.dropzone-container'), { | ||
| 116 | + url: scope.uploadUrl, | ||
| 117 | + init: function() { | ||
| 118 | + var dz = this; | ||
| 119 | + dz.on('sending', function(file, xhr, data) { | ||
| 120 | + var token = window.document.querySelector('meta[name=token]').getAttribute('content'); | ||
| 121 | + data.append('_token', token); | ||
| 122 | + }); | ||
| 123 | + if (typeof scope.eventSuccess !== 'undefined') dz.on('success', scope.eventSuccess); | ||
| 124 | + dz.on('success', function(file, data) { | ||
| 125 | + $(file.previewElement).fadeOut(400, function () { | ||
| 126 | + dz.removeFile(file); | ||
| 127 | + }); | ||
| 128 | + }); | ||
| 129 | + if (typeof scope.eventError !== 'undefined') dz.on('error', scope.eventError); | ||
| 130 | + dz.on('error', function (file, errorMessage, xhr) { | ||
| 131 | + if (errorMessage.file) { | ||
| 132 | + $(file.previewElement).find('[data-dz-errormessage]').text(errorMessage.file[0]); | ||
| 133 | + } | ||
| 134 | + }); | ||
| 135 | + } | ||
| 136 | + }); | ||
| 137 | + } | ||
| 138 | + }; | ||
| 139 | + }]); | ||
| 140 | + | ||
| 141 | + | ||
| 142 | + ngApp.directive('dropdown', [function() { | ||
| 143 | + return { | ||
| 144 | + restrict: 'A', | ||
| 145 | + link: function(scope, element, attrs) { | ||
| 146 | + var menu = element.find('ul'); | ||
| 147 | + element.find('[dropdown-toggle]').on('click', function() { | ||
| 148 | + menu.show().addClass('anim menuIn'); | ||
| 149 | + element.mouseleave(function() { | ||
| 150 | + menu.hide(); | ||
| 151 | + menu.removeClass('anim menuIn'); | ||
| 152 | + }); | ||
| 153 | + }); | ||
| 154 | + } | ||
| 155 | + }; | ||
| 156 | + }]); | ||
| 157 | + | ||
| 158 | + | ||
| 32 | }; | 159 | }; |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -6,9 +6,32 @@ window.ZeroClipboard.config({ | ... | @@ -6,9 +6,32 @@ window.ZeroClipboard.config({ |
| 6 | 6 | ||
| 7 | // AngularJS - Create application and load components | 7 | // AngularJS - Create application and load components |
| 8 | var angular = require('angular'); | 8 | var angular = require('angular'); |
| 9 | -var angularResource = require('angular-resource'); | 9 | +var ngResource = require('angular-resource'); |
| 10 | -var app = angular.module('bookStack', ['ngResource']); | 10 | +var ngAnimate = require('angular-animate'); |
| 11 | -var directives = require('./directives')(app); | 11 | +var ngSanitize = require('angular-sanitize'); |
| 12 | + | ||
| 13 | +var ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize']); | ||
| 14 | +var services = require('./services')(ngApp); | ||
| 15 | +var directives = require('./directives')(ngApp); | ||
| 16 | +var controllers = require('./controllers')(ngApp); | ||
| 17 | + | ||
| 18 | +//Global jQuery Config & Extensions | ||
| 19 | + | ||
| 20 | +// Smooth scrolling | ||
| 21 | +jQuery.fn.smoothScrollTo = function() { | ||
| 22 | + if(this.length === 0) return; | ||
| 23 | + $('body').animate({ | ||
| 24 | + scrollTop: this.offset().top - 60 // Adjust to change final scroll position top margin | ||
| 25 | + }, 800); // Adjust to change animations speed (ms) | ||
| 26 | + return this; | ||
| 27 | +}; | ||
| 28 | + | ||
| 29 | +// Making contains text expression not worry about casing | ||
| 30 | +$.expr[":"].contains = $.expr.createPseudo(function(arg) { | ||
| 31 | + return function( elem ) { | ||
| 32 | + return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0; | ||
| 33 | + }; | ||
| 34 | +}); | ||
| 12 | 35 | ||
| 13 | // Global jQuery Elements | 36 | // Global jQuery Elements |
| 14 | $(function () { | 37 | $(function () { |
| ... | @@ -18,9 +41,6 @@ $(function () { | ... | @@ -18,9 +41,6 @@ $(function () { |
| 18 | $(this).fadeOut(100); | 41 | $(this).fadeOut(100); |
| 19 | }); | 42 | }); |
| 20 | 43 | ||
| 21 | - // Dropdown toggles | ||
| 22 | - $('[data-dropdown]').dropDown(); | ||
| 23 | - | ||
| 24 | // Chapter page list toggles | 44 | // Chapter page list toggles |
| 25 | $('.chapter-toggle').click(function(e) { | 45 | $('.chapter-toggle').click(function(e) { |
| 26 | e.preventDefault(); | 46 | e.preventDefault(); |
| ... | @@ -30,6 +50,11 @@ $(function () { | ... | @@ -30,6 +50,11 @@ $(function () { |
| 30 | 50 | ||
| 31 | }); | 51 | }); |
| 32 | 52 | ||
| 53 | + | ||
| 54 | +function elemExists(selector) { | ||
| 55 | + return document.querySelector(selector) !== null; | ||
| 56 | +} | ||
| 57 | + | ||
| 33 | // TinyMCE editor | 58 | // TinyMCE editor |
| 34 | if(elemExists('#html-editor')) { | 59 | if(elemExists('#html-editor')) { |
| 35 | var tinyMceOptions = require('./pages/page-form'); | 60 | var tinyMceOptions = require('./pages/page-form'); | ... | ... |
| 1 | - | ||
| 2 | -// Smooth scrolling | ||
| 3 | -jQuery.fn.smoothScrollTo = function() { | ||
| 4 | - if(this.length === 0) return; | ||
| 5 | - $('body').animate({ | ||
| 6 | - scrollTop: this.offset().top - 60 // Adjust to change final scroll position top margin | ||
| 7 | - }, 800); // Adjust to change animations speed (ms) | ||
| 8 | - return this; | ||
| 9 | -}; | ||
| 10 | - | ||
| 11 | -// Making contains text expression not worry about casing | ||
| 12 | -$.expr[":"].contains = $.expr.createPseudo(function(arg) { | ||
| 13 | - return function( elem ) { | ||
| 14 | - return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0; | ||
| 15 | - }; | ||
| 16 | -}); | ||
| 17 | - | ||
| 18 | -// Show a success message after the element it's called upon. | ||
| 19 | -jQuery.fn.showSuccess = function (message) { | ||
| 20 | - var elem = $(this); | ||
| 21 | - var success = $('<div class="text-pos" style="display:none;"><i class="zmdi zmdi-check-circle"></i>' + message + '</div>'); | ||
| 22 | - elem.after(success); | ||
| 23 | - success.slideDown(400, function () { | ||
| 24 | - setTimeout(function () { | ||
| 25 | - success.slideUp(400, function () { | ||
| 26 | - success.remove(); | ||
| 27 | - }) | ||
| 28 | - }, 2000); | ||
| 29 | - }); | ||
| 30 | -}; | ||
| 31 | - | ||
| 32 | -// Show a failure messages from laravel. Searches for the name of the inputs. | ||
| 33 | -jQuery.fn.showFailure = function (messageMap) { | ||
| 34 | - var elem = $(this); | ||
| 35 | - $.each(messageMap, function (key, messages) { | ||
| 36 | - var input = elem.find('[name="' + key + '"]').last(); | ||
| 37 | - var fail = $('<div class="text-neg" style="display:none;"><i class="zmdi zmdi-alert-circle"></i>' + messages.join("\n") + '</div>'); | ||
| 38 | - input.after(fail); | ||
| 39 | - fail.slideDown(400, function () { | ||
| 40 | - setTimeout(function () { | ||
| 41 | - fail.slideUp(400, function () { | ||
| 42 | - fail.remove(); | ||
| 43 | - }) | ||
| 44 | - }, 2000); | ||
| 45 | - }); | ||
| 46 | - }); | ||
| 47 | - | ||
| 48 | -}; | ||
| 49 | - | ||
| 50 | -// Submit the form that the called upon element sits in. | ||
| 51 | -jQuery.fn.submitForm = function() { | ||
| 52 | - $(this).closest('form').submit(); | ||
| 53 | -}; | ||
| 54 | - | ||
| 55 | -// Dropdown menu display | ||
| 56 | -jQuery.fn.dropDown = function() { | ||
| 57 | - var container = $(this), | ||
| 58 | - menu = container.find('ul'); | ||
| 59 | - container.find('[data-dropdown-toggle]').on('click', function() { | ||
| 60 | - menu.show().addClass('anim menuIn'); | ||
| 61 | - container.mouseleave(function() { | ||
| 62 | - menu.hide(); | ||
| 63 | - menu.removeClass('anim menuIn'); | ||
| 64 | - }); | ||
| 65 | - }); | ||
| 66 | -}; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | - | ||
| 2 | -module.exports = { | ||
| 3 | - el: '#book-dashboard', | ||
| 4 | - data: { | ||
| 5 | - searching: false, | ||
| 6 | - searchTerm: '', | ||
| 7 | - searchResults: '' | ||
| 8 | - }, | ||
| 9 | - methods: { | ||
| 10 | - searchBook: function (e) { | ||
| 11 | - e.preventDefault(); | ||
| 12 | - var term = this.searchTerm; | ||
| 13 | - if (term.length == 0) return; | ||
| 14 | - this.searching = true; | ||
| 15 | - this.searchResults = ''; | ||
| 16 | - var searchUrl = this.$els.form.getAttribute('action'); | ||
| 17 | - searchUrl += '?term=' + encodeURIComponent(term); | ||
| 18 | - this.$http.get(searchUrl, function (data) { | ||
| 19 | - this.$set('searchResults', data); | ||
| 20 | - }); | ||
| 21 | - }, | ||
| 22 | - checkSearchForm: function (e) { | ||
| 23 | - if (this.searchTerm.length < 1) { | ||
| 24 | - this.searching = false; | ||
| 25 | - } | ||
| 26 | - }, | ||
| 27 | - clearSearch: function(e) { | ||
| 28 | - this.searching = false; | ||
| 29 | - this.searchTerm = ''; | ||
| 30 | - } | ||
| 31 | - } | ||
| 32 | -}; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -98,7 +98,7 @@ module.exports = { | ... | @@ -98,7 +98,7 @@ module.exports = { |
| 98 | icon: 'image', | 98 | icon: 'image', |
| 99 | tooltip: 'Insert an image', | 99 | tooltip: 'Insert an image', |
| 100 | onclick: function() { | 100 | onclick: function() { |
| 101 | - ImageManager.show(function(image) { | 101 | + window.ImageManager.showExternal(function(image) { |
| 102 | var html = '<a href="'+image.url+'" target="_blank">'; | 102 | var html = '<a href="'+image.url+'" target="_blank">'; |
| 103 | html += '<img src="'+image.thumbs.display+'" alt="'+image.name+'">'; | 103 | html += '<img src="'+image.thumbs.display+'" alt="'+image.name+'">'; |
| 104 | html += '</a>'; | 104 | html += '</a>'; |
| ... | @@ -106,6 +106,7 @@ module.exports = { | ... | @@ -106,6 +106,7 @@ module.exports = { |
| 106 | }); | 106 | }); |
| 107 | } | 107 | } |
| 108 | }); | 108 | }); |
| 109 | + | ||
| 109 | // Paste image-uploads | 110 | // Paste image-uploads |
| 110 | editor.on('paste', function(e) { | 111 | editor.on('paste', function(e) { |
| 111 | if(e.clipboardData) { | 112 | if(e.clipboardData) { | ... | ... |
resources/assets/js/services.js
0 → 100644
| ... | @@ -18,6 +18,10 @@ | ... | @@ -18,6 +18,10 @@ |
| 18 | 18 | ||
| 19 | [v-cloak], [v-show] {display: none;} | 19 | [v-cloak], [v-show] {display: none;} |
| 20 | 20 | ||
| 21 | +[ng\:cloak], [ng-cloak], .ng-cloak { | ||
| 22 | + display: none !important; | ||
| 23 | +} | ||
| 24 | + | ||
| 21 | // Jquery Sortable Styles | 25 | // Jquery Sortable Styles |
| 22 | .dragged { | 26 | .dragged { |
| 23 | position: absolute; | 27 | position: absolute; | ... | ... |
| ... | @@ -52,8 +52,8 @@ | ... | @@ -52,8 +52,8 @@ |
| 52 | @endif | 52 | @endif |
| 53 | </div> | 53 | </div> |
| 54 | @if($signedIn) | 54 | @if($signedIn) |
| 55 | - <div class="dropdown-container" data-dropdown> | 55 | + <div class="dropdown-container" dropdown> |
| 56 | - <span class="user-name" data-dropdown-toggle> | 56 | + <span class="user-name" dropdown-toggle> |
| 57 | <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}"> | 57 | <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}"> |
| 58 | <span class="name">{{ $currentUser->name }}</span> <i class="zmdi zmdi-caret-down"></i> | 58 | <span class="name">{{ $currentUser->name }}</span> <i class="zmdi zmdi-caret-down"></i> |
| 59 | </span> | 59 | </span> | ... | ... |
| ... | @@ -27,15 +27,15 @@ | ... | @@ -27,15 +27,15 @@ |
| 27 | </div> | 27 | </div> |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | - <div class="container" id="book-dashboard"> | 30 | + <div class="container" id="book-dashboard" ng-controller="BookShowController" book-id="{{ $book->id }}"> |
| 31 | <div class="row"> | 31 | <div class="row"> |
| 32 | <div class="col-md-7"> | 32 | <div class="col-md-7"> |
| 33 | 33 | ||
| 34 | <h1>{{$book->name}}</h1> | 34 | <h1>{{$book->name}}</h1> |
| 35 | - <div class="book-content anim fadeIn" v-show="!searching"> | 35 | + <div class="book-content" ng-show="!searching"> |
| 36 | - <p class="text-muted">{{$book->description}}</p> | 36 | + <p class="text-muted" ng-non-bindable>{{$book->description}}</p> |
| 37 | 37 | ||
| 38 | - <div class="page-list"> | 38 | + <div class="page-list" ng-non-bindable> |
| 39 | <hr> | 39 | <hr> |
| 40 | @if(count($bookChildren) > 0) | 40 | @if(count($bookChildren) > 0) |
| 41 | @foreach($bookChildren as $childElement) | 41 | @foreach($bookChildren as $childElement) |
| ... | @@ -62,12 +62,12 @@ | ... | @@ -62,12 +62,12 @@ |
| 62 | </p> | 62 | </p> |
| 63 | </div> | 63 | </div> |
| 64 | </div> | 64 | </div> |
| 65 | - <div class="search-results" v-show="searching"> | 65 | + <div class="search-results" ng-cloak ng-show="searching"> |
| 66 | - <h3 class="text-muted">Search Results <a v-if="searching" @click="clearSearch" class="text-small"><i class="zmdi zmdi-close"></i>Clear Search</a></h3> | 66 | + <h3 class="text-muted">Search Results <a ng-if="searching" ng-click="clearSearch()" class="text-small"><i class="zmdi zmdi-close"></i>Clear Search</a></h3> |
| 67 | - <div v-if="!searchResults"> | 67 | + <div ng-if="!searchResults"> |
| 68 | @include('partials/loading-icon') | 68 | @include('partials/loading-icon') |
| 69 | </div> | 69 | </div> |
| 70 | - <div v-html="searchResults"></div> | 70 | + <div ng-bind-html="searchResults"></div> |
| 71 | </div> | 71 | </div> |
| 72 | 72 | ||
| 73 | 73 | ||
| ... | @@ -76,11 +76,10 @@ | ... | @@ -76,11 +76,10 @@ |
| 76 | <div class="col-md-4 col-md-offset-1"> | 76 | <div class="col-md-4 col-md-offset-1"> |
| 77 | <div class="margin-top large"></div> | 77 | <div class="margin-top large"></div> |
| 78 | <div class="search-box"> | 78 | <div class="search-box"> |
| 79 | - <form @submit="searchBook" @input="checkSearchForm" v-el:form action="/search/book/{{ $book->id }}"> | 79 | + <form ng-submit="searchBook($event)"> |
| 80 | - {!! csrf_field() !!} | 80 | + <input ng-model="searchTerm" ng-change="checkSearchForm()" type="text" name="term" placeholder="Search This Book"> |
| 81 | - <input v-model="searchTerm" type="text" name="term" placeholder="Search This Book"> | ||
| 82 | <button type="submit"><i class="zmdi zmdi-search"></i></button> | 81 | <button type="submit"><i class="zmdi zmdi-search"></i></button> |
| 83 | - <button v-if="searching" @click="clearSearch" type="button"><i class="zmdi zmdi-close"></i></button> | 82 | + <button ng-if="searching" ng-click="clearSearch()" type="button"><i class="zmdi zmdi-close"></i></button> |
| 84 | </form> | 83 | </form> |
| 85 | </div> | 84 | </div> |
| 86 | <div class="activity anim fadeIn"> | 85 | <div class="activity anim fadeIn"> | ... | ... |
| ... | @@ -16,5 +16,5 @@ | ... | @@ -16,5 +16,5 @@ |
| 16 | @endif | 16 | @endif |
| 17 | </form> | 17 | </form> |
| 18 | </div> | 18 | </div> |
| 19 | - <image-manager image-type="gallery"></image-manager> | 19 | + @include('partials/image-manager', ['imageType' => 'gallery']) |
| 20 | @stop | 20 | @stop |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -14,6 +14,6 @@ | ... | @@ -14,6 +14,6 @@ |
| 14 | @include('pages/form', ['model' => $page]) | 14 | @include('pages/form', ['model' => $page]) |
| 15 | </form> | 15 | </form> |
| 16 | </div> | 16 | </div> |
| 17 | - <image-manager image-type="gallery"></image-manager> | 17 | + @include('partials/image-manager', ['imageType' => 'gallery']) |
| 18 | 18 | ||
| 19 | @stop | 19 | @stop |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | +<div id="image-manager" image-type="{{ $imageType }}" ng-controller="ImageManagerController"> | ||
| 2 | + <div class="overlay anim-slide" ng-show="showing" ng-cloak ng-click="hide()"> | ||
| 3 | + <div class="image-manager-body" ng-click="$event.stopPropagation()"> | ||
| 4 | + | ||
| 5 | + <div class="image-manager-content"> | ||
| 6 | + <div class="image-manager-list"> | ||
| 7 | + <div ng-repeat="image in images"> | ||
| 8 | + <img class="anim fadeIn" | ||
| 9 | + ng-class="{selected: (image==selectedImage)}" | ||
| 10 | + ng-src="@{{image.thumbs.gallery}}" ng-attr-alt="@{{image.title}}" ng-attr-title="@{{image.name}}" | ||
| 11 | + ng-click="imageSelect(image)" | ||
| 12 | + ng-style="{animationDelay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'}"> | ||
| 13 | + </div> | ||
| 14 | + <div class="load-more" ng-show="hasMore" ng-click="fetchData()">Load More</div> | ||
| 15 | + </div> | ||
| 16 | + </div> | ||
| 17 | + | ||
| 18 | + <button class="neg button image-manager-close" ng-click="hide()">x</button> | ||
| 19 | + | ||
| 20 | + <div class="image-manager-sidebar"> | ||
| 21 | + <h2>Images</h2> | ||
| 22 | + <hr class="even"> | ||
| 23 | + <drop-zone upload-url="@{{getUploadUrl()}}" event-success="uploadSuccess"></drop-zone> | ||
| 24 | + <div class="image-manager-details anim fadeIn" ng-show="selectedImage"> | ||
| 25 | + | ||
| 26 | + <hr class="even"> | ||
| 27 | + | ||
| 28 | + <form ng-submit="saveImageDetails($event)"> | ||
| 29 | + <div class="form-group"> | ||
| 30 | + <label for="name">Image Name</label> | ||
| 31 | + <input type="text" id="name" name="name" ng-model="selectedImage.name"> | ||
| 32 | + <p class="text-pos text-small" ng-show="imageUpdateSuccess"><i class="fa fa-check"></i> Image name updated</p> | ||
| 33 | + <p class="text-neg text-small" ng-show="imageUpdateFailure"><i class="fa fa-times"></i> <span ng-bind="imageUpdateFailure"></span></p> | ||
| 34 | + </div> | ||
| 35 | + </form> | ||
| 36 | + | ||
| 37 | + <hr class="even"> | ||
| 38 | + | ||
| 39 | + <div ng-show="dependantPages"> | ||
| 40 | + <p class="text-neg text-small"> | ||
| 41 | + This image is used in the pages below, Click delete again to confirm you want to delete | ||
| 42 | + this image. | ||
| 43 | + </p> | ||
| 44 | + <ul class="text-neg"> | ||
| 45 | + <li ng-repeat="page in dependantPages"> | ||
| 46 | + <a ng-href="@{{ page.url }}" target="_blank" class="text-neg" ng-bind="page.name"></a> | ||
| 47 | + </li> | ||
| 48 | + </ul> | ||
| 49 | + </div> | ||
| 50 | + | ||
| 51 | + <form ng-submit="deleteImage($event)"> | ||
| 52 | + <button class="button neg"><i class="zmdi zmdi-delete"></i>Delete Image</button> | ||
| 53 | + </form> | ||
| 54 | + </div> | ||
| 55 | + | ||
| 56 | + <p class="text-pos" ng-show="imageDeleteSuccess"><i class="fa fa-check"></i> Image deleted</p> | ||
| 57 | + | ||
| 58 | + <div class="image-manager-bottom"> | ||
| 59 | + <button class="button pos anim fadeIn" ng-show="selectedImage" ng-click="selectButtonClick()"> | ||
| 60 | + <i class="zmdi zmdi-square-right"></i>Select Image | ||
| 61 | + </button> | ||
| 62 | + </div> | ||
| 63 | + | ||
| 64 | + </div> | ||
| 65 | + </div> | ||
| 66 | + </div> | ||
| 67 | +</div> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -33,7 +33,7 @@ | ... | @@ -33,7 +33,7 @@ |
| 33 | <div class="form-group" id="logo-control"> | 33 | <div class="form-group" id="logo-control"> |
| 34 | <label for="setting-app-logo">Application Logo</label> | 34 | <label for="setting-app-logo">Application Logo</label> |
| 35 | <p class="small">This image should be 43px in height. <br>Large images will be scaled down.</p> | 35 | <p class="small">This image should be 43px in height. <br>Large images will be scaled down.</p> |
| 36 | - <image-picker resize-height="43" resize-width="200" current-image="{{ Setting::get('app-logo', '') }}" default-image="/logo.png" name="setting-app-logo" image-class="logo-image"></image-picker> | 36 | + <image-picker resize-height="43" show-remove="true" resize-width="200" current-image="{{ Setting::get('app-logo', '') }}" default-image="/logo.png" name="setting-app-logo" image-class="logo-image"></image-picker> |
| 37 | </div> | 37 | </div> |
| 38 | </div> | 38 | </div> |
| 39 | </div> | 39 | </div> |
| ... | @@ -86,6 +86,6 @@ | ... | @@ -86,6 +86,6 @@ |
| 86 | 86 | ||
| 87 | </div> | 87 | </div> |
| 88 | 88 | ||
| 89 | -<image-manager image-type="system"></image-manager> | 89 | +@include('partials/image-manager', ['imageType' => 'system']) |
| 90 | 90 | ||
| 91 | @stop | 91 | @stop | ... | ... |
| ... | @@ -33,7 +33,7 @@ | ... | @@ -33,7 +33,7 @@ |
| 33 | <div class="form-group" id="logo-control"> | 33 | <div class="form-group" id="logo-control"> |
| 34 | <label for="user-avatar">User Avatar</label> | 34 | <label for="user-avatar">User Avatar</label> |
| 35 | <p class="small">This image should be approx 256px square.</p> | 35 | <p class="small">This image should be approx 256px square.</p> |
| 36 | - <image-picker resize-height="512" resize-width="512" current-image="{{ $user->getAvatar(80) }}" current-id="{{ $user->image_id }}" default-image="/user_avatar.png" name="image_id" show-remove="false" image-class="avatar large"></image-picker> | 36 | + <image-picker resize-height="512" resize-width="512" current-image="{{ $user->getAvatar(80) }}" current-id="{{ $user->image_id }}" default-image="/user_avatar.png" name="image_id" show-remove="false" image-class="['avatar' ,'large']"></image-picker> |
| 37 | </div> | 37 | </div> |
| 38 | </div> | 38 | </div> |
| 39 | </div> | 39 | </div> |
| ... | @@ -79,5 +79,5 @@ | ... | @@ -79,5 +79,5 @@ |
| 79 | </div> | 79 | </div> |
| 80 | 80 | ||
| 81 | <p class="margin-top large"><br></p> | 81 | <p class="margin-top large"><br></p> |
| 82 | - <image-manager image-type="user"></image-manager> | 82 | + @include('partials/image-manager', ['imageType' => 'user']) |
| 83 | @stop | 83 | @stop | ... | ... |
-
Please register or sign in to post a comment