Dan Brown

Modularised/bundled js and made image-manager a proper component

...@@ -14,12 +14,9 @@ ...@@ -14,12 +14,9 @@
14 "tests" 14 "tests"
15 ], 15 ],
16 "dependencies": { 16 "dependencies": {
17 - "dropzone": "~4.0.1",
18 "tinymce-dist": "~4.2.1", 17 "tinymce-dist": "~4.2.1",
19 "bootstrap": "~3.3.5", 18 "bootstrap": "~3.3.5",
20 "jquery-sortable": "~0.9.13", 19 "jquery-sortable": "~0.9.13",
21 - "material-design-iconic-font": "~2.1.1", 20 + "material-design-iconic-font": "~2.1.1"
22 - "vue": "~0.12.10",
23 - "vue-resource": "~0.1.15"
24 } 21 }
25 } 22 }
......
1 var elixir = require('laravel-elixir'); 1 var elixir = require('laravel-elixir');
2 2
3 +elixir.config.js.browserify.transformers.push({
4 + name: 'vueify',
5 + options: {}
6 +});
3 7
4 elixir(function(mix) { 8 elixir(function(mix) {
5 mix.sass('styles.scss'); 9 mix.sass('styles.scss');
6 - mix.scripts('image-manager.js', 'public/js/image-manager.js'); 10 + mix.browserify(['jquery-extensions.js', 'global.js'], 'public/js/common.js');
7 - mix.browserify(['jquery-extensions.js', 'pages/book-show.js' ,'global.js'], 'public/js/common.js');
8 }); 11 });
......
...@@ -3,11 +3,14 @@ ...@@ -3,11 +3,14 @@
3 "devDependencies": { 3 "devDependencies": {
4 "gulp": "^3.8.8", 4 "gulp": "^3.8.8",
5 "insert-css": "^0.2.0", 5 "insert-css": "^0.2.0",
6 - "laravel-elixir-livereload": "1.1.3" 6 + "laravel-elixir-livereload": "1.1.3",
7 + "vueify": "^1.1.5"
7 }, 8 },
8 "dependencies": { 9 "dependencies": {
9 "bootstrap-sass": "^3.0.0", 10 "bootstrap-sass": "^3.0.0",
11 + "dropzone": "^4.0.1",
10 "laravel-elixir": "^3.3.1", 12 "laravel-elixir": "^3.3.1",
11 - "vue": "^0.12.16" 13 + "vue": "^0.12.16",
14 + "vue-resource": "^0.1.16"
12 } 15 }
13 } 16 }
......
1 - 1 +<template>
2 - 2 + <div id="image-manager">
3 -window.ImageManager = new Vue({ 3 + <div class="overlay" v-el="overlay" v-on="click: overlayClick" >
4 - 4 + <div class="image-manager-body">
5 - el: '#image-manager', 5 + <div class="image-manager-content">
6 - 6 + <div class="image-manager-list">
7 - data: { 7 + <div v-repeat="image: images">
8 + <img class="anim fadeIn"
9 + v-class="selected: (image==selectedImage)"
10 + v-attr="src: image.thumbnail, alt: image.name, title: image.name"
11 + v-on="click: imageClick(image)"
12 + v-style="animation-delay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'">
13 + </div>
14 + <div class="load-more" v-show="hasMore" v-on="click: fetchData">Load More</div>
15 + </div>
16 + </div>
17 + <button class="neg button image-manager-close" v-on="click: hide()">x</button>
18 + <div class="image-manager-sidebar">
19 + <h2 v-el="imageTitle">Images</h2>
20 + <hr class="even">
21 + <div class="dropzone-container" v-el="dropZone">
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 v-on="submit: saveImageDetails" v-el="imageForm">
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 this image.
36 + </p>
37 + <ul class="text-neg">
38 + <li v-repeat="page: dependantPages">
39 + <a v-attr="href: page.url" target="_blank" class="text-neg">@{{ page.name }}</a>
40 + </li>
41 + </ul>
42 + </div>
43 +
44 + <form v-on="submit: deleteImage" v-el="imageDeleteForm">
45 + <button class="button neg"><i class="zmdi zmdi-delete"></i>Delete Image</button>
46 + </form>
47 + </div>
48 + <div class="image-manager-bottom">
49 + <button class="button pos anim fadeIn" v-show="selectedImage" v-on="click:selectButtonClick"><i class="zmdi zmdi-square-right"></i>Select Image</button>
50 + </div>
51 + </div>
52 + </div>
53 + </div>
54 + </div>
55 +</template>
56 +
57 +<script>
58 +
59 + var Dropzone = require('dropzone');
60 +
61 + module.exports = {
62 + data: function(){
63 + return {
8 images: [], 64 images: [],
9 hasMore: false, 65 hasMore: false,
10 page: 0, 66 page: 0,
11 cClickTime: 0, 67 cClickTime: 0,
12 selectedImage: false, 68 selectedImage: false,
13 dependantPages: false, 69 dependantPages: false,
14 - deleteForm: {} 70 + deleteForm: {},
71 + token: document.querySelector('meta[name=token]').getAttribute('content')
72 + }
15 }, 73 },
16 74
17 created: function () { 75 created: function () {
18 // Get initial images 76 // Get initial images
19 this.fetchData(this.page); 77 this.fetchData(this.page);
78 + window.ImageManager = this;
20 }, 79 },
21 80
22 ready: function () { 81 ready: function () {
...@@ -41,7 +100,7 @@ window.ImageManager = new Vue({ ...@@ -41,7 +100,7 @@ window.ImageManager = new Vue({
41 init: function () { 100 init: function () {
42 var dz = this; 101 var dz = this;
43 this.on("sending", function (file, xhr, data) { 102 this.on("sending", function (file, xhr, data) {
44 - data.append("_token", document.querySelector('meta[name=token]').getAttribute('content')); 103 + data.append("_token", _this.token);
45 }); 104 });
46 this.on("success", function (file, data) { 105 this.on("success", function (file, data) {
47 _this.images.unshift(data); 106 _this.images.unshift(data);
...@@ -95,10 +154,11 @@ window.ImageManager = new Vue({ ...@@ -95,10 +154,11 @@ window.ImageManager = new Vue({
95 saveImageDetails: function (e) { 154 saveImageDetails: function (e) {
96 e.preventDefault(); 155 e.preventDefault();
97 var _this = this; 156 var _this = this;
157 + _this.selectedImage._token = _this.token;
98 var form = $(_this.$$.imageForm); 158 var form = $(_this.$$.imageForm);
99 $.ajax('/images/update/' + _this.selectedImage.id, { 159 $.ajax('/images/update/' + _this.selectedImage.id, {
100 method: 'PUT', 160 method: 'PUT',
101 - data: form.serialize() 161 + data: _this.selectedImage
102 }).done(function () { 162 }).done(function () {
103 form.showSuccess('Image name updated'); 163 form.showSuccess('Image name updated');
104 }).fail(function (jqXHR) { 164 }).fail(function (jqXHR) {
...@@ -110,6 +170,7 @@ window.ImageManager = new Vue({ ...@@ -110,6 +170,7 @@ window.ImageManager = new Vue({
110 e.preventDefault(); 170 e.preventDefault();
111 var _this = this; 171 var _this = this;
112 _this.deleteForm.force = _this.dependantPages !== false; 172 _this.deleteForm.force = _this.dependantPages !== false;
173 + _this.deleteForm._token = _this.token;
113 $.ajax('/images/' + _this.selectedImage.id, { 174 $.ajax('/images/' + _this.selectedImage.id, {
114 method: 'DELETE', 175 method: 'DELETE',
115 data: _this.deleteForm 176 data: _this.deleteForm
...@@ -127,4 +188,5 @@ window.ImageManager = new Vue({ ...@@ -127,4 +188,5 @@ window.ImageManager = new Vue({
127 188
128 } 189 }
129 190
130 -}); 191 + };
192 +</script>
...\ No newline at end of file ...\ No newline at end of file
......
1 1
2 -<div class="image-picker"> 2 +<template>
3 + <div class="image-picker">
3 <div> 4 <div>
4 <img v-if="image && image !== 'none'" v-attr="src: image, class: imageClass" alt="Image Preview"> 5 <img v-if="image && image !== 'none'" v-attr="src: image, class: imageClass" alt="Image Preview">
5 </div> 6 </div>
...@@ -7,4 +8,30 @@ ...@@ -7,4 +8,30 @@
7 <br> 8 <br>
8 <button class="text-button" v-on="click: reset" type="button">Reset</button> <span class="sep">|</span> <button class="text-button neg" v-on="click: remove" type="button">Remove</button> 9 <button class="text-button" v-on="click: reset" type="button">Reset</button> <span class="sep">|</span> <button class="text-button neg" v-on="click: remove" type="button">Remove</button>
9 <input type="hidden" v-attr="name: name, id: name" v-model="image"> 10 <input type="hidden" v-attr="name: name, id: name" v-model="image">
10 -</div>
...\ No newline at end of file ...\ No newline at end of file
11 + </div>
12 +</template>
13 +
14 +<script>
15 + module.exports = {
16 + props: ['currentImage', 'name', 'imageClass'],
17 + data: function() {
18 + return {
19 + image: this.currentImage
20 + }
21 + },
22 + methods: {
23 + showImageManager: function(e) {
24 + var _this = this;
25 + ImageManager.show(function(image) {
26 + _this.image = image.url;
27 + });
28 + },
29 + reset: function() {
30 + this.image = '';
31 + },
32 + remove: function() {
33 + this.image = 'none';
34 + }
35 + }
36 + }
37 +</script>
...\ No newline at end of file ...\ No newline at end of file
......
1 +
2 +// Global jQuery Elements
1 $(function () { 3 $(function () {
2 4
3 // Notification hiding 5 // Notification hiding
4 $('.notification').click(function () { 6 $('.notification').click(function () {
5 $(this).fadeOut(100); 7 $(this).fadeOut(100);
6 -
7 }); 8 });
8 9
9 // Dropdown toggles 10 // Dropdown toggles
...@@ -18,34 +19,25 @@ $(function () { ...@@ -18,34 +19,25 @@ $(function () {
18 19
19 }); 20 });
20 21
22 +function elemExists(selector) {
23 + return document.querySelector(selector) !== null;
24 +}
25 +
26 +// Vue JS elements
27 +var Vue = require('vue');
28 +Vue.use(require('vue-resource'));
21 29
22 // Vue Components 30 // Vue Components
31 +Vue.component('image-manager', require('./components/image-manager.vue'));
32 +Vue.component('image-picker', require('./components/image-picker.vue'));
23 33
24 -Vue.component('image-picker', { 34 +// Vue Controllers
25 - template: require('./templates/image-picker.html'), 35 +if(elemExists('#book-dashboard')) {
26 - props: ['currentImage', 'name', 'imageClass'], 36 + new Vue(require('./pages/book-show'));
27 - data: function() { 37 +}
28 - return {
29 - image: this.currentImage
30 - }
31 - },
32 - methods: {
33 - showImageManager: function(e) {
34 - var _this = this;
35 - ImageManager.show(function(image) {
36 - _this.image = image.url;
37 - });
38 - },
39 - reset: function() {
40 - this.image = '';
41 - },
42 - remove: function() {
43 - this.image = 'none';
44 - }
45 - }
46 -});
47 38
48 // Global Vue Instance 39 // Global Vue Instance
40 +// Needs to be loaded after all components we want to use.
49 var app = new Vue({ 41 var app = new Vue({
50 el: '#app' 42 el: '#app'
51 }); 43 });
...\ No newline at end of file ...\ No newline at end of file
......
1 1
2 -new Vue({ 2 +module.exports = {
3 el: '#book-dashboard', 3 el: '#book-dashboard',
4 data: { 4 data: {
5 searching: false, 5 searching: false,
...@@ -29,4 +29,4 @@ new Vue({ ...@@ -29,4 +29,4 @@ new Vue({
29 this.searchTerm = ''; 29 this.searchTerm = '';
30 } 30 }
31 } 31 }
32 -});
...\ No newline at end of file ...\ No newline at end of file
32 +};
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -110,7 +110,6 @@ form.search-box { ...@@ -110,7 +110,6 @@ form.search-box {
110 right: 0; 110 right: 0;
111 margin: $-m 0; 111 margin: $-m 0;
112 background-color: #FFFFFF; 112 background-color: #FFFFFF;
113 - list-style: none;
114 box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.1); 113 box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.1);
115 border-radius: 1px; 114 border-radius: 1px;
116 border: 1px solid #EEE; 115 border: 1px solid #EEE;
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 @import "lists"; 15 @import "lists";
16 @import "pages"; 16 @import "pages";
17 17
18 +[v-cloak] {display: none;}
19 +
18 // Jquery Sortable Styles 20 // Jquery Sortable Styles
19 .dragged { 21 .dragged {
20 position: absolute; 22 position: absolute;
......
...@@ -8,16 +8,13 @@ ...@@ -8,16 +8,13 @@
8 <meta name="token" content="{{ csrf_token() }}"> 8 <meta name="token" content="{{ csrf_token() }}">
9 9
10 <!-- Styles and Fonts --> 10 <!-- Styles and Fonts -->
11 - <link rel="stylesheet" href="/css/app.css"> 11 + <link rel="stylesheet" href="/css/styles.css">
12 <link href='//fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'> 12 <link href='//fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'>
13 <link rel="stylesheet" href="/bower/material-design-iconic-font/dist/css/material-design-iconic-font.min.css"> 13 <link rel="stylesheet" href="/bower/material-design-iconic-font/dist/css/material-design-iconic-font.min.css">
14 14
15 <!-- Scripts --> 15 <!-- Scripts -->
16 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 16 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
17 <script src="/bower/jquery-sortable/source/js/jquery-sortable.js"></script> 17 <script src="/bower/jquery-sortable/source/js/jquery-sortable.js"></script>
18 - <script src="/bower/dropzone/dist/min/dropzone.min.js"></script>
19 - <script src="/bower/vue/dist/vue.min.js"></script>
20 - <script src="/bower/vue-resource/dist/vue-resource.min.js"></script>
21 18
22 @yield('head') 19 @yield('head')
23 </head> 20 </head>
......
...@@ -16,7 +16,3 @@ ...@@ -16,7 +16,3 @@
16 </div> 16 </div>
17 17
18 @stop 18 @stop
...\ No newline at end of file ...\ No newline at end of file
19 -
20 -@section('bottom')
21 - @include('pages/image-manager')
22 -@stop
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -17,7 +17,3 @@ ...@@ -17,7 +17,3 @@
17 </div> 17 </div>
18 18
19 @stop 19 @stop
...\ No newline at end of file ...\ No newline at end of file
20 -
21 -@section('bottom')
22 - @include('pages/image-manager')
23 -@stop
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -17,8 +17,3 @@ ...@@ -17,8 +17,3 @@
17 </form> 17 </form>
18 </div> 18 </div>
19 @stop 19 @stop
...\ No newline at end of file ...\ No newline at end of file
20 -
21 -@section('bottom')
22 - @include('pages/image-manager')
23 - <script src="/js/image-manager.js"></script>
24 -@stop
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -15,7 +15,3 @@ ...@@ -15,7 +15,3 @@
15 </div> 15 </div>
16 16
17 @stop 17 @stop
...\ No newline at end of file ...\ No newline at end of file
18 -
19 -@section('bottom')
20 - @include('pages/image-manager')
21 -@stop
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -16,8 +16,3 @@ ...@@ -16,8 +16,3 @@
16 </div> 16 </div>
17 17
18 @stop 18 @stop
...\ No newline at end of file ...\ No newline at end of file
19 -
20 -@section('bottom')
21 - @include('pages/image-manager')
22 - <script src="/js/image-manager.js"></script>
23 -@stop
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -99,3 +99,5 @@ ...@@ -99,3 +99,5 @@
99 99
100 }); 100 });
101 </script> 101 </script>
102 +
103 +<image-manager></image-manager>
...\ No newline at end of file ...\ No newline at end of file
......
1 -
2 -<div id="image-manager">
3 - <div class="overlay" v-el="overlay" v-on="click: overlayClick" >
4 - <div class="image-manager-body">
5 - <div class="image-manager-content">
6 - <div class="image-manager-list">
7 - <div v-repeat="image: images">
8 - <img class="anim fadeIn"
9 - v-class="selected: (image==selectedImage)"
10 - v-attr="src: image.thumbnail, alt: image.name, title: image.name"
11 - v-on="click: imageClick(image)"
12 - v-style="animation-delay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'">
13 - </div>
14 - <div class="load-more" v-show="hasMore" v-on="click: fetchData">Load More</div>
15 - </div>
16 - </div>
17 - <button class="neg button image-manager-close" v-on="click: hide()">x</button>
18 - <div class="image-manager-sidebar">
19 - <h2 v-el="imageTitle">Images</h2>
20 - <hr class="even">
21 - <div class="dropzone-container" v-el="dropZone">
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 v-on="submit: saveImageDetails" v-el="imageForm">
27 - {{ csrf_field() }}
28 - <div class="form-group">
29 - <label for="name">Image Name</label>
30 - <input type="text" id="name" name="name" v-model="selectedImage.name">
31 - </div>
32 - </form>
33 - <hr class="even">
34 - <div v-show="dependantPages">
35 - <p class="text-neg text-small">
36 - This image is used in the pages below, Click delete again to confirm you want to delete this image.
37 - </p>
38 - <ul class="text-neg">
39 - <li v-repeat="page: dependantPages">
40 - <a v-attr="href: page.url" target="_blank" class="text-neg">@{{ page.name }}</a>
41 - </li>
42 - </ul>
43 - </div>
44 -
45 - <form v-on="submit: deleteImage" v-el="imageDeleteForm">
46 - <input type="hidden" v-model="deleteForm._token" value="{{ csrf_token() }}">
47 - <button class="button neg"><i class="zmdi zmdi-delete"></i>Delete Image</button>
48 - </form>
49 - </div>
50 - <div class="image-manager-bottom">
51 - <button class="button pos anim fadeIn" v-show="selectedImage" v-on="click:selectButtonClick"><i class="zmdi zmdi-square-right"></i>Select Image</button>
52 - </div>
53 - </div>
54 - </div>
55 - </div>
56 -</div>
...@@ -84,9 +84,6 @@ ...@@ -84,9 +84,6 @@
84 84
85 </div> 85 </div>
86 86
87 -@stop 87 +<image-manager></image-manager>
88 88
89 -@section('bottom')
90 - @include('pages/image-manager')
91 - <script src="/js/image-manager.js"></script>
92 @stop 89 @stop
......