blob: 38743ad60f485d14948e08175484ae2ecc54e6be [file] [log] [blame]
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -08001$.Class("ChronoShare", {}, {
2 init: function(username, foldername) {
3 $("#folder-name").text(foldername);
4 $("#user-name").text(username);
Alexander Afanasyev46bd8062013-02-27 23:59:15 -08005
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -08006 this.username = new Name(username);
7 this.files = new Name("/localhost")
8 .add(this.username)
9 .add("chronoshare")
10 .add(foldername)
11 .add("info")
12 .add("files")
13 .add("folder");
Alexander Afanasyev46bd8062013-02-27 23:59:15 -080014
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080015 this.actions = new Name("/localhost")
16 .add(this.username)
17 .add("chronoshare")
18 .add(foldername)
19 .add("info")
20 .add("actions");
Alexander Afanasyev46bd8062013-02-27 23:59:15 -080021
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080022 this.restore = new Name("/localhost")
23 .add(this.username)
24 .add("chronoshare")
25 .add(foldername)
26 .add("cmd")
27 .add("restore")
28 .add("file");
Alexander Afanasyev46bd8062013-02-27 23:59:15 -080029
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080030 this.ndn = new NDN({host: "127.0.0.1"});
31 this.ndn.verify = false; // disable content verification, works WAAAAY faster
32 },
Alexander Afanasyev46bd8062013-02-27 23:59:15 -080033
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080034 run: function() {
35 console.log("RUN page: " + PAGE);
36 $("#loader").fadeIn(500);
37 $("#error").addClass("hidden");
Alexander Afanasyev46bd8062013-02-27 23:59:15 -080038
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080039 cmd = {};
40 if (PAGE == "fileList") {
41 cmd = this.info_files(PARAMS.item);
42 }
43 else if (PAGE == "folderHistory") {
44 cmd = this.info_actions("folder", PARAMS.item);
45 }
46 else if (PAGE == "fileHistory") {
47 cmd = this.info_actions("file", PARAMS.item);
48 }
Alexander Afanasyevf63a5142013-02-28 02:21:42 -080049
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080050 if (cmd.request && cmd.callback) {
51 console.log(cmd.request.to_uri());
52 this.ndn.expressInterest(cmd.request, cmd.callback);
53 }
54 else {
55 $("#loader").fadeOut(500); // ("hidden");
56 $("#content").empty();
57 if (cmd.error) {
58 $("#error").html(cmd.error);
59 }
60 else {
61 $("#error").html("Unknown error with " + PAGE);
62 }
63 $("#error").removeClass("hidden");
64 }
65 },
Alexander Afanasyevf63a5142013-02-28 02:21:42 -080066
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080067 info_files: function(folder) {
68 request = new Name()
69 .add(this.files)
70 ./*add (folder_in_question).*/ addSegment(
71 PARAMS.offset ? PARAMS.offset : 0);
72 return {request: request, callback: new FilesClosure(this)};
73 },
Alexander Afanasyevf63a5142013-02-28 02:21:42 -080074
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080075 info_actions: function(type /*"file" or "folder"*/,
76 fileOrFolder /*file or folder name*/) {
77 if (type == "file" && !fileOrFolder) {
78 return {error: "info_actions: fileOrFolder parameter is missing"};
79 }
Alexander Afanasyevf63a5142013-02-28 02:21:42 -080080
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080081 request = new Name().add(this.actions).add(type);
82 if (fileOrFolder) {
83 request.add(fileOrFolder);
84 }
85 request.addSegment(PARAMS.offset ? PARAMS.offset : 0);
86 return {request: request, callback: new HistoryClosure(this)};
87 },
Alexander Afanasyev46bd8062013-02-27 23:59:15 -080088
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080089 cmd_restore_file:
90 function(filename, version, hash,
91 callback /*function (bool <- data received, status <- returned status)*/) {
92 request =
93 new Name().add(this.restore).add(filename).addSegment(version).add(hash);
94 console.log(request.to_uri());
95 this.ndn.expressInterest(request,
96 new CmdRestoreFileClosure(this, callback));
Alexander Afanasyev4c17b482013-03-02 01:32:35 -080097 },
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080098
99 get_file:
100 function(modifiedBy, hash, segments,
101 callback /*function (bool <- data received, data <- returned data)*/) {
102 baseName = new Name(modifiedBy).add("chronoshare").add("file").add(hash);
103
104 new FileGetter(this.ndn, baseName, segments, callback).start();
Alexander Afanasyev4c17b482013-03-02 01:32:35 -0800105 }
106});
107
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800108$.Class("CmdRestoreFileClosure", {}, {
109 init: function(chronoshare, callback) {
110 this.chronoshare = chronoshare;
111 this.callback = callback;
112 },
113 upcall: function(kind, upcallInfo) {
114 if (kind == Closure.UPCALL_CONTENT ||
115 kind == Closure.UPCALL_CONTENT_UNVERIFIED) { // disable content verification
116 convertedData = DataUtils.toString(upcallInfo.contentObject.content);
117 this.callback(true, convertedData);
Alexander Afanasyevc24db642013-03-09 16:41:02 -0800118 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800119 else if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
120 this.callback(false, "Interest timed out");
121 }
122 else {
123 this.callback(false, "Unknown error happened");
124 }
125 }
Alexander Afanasyevc24db642013-03-09 16:41:02 -0800126});
127
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800128$.Class("FileGetter", {}, {
129 init: function(ndn, baseName, segments, callback) {
130 this.ndn = ndn;
131 this.callback = callback;
132 this.baseName = baseName;
133 this.segments = segments;
134 this.lastSegmentRequested = -1;
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800135
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800136 this.data = "";
137 },
Alexander Afanasyev46bd8062013-02-27 23:59:15 -0800138
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800139 start: function() {
140 this.lastSegmentRequested++;
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800141
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800142 request =
143 new Name().add(this.baseName).addSegment(this.lastSegmentRequested);
Zhenkai Zhu5c2475b2013-02-26 22:57:31 -0800144
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800145 console.log(request.to_uri());
146 this.ndn.expressInterest(request, this);
147 },
Alexander Afanasyev10babd22013-03-04 13:53:36 -0800148
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800149 upcall: function(kind, upcallInfo) {
150 if (kind == Closure.UPCALL_CONTENT ||
151 kind == Closure.UPCALL_CONTENT_UNVERIFIED) { // disable content verification
152 convertedData = DataUtils.toString(upcallInfo.contentObject.content);
153
154 this.data += convertedData;
155
156 if (this.lastSegmentRequested + 1 == this.segments) {
157 this.callback(true, this.data);
158 }
159 else {
160 this.start();
161 }
162 }
163 else {
164 this.callback(false, "Interest timed out");
165 }
166 }
167});
168
169$.Class("RestPipelineClosure", {}, {
170 init: function(collectionName, moreName) {
171 this.collectionName = collectionName;
172 this.moreName = moreName;
173 $("#json").empty();
174
175 this.collection = [];
176 this.counter = 0;
177 },
178
179 upcall: function(kind, upcallInfo) {
180 if (kind == Closure.UPCALL_CONTENT ||
181 kind == Closure.UPCALL_CONTENT_UNVERIFIED) { // disable content verification
182
183 convertedData = DataUtils.toString(upcallInfo.contentObject.content);
184 if (PARAMS.debug) {
185 $("#json").append($(document.createTextNode(convertedData)));
186 $("#json").removeClass("hidden");
187 }
188 data = JSON.parse(convertedData);
189
190 this.collection = this.collection.concat(data[this.collectionName]);
191 if (data[this.moreName] !== undefined) {
192 nextSegment =
193 upcallInfo.interest.name.cut(1).addSegment(data[this.moreName]);
194 this.counter++;
195
196 if (this.counter < 5) {
197 console.log("MORE: " + nextSegment.to_uri());
198 CHRONOSHARE.ndn.expressInterest(nextSegment, this);
Alexander Afanasyevfd5e6272013-02-27 20:25:20 -0800199 }
200 else {
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800201 $("#loader").fadeOut(500); // ("hidden");
202 this.onData(this.collection, data[this.moreName]);
Alexander Afanasyevfd5e6272013-02-27 20:25:20 -0800203 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800204 }
205 else {
206 $("#loader").fadeOut(500); // ("hidden");
207 this.onData(this.collection, undefined);
208 }
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800209 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800210 else if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
211 $("#loader").fadeOut(500); // ("hidden");
212 this.onTimeout(upcallInfo.interest);
213 }
214 else {
215 $("#loader").fadeOut(500); // ("hidden");
216 this.onUnknownError(upcallInfo.interest);
217 }
218
219 return Closure.RESULT_OK; // make sure we never re-express the interest
220 },
221
222 onData: function(data, more) {},
223
224 onTimeout: function() {
225 $("#error").html("Interest timed out");
226 $("#error").removeClass("hidden");
227 },
228
229 onUnknownError: function() {
230 $("#error").html("Unknown error happened");
231 $("#error").removeClass("hidden");
232 }
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800233});
234
235// $.Class ("FilesClosure", {}, {
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800236RestPipelineClosure("FilesClosure", {}, {
237 init: function(chronoshare) {
238 this._super("files", "more");
239 this.chronoshare = chronoshare;
240 },
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800241
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800242 onData: function(data, more) {
243 tbody = $("<tbody />", {"id": "file-list-files"});
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800244
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800245 /// @todo Eventually set title for other pages
246 $("title").text("ChronoShare - List of files" +
247 (PARAMS.item ? " - " + PARAMS.item : ""));
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800248
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800249 // error handling?
250 newcontent =
251 $("<div />", {"id": "content"})
252 .append($("<h2 />").append($(document.createTextNode("List of files ")),
253 $("<green />").text(PARAMS.item)),
254 $("<table />", {"class": "item-list"})
255 .append(
256 $("<thead />")
257 .append($("<tr />")
258 .append($("<th />", {
259 "class": "filename border-left",
260 "scope": "col"
261 }).text("Filename"))
262 .append($("<th />",
263 {"class": "version", "scope": "col"})
264 .text("Version"))
265 .append($("<th />",
266 {"class": "size", "scope": "col"})
267 .text("Size"))
268 .append($("<th />", {
269 "class": "modified",
270 "scope": "col"
271 }).text("Modified"))
272 .append($("<th />", {
273 "class": "modified-by border-right",
274 "scope": "col"
275 }).text("Modified By"))))
276 .append(tbody)
277 .append($("<tfoot />").append($("<tr />").append($("<td />", {
278 "colspan": "5",
279 "class": "border-right border-left"
280 })))));
281 newcontent.hide();
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800282
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800283 for (var i = 0; i < data.length; i++) {
284 file = data[i];
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800285
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800286 row = $("<tr />", {"class": "with-context-menu"});
287 if (i % 2) {
288 row.addClass("odd");
289 }
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800290
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800291 row.bind('mouseenter mouseleave', function() {
292 $(this).toggleClass('highlighted');
293 });
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800294
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800295 row.attr("filename",
296 file.filename); // encodeURIComponent(encodeURIComponent(file.filename)));
297 row.bind('click', function(e) {
298 openHistoryForItem($(this).attr("filename"))
299 });
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800300
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800301 row.append(
302 $("<td />", {"class": "filename border-left"})
303 .text(file.filename)
304 .prepend(
305 $("<img />", {"src": imgFullPath(fileExtension(file.filename))})));
306 row.append($("<td />", {"class": "version"}).text(file.version));
307 row.append(
308 $("<td />", {"class": "size"}).text(SegNumToFileSize(file.segNum)));
309 row.append($("<td />", {
310 "class": "modified"
311 }).text(new Date(file.timestamp + "+00:00"))); // convert from UTC
312 row.append($("<td />", {"class": "modified-by border-right"})
313 .append($("<userName />").text(file.owner.userName))
314 .append($("<seqNo> /").text(file.owner.seqNo)));
Alexander Afanasyev1663a412013-03-02 13:52:00 -0800315
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800316 tbody = tbody.append(row);
Zhenkai Zhu5c2475b2013-02-26 22:57:31 -0800317 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800318
319 displayContent(newcontent, more, this.base_url());
320
321 $.contextMenu('destroy', ".with-context-menu"); // cleanup
322 $.contextMenu({
323 selector: ".with-context-menu",
324 items: {
325 "info": {name: "x", type: "html", html: "<b>File operations</b>"},
326 "sep1": "---------",
327 history: {
328 name: "View file history",
329 icon: "quit", // need a better icon
330 callback: function(key, opt) {
331 openHistoryForItem(opt.$trigger.attr("filename"));
332 }
333 },
334 }
335 });
336 },
337
338 base_url: function() {
339 url = "#fileList" +
340 "&user=" + encodeURIComponent(encodeURIComponent(PARAMS.user)) +
341 "&folder=" + encodeURIComponent(encodeURIComponent(PARAMS.folder));
342 if (PARAMS.item !== undefined) {
343 url += "&item=" + encodeURIComponent(encodeURIComponent(PARAMS.item));
344 }
345 return url;
346 }
Alexander Afanasyevfd5e6272013-02-27 20:25:20 -0800347});
Zhenkai Zhu5c2475b2013-02-26 22:57:31 -0800348
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800349RestPipelineClosure("HistoryClosure", {}, {
350 init: function(chronoshare) {
351 this._super("actions", "more");
352 this.chronoshare = chronoshare;
353 },
Alexander Afanasyevfd5e6272013-02-27 20:25:20 -0800354
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800355 previewFile: function(file) {
356 if (fileExtension(file.attr("filename")) == "txt") {
357 CHRONOSHARE.get_file(file.attr("file_modified_by"),
358 DataUtils.toNumbers(file.attr("file_hash")),
359 file.attr("file_seg_num"), function(status, data) {
360 $("<div />", {
361 "title": "Preview of " + file.attr("filename") +
362 " version " + file.attr("file_version")
363 })
364 .append($("<pre />").text(data))
365 .dialog({
366 resizable: true,
367 width: $(window).width() * 0.8,
368 maxHeight: $(window).height() * 0.8,
369 show: "blind",
370 hide: "fold",
371 modal: true,
372 });
373 });
Alexander Afanasyevf63a5142013-02-28 02:21:42 -0800374 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800375 else {
376 custom_alert("Preview is not support for this type of file");
377 }
378 },
379
380 onData: function(data, more) {
381 tbody = $("<tbody />", {"id": "history-list-actions"});
382
383 /// @todo Eventually set title for other pages
384 $("title").text("ChronoShare - Recent actions" +
385 (PARAMS.item ? " - " + PARAMS.item : ""));
386
387 newcontent =
388 $("<div />", {"id": "content"})
389 .append($("<h2 />").append($(document.createTextNode("Recent actions ")),
390 $("<green />").text(PARAMS.item)),
391 $("<table />", {"class": "item-list"})
392 .append(
393 $("<thead />")
394 .append($("<tr />")
395 .append($("<th />", {
396 "class": "filename border-left",
397 "scope": "col"
398 }).text("Filename"))
399 .append($("<th />",
400 {"class": "version", "scope": "col"})
401 .text("Version"))
402 .append($("<th />",
403 {"class": "size", "scope": "col"})
404 .text("Size"))
405 .append($("<th />", {
406 "class": "modified",
407 "scope": "col"
408 }).text("Modified"))
409 .append($("<th />", {
410 "class": "modified-by border-right",
411 "scope": "col"
412 }).text("Modified By"))))
413 .append(tbody)
414 .append($("<tfoot />").append($("<tr />").append($("<td />", {
415 "colspan": "5",
416 "class": "border-right border-left"
417 })))));
418
419 for (var i = 0; i < data.length; i++) {
420 action = data[i];
421
422 row = $("<tr />");
423 if (i % 2) {
424 row.addClass("odd");
425 }
426 if (action.action == "DELETE") {
427 row.addClass("delete");
428 }
429 else {
430 row.addClass("with-context-menu");
431 row.attr("file_version", action.version);
432 row.attr("file_hash", action.update.hash);
433 row.attr("file_seg_num", action.update.segNum);
434 row.attr("file_modified_by", action.id.userName);
435 }
436
437 row.attr("filename", action.filename);
438
439 self = this;
440 if (PARAMS.item != action.filename) {
441 row.bind('click', function(e) {
442 openHistoryForItem($(this).attr("filename"))
443 });
444 }
445 else {
446 row.bind('click', function(e) {
447 self.previewFile($(this));
448 });
449 }
450
451 row.bind('mouseenter mouseleave', function() {
452 $(this).toggleClass('highlighted');
453 });
454
455 row.append(
456 $("<td />", {"class": "filename border-left"})
457 .text(action.filename)
458 .prepend($("<img />",
459 {"src": imgFullPath(fileExtension(action.filename))})));
460 row.append($("<td />", {"class": "version"}).text(action.version));
461 row.append(
462 $("<td />", {
463 "class": "size"
464 }).text(action.update ? SegNumToFileSize(action.update.segNum) : ""));
465 row.append($("<td />", {
466 "class": "timestamp"
467 }).text(new Date(action.timestamp + "+00:00"))); // conversion
468 // from UTC
469 // timezone (we
470 // store action
471 // time in UTC)
472 row.append($("<td />", {"class": "modified-by border-right"})
473 .append($("<userName />").text(action.id.userName))
474 .append($("<seqNo> /").text(action.id.seqNo)));
475
476 tbody = tbody.append(row);
477 }
478
479 displayContent(newcontent, more, this.base_url(PAGE));
480
481 self = this;
482 $.contextMenu('destroy', ".with-context-menu"); // cleanup
483 $.contextMenu({
484 selector: ".with-context-menu",
485 items: {
486 "sep1": "---------",
487 preview: {
488 name: "Preview revision",
489 icon: "edit", // ned a better icon
490 callback: function(key, opt) {
491 self.previewFile(opt.$trigger);
492 }
493 },
494 "sep3": "---------",
495 restore: {
496 name: "Restore this revision",
497 icon: "cut", // need a better icon
498 callback: function(key, opt) {
499 filename = opt.$trigger.attr("filename");
500 version = opt.$trigger.attr("file_version");
501 hash = DataUtils.toNumbers(opt.$trigger.attr("file_hash"));
502 console.log(hash);
503 modified_by = opt.$trigger.attr("file_modified_by");
504
505 $("<div />", {"title": "Restore version " + version + "?"})
506 .append(
507 $("<p />").append($("<span />", {
508 "class": "ui-icon ui-icon-alert",
509 "style": "float: left; margin: 0 7px 50px 0;"
510 }),
511 $(document.createTextNode(
512 "Are you sure you want restore version ")),
513 $("<green/>").text(version),
514 $(document.createTextNode(" by ")),
515 $("<green/>").text(modified_by)))
516 .dialog({
517 resizable: true,
518 height: 200,
519 width: 300,
520 modal: true,
521 show: "blind",
522 hide: "fold",
523 buttons: {
524 "Restore": function() {
525 self = $(this);
526 CHRONOSHARE.cmd_restore_file(filename, version, hash,
527 function(didGetData, response) {
528 if (!didGetData ||
529 response != "OK") {
530 custom_alert(response);
531 }
532 console.log(response);
533 self.dialog("close");
534
535 $.timer(function() {
536 CHRONOSHARE.run();
537 })
538 .once(1000);
539 });
540 },
541 Cancel: function() {
542 $(this).dialog("close");
543 }
544 }
545 });
546 // openHistoryForItem (opt.$trigger.attr ("filename"));
547 }
548 },
549 "sep2": "---------",
550 }
551 });
552 },
553
554 base_no_item_url: function(page) {
555 url = "#" + page + "&user=" +
556 encodeURIComponent(encodeURIComponent(PARAMS.user)) + "&folder=" +
557 encodeURIComponent(encodeURIComponent(PARAMS.folder));
558 return url;
559 },
560
561 base_url: function(page) {
562 url = "#" + page + "&user=" +
563 encodeURIComponent(encodeURIComponent(PARAMS.user)) + "&folder=" +
564 encodeURIComponent(encodeURIComponent(PARAMS.folder));
565 if (PARAMS.item !== undefined) {
566 url += "&item=" + encodeURIComponent(encodeURIComponent(PARAMS.item));
567 }
568 return url;
569 }
Alexander Afanasyevf63a5142013-02-28 02:21:42 -0800570});