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