]> git.immae.eu Git - perso/Immae/Projets/Nodejs/Surfer.git/blob - app/js/app.js
Work off of the location hash to make browser history work
[perso/Immae/Projets/Nodejs/Surfer.git] / app / js / app.js
1 (function () {
2 'use strict';
3
4 function login(username, password) {
5 username = username || app.loginData.username;
6 password = password || app.loginData.password;
7
8 app.busy = true;
9
10 superagent.get('/api/files/').query({ username: username, password: password }).end(function (error, result) {
11 app.busy = false;
12
13 if (error) return console.error(error);
14 if (result.statusCode === 401) return console.error('Invalid credentials');
15
16 app.session.valid = true;
17 app.session.username = username;
18 app.session.password = password;
19
20 // clearly not the best option
21 localStorage.username = username;
22 localStorage.password = password;
23
24 loadDirectory(window.location.hash.slice(1));
25 });
26 }
27
28 function logout() {
29 app.session.valid = false;
30 app.session.username = null;
31 app.session.password = null;
32
33 delete localStorage.username;
34 delete localStorage.password;
35 }
36
37 function sanitize(filePath) {
38 filePath = '/' + filePath;
39 return filePath.replace(/\/+/g, '/');
40 }
41
42 function encode(filePath) {
43 return filePath.split('/').map(encodeURIComponent).join('/');
44 }
45
46 function decode(filePath) {
47 return filePath.split('/').map(decodeURIComponent).join('/');
48 }
49
50 var mimeTypes = {
51 images: [ '.png', '.jpg', '.jpeg', '.tiff', '.gif' ],
52 text: [ '.txt', '.md' ],
53 pdf: [ '.pdf' ],
54 html: [ '.html', '.htm', '.php' ],
55 video: [ '.mp4', '.mpg', '.mpeg', '.ogg', '.mkv' ]
56 };
57
58 function getPreviewUrl(entry, basePath) {
59 var path = '/_admin/img/';
60
61 if (entry.isDirectory) return path + 'directory.png';
62 if (mimeTypes.images.some(function (e) { return entry.filePath.endsWith(e); })) return sanitize(basePath + '/' + entry.filePath);
63 if (mimeTypes.text.some(function (e) { return entry.filePath.endsWith(e); })) return path +'text.png';
64 if (mimeTypes.pdf.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'pdf.png';
65 if (mimeTypes.html.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'html.png';
66 if (mimeTypes.video.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'video.png';
67
68 return path + 'unknown.png';
69 }
70
71 function refresh() {
72 loadDirectory(app.path);
73 }
74
75 function loadDirectory(filePath) {
76 app.busy = true;
77
78 filePath = filePath ? sanitize(filePath) : '/';
79
80 console.log(filePath);
81
82 superagent.get('/api/files/' + filePath).query({ username: app.session.username, password: app.session.password }).end(function (error, result) {
83 app.busy = false;
84
85 if (error) return console.error(error);
86 if (result.statusCode === 401) return logout();
87
88 result.body.entries.sort(function (a, b) { return a.isDirectory && b.isFile ? -1 : 1; });
89 app.entries = result.body.entries.map(function (entry) {
90 entry.previewUrl = getPreviewUrl(entry, filePath);
91 return entry;
92 });
93 app.path = filePath;
94 app.pathParts = decode(filePath).split('/').filter(function (e) { return !!e; });
95
96 // update in case this was triggered from code
97 window.location.hash = app.path;
98
99 Vue.nextTick(function () {
100 $(function () {
101 $('[data-toggle="tooltip"]').tooltip();
102 });
103 });
104 });
105 }
106
107 function open(entry) {
108 var path = encode(sanitize(app.path + '/' + entry.filePath));
109
110 if (entry.isDirectory) {
111 window.location.hash = path;
112 return;
113 }
114
115 window.open(path);
116 }
117
118 function up() {
119 window.location.hash = encode(sanitize(app.path.split('/').slice(0, -1).filter(function (p) { return !!p; }).join('/')));
120 }
121
122 function upload() {
123 $(app.$els.upload).on('change', function () {
124 app.busy = true;
125
126 // detach event handler
127 $(app.$els.upload).off('change');
128
129 var file = app.$els.upload.files[0];
130 var path = encode(sanitize(app.path + '/' + file.name));
131
132 var formData = new FormData();
133 formData.append('file', file);
134
135 superagent.put('/api/files' + path).query({ username: app.session.username, password: app.session.password }).send(formData).end(function (error, result) {
136 app.busy = false;
137
138 if (error) return console.error(error);
139 if (result.statusCode !== 201) return console.error('Error uploading file: ', result.statusCode);
140
141 refresh();
142 });
143 });
144
145 app.$els.upload.click();
146 }
147
148 function delAsk(entry) {
149 $('#modalDelete').modal('show');
150 app.deleteData = entry;
151 }
152
153 function del(entry) {
154 app.busy = true;
155
156 var path = encode(sanitize(app.path + '/' + entry.filePath));
157
158 superagent.del('/api/files' + path).query({ username: app.session.username, password: app.session.password, recursive: true }).end(function (error, result) {
159 app.busy = false;
160
161 if (error) return console.error(error);
162 if (result.statusCode !== 200) return console.error('Error deleting file: ', result.statusCode);
163
164 refresh();
165
166 $('#modalDelete').modal('hide');
167 });
168 }
169
170 function createDirectoryAsk() {
171 $('#modalcreateDirectory').modal('show');
172 app.createDirectoryData = '';
173 }
174
175 function createDirectory(name) {
176 app.busy = true;
177
178 var path = encode(sanitize(app.path + '/' + name));
179
180 superagent.put('/api/files' + path).query({ username: app.session.username, password: app.session.password, directory: true }).end(function (error, result) {
181 app.busy = false;
182
183 if (error) return console.error(error);
184 if (result.statusCode !== 201) return console.error('Error creating directory: ', result.statusCode);
185
186 app.createDirectoryData = '';
187 refresh();
188
189 $('#modalcreateDirectory').modal('hide');
190 });
191 }
192
193 Vue.filter('prettyDate', function (value) {
194 var d = new Date(value);
195 return d.toDateString();
196 });
197
198 Vue.filter('prettyFileSize', function (value) {
199 return filesize(value);
200 });
201
202 var app = new Vue({
203 el: '#app',
204 data: {
205 busy: true,
206 path: '/',
207 pathParts: [],
208 session: {
209 valid: false
210 },
211 loginData: {},
212 deleteData: {},
213 createDirectoryData: '',
214 entries: []
215 },
216 methods: {
217 login: login,
218 logout: logout,
219 loadDirectory: loadDirectory,
220 open: open,
221 up: up,
222 upload: upload,
223 delAsk: delAsk,
224 del: del,
225 createDirectoryAsk: createDirectoryAsk,
226 createDirectory: createDirectory
227 }
228 });
229
230 login(localStorage.username, localStorage.password);
231
232 $(window).on('hashchange', function () {
233 loadDirectory(window.location.hash.slice(1));
234 });
235
236 })();