]> BookStack Code Mirror - bookstack/blob - resources/js/vues/image-manager.js
added additional color settings into UI
[bookstack] / resources / js / vues / image-manager.js
1 import * as Dates from "../services/dates";
2 import dropzone from "./components/dropzone";
3
4 let page = 1;
5 let previousClickTime = 0;
6 let previousClickImage = 0;
7 let dataLoaded = false;
8 let callback = false;
9 let baseUrl = '';
10
11 let preSearchImages = [];
12 let preSearchHasMore = false;
13
14 const data = {
15     images: [],
16
17     imageType: false,
18     uploadedTo: false,
19
20     selectedImage: false,
21     dependantPages: false,
22     showing: false,
23     filter: null,
24     hasMore: false,
25     searching: false,
26     searchTerm: '',
27
28     imageUpdateSuccess: false,
29     imageDeleteSuccess: false,
30     deleteConfirm: false,
31 };
32
33 const methods = {
34
35     show(providedCallback, imageType = null) {
36         callback = providedCallback;
37         this.showing = true;
38         this.$el.children[0].components.overlay.show();
39
40         // Get initial images if they have not yet been loaded in.
41         if (dataLoaded && imageType === this.imageType) return;
42         if (imageType) {
43             this.imageType = imageType;
44             this.resetState();
45         }
46         this.fetchData();
47         dataLoaded = true;
48     },
49
50     hide() {
51         if (this.$refs.dropzone) {
52             this.$refs.dropzone.onClose();
53         }
54         this.showing = false;
55         this.selectedImage = false;
56         this.$el.children[0].components.overlay.hide();
57     },
58
59     async fetchData() {
60         const params = {
61             page,
62             search: this.searching ? this.searchTerm : null,
63             uploaded_to: this.uploadedTo || null,
64             filter_type: this.filter,
65         };
66
67         const {data} = await this.$http.get(baseUrl, params);
68         this.images = this.images.concat(data.images);
69         this.hasMore = data.has_more;
70         page++;
71     },
72
73     setFilterType(filterType) {
74         this.filter = filterType;
75         this.resetState();
76         this.fetchData();
77     },
78
79     resetState() {
80         this.cancelSearch();
81         this.resetListView();
82         this.deleteConfirm = false;
83         baseUrl = window.baseUrl(`/images/${this.imageType}`);
84     },
85
86     resetListView() {
87         this.images = [];
88         this.hasMore = false;
89         page = 1;
90     },
91
92     searchImages() {
93         if (this.searchTerm === '') return this.cancelSearch();
94
95         // Cache current settings for later
96         if (!this.searching) {
97             preSearchImages = this.images;
98             preSearchHasMore = this.hasMore;
99         }
100
101         this.searching = true;
102         this.resetListView();
103         this.fetchData();
104     },
105
106     cancelSearch() {
107         if (!this.searching) return;
108         this.searching = false;
109         this.searchTerm = '';
110         this.images = preSearchImages;
111         this.hasMore = preSearchHasMore;
112     },
113
114     imageSelect(image) {
115         const dblClickTime = 300;
116         const currentTime = Date.now();
117         const timeDiff = currentTime - previousClickTime;
118         const isDblClick = timeDiff < dblClickTime && image.id === previousClickImage;
119
120         if (isDblClick) {
121             this.callbackAndHide(image);
122         } else {
123             this.selectedImage = image;
124             this.deleteConfirm = false;
125             this.dependantPages = false;
126         }
127
128         previousClickTime = currentTime;
129         previousClickImage = image.id;
130     },
131
132     callbackAndHide(imageResult) {
133         if (callback) callback(imageResult);
134         this.hide();
135     },
136
137     async saveImageDetails() {
138         let url = window.baseUrl(`/images/${this.selectedImage.id}`);
139         try {
140             await this.$http.put(url, this.selectedImage)
141         } catch (error) {
142             if (error.response.status === 422) {
143                 let errors = error.response.data;
144                 let message = '';
145                 Object.keys(errors).forEach((key) => {
146                     message += errors[key].join('\n');
147                 });
148                 this.$events.emit('error', message);
149             }
150         }
151     },
152
153     async deleteImage() {
154
155         if (!this.deleteConfirm) {
156             const url = window.baseUrl(`/images/usage/${this.selectedImage.id}`);
157             try {
158                 const {data} = await this.$http.get(url);
159                 this.dependantPages = data;
160             } catch (error) {
161                 console.error(error);
162             }
163             this.deleteConfirm = true;
164             return;
165         }
166
167         const url = window.baseUrl(`/images/${this.selectedImage.id}`);
168         await this.$http.delete(url);
169         this.images.splice(this.images.indexOf(this.selectedImage), 1);
170         this.selectedImage = false;
171         this.$events.emit('success', trans('components.image_delete_success'));
172         this.deleteConfirm = false;
173     },
174
175     getDate(stringDate) {
176         return Dates.formatDateTime(new Date(stringDate));
177     },
178
179     uploadSuccess(event) {
180         this.images.unshift(event.data);
181         this.$events.emit('success', trans('components.image_upload_success'));
182     },
183 };
184
185 const computed = {
186     uploadUrl() {
187         return window.baseUrl(`/images/${this.imageType}`);
188     }
189 };
190
191 function mounted() {
192     window.ImageManager = this;
193     this.imageType = this.$el.getAttribute('image-type');
194     this.uploadedTo = this.$el.getAttribute('uploaded-to');
195     baseUrl = window.baseUrl('/images/' + this.imageType)
196 }
197
198 export default {
199     mounted,
200     methods,
201     data,
202     computed,
203     components: {dropzone},
204 };