Showing
15 changed files
with
309 additions
and
63 deletions
| ... | @@ -69,7 +69,7 @@ module.exports = function (ngApp, events) { | ... | @@ -69,7 +69,7 @@ module.exports = function (ngApp, events) { |
| 69 | */ | 69 | */ |
| 70 | function callbackAndHide(returnData) { | 70 | function callbackAndHide(returnData) { |
| 71 | if (callback) callback(returnData); | 71 | if (callback) callback(returnData); |
| 72 | - $scope.showing = false; | 72 | + $scope.hide(); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | /** | 75 | /** |
| ... | @@ -109,6 +109,7 @@ module.exports = function (ngApp, events) { | ... | @@ -109,6 +109,7 @@ module.exports = function (ngApp, events) { |
| 109 | function show(doneCallback) { | 109 | function show(doneCallback) { |
| 110 | callback = doneCallback; | 110 | callback = doneCallback; |
| 111 | $scope.showing = true; | 111 | $scope.showing = true; |
| 112 | + $('#image-manager').find('.overlay').css('display', 'flex').hide().fadeIn(240); | ||
| 112 | // Get initial images if they have not yet been loaded in. | 113 | // Get initial images if they have not yet been loaded in. |
| 113 | if (!dataLoaded) { | 114 | if (!dataLoaded) { |
| 114 | fetchData(); | 115 | fetchData(); |
| ... | @@ -131,6 +132,7 @@ module.exports = function (ngApp, events) { | ... | @@ -131,6 +132,7 @@ module.exports = function (ngApp, events) { |
| 131 | */ | 132 | */ |
| 132 | $scope.hide = function () { | 133 | $scope.hide = function () { |
| 133 | $scope.showing = false; | 134 | $scope.showing = false; |
| 135 | + $('#image-manager').find('.overlay').fadeOut(240); | ||
| 134 | }; | 136 | }; |
| 135 | 137 | ||
| 136 | var baseUrl = window.baseUrl('/images/' + $scope.imageType + '/all/'); | 138 | var baseUrl = window.baseUrl('/images/' + $scope.imageType + '/all/'); | ... | ... |
| ... | @@ -271,8 +271,6 @@ module.exports = function (ngApp, events) { | ... | @@ -271,8 +271,6 @@ module.exports = function (ngApp, events) { |
| 271 | scope.mdModel = content; | 271 | scope.mdModel = content; |
| 272 | scope.mdChange(markdown(content)); | 272 | scope.mdChange(markdown(content)); |
| 273 | 273 | ||
| 274 | - console.log('test'); | ||
| 275 | - | ||
| 276 | element.on('change input', (event) => { | 274 | element.on('change input', (event) => { |
| 277 | content = element.val(); | 275 | content = element.val(); |
| 278 | $timeout(() => { | 276 | $timeout(() => { |
| ... | @@ -304,6 +302,7 @@ module.exports = function (ngApp, events) { | ... | @@ -304,6 +302,7 @@ module.exports = function (ngApp, events) { |
| 304 | const input = element.find('[markdown-input] textarea').first(); | 302 | const input = element.find('[markdown-input] textarea').first(); |
| 305 | const display = element.find('.markdown-display').first(); | 303 | const display = element.find('.markdown-display').first(); |
| 306 | const insertImage = element.find('button[data-action="insertImage"]'); | 304 | const insertImage = element.find('button[data-action="insertImage"]'); |
| 305 | + const insertEntityLink = element.find('button[data-action="insertEntityLink"]') | ||
| 307 | 306 | ||
| 308 | let currentCaretPos = 0; | 307 | let currentCaretPos = 0; |
| 309 | 308 | ||
| ... | @@ -355,6 +354,13 @@ module.exports = function (ngApp, events) { | ... | @@ -355,6 +354,13 @@ module.exports = function (ngApp, events) { |
| 355 | input[0].selectionEnd = caretPos + ('; | 354 | input[0].selectionEnd = caretPos + ('; |
| 356 | return; | 355 | return; |
| 357 | } | 356 | } |
| 357 | + | ||
| 358 | + // Insert entity link shortcut | ||
| 359 | + if (event.which === 75 && event.ctrlKey && event.shiftKey) { | ||
| 360 | + showLinkSelector(); | ||
| 361 | + return; | ||
| 362 | + } | ||
| 363 | + | ||
| 358 | // Pass key presses to controller via event | 364 | // Pass key presses to controller via event |
| 359 | scope.$emit('editor-keydown', event); | 365 | scope.$emit('editor-keydown', event); |
| 360 | }); | 366 | }); |
| ... | @@ -370,6 +376,26 @@ module.exports = function (ngApp, events) { | ... | @@ -370,6 +376,26 @@ module.exports = function (ngApp, events) { |
| 370 | }); | 376 | }); |
| 371 | }); | 377 | }); |
| 372 | 378 | ||
| 379 | + function showLinkSelector() { | ||
| 380 | + window.showEntityLinkSelector((entity) => { | ||
| 381 | + let selectionStart = currentCaretPos; | ||
| 382 | + let selectionEnd = input[0].selectionEnd; | ||
| 383 | + let textSelected = (selectionEnd !== selectionStart); | ||
| 384 | + let currentContent = input.val(); | ||
| 385 | + | ||
| 386 | + if (textSelected) { | ||
| 387 | + let selectedText = currentContent.substring(selectionStart, selectionEnd); | ||
| 388 | + let linkText = `[${selectedText}](${entity.link})`; | ||
| 389 | + input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionEnd)); | ||
| 390 | + } else { | ||
| 391 | + let linkText = ` [${entity.name}](${entity.link}) `; | ||
| 392 | + input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionStart)) | ||
| 393 | + } | ||
| 394 | + input.change(); | ||
| 395 | + }); | ||
| 396 | + } | ||
| 397 | + insertEntityLink.click(showLinkSelector); | ||
| 398 | + | ||
| 373 | // Upload and insert image on paste | 399 | // Upload and insert image on paste |
| 374 | function editorPaste(e) { | 400 | function editorPaste(e) { |
| 375 | e = e.originalEvent; | 401 | e = e.originalEvent; |
| ... | @@ -677,6 +703,58 @@ module.exports = function (ngApp, events) { | ... | @@ -677,6 +703,58 @@ module.exports = function (ngApp, events) { |
| 677 | } | 703 | } |
| 678 | }]); | 704 | }]); |
| 679 | 705 | ||
| 706 | + ngApp.directive('entityLinkSelector', [function($http) { | ||
| 707 | + return { | ||
| 708 | + restict: 'A', | ||
| 709 | + link: function(scope, element, attrs) { | ||
| 710 | + | ||
| 711 | + const selectButton = element.find('.entity-link-selector-confirm'); | ||
| 712 | + let callback = false; | ||
| 713 | + let entitySelection = null; | ||
| 714 | + | ||
| 715 | + // Handle entity selection change, Stores the selected entity locally | ||
| 716 | + function entitySelectionChange(entity) { | ||
| 717 | + entitySelection = entity; | ||
| 718 | + if (entity === null) { | ||
| 719 | + selectButton.attr('disabled', 'true'); | ||
| 720 | + } else { | ||
| 721 | + selectButton.removeAttr('disabled'); | ||
| 722 | + } | ||
| 723 | + } | ||
| 724 | + events.listen('entity-select-change', entitySelectionChange); | ||
| 725 | + | ||
| 726 | + // Handle selection confirm button click | ||
| 727 | + selectButton.click(event => { | ||
| 728 | + hide(); | ||
| 729 | + if (entitySelection !== null) callback(entitySelection); | ||
| 730 | + }); | ||
| 731 | + | ||
| 732 | + // Show selector interface | ||
| 733 | + function show() { | ||
| 734 | + element.fadeIn(240); | ||
| 735 | + } | ||
| 736 | + | ||
| 737 | + // Hide selector interface | ||
| 738 | + function hide() { | ||
| 739 | + element.fadeOut(240); | ||
| 740 | + } | ||
| 741 | + | ||
| 742 | + // Listen to confirmation of entity selections (doubleclick) | ||
| 743 | + events.listen('entity-select-confirm', entity => { | ||
| 744 | + hide(); | ||
| 745 | + callback(entity); | ||
| 746 | + }); | ||
| 747 | + | ||
| 748 | + // Show entity selector, Accessible globally, and store the callback | ||
| 749 | + window.showEntityLinkSelector = function(passedCallback) { | ||
| 750 | + show(); | ||
| 751 | + callback = passedCallback; | ||
| 752 | + }; | ||
| 753 | + | ||
| 754 | + } | ||
| 755 | + }; | ||
| 756 | + }]); | ||
| 757 | + | ||
| 680 | 758 | ||
| 681 | ngApp.directive('entitySelector', ['$http', '$sce', function ($http, $sce) { | 759 | ngApp.directive('entitySelector', ['$http', '$sce', function ($http, $sce) { |
| 682 | return { | 760 | return { |
| ... | @@ -690,26 +768,60 @@ module.exports = function (ngApp, events) { | ... | @@ -690,26 +768,60 @@ module.exports = function (ngApp, events) { |
| 690 | // Add input for forms | 768 | // Add input for forms |
| 691 | const input = element.find('[entity-selector-input]').first(); | 769 | const input = element.find('[entity-selector-input]').first(); |
| 692 | 770 | ||
| 771 | + // Detect double click events | ||
| 772 | + var lastClick = 0; | ||
| 773 | + function isDoubleClick() { | ||
| 774 | + let now = Date.now(); | ||
| 775 | + let answer = now - lastClick < 300; | ||
| 776 | + lastClick = now; | ||
| 777 | + return answer; | ||
| 778 | + } | ||
| 779 | + | ||
| 693 | // Listen to entity item clicks | 780 | // Listen to entity item clicks |
| 694 | element.on('click', '.entity-list a', function(event) { | 781 | element.on('click', '.entity-list a', function(event) { |
| 695 | event.preventDefault(); | 782 | event.preventDefault(); |
| 696 | event.stopPropagation(); | 783 | event.stopPropagation(); |
| 697 | let item = $(this).closest('[data-entity-type]'); | 784 | let item = $(this).closest('[data-entity-type]'); |
| 698 | - itemSelect(item); | 785 | + itemSelect(item, isDoubleClick()); |
| 699 | }); | 786 | }); |
| 700 | element.on('click', '[data-entity-type]', function(event) { | 787 | element.on('click', '[data-entity-type]', function(event) { |
| 701 | - itemSelect($(this)); | 788 | + itemSelect($(this), isDoubleClick()); |
| 702 | }); | 789 | }); |
| 703 | 790 | ||
| 704 | // Select entity action | 791 | // Select entity action |
| 705 | - function itemSelect(item) { | 792 | + function itemSelect(item, doubleClick) { |
| 706 | let entityType = item.attr('data-entity-type'); | 793 | let entityType = item.attr('data-entity-type'); |
| 707 | let entityId = item.attr('data-entity-id'); | 794 | let entityId = item.attr('data-entity-id'); |
| 708 | - let isSelected = !item.hasClass('selected'); | 795 | + let isSelected = !item.hasClass('selected') || doubleClick; |
| 709 | element.find('.selected').removeClass('selected').removeClass('primary-background'); | 796 | element.find('.selected').removeClass('selected').removeClass('primary-background'); |
| 710 | if (isSelected) item.addClass('selected').addClass('primary-background'); | 797 | if (isSelected) item.addClass('selected').addClass('primary-background'); |
| 711 | let newVal = isSelected ? `${entityType}:${entityId}` : ''; | 798 | let newVal = isSelected ? `${entityType}:${entityId}` : ''; |
| 712 | input.val(newVal); | 799 | input.val(newVal); |
| 800 | + | ||
| 801 | + if (!isSelected) { | ||
| 802 | + events.emit('entity-select-change', null); | ||
| 803 | + } | ||
| 804 | + | ||
| 805 | + if (!doubleClick && !isSelected) return; | ||
| 806 | + | ||
| 807 | + let link = item.find('.entity-list-item-link').attr('href'); | ||
| 808 | + let name = item.find('.entity-list-item-name').text(); | ||
| 809 | + | ||
| 810 | + if (doubleClick) { | ||
| 811 | + events.emit('entity-select-confirm', { | ||
| 812 | + id: Number(entityId), | ||
| 813 | + name: name, | ||
| 814 | + link: link | ||
| 815 | + }); | ||
| 816 | + } | ||
| 817 | + | ||
| 818 | + if (isSelected) { | ||
| 819 | + events.emit('entity-select-change', { | ||
| 820 | + id: Number(entityId), | ||
| 821 | + name: name, | ||
| 822 | + link: link | ||
| 823 | + }); | ||
| 824 | + } | ||
| 713 | } | 825 | } |
| 714 | 826 | ||
| 715 | // Get search url with correct types | 827 | // Get search url with correct types | ... | ... |
| ... | @@ -18,7 +18,7 @@ window.baseUrl = function(path) { | ... | @@ -18,7 +18,7 @@ window.baseUrl = function(path) { |
| 18 | var ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']); | 18 | var ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']); |
| 19 | 19 | ||
| 20 | // Global Event System | 20 | // Global Event System |
| 21 | -class Events { | 21 | +class EventManager { |
| 22 | constructor() { | 22 | constructor() { |
| 23 | this.listeners = {}; | 23 | this.listeners = {}; |
| 24 | } | 24 | } |
| ... | @@ -39,12 +39,12 @@ class Events { | ... | @@ -39,12 +39,12 @@ class Events { |
| 39 | return this; | 39 | return this; |
| 40 | } | 40 | } |
| 41 | }; | 41 | }; |
| 42 | -window.Events = new Events(); | 42 | +window.Events = new EventManager(); |
| 43 | 43 | ||
| 44 | 44 | ||
| 45 | -var services = require('./services')(ngApp, Events); | 45 | +var services = require('./services')(ngApp, window.Events); |
| 46 | -var directives = require('./directives')(ngApp, Events); | 46 | +var directives = require('./directives')(ngApp, window.Events); |
| 47 | -var controllers = require('./controllers')(ngApp, Events); | 47 | +var controllers = require('./controllers')(ngApp, window.Events); |
| 48 | 48 | ||
| 49 | //Global jQuery Config & Extensions | 49 | //Global jQuery Config & Extensions |
| 50 | 50 | ||
| ... | @@ -130,6 +130,27 @@ $(function () { | ... | @@ -130,6 +130,27 @@ $(function () { |
| 130 | $('.entity-list.compact').find('p').not('.empty-text').slideToggle(240); | 130 | $('.entity-list.compact').find('p').not('.empty-text').slideToggle(240); |
| 131 | }); | 131 | }); |
| 132 | 132 | ||
| 133 | + // Popup close | ||
| 134 | + $('.popup-close').click(function() { | ||
| 135 | + $(this).closest('.overlay').fadeOut(240); | ||
| 136 | + }); | ||
| 137 | + $('.overlay').click(function(event) { | ||
| 138 | + if (!$(event.target).hasClass('overlay')) return; | ||
| 139 | + $(this).fadeOut(240); | ||
| 140 | + }); | ||
| 141 | + | ||
| 142 | + // Prevent markdown display link click redirect | ||
| 143 | + $('.markdown-display').on('click', 'a', function(event) { | ||
| 144 | + event.preventDefault(); | ||
| 145 | + window.open($(this).attr('href')); | ||
| 146 | + }); | ||
| 147 | + | ||
| 148 | + // Detect IE for css | ||
| 149 | + if(navigator.userAgent.indexOf('MSIE')!==-1 | ||
| 150 | + || navigator.appVersion.indexOf('Trident/') > 0 | ||
| 151 | + || navigator.userAgent.indexOf('Safari') !== -1){ | ||
| 152 | + $('body').addClass('flexbox-support'); | ||
| 153 | + } | ||
| 133 | 154 | ||
| 134 | }); | 155 | }); |
| 135 | 156 | ... | ... |
| ... | @@ -95,7 +95,21 @@ var mceOptions = module.exports = { | ... | @@ -95,7 +95,21 @@ var mceOptions = module.exports = { |
| 95 | alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-right'}, | 95 | alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-right'}, |
| 96 | }, | 96 | }, |
| 97 | file_browser_callback: function (field_name, url, type, win) { | 97 | file_browser_callback: function (field_name, url, type, win) { |
| 98 | + | ||
| 99 | + if (type === 'file') { | ||
| 100 | + window.showEntityLinkSelector(function(entity) { | ||
| 101 | + var originalField = win.document.getElementById(field_name); | ||
| 102 | + originalField.value = entity.link; | ||
| 103 | + $(originalField).closest('.mce-form').find('input').eq(2).val(entity.name); | ||
| 104 | + }); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + if (type === 'image') { | ||
| 108 | + // Show image manager | ||
| 98 | window.ImageManager.showExternal(function (image) { | 109 | window.ImageManager.showExternal(function (image) { |
| 110 | + | ||
| 111 | + // Set popover link input to image url then fire change event | ||
| 112 | + // to ensure the new value sticks | ||
| 99 | win.document.getElementById(field_name).value = image.url; | 113 | win.document.getElementById(field_name).value = image.url; |
| 100 | if ("createEvent" in document) { | 114 | if ("createEvent" in document) { |
| 101 | var evt = document.createEvent("HTMLEvents"); | 115 | var evt = document.createEvent("HTMLEvents"); |
| ... | @@ -104,11 +118,15 @@ var mceOptions = module.exports = { | ... | @@ -104,11 +118,15 @@ var mceOptions = module.exports = { |
| 104 | } else { | 118 | } else { |
| 105 | win.document.getElementById(field_name).fireEvent("onchange"); | 119 | win.document.getElementById(field_name).fireEvent("onchange"); |
| 106 | } | 120 | } |
| 121 | + | ||
| 122 | + // Replace the actively selected content with the linked image | ||
| 107 | var html = '<a href="' + image.url + '" target="_blank">'; | 123 | var html = '<a href="' + image.url + '" target="_blank">'; |
| 108 | html += '<img src="' + image.thumbs.display + '" alt="' + image.name + '">'; | 124 | html += '<img src="' + image.thumbs.display + '" alt="' + image.name + '">'; |
| 109 | html += '</a>'; | 125 | html += '</a>'; |
| 110 | win.tinyMCE.activeEditor.execCommand('mceInsertContent', false, html); | 126 | win.tinyMCE.activeEditor.execCommand('mceInsertContent', false, html); |
| 111 | }); | 127 | }); |
| 128 | + } | ||
| 129 | + | ||
| 112 | }, | 130 | }, |
| 113 | paste_preprocess: function (plugin, args) { | 131 | paste_preprocess: function (plugin, args) { |
| 114 | var content = args.content; | 132 | var content = args.content; |
| ... | @@ -119,6 +137,8 @@ var mceOptions = module.exports = { | ... | @@ -119,6 +137,8 @@ var mceOptions = module.exports = { |
| 119 | extraSetups: [], | 137 | extraSetups: [], |
| 120 | setup: function (editor) { | 138 | setup: function (editor) { |
| 121 | 139 | ||
| 140 | + // Run additional setup actions | ||
| 141 | + // Used by the angular side of things | ||
| 122 | for (var i = 0; i < mceOptions.extraSetups.length; i++) { | 142 | for (var i = 0; i < mceOptions.extraSetups.length; i++) { |
| 123 | mceOptions.extraSetups[i](editor); | 143 | mceOptions.extraSetups[i](editor); |
| 124 | } | 144 | } | ... | ... |
| ... | @@ -100,3 +100,13 @@ $button-border-radius: 2px; | ... | @@ -100,3 +100,13 @@ $button-border-radius: 2px; |
| 100 | } | 100 | } |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | +.button[disabled] { | ||
| 104 | + background-color: #BBB; | ||
| 105 | + cursor: default; | ||
| 106 | + &:hover { | ||
| 107 | + background-color: #BBB; | ||
| 108 | + cursor: default; | ||
| 109 | + box-shadow: none; | ||
| 110 | + } | ||
| 111 | +} | ||
| 112 | + | ... | ... |
| 1 | .overlay { | 1 | .overlay { |
| 2 | - background-color: rgba(0, 0, 0, 0.2); | 2 | + background-color: rgba(0, 0, 0, 0.333); |
| 3 | position: fixed; | 3 | position: fixed; |
| 4 | z-index: 95536; | 4 | z-index: 95536; |
| 5 | width: 100%; | 5 | width: 100%; |
| ... | @@ -10,37 +10,81 @@ | ... | @@ -10,37 +10,81 @@ |
| 10 | left: 0; | 10 | left: 0; |
| 11 | right: 0; | 11 | right: 0; |
| 12 | bottom: 0; | 12 | bottom: 0; |
| 13 | + display: flex; | ||
| 14 | + align-items: center; | ||
| 15 | + justify-content: center; | ||
| 16 | + display: none; | ||
| 13 | } | 17 | } |
| 14 | 18 | ||
| 15 | -.image-manager-body { | 19 | +.popup-body-wrap { |
| 20 | + display: flex; | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +.popup-body { | ||
| 16 | background-color: #FFF; | 24 | background-color: #FFF; |
| 17 | max-height: 90%; | 25 | max-height: 90%; |
| 18 | - width: 90%; | 26 | + width: 1200px; |
| 19 | - height: 90%; | 27 | + height: auto; |
| 20 | margin: 2% 5%; | 28 | margin: 2% 5%; |
| 21 | border-radius: 4px; | 29 | border-radius: 4px; |
| 22 | box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.3); | 30 | box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.3); |
| 23 | overflow: hidden; | 31 | overflow: hidden; |
| 24 | - position: fixed; | ||
| 25 | - top: 0; | ||
| 26 | - bottom: 0; | ||
| 27 | - left: 0; | ||
| 28 | z-index: 999; | 32 | z-index: 999; |
| 29 | display: flex; | 33 | display: flex; |
| 30 | - h1, h2, h3 { | 34 | + flex-direction: column; |
| 31 | - font-weight: 300; | 35 | + &.small { |
| 36 | + margin: 2% auto; | ||
| 37 | + width: 800px; | ||
| 38 | + max-width: 90%; | ||
| 39 | + } | ||
| 40 | + &:before { | ||
| 41 | + display: flex; | ||
| 42 | + align-self: flex-start; | ||
| 32 | } | 43 | } |
| 33 | } | 44 | } |
| 34 | 45 | ||
| 35 | -#image-manager .dropzone-container { | 46 | +//body.ie .popup-body { |
| 36 | - position: relative; | 47 | +// min-height: 100%; |
| 37 | - border: 3px dashed #DDD; | 48 | +//} |
| 38 | -} | ||
| 39 | 49 | ||
| 40 | -.image-manager-bottom { | 50 | +.corner-button { |
| 41 | position: absolute; | 51 | position: absolute; |
| 42 | - bottom: 0; | 52 | + top: 0; |
| 43 | right: 0; | 53 | right: 0; |
| 54 | + margin: 0; | ||
| 55 | + height: 40px; | ||
| 56 | + border-radius: 0; | ||
| 57 | + box-shadow: none; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +.popup-header, .popup-footer { | ||
| 61 | + display: block !important; | ||
| 62 | + position: relative; | ||
| 63 | + height: 40px; | ||
| 64 | + flex: none !important; | ||
| 65 | + .popup-title { | ||
| 66 | + color: #FFF; | ||
| 67 | + padding: 8px $-m; | ||
| 68 | + } | ||
| 69 | +} | ||
| 70 | +body.flexbox-support #entity-selector-wrap .popup-body .form-group { | ||
| 71 | + height: 444px; | ||
| 72 | + min-height: 444px; | ||
| 73 | +} | ||
| 74 | +#entity-selector-wrap .popup-body .form-group { | ||
| 75 | + margin: 0; | ||
| 76 | +} | ||
| 77 | +//body.ie #entity-selector-wrap .popup-body .form-group { | ||
| 78 | +// min-height: 60vh; | ||
| 79 | +//} | ||
| 80 | + | ||
| 81 | +.image-manager-body { | ||
| 82 | + min-height: 70vh; | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +#image-manager .dropzone-container { | ||
| 86 | + position: relative; | ||
| 87 | + border: 3px dashed #DDD; | ||
| 44 | } | 88 | } |
| 45 | 89 | ||
| 46 | .image-manager-list .image { | 90 | .image-manager-list .image { |
| ... | @@ -103,18 +147,13 @@ | ... | @@ -103,18 +147,13 @@ |
| 103 | 147 | ||
| 104 | .image-manager-sidebar { | 148 | .image-manager-sidebar { |
| 105 | width: 300px; | 149 | width: 300px; |
| 106 | - height: 100%; | ||
| 107 | margin-left: 1px; | 150 | margin-left: 1px; |
| 108 | - padding: 0 $-l; | 151 | + padding: $-m $-l; |
| 152 | + overflow-y: auto; | ||
| 109 | border-left: 1px solid #DDD; | 153 | border-left: 1px solid #DDD; |
| 110 | -} | 154 | + .dropzone-container { |
| 111 | - | 155 | + margin-top: $-m; |
| 112 | -.image-manager-close { | 156 | + } |
| 113 | - position: absolute; | ||
| 114 | - top: 0; | ||
| 115 | - right: 0; | ||
| 116 | - margin: 0; | ||
| 117 | - border-radius: 0; | ||
| 118 | } | 157 | } |
| 119 | 158 | ||
| 120 | .image-manager-list { | 159 | .image-manager-list { |
| ... | @@ -125,7 +164,6 @@ | ... | @@ -125,7 +164,6 @@ |
| 125 | .image-manager-content { | 164 | .image-manager-content { |
| 126 | display: flex; | 165 | display: flex; |
| 127 | flex-direction: column; | 166 | flex-direction: column; |
| 128 | - height: 100%; | ||
| 129 | flex: 1; | 167 | flex: 1; |
| 130 | .container { | 168 | .container { |
| 131 | width: 100%; | 169 | width: 100%; |
| ... | @@ -141,12 +179,13 @@ | ... | @@ -141,12 +179,13 @@ |
| 141 | * Copyright (c) 2012 Matias Meno <m@tias.me> | 179 | * Copyright (c) 2012 Matias Meno <m@tias.me> |
| 142 | */ | 180 | */ |
| 143 | .dz-message { | 181 | .dz-message { |
| 144 | - font-size: 1.4em; | 182 | + font-size: 1.2em; |
| 183 | + line-height: 1.1; | ||
| 145 | font-style: italic; | 184 | font-style: italic; |
| 146 | color: #aaa; | 185 | color: #aaa; |
| 147 | text-align: center; | 186 | text-align: center; |
| 148 | cursor: pointer; | 187 | cursor: pointer; |
| 149 | - padding: $-xl $-m; | 188 | + padding: $-l $-m; |
| 150 | transition: all ease-in-out 120ms; | 189 | transition: all ease-in-out 120ms; |
| 151 | } | 190 | } |
| 152 | 191 | ... | ... |
| ... | @@ -25,6 +25,14 @@ body.flexbox { | ... | @@ -25,6 +25,14 @@ body.flexbox { |
| 25 | } | 25 | } |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | +.flex-child > div { | ||
| 29 | + flex: 1; | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +//body.ie .flex-child > div { | ||
| 33 | +// flex: 1 0 0px; | ||
| 34 | +//} | ||
| 35 | + | ||
| 28 | /** Rules for all columns */ | 36 | /** Rules for all columns */ |
| 29 | div[class^="col-"] img { | 37 | div[class^="col-"] img { |
| 30 | max-width: 100%; | 38 | max-width: 100%; | ... | ... |
| ... | @@ -12,7 +12,7 @@ | ... | @@ -12,7 +12,7 @@ |
| 12 | @import "animations"; | 12 | @import "animations"; |
| 13 | @import "tinymce"; | 13 | @import "tinymce"; |
| 14 | @import "highlightjs"; | 14 | @import "highlightjs"; |
| 15 | -@import "image-manager"; | 15 | +@import "components"; |
| 16 | @import "header"; | 16 | @import "header"; |
| 17 | @import "lists"; | 17 | @import "lists"; |
| 18 | @import "pages"; | 18 | @import "pages"; | ... | ... |
| 1 | <div class="book entity-list-item" data-entity-type="book" data-entity-id="{{$book->id}}"> | 1 | <div class="book entity-list-item" data-entity-type="book" data-entity-id="{{$book->id}}"> |
| 2 | - <h3 class="text-book"><a class="text-book" href="{{$book->getUrl()}}"><i class="zmdi zmdi-book"></i>{{$book->name}}</a></h3> | 2 | + <h3 class="text-book"><a class="text-book entity-list-item-link" href="{{$book->getUrl()}}"><i class="zmdi zmdi-book"></i><span class="entity-list-item-name">{{$book->name}}</span></a></h3> |
| 3 | @if(isset($book->searchSnippet)) | 3 | @if(isset($book->searchSnippet)) |
| 4 | <p class="text-muted">{!! $book->searchSnippet !!}</p> | 4 | <p class="text-muted">{!! $book->searchSnippet !!}</p> |
| 5 | @else | 5 | @else | ... | ... |
| ... | @@ -6,8 +6,8 @@ | ... | @@ -6,8 +6,8 @@ |
| 6 | </a> | 6 | </a> |
| 7 | <span class="text-muted"> » </span> | 7 | <span class="text-muted"> » </span> |
| 8 | @endif | 8 | @endif |
| 9 | - <a href="{{ $chapter->getUrl() }}" class="text-chapter"> | 9 | + <a href="{{ $chapter->getUrl() }}" class="text-chapter entity-list-item-link"> |
| 10 | - <i class="zmdi zmdi-collection-bookmark"></i>{{ $chapter->name }} | 10 | + <i class="zmdi zmdi-collection-bookmark"></i><span class="entity-list-item-name">{{ $chapter->name }}</span> |
| 11 | </a> | 11 | </a> |
| 12 | </h3> | 12 | </h3> |
| 13 | @if(isset($chapter->searchSnippet)) | 13 | @if(isset($chapter->searchSnippet)) | ... | ... |
| ... | @@ -19,6 +19,14 @@ | ... | @@ -19,6 +19,14 @@ |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | </div> | 21 | </div> |
| 22 | + | ||
| 22 | @include('partials/image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id]) | 23 | @include('partials/image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id]) |
| 24 | + @include('partials/entity-selector-popup') | ||
| 25 | + | ||
| 26 | + <script> | ||
| 27 | + (function() { | ||
| 28 | + | ||
| 29 | + })(); | ||
| 30 | + </script> | ||
| 23 | 31 | ||
| 24 | @stop | 32 | @stop |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -74,6 +74,8 @@ | ... | @@ -74,6 +74,8 @@ |
| 74 | <span class="float left">Editor</span> | 74 | <span class="float left">Editor</span> |
| 75 | <div class="float right buttons"> | 75 | <div class="float right buttons"> |
| 76 | <button class="text-button" type="button" data-action="insertImage"><i class="zmdi zmdi-image"></i>Insert Image</button> | 76 | <button class="text-button" type="button" data-action="insertImage"><i class="zmdi zmdi-image"></i>Insert Image</button> |
| 77 | + | | ||
| 78 | + <button class="text-button" type="button" data-action="insertEntityLink"><i class="zmdi zmdi-link"></i>Insert Entity Link</button> | ||
| 77 | </div> | 79 | </div> |
| 78 | </div> | 80 | </div> |
| 79 | 81 | ... | ... |
| 1 | <div class="page {{$page->draft ? 'draft' : ''}} entity-list-item" data-entity-type="page" data-entity-id="{{$page->id}}"> | 1 | <div class="page {{$page->draft ? 'draft' : ''}} entity-list-item" data-entity-type="page" data-entity-id="{{$page->id}}"> |
| 2 | <h3> | 2 | <h3> |
| 3 | - <a href="{{ $page->getUrl() }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ $page->name }}</a> | 3 | + <a href="{{ $page->getUrl() }}" class="text-page entity-list-item-link"><i class="zmdi zmdi-file-text"></i><span class="entity-list-item-name">{{ $page->name }}</span></a> |
| 4 | </h3> | 4 | </h3> |
| 5 | 5 | ||
| 6 | @if(isset($page->searchSnippet)) | 6 | @if(isset($page->searchSnippet)) | ... | ... |
| 1 | +<div id="entity-selector-wrap"> | ||
| 2 | + <div class="overlay" entity-link-selector> | ||
| 3 | + <div class="popup-body small flex-child"> | ||
| 4 | + <div class="popup-header primary-background"> | ||
| 5 | + <div class="popup-title">Entity Select</div> | ||
| 6 | + <button type="button" class="corner-button neg button popup-close">x</button> | ||
| 7 | + </div> | ||
| 8 | + @include('partials/entity-selector', ['name' => 'entity-selector']) | ||
| 9 | + <div class="popup-footer"> | ||
| 10 | + <button type="button" disabled="true" class="button entity-link-selector-confirm pos corner-button">Select</button> | ||
| 11 | + </div> | ||
| 12 | + </div> | ||
| 13 | + </div> | ||
| 14 | +</div> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <div id="image-manager" image-type="{{ $imageType }}" ng-controller="ImageManagerController" uploaded-to="{{ $uploaded_to or 0 }}"> | 1 | <div id="image-manager" image-type="{{ $imageType }}" ng-controller="ImageManagerController" uploaded-to="{{ $uploaded_to or 0 }}"> |
| 2 | - <div class="overlay anim-slide" ng-show="showing" ng-cloak ng-click="hide()"> | 2 | + <div class="overlay" ng-cloak ng-click="hide()"> |
| 3 | - <div class="image-manager-body" ng-click="$event.stopPropagation()"> | 3 | + <div class="popup-body" ng-click="$event.stopPropagation()"> |
| 4 | + | ||
| 5 | + <div class="popup-header primary-background"> | ||
| 6 | + <div class="popup-title">Image Select</div> | ||
| 7 | + <button class="popup-close neg corner-button button">x</button> | ||
| 8 | + </div> | ||
| 9 | + | ||
| 10 | + <div class="flex-fill image-manager-body"> | ||
| 4 | 11 | ||
| 5 | <div class="image-manager-content"> | 12 | <div class="image-manager-content"> |
| 6 | <div ng-if="imageType === 'gallery'" class="container"> | 13 | <div ng-if="imageType === 'gallery'" class="container"> |
| ... | @@ -24,7 +31,7 @@ | ... | @@ -24,7 +31,7 @@ |
| 24 | <img ng-src="@{{image.thumbs.gallery}}" ng-attr-alt="@{{image.title}}" ng-attr-title="@{{image.name}}"> | 31 | <img ng-src="@{{image.thumbs.gallery}}" ng-attr-alt="@{{image.title}}" ng-attr-title="@{{image.name}}"> |
| 25 | <div class="image-meta"> | 32 | <div class="image-meta"> |
| 26 | <span class="name" ng-bind="image.name"></span> | 33 | <span class="name" ng-bind="image.name"></span> |
| 27 | - <span class="date">Uploaded @{{ getDate(image.created_at) | date:'mediumDate' }}</span> | 34 | + <span class="date">Uploaded @{{ getDate(image.created_at) }}</span> |
| 28 | </div> | 35 | </div> |
| 29 | </div> | 36 | </div> |
| 30 | </div> | 37 | </div> |
| ... | @@ -32,14 +39,10 @@ | ... | @@ -32,14 +39,10 @@ |
| 32 | </div> | 39 | </div> |
| 33 | </div> | 40 | </div> |
| 34 | 41 | ||
| 35 | - <button class="neg button image-manager-close" ng-click="hide()">x</button> | ||
| 36 | - | ||
| 37 | <div class="image-manager-sidebar"> | 42 | <div class="image-manager-sidebar"> |
| 38 | - <h2>Images</h2> | 43 | + <div class="inner"> |
| 39 | - <drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone> | ||
| 40 | - <div class="image-manager-details anim fadeIn" ng-show="selectedImage"> | ||
| 41 | 44 | ||
| 42 | - <hr class="even"> | 45 | + <div class="image-manager-details anim fadeIn" ng-show="selectedImage"> |
| 43 | 46 | ||
| 44 | <form ng-submit="saveImageDetails($event)"> | 47 | <form ng-submit="saveImageDetails($event)"> |
| 45 | <div> | 48 | <div> |
| ... | @@ -53,8 +56,6 @@ | ... | @@ -53,8 +56,6 @@ |
| 53 | </div> | 56 | </div> |
| 54 | </form> | 57 | </form> |
| 55 | 58 | ||
| 56 | - <hr class="even"> | ||
| 57 | - | ||
| 58 | <div ng-show="dependantPages"> | 59 | <div ng-show="dependantPages"> |
| 59 | <p class="text-neg text-small"> | 60 | <p class="text-neg text-small"> |
| 60 | This image is used in the pages below, Click delete again to confirm you want to delete | 61 | This image is used in the pages below, Click delete again to confirm you want to delete |
| ... | @@ -67,18 +68,27 @@ | ... | @@ -67,18 +68,27 @@ |
| 67 | </ul> | 68 | </ul> |
| 68 | </div> | 69 | </div> |
| 69 | 70 | ||
| 70 | - <form ng-submit="deleteImage($event)"> | 71 | + <div class="clearfix"> |
| 71 | - <button class="button neg"><i class="zmdi zmdi-delete"></i>Delete Image</button> | 72 | + <form class="float left" ng-submit="deleteImage($event)"> |
| 73 | + <button class="button icon neg"><i class="zmdi zmdi-delete"></i></button> | ||
| 72 | </form> | 74 | </form> |
| 73 | - </div> | 75 | + <button class="button pos anim fadeIn float right" ng-show="selectedImage" ng-click="selectButtonClick()"> |
| 74 | - | ||
| 75 | - <div class="image-manager-bottom"> | ||
| 76 | - <button class="button pos anim fadeIn" ng-show="selectedImage" ng-click="selectButtonClick()"> | ||
| 77 | <i class="zmdi zmdi-square-right"></i>Select Image | 76 | <i class="zmdi zmdi-square-right"></i>Select Image |
| 78 | </button> | 77 | </button> |
| 79 | </div> | 78 | </div> |
| 80 | 79 | ||
| 81 | </div> | 80 | </div> |
| 81 | + | ||
| 82 | + <drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone> | ||
| 83 | + | ||
| 84 | + | ||
| 85 | + </div> | ||
| 86 | + </div> | ||
| 87 | + | ||
| 88 | + | ||
| 89 | + | ||
| 90 | + </div> | ||
| 91 | + | ||
| 82 | </div> | 92 | </div> |
| 83 | </div> | 93 | </div> |
| 84 | </div> | 94 | </div> |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or sign in to post a comment