]> BookStack Code Mirror - bookstack/commitdiff
Merge branch 'page_link_selector'
authorDan Brown <redacted>
Sat, 3 Sep 2016 09:40:27 +0000 (10:40 +0100)
committerDan Brown <redacted>
Sat, 3 Sep 2016 09:40:27 +0000 (10:40 +0100)
15 files changed:
resources/assets/js/controllers.js
resources/assets/js/directives.js
resources/assets/js/global.js
resources/assets/js/pages/page-form.js
resources/assets/sass/_buttons.scss
resources/assets/sass/_components.scss [moved from resources/assets/sass/_image-manager.scss with 86% similarity]
resources/assets/sass/_grid.scss
resources/assets/sass/styles.scss
resources/views/books/list-item.blade.php
resources/views/chapters/list-item.blade.php
resources/views/pages/edit.blade.php
resources/views/pages/form.blade.php
resources/views/pages/list-item.blade.php
resources/views/partials/entity-selector-popup.blade.php [new file with mode: 0644]
resources/views/partials/image-manager.blade.php

index 28a45e59193737786e6fe12c83a600876c7902d2..fcaba2914b8557bac98a33fe5c5ce5c32bb37355 100644 (file)
@@ -69,7 +69,7 @@ module.exports = function (ngApp, events) {
              */
             function callbackAndHide(returnData) {
                 if (callback) callback(returnData);
-                $scope.showing = false;
+                $scope.hide();
             }
 
             /**
@@ -109,6 +109,7 @@ module.exports = function (ngApp, events) {
             function show(doneCallback) {
                 callback = doneCallback;
                 $scope.showing = true;
+                $('#image-manager').find('.overlay').css('display', 'flex').hide().fadeIn(240);
                 // Get initial images if they have not yet been loaded in.
                 if (!dataLoaded) {
                     fetchData();
@@ -131,6 +132,7 @@ module.exports = function (ngApp, events) {
              */
             $scope.hide = function () {
                 $scope.showing = false;
+                $('#image-manager').find('.overlay').fadeOut(240);
             };
 
             var baseUrl = window.baseUrl('/images/' + $scope.imageType + '/all/');
index 286854832d75a2730a85c49b94976596ad4e7e7f..1271b31123dc937ddfc07c220367b204799dc7fc 100644 (file)
@@ -271,8 +271,6 @@ module.exports = function (ngApp, events) {
                 scope.mdModel = content;
                 scope.mdChange(markdown(content));
 
-                console.log('test');
-
                 element.on('change input', (event) => {
                     content = element.val();
                     $timeout(() => {
@@ -304,6 +302,7 @@ module.exports = function (ngApp, events) {
                 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"]')
 
                 let currentCaretPos = 0;
 
@@ -355,6 +354,13 @@ module.exports = function (ngApp, events) {
                         input[0].selectionEnd = caretPos + ('![](http://'.length);
                         return;
                     }
+
+                    // Insert entity link shortcut
+                    if (event.which === 75 && event.ctrlKey && event.shiftKey) {
+                        showLinkSelector();
+                        return;
+                    }
+
                     // Pass key presses to controller via event
                     scope.$emit('editor-keydown', event);
                 });
@@ -370,6 +376,26 @@ module.exports = function (ngApp, events) {
                     });
                 });
 
+                function showLinkSelector() {
+                    window.showEntityLinkSelector((entity) => {
+                        let selectionStart = currentCaretPos;
+                        let selectionEnd = input[0].selectionEnd;
+                        let textSelected = (selectionEnd !== selectionStart);
+                        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));
+                        } else {
+                            let linkText = ` [${entity.name}](${entity.link}) `;
+                            input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionStart))
+                        }
+                        input.change();
+                    });
+                }
+                insertEntityLink.click(showLinkSelector);
+
                 // Upload and insert image on paste
                 function editorPaste(e) {
                     e = e.originalEvent;
@@ -677,6 +703,58 @@ module.exports = function (ngApp, events) {
         }
     }]);
 
+    ngApp.directive('entityLinkSelector', [function($http) {
+        return {
+            restict: 'A',
+            link: function(scope, element, attrs) {
+
+                const selectButton = element.find('.entity-link-selector-confirm');
+                let callback = false;
+                let entitySelection = null;
+
+                // Handle entity selection change, Stores the selected entity locally
+                function entitySelectionChange(entity) {
+                    entitySelection = entity;
+                    if (entity === null) {
+                        selectButton.attr('disabled', 'true');
+                    } else {
+                        selectButton.removeAttr('disabled');
+                    }
+                }
+                events.listen('entity-select-change', entitySelectionChange);
+
+                // Handle selection confirm button click
+                selectButton.click(event => {
+                    hide();
+                    if (entitySelection !== null) callback(entitySelection);
+                });
+
+                // Show selector interface
+                function show() {
+                    element.fadeIn(240);
+                }
+
+                // Hide selector interface
+                function hide() {
+                    element.fadeOut(240);
+                }
+
+                // Listen to confirmation of entity selections (doubleclick)
+                events.listen('entity-select-confirm', entity => {
+                    hide();
+                    callback(entity);
+                });
+
+                // Show entity selector, Accessible globally, and store the callback
+                window.showEntityLinkSelector = function(passedCallback) {
+                    show();
+                    callback = passedCallback;
+                };
+
+            }
+        };
+    }]);
+
 
     ngApp.directive('entitySelector', ['$http', '$sce', function ($http, $sce) {
         return {
@@ -690,26 +768,60 @@ module.exports = function (ngApp, events) {
                 // Add input for forms
                 const input = element.find('[entity-selector-input]').first();
 
+                // Detect double click events
+                var lastClick = 0;
+                function isDoubleClick() {
+                    let now = Date.now();
+                    let answer = now - lastClick < 300;
+                    lastClick = now;
+                    return answer;
+                }
+
                 // Listen to entity item clicks
                 element.on('click', '.entity-list a', function(event) {
                     event.preventDefault();
                     event.stopPropagation();
                     let item = $(this).closest('[data-entity-type]');
-                    itemSelect(item);
+                    itemSelect(item, isDoubleClick());
                 });
                 element.on('click', '[data-entity-type]', function(event) {
-                    itemSelect($(this));
+                    itemSelect($(this), isDoubleClick());
                 });
 
                 // Select entity action
-                function itemSelect(item) {
+                function itemSelect(item, doubleClick) {
                     let entityType = item.attr('data-entity-type');
                     let entityId = item.attr('data-entity-id');
-                    let isSelected = !item.hasClass('selected');
+                    let isSelected = !item.hasClass('selected') || doubleClick;
                     element.find('.selected').removeClass('selected').removeClass('primary-background');
                     if (isSelected) item.addClass('selected').addClass('primary-background');
                     let newVal = isSelected ? `${entityType}:${entityId}` : '';
                     input.val(newVal);
+
+                    if (!isSelected) {
+                        events.emit('entity-select-change', null);
+                    }
+
+                    if (!doubleClick && !isSelected) return;
+
+                    let link = item.find('.entity-list-item-link').attr('href');
+                    let name = item.find('.entity-list-item-name').text();
+
+                    if (doubleClick) {
+                        events.emit('entity-select-confirm', {
+                            id: Number(entityId),
+                            name: name,
+                            link: link
+                        });
+                    }
+
+                    if (isSelected) {
+                        events.emit('entity-select-change', {
+                            id: Number(entityId),
+                            name: name,
+                            link: link
+                        });
+                    }
                 }
 
                 // Get search url with correct types
index 3a107afa8d29584fdf397fadee2fefac1d95135c..9ca335ee7c4546f39b902b807d69c60ab4eff366 100644 (file)
@@ -18,7 +18,7 @@ window.baseUrl = function(path) {
 var ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']);
 
 // Global Event System
-class Events {
+class EventManager {
     constructor() {
         this.listeners = {};
     }
@@ -39,12 +39,12 @@ class Events {
         return this;
     }
 };
-window.Events = new Events();
+window.Events = new EventManager();
 
 
-var services = require('./services')(ngApp, Events);
-var directives = require('./directives')(ngApp, Events);
-var controllers = require('./controllers')(ngApp, Events);
+var services = require('./services')(ngApp, window.Events);
+var directives = require('./directives')(ngApp, window.Events);
+var controllers = require('./controllers')(ngApp, window.Events);
 
 //Global jQuery Config & Extensions
 
@@ -130,6 +130,27 @@ $(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'));
+    });
+
+    // Detect IE for css
+    if(navigator.userAgent.indexOf('MSIE')!==-1
+        || navigator.appVersion.indexOf('Trident/') > 0
+        || navigator.userAgent.indexOf('Safari') !== -1){
+        $('body').addClass('flexbox-support');
+    }
 
 });
 
index 15fcdbb8e6cacb5479d97eb58da35b61b94a9648..daf9639d7d83948602e919229fc0c3da566acd5b 100644 (file)
@@ -95,20 +95,38 @@ var mceOptions = 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) {
-        window.ImageManager.showExternal(function (image) {
-            win.document.getElementById(field_name).value = image.url;
-            if ("createEvent" in document) {
-                var evt = document.createEvent("HTMLEvents");
-                evt.initEvent("change", false, true);
-                win.document.getElementById(field_name).dispatchEvent(evt);
-            } else {
-                win.document.getElementById(field_name).fireEvent("onchange");
-            }
-            var html = '<a href="' + image.url + '" target="_blank">';
-            html += '<img src="' + image.thumbs.display + '" alt="' + image.name + '">';
-            html += '</a>';
-            win.tinyMCE.activeEditor.execCommand('mceInsertContent', false, html);
-        });
+
+        if (type === 'file') {
+            window.showEntityLinkSelector(function(entity) {
+                var originalField = win.document.getElementById(field_name);
+                originalField.value = entity.link;
+                $(originalField).closest('.mce-form').find('input').eq(2).val(entity.name);
+            });
+        }
+
+        if (type === 'image') {
+            // Show image manager
+            window.ImageManager.showExternal(function (image) {
+
+                // Set popover link input to image url then fire change event
+                // to ensure the new value sticks
+                win.document.getElementById(field_name).value = image.url;
+                if ("createEvent" in document) {
+                    var evt = document.createEvent("HTMLEvents");
+                    evt.initEvent("change", false, true);
+                    win.document.getElementById(field_name).dispatchEvent(evt);
+                } else {
+                    win.document.getElementById(field_name).fireEvent("onchange");
+                }
+
+                // Replace the actively selected content with the linked image
+                var html = '<a href="' + image.url + '" target="_blank">';
+                html += '<img src="' + image.thumbs.display + '" alt="' + image.name + '">';
+                html += '</a>';
+                win.tinyMCE.activeEditor.execCommand('mceInsertContent', false, html);
+            });
+        }
+
     },
     paste_preprocess: function (plugin, args) {
         var content = args.content;
@@ -119,6 +137,8 @@ var mceOptions = module.exports = {
     extraSetups: [],
     setup: function (editor) {
 
+        // Run additional setup actions
+        // Used by the angular side of things
         for (var i = 0; i < mceOptions.extraSetups.length; i++) {
             mceOptions.extraSetups[i](editor);
         }
index 5bdb0cf2857fd7ef1b9534558ee5202080461662..5de8896735aa9799ef5a4b12cf04b098c0366b42 100644 (file)
@@ -100,3 +100,13 @@ $button-border-radius: 2px;
   }
 }
 
+.button[disabled] {
+  background-color: #BBB;
+  cursor: default;
+  &:hover {
+    background-color: #BBB;
+    cursor: default;
+    box-shadow: none;
+  }
+}
+
similarity index 86%
rename from resources/assets/sass/_image-manager.scss
rename to resources/assets/sass/_components.scss
index 73b3b59d6c13649fb27b081941b5ebe3f77f31c9..ccb69b44e3f91ddef14344a8290678b504cb51d3 100644 (file)
@@ -1,5 +1,5 @@
 .overlay {
-  background-color: rgba(0, 0, 0, 0.2);
+  background-color: rgba(0, 0, 0, 0.333);
   position: fixed;
   z-index: 95536;
   width: 100%;
   left: 0;
   right: 0;
   bottom: 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  display: none;
 }
 
-.image-manager-body {
+.popup-body-wrap {
+  display: flex;
+}
+
+.popup-body {
   background-color: #FFF;
   max-height: 90%;
-  width: 90%;
-  height: 90%;
+  width: 1200px;
+  height: auto;
   margin: 2% 5%;
   border-radius: 4px;
   box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.3);
   overflow: hidden;
-  position: fixed;
-  top: 0;
-  bottom: 0;
-  left: 0;
   z-index: 999;
   display: flex;
-  h1, h2, h3 {
-    font-weight: 300;
+  flex-direction: column;
+  &.small {
+    margin: 2% auto;
+    width: 800px;
+    max-width: 90%;
+  }
+  &:before {
+    display: flex;
+    align-self: flex-start;
   }
 }
 
-#image-manager .dropzone-container {
-  position: relative;
-  border: 3px dashed #DDD;
-}
+//body.ie .popup-body {
+//  min-height: 100%;
+//}
 
-.image-manager-bottom {
+.corner-button {
   position: absolute;
-  bottom: 0;
+  top: 0;
   right: 0;
+  margin: 0;
+  height: 40px;
+  border-radius: 0;
+  box-shadow: none;
+}
+
+.popup-header, .popup-footer {
+  display: block !important;
+  position: relative;
+  height: 40px;
+  flex: none !important;
+  .popup-title {
+    color: #FFF;
+    padding: 8px $-m;
+  }
+}
+body.flexbox-support #entity-selector-wrap .popup-body .form-group {
+  height: 444px;
+  min-height: 444px;
+}
+#entity-selector-wrap .popup-body .form-group {
+  margin: 0;
+}
+//body.ie #entity-selector-wrap .popup-body .form-group {
+//  min-height: 60vh;
+//}
+
+.image-manager-body {
+  min-height: 70vh;
+}
+
+#image-manager .dropzone-container {
+  position: relative;
+  border: 3px dashed #DDD;
 }
 
 .image-manager-list .image {
 
 .image-manager-sidebar {
   width: 300px;
-  height: 100%;
   margin-left: 1px;
-  padding: 0 $-l;
+  padding: $-m $-l;
+  overflow-y: auto;
   border-left: 1px solid #DDD;
-}
-
-.image-manager-close {
-  position: absolute;
-  top: 0;
-  right: 0;
-  margin: 0;
-  border-radius: 0;
+  .dropzone-container {
+    margin-top: $-m;
+  }
 }
 
 .image-manager-list {
 .image-manager-content {
   display: flex;
   flex-direction: column;
-  height: 100%;
   flex: 1;
   .container {
     width: 100%;
  * Copyright (c) 2012 Matias Meno <[email protected]>
  */
 .dz-message {
-  font-size: 1.4em;
+  font-size: 1.2em;
+  line-height: 1.1;
   font-style: italic;
   color: #aaa;
   text-align: center;
   cursor: pointer;
-  padding: $-xl $-m;
+  padding: $-l $-m;
   transition: all ease-in-out 120ms;
 }
 
index 1a1321e587335c498a3e8c0f8ab3248d01809d4f..231c12d4d7469d2468058e369bb0e6e5ea50bab5 100644 (file)
@@ -25,6 +25,14 @@ body.flexbox {
   }
 }
 
+.flex-child > div {
+  flex: 1;
+}
+
+//body.ie .flex-child > div {
+//  flex: 1 0 0px;
+//}
+
 /** Rules for all columns */
 div[class^="col-"] img {
   max-width: 100%;
index 21043258877c92564b912505f475dd8cfc74edaf..7d33bd0a640e87be1abeec580ee95f5beae3e3a8 100644 (file)
@@ -12,7 +12,7 @@
 @import "animations";
 @import "tinymce";
 @import "highlightjs";
-@import "image-manager";
+@import "components";
 @import "header";
 @import "lists";
 @import "pages";
index 945eb901563c1a9b64a8e02afe79ba4cf5278a30..2eefdfbf531c0a9917cc2606a344e32402863ffd 100644 (file)
@@ -1,5 +1,5 @@
 <div class="book entity-list-item"  data-entity-type="book" data-entity-id="{{$book->id}}">
-    <h3 class="text-book"><a class="text-book" href="{{$book->getUrl()}}"><i class="zmdi zmdi-book"></i>{{$book->name}}</a></h3>
+    <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>
     @if(isset($book->searchSnippet))
         <p class="text-muted">{!! $book->searchSnippet !!}</p>
     @else
index 3677851df77dc712b0faa200de480e0b757c0cf2..35d3a7589d927b313e8e8488c8ff2490cc82a289 100644 (file)
@@ -6,8 +6,8 @@
             </a>
             <span class="text-muted">&nbsp;&nbsp;&raquo;&nbsp;&nbsp;</span>
         @endif
-        <a href="{{ $chapter->getUrl() }}" class="text-chapter">
-            <i class="zmdi zmdi-collection-bookmark"></i>{{ $chapter->name }}
+        <a href="{{ $chapter->getUrl() }}" class="text-chapter entity-list-item-link">
+            <i class="zmdi zmdi-collection-bookmark"></i><span class="entity-list-item-name">{{ $chapter->name }}</span>
         </a>
     </h3>
     @if(isset($chapter->searchSnippet))
index 9fe6a6a1902f6b7ccbfa7a0ba8043e04d384b1f9..58df580a5fb80f22232a9f8634bd25d4663dba88 100644 (file)
 
 
     </div>
+    
     @include('partials/image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id])
+    @include('partials/entity-selector-popup')
+
+    <script>
+        (function() {
+
+        })();
+    </script>
 
 @stop
\ No newline at end of file
index 5aee9c596f2ef1bd8b0e58b1187f000b426d51e6..0e0c3672e9df6f25c8518a4258a97cec22319b00 100644 (file)
@@ -74,6 +74,8 @@
                         <span class="float left">Editor</span>
                         <div class="float right buttons">
                             <button class="text-button" type="button" data-action="insertImage"><i class="zmdi zmdi-image"></i>Insert Image</button>
+                            &nbsp;|&nbsp;
+                            <button class="text-button" type="button" data-action="insertEntityLink"><i class="zmdi zmdi-link"></i>Insert Entity Link</button>
                         </div>
                     </div>
 
index a95870db044725453b3404daf20d94e6796b08ea..98243f6fa88ba63a2d09c20af659917025348186 100644 (file)
@@ -1,6 +1,6 @@
 <div class="page {{$page->draft ? 'draft' : ''}} entity-list-item" data-entity-type="page" data-entity-id="{{$page->id}}">
     <h3>
-        <a href="{{ $page->getUrl() }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ $page->name }}</a>
+        <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>
     </h3>
 
     @if(isset($page->searchSnippet))
diff --git a/resources/views/partials/entity-selector-popup.blade.php b/resources/views/partials/entity-selector-popup.blade.php
new file mode 100644 (file)
index 0000000..b916689
--- /dev/null
@@ -0,0 +1,14 @@
+<div id="entity-selector-wrap">
+    <div class="overlay" entity-link-selector>
+        <div class="popup-body small flex-child">
+            <div class="popup-header primary-background">
+                <div class="popup-title">Entity Select</div>
+                <button type="button" class="corner-button neg button popup-close">x</button>
+            </div>
+            @include('partials/entity-selector', ['name' => 'entity-selector'])
+            <div class="popup-footer">
+                <button type="button" disabled="true" class="button entity-link-selector-confirm pos corner-button">Select</button>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
index 69928e119d926b92fc43c68e804ff48c925449d0..83625ad88d0ec665d68092e5062cb55d15e42b72 100644 (file)
@@ -1,84 +1,94 @@
 <div id="image-manager" image-type="{{ $imageType }}" ng-controller="ImageManagerController" uploaded-to="{{ $uploaded_to or 0 }}">
-    <div class="overlay anim-slide" ng-show="showing" ng-cloak ng-click="hide()">
-        <div class="image-manager-body" ng-click="$event.stopPropagation()">
-
-            <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="View all images" ng-class="{selected: (view=='all')}" ng-click="setView('all')"><i class="zmdi zmdi-collection-image"></i> All</div>
-                        <div class="col-xs-4 tab-item" title="View images uploaded to this book" ng-class="{selected: (view=='book')}" ng-click="setView('book')"><i class="zmdi zmdi-book text-book"></i> Book</div>
-                        <div class="col-xs-4 tab-item" title="View images uploaded to this page" ng-class="{selected: (view=='page')}" ng-click="setView('page')"><i class="zmdi zmdi-file-text text-page"></i> Page</div>
+    <div class="overlay" ng-cloak ng-click="hide()">
+        <div class="popup-body" ng-click="$event.stopPropagation()">
+
+            <div class="popup-header primary-background">
+                <div class="popup-title">Image Select</div>
+                <button class="popup-close neg corner-button button">x</button>
+            </div>
+
+            <div class="flex-fill image-manager-body">
+
+                <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="View all images" ng-class="{selected: (view=='all')}" ng-click="setView('all')"><i class="zmdi zmdi-collection-image"></i> All</div>
+                            <div class="col-xs-4 tab-item" title="View images uploaded to this book" ng-class="{selected: (view=='book')}" ng-click="setView('book')"><i class="zmdi zmdi-book text-book"></i> Book</div>
+                            <div class="col-xs-4 tab-item" title="View images uploaded to this page" ng-class="{selected: (view=='page')}" ng-click="setView('page')"><i class="zmdi zmdi-file-text text-page"></i> Page</div>
+                        </div>
                     </div>
-                </div>
-                <div ng-show="view === 'all'" >
-                    <form ng-submit="searchImages()" class="contained-search-box">
-                        <input type="text" placeholder="Search by image name" ng-model="searchTerm">
-                        <button ng-class="{active: searching}" title="Clear Search" type="button" ng-click="cancelSearch()" class="text-button cancel"><i class="zmdi zmdi-close-circle-o"></i></button>
-                        <button title="Search" class="text-button" type="submit"><i class="zmdi zmdi-search"></i></button>
-                    </form>
-                </div>
-                <div class="image-manager-list">
-                    <div ng-repeat="image in images">
-                        <div class="image anim fadeIn" ng-style="{animationDelay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'}"
-                             ng-class="{selected: (image==selectedImage)}" ng-click="imageSelect(image)">
-                            <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">Uploaded @{{ getDate(image.created_at) | date:'mediumDate' }}</span>
+                    <div ng-show="view === 'all'" >
+                        <form ng-submit="searchImages()" class="contained-search-box">
+                            <input type="text" placeholder="Search by image name" ng-model="searchTerm">
+                            <button ng-class="{active: searching}" title="Clear Search" type="button" ng-click="cancelSearch()" class="text-button cancel"><i class="zmdi zmdi-close-circle-o"></i></button>
+                            <button title="Search" class="text-button" type="submit"><i class="zmdi zmdi-search"></i></button>
+                        </form>
+                    </div>
+                    <div class="image-manager-list">
+                        <div ng-repeat="image in images">
+                            <div class="image anim fadeIn" ng-style="{animationDelay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'}"
+                                 ng-class="{selected: (image==selectedImage)}" ng-click="imageSelect(image)">
+                                <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">Uploaded @{{ getDate(image.created_at)  }}</span>
+                                </div>
                             </div>
                         </div>
+                        <div class="load-more" ng-show="hasMore" ng-click="fetchData()">Load More</div>
                     </div>
-                    <div class="load-more" ng-show="hasMore" ng-click="fetchData()">Load More</div>
                 </div>
-            </div>
 
-            <button class="neg button image-manager-close" ng-click="hide()">x</button>
+                <div class="image-manager-sidebar">
+                    <div class="inner">
 
-            <div class="image-manager-sidebar">
-                <h2>Images</h2>
-                <drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
-                <div class="image-manager-details anim fadeIn" ng-show="selectedImage">
+                        <div class="image-manager-details anim fadeIn" ng-show="selectedImage">
 
-                    <hr class="even">
+                            <form ng-submit="saveImageDetails($event)">
+                                <div>
+                                    <a ng-href="@{{selectedImage.url}}" target="_blank" style="display: block;">
+                                        <img ng-src="@{{selectedImage.thumbs.gallery}}" ng-attr-alt="@{{selectedImage.title}}" ng-attr-title="@{{selectedImage.name}}">
+                                    </a>
+                                </div>
+                                <div class="form-group">
+                                    <label for="name">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">
+                                    This image is used in the pages below, Click delete again to confirm you want to delete
+                                    this image.
+                                </p>
+                                <ul class="text-neg">
+                                    <li ng-repeat="page in dependantPages">
+                                        <a ng-href="@{{ page.url }}" target="_blank" class="text-neg" ng-bind="page.name"></a>
+                                    </li>
+                                </ul>
+                            </div>
+
+                            <div class="clearfix">
+                                <form class="float left" ng-submit="deleteImage($event)">
+                                    <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>Select Image
+                                </button>
+                            </div>
 
-                    <form ng-submit="saveImageDetails($event)">
-                        <div>
-                            <a ng-href="@{{selectedImage.url}}" target="_blank" style="display: block;">
-                                <img ng-src="@{{selectedImage.thumbs.gallery}}" ng-attr-alt="@{{selectedImage.title}}" ng-attr-title="@{{selectedImage.name}}">
-                            </a>
-                        </div>
-                        <div class="form-group">
-                            <label for="name">Image Name</label>
-                            <input type="text" id="name" name="name" ng-model="selectedImage.name">
                         </div>
-                    </form>
-
-                    <hr class="even">
-
-                    <div ng-show="dependantPages">
-                        <p class="text-neg text-small">
-                            This image is used in the pages below, Click delete again to confirm you want to delete
-                            this image.
-                        </p>
-                        <ul class="text-neg">
-                            <li ng-repeat="page in dependantPages">
-                                <a ng-href="@{{ page.url }}" target="_blank" class="text-neg" ng-bind="page.name"></a>
-                            </li>
-                        </ul>
-                    </div>
 
-                    <form ng-submit="deleteImage($event)">
-                        <button class="button neg"><i class="zmdi zmdi-delete"></i>Delete Image</button>
-                    </form>
-                </div>
+                        <drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
 
-                <div class="image-manager-bottom">
-                    <button class="button pos anim fadeIn" ng-show="selectedImage" ng-click="selectButtonClick()">
-                        <i class="zmdi zmdi-square-right"></i>Select Image
-                    </button>
+
+                    </div>
                 </div>
 
+
+
             </div>
+
         </div>
     </div>
 </div>
\ No newline at end of file