]> git.immae.eu Git - perso/Immae/Projets/Nodejs/Surfer.git/blame - app/js/app.js
URI decode all paths
[perso/Immae/Projets/Nodejs/Surfer.git] / app / js / app.js
CommitLineData
6eb72d64
JZ
1(function () {
2'use strict';
3
4function 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;
d3312ed1 23
04bc2989 24 loadDirectory(window.location.hash.slice(1));
6eb72d64
JZ
25 });
26}
27
28function logout() {
29 app.session.valid = false;
95c627bf
JZ
30 app.session.username = null;
31 app.session.password = null;
6eb72d64
JZ
32
33 delete localStorage.username;
34 delete localStorage.password;
35}
36
d3312ed1
JZ
37function sanitize(filePath) {
38 filePath = '/' + filePath;
39 return filePath.replace(/\/+/g, '/');
40}
41
537bfb04
JZ
42function encode(filePath) {
43 return filePath.split('/').map(encodeURIComponent).join('/');
44}
45
04bc2989
JZ
46function decode(filePath) {
47 return filePath.split('/').map(decodeURIComponent).join('/');
48}
49
a26d1f9b
JZ
50var 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
58function 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
537bfb04
JZ
71function refresh() {
72 loadDirectory(app.path);
73}
74
d3312ed1
JZ
75function 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
9209abec 85 if (result && result.statusCode === 401) return logout();
d3312ed1 86 if (error) return console.error(error);
d3312ed1 87
04bc2989 88 result.body.entries.sort(function (a, b) { return a.isDirectory && b.isFile ? -1 : 1; });
a26d1f9b
JZ
89 app.entries = result.body.entries.map(function (entry) {
90 entry.previewUrl = getPreviewUrl(entry, filePath);
91 return entry;
92 });
d3312ed1 93 app.path = filePath;
04bc2989
JZ
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;
3e98fb0c
JZ
98
99 Vue.nextTick(function () {
100 $(function () {
101 $('[data-toggle="tooltip"]').tooltip();
102 });
103 });
d3312ed1
JZ
104 });
105}
106
107function open(entry) {
04bc2989 108 var path = encode(sanitize(app.path + '/' + entry.filePath));
d3312ed1 109
04bc2989
JZ
110 if (entry.isDirectory) {
111 window.location.hash = path;
112 return;
113 }
d3312ed1 114
ee9d1ada 115 window.open(path);
d3312ed1
JZ
116}
117
118function up() {
04bc2989 119 window.location.hash = encode(sanitize(app.path.split('/').slice(0, -1).filter(function (p) { return !!p; }).join('/')));
d3312ed1
JZ
120}
121
537bfb04 122function upload() {
403359cf 123 $(app.$els.upload).on('change', function () {
537bfb04
JZ
124 app.busy = true;
125
403359cf
JZ
126 // detach event handler
127 $(app.$els.upload).off('change');
128
537bfb04
JZ
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
9209abec
JZ
138 if (result && result.statusCode === 401) return logout();
139 if (result && result.statusCode !== 201) return console.error('Error uploading file: ', result.statusCode);
537bfb04 140 if (error) return console.error(error);
537bfb04
JZ
141
142 refresh();
143 });
144 });
145
e41fd8d8
JZ
146 // reset the form first to make the change handler retrigger even on the same file selected
147 $('#fileUploadForm')[0].reset();
148
537bfb04
JZ
149 app.$els.upload.click();
150}
151
9138d7d4
JZ
152function delAsk(entry) {
153 $('#modalDelete').modal('show');
154 app.deleteData = entry;
155}
156
157function del(entry) {
158 app.busy = true;
159
160 var path = encode(sanitize(app.path + '/' + entry.filePath));
161
162 superagent.del('/api/files' + path).query({ username: app.session.username, password: app.session.password, recursive: true }).end(function (error, result) {
163 app.busy = false;
164
9209abec
JZ
165 if (result && result.statusCode === 401) return logout();
166 if (result && result.statusCode !== 200) return console.error('Error deleting file: ', result.statusCode);
9138d7d4 167 if (error) return console.error(error);
9138d7d4
JZ
168
169 refresh();
170
171 $('#modalDelete').modal('hide');
172 });
173}
174
403359cf
JZ
175function createDirectoryAsk() {
176 $('#modalcreateDirectory').modal('show');
177 app.createDirectoryData = '';
9209abec 178 app.createDirectoryError = null;
403359cf
JZ
179}
180
181function createDirectory(name) {
182 app.busy = true;
9209abec 183 app.createDirectoryError = null;
403359cf
JZ
184
185 var path = encode(sanitize(app.path + '/' + name));
186
187 superagent.put('/api/files' + path).query({ username: app.session.username, password: app.session.password, directory: true }).end(function (error, result) {
188 app.busy = false;
189
9209abec
JZ
190 if (result && result.statusCode === 401) return logout();
191 if (result && result.statusCode === 403) {
192 app.createDirectoryError = 'Name not allowed';
193 return;
194 }
195 if (result && result.statusCode === 409) {
196 app.createDirectoryError = 'Directory already exists';
197 return;
198 }
199 if (result && result.statusCode !== 201) return console.error('Error creating directory: ', result.statusCode);
403359cf 200 if (error) return console.error(error);
403359cf
JZ
201
202 app.createDirectoryData = '';
203 refresh();
204
205 $('#modalcreateDirectory').modal('hide');
206 });
207}
208
235212c4
JZ
209Vue.filter('prettyDate', function (value) {
210 var d = new Date(value);
211 return d.toDateString();
212});
213
8fce52f8
JZ
214Vue.filter('prettyFileSize', function (value) {
215 return filesize(value);
216});
217
6eb72d64
JZ
218var app = new Vue({
219 el: '#app',
220 data: {
221 busy: true,
d3312ed1
JZ
222 path: '/',
223 pathParts: [],
6eb72d64
JZ
224 session: {
225 valid: false
226 },
d3312ed1 227 loginData: {},
9138d7d4 228 deleteData: {},
403359cf 229 createDirectoryData: '',
9209abec 230 createDirectoryError: null,
d3312ed1 231 entries: []
6eb72d64
JZ
232 },
233 methods: {
234 login: login,
d3312ed1
JZ
235 logout: logout,
236 loadDirectory: loadDirectory,
237 open: open,
537bfb04 238 up: up,
9138d7d4
JZ
239 upload: upload,
240 delAsk: delAsk,
403359cf
JZ
241 del: del,
242 createDirectoryAsk: createDirectoryAsk,
243 createDirectory: createDirectory
6eb72d64
JZ
244 }
245});
246
9209abec
JZ
247window.app = app;
248
6eb72d64
JZ
249login(localStorage.username, localStorage.password);
250
04bc2989
JZ
251$(window).on('hashchange', function () {
252 loadDirectory(window.location.hash.slice(1));
253});
254
9209abec
JZ
255// setup all the dialog focus handling
256['modalcreateDirectory'].forEach(function (id) {
257 $('#' + id).on('shown.bs.modal', function () {
258 $(this).find("[autofocus]:first").focus();
259 });
260});
261
6eb72d64 262})();