]> BookStack Code Mirror - bookstack/blob - resources/assets/js/components/image-manager.vue
Modularised/bundled js and made image-manager a proper component
[bookstack] / resources / assets / js / components / image-manager.vue
1 <template>
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                             <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 {
64                 images: [],
65                 hasMore: false,
66                 page: 0,
67                 cClickTime: 0,
68                 selectedImage: false,
69                 dependantPages: false,
70                 deleteForm: {},
71                 token: document.querySelector('meta[name=token]').getAttribute('content')
72             }
73         },
74
75         created: function () {
76             // Get initial images
77             this.fetchData(this.page);
78             window.ImageManager = this;
79         },
80
81         ready: function () {
82             // Create dropzone
83             this.setupDropZone();
84         },
85
86         methods: {
87             fetchData: function () {
88                 var _this = this;
89                 this.$http.get('/images/all/' + _this.page, function (data) {
90                     _this.images = _this.images.concat(data.images);
91                     _this.hasMore = data.hasMore;
92                     _this.page++;
93                 });
94             },
95
96             setupDropZone: function () {
97                 var _this = this;
98                 var dropZone = new Dropzone(_this.$$.dropZone, {
99                     url: '/upload/image',
100                     init: function () {
101                         var dz = this;
102                         this.on("sending", function (file, xhr, data) {
103                             data.append("_token", _this.token);
104                         });
105                         this.on("success", function (file, data) {
106                             _this.images.unshift(data);
107                             $(file.previewElement).fadeOut(400, function () {
108                                 dz.removeFile(file);
109                             });
110                         });
111                     }
112                 });
113             },
114
115             imageClick: function (image) {
116                 var dblClickTime = 380;
117                 var cTime = (new Date()).getTime();
118                 var timeDiff = cTime - this.cClickTime;
119                 if (this.cClickTime !== 0 && timeDiff < dblClickTime && this.selectedImage === image) {
120                     // DoubleClick
121                     if (this.callback) {
122                         this.callback(image);
123                     }
124                     this.hide();
125                 } else {
126                     this.selectedImage = (this.selectedImage === image) ? false : image;
127                     this.dependantPages = false;
128                 }
129                 this.cClickTime = cTime;
130             },
131
132             selectButtonClick: function () {
133                 if (this.callback) {
134                     this.callback(this.selectedImage);
135                 }
136                 this.hide();
137             },
138
139             show: function (callback) {
140                 this.callback = callback;
141                 this.$$.overlay.style.display = 'block';
142             },
143
144             overlayClick: function (e) {
145                 if (e.target.className === 'overlay') {
146                     this.hide();
147                 }
148             },
149
150             hide: function () {
151                 this.$$.overlay.style.display = 'none';
152             },
153
154             saveImageDetails: function (e) {
155                 e.preventDefault();
156                 var _this = this;
157                 _this.selectedImage._token = _this.token;
158                 var form = $(_this.$$.imageForm);
159                 $.ajax('/images/update/' + _this.selectedImage.id, {
160                     method: 'PUT',
161                     data: _this.selectedImage
162                 }).done(function () {
163                     form.showSuccess('Image name updated');
164                 }).fail(function (jqXHR) {
165                     form.showFailure(jqXHR.responseJSON);
166                 })
167             },
168
169             deleteImage: function (e) {
170                 e.preventDefault();
171                 var _this = this;
172                 _this.deleteForm.force = _this.dependantPages !== false;
173                 _this.deleteForm._token = _this.token;
174                 $.ajax('/images/' + _this.selectedImage.id, {
175                     method: 'DELETE',
176                     data: _this.deleteForm
177                 }).done(function () {
178                     _this.images.splice(_this.images.indexOf(_this.selectedImage), 1);
179                     _this.selectedImage = false;
180                     $(_this.$$.imageTitle).showSuccess('Image Deleted');
181                 }).fail(function(jqXHR, textStatus) {
182                     // Pages failure
183                     if(jqXHR.status === 400) {
184                         _this.dependantPages = jqXHR.responseJSON;
185                     }
186                 });
187             }
188
189         }
190
191     };
192 </script>