44
43
"application/x-javascript" : "text",
45
44
"application/javascript" : "text",
46
45
"application/json" : "text",
47
"application/xml" : "text",
48
"application/ogg" : "audio",
49
"image/svg+xml": "object"
46
"application/xml" : "text"
52
49
/* Mapping MIME types to icons, just the file's basename */
58
55
default_type_icon = "txt.png";
60
57
/* Relative to IVLE root */
61
type_icons_path = "+media/ivle.webapp.core/images/mime";
62
type_icons_path_large = "+media/ivle.webapp.core/images/mime/large";
58
type_icons_path = "media/images/mime";
59
type_icons_path_large = "media/images/mime/large";
64
61
/* Mapping SVN status to icons, just the file's basename */
66
"unversioned": "unversioned.png",
67
"ignored": null, /* Supposed to be innocuous */
68
64
"normal": "normal.png",
69
65
"added": "added.png",
70
66
"missing": "missing.png",
71
67
"deleted": "deleted.png",
72
"replaced": "replaced.png",
73
68
"modified": "modified.png",
74
69
"conflicted": "conflicted.png",
75
70
"revision": "revision.png"
140
134
* May be "application/x-www-form-urlencoded" or "multipart/form-data".
141
135
* Defaults to "application/x-www-form-urlencoded".
142
136
* "multipart/form-data" is recommended for large uploads.
143
* \param callback, optional.
144
* A callback function for after the action has been handled.
146
function do_action(action, path, args, content_type, callback)
138
function do_action(action, path, args, content_type, ignore_response)
148
140
args.action = action;
149
141
/* Callback action, when the server returns */
150
var callback_inner = function(response)
142
var callback = function(response)
152
144
/* Check for action errors reported by the server, and report them
154
146
var error = response.getResponseHeader("X-IVLE-Action-Error");
155
if (error != null && error != "")
156
148
/* Note: This header (in particular) comes URI-encoded, to
157
149
* allow multi-line error messages. Decode */
158
150
alert("Error: " + decodeURIComponent(error.toString()) + ".");
159
151
/* Now read the response and set up the page accordingly */
160
if (callback != null)
161
callback(path, response);
152
if (ignore_response != true)
153
handle_response(path, response, true);
163
155
/* Call the server and perform the action. This mutates the server. */
164
ajax_call(callback_inner, service_app, path, args, "POST", content_type);
156
ajax_call(callback, service_app, path, args, "POST", content_type);
167
159
/** Calls the server using Ajax, requesting a directory listing. This should
322
310
setup_for_listing();
325
/* Top-level dir, with subjects */
326
special_home_listing(listing, subjects, path);
330
/* Not the top-level dir. Do a normal dir listing. */
331
handle_dir_listing(path, listing.listing);
311
home_listing(listing, subjects, path);
336
/* Read the response and set up the page accordingly */
337
var content_type = current_file.type;
338
handle_contents_response(path, content_type, url_args);
315
/* Need to make a 2nd ajax call, this time get the actual file
317
callback = function(response)
319
/* Read the response and set up the page accordingly */
320
handle_contents_response(path, response);
322
/* Call the server and request the listing. */
324
args = shallow_clone_object(url_args);
327
/* This time, get the contents of the file, not its metadata */
328
args['return'] = "contents";
329
ajax_call(callback, service_app, path, args, "GET");
341
331
update_actions(isdir);
344
function handle_contents_response(path, content_type)
334
function handle_contents_response(path, response)
346
336
/* Treat this as an ordinary file. Get the file type. */
347
//var content_type = response.getResponseHeader("Content-Type");
337
var content_type = response.getResponseHeader("Content-Type");
348
338
var handler_type = get_handler_type(content_type);
339
would_be_handler_type = handler_type;
349
340
/* handler_type should now be set to either
350
* "text", "image", "video", "audio" or "binary". */
341
* "text", "image", "audio" or "binary". */
351
342
switch (handler_type)
354
handle_text(path, content_type);
345
handle_text(path, response.responseText,
346
would_be_handler_type);
360
handle_video(path, content_type);
349
/* TODO: Custom image handler */
350
handle_binary(path, response.responseText);
363
handle_audio(path, content_type);
366
handle_object(path, content_type);
353
/* TODO: Custom audio handler */
354
handle_binary(path, response.responseText);
369
357
handle_binary(path);
524
502
return default_svn_nice;
527
/** Returns true if a file is versioned (not unversioned or ignored).
529
function svnstatus_versioned(svnstatus)
531
return svnstatus != "unversioned" && svnstatus != "ignored";
534
505
/** Displays a download link to the binary file.
536
507
function handle_binary(path)
538
// Disable save button
539
using_codepress = false;
540
disable_save_if_safe();
542
// Show download link
543
509
var files = document.getElementById("filesbody");
544
510
var div = document.createElement("div");
545
511
files.appendChild(div);
546
512
div.setAttribute("class", "padding");
547
var download_link = app_url(download_app, path);
513
var download_link = app_path(download_app, path);
548
514
var par1 = dom_make_text_elem("p",
549
515
"The file " + path + " is a binary file. To download this file, " +
550
516
"click the following link:");
554
520
div.appendChild(par2);
557
/** Displays an image file.
559
function handle_image(path)
561
/* Disable save button */
562
using_codepress = false;
563
disable_save_if_safe();
566
var url = app_url(service_app, path) + "?return=contents";
569
var img = $("<img />");
570
img.attr("alt", path);
571
img.attr("src", url);
574
var div = $('<div class="padding" />');
575
div.append('<h1>Image Preview</h1>');
577
$("#filesbody").append(div);
580
/** Displays a video.
582
function handle_video(path, type)
584
/* Disable save button and hide the save panel */
585
using_codepress = false;
586
disable_save_if_safe();
589
var url = app_url(service_app, path) + "?return=contents";
590
var download_url = app_url(download_app, path);
592
/* Fallback Download Link */
593
var link = $('<p>Could not display video in browser.<p><p><a /></p>');
594
var a = link.find('a');
595
a.attr("href", download_url);
596
a.text("Download " + path);
598
/* Fallback Object Tag */
599
var obj = $('<object />');
600
obj.attr("type", type);
601
obj.attr("data", url);
604
/* HTML 5 Video Tag */
605
var video = $('<video controls="true" autoplay="true" />');
606
video.attr("src", url);
607
var support = video[0].canPlayType && video[0].canPlayType(type);
608
if (support != "probably" && support != "maybe") {
614
var div = $('<div class="padding" />');
615
div.append('<h1>Video Preview</h1>');
617
$("#filesbody").append(div);
620
/** Display audio content
622
function handle_audio(path, type)
624
/* Disable save button and hide the save panel */
625
using_codepress = false;
626
disable_save_if_safe();
629
var url = app_url(service_app, path) + "?return=contents";
630
var download_url = app_url(download_app, path);
632
/* Fallback Download Link */
633
var link = $('<p>Could not display audio in browser.<p><p><a /></p>');
634
var a = link.find('a');
635
a.attr("href", download_url);
636
a.text("Download " + path);
638
/* Fallback Object Tag */
639
var obj = $('<object />');
640
obj.attr("type", type);
641
obj.attr("data", url);
644
/* HTML 5 Audio Tag */
645
var audio = $('<audio controls="true" autoplay="true" />');
646
audio.attr("src", url);
647
var support = audio[0].canPlayType && audio[0].canPlayType(type);
648
if (support != "probably" && support != "maybe") {
654
var div = $('<div class="padding" />');
655
div.append('<h1>Audio Preview</h1>');
657
$("#filesbody").append(div);
660
/** Display generic object content
662
function handle_object(path, content_type)
664
/* Disable save button and hide the save panel */
665
using_codepress = false;
666
disable_save_if_safe();
669
var url = app_url(service_app, path) + "?return=contents";
670
var download_url = app_url(download_app, path);
672
/* Fallback Download Link */
673
var link = $('<p><a /></p>');
674
var a = link.find('a');
675
a.attr("href", download_url);
676
a.text("Download " + path);
679
var obj = $('<object width="100%" height="500px" />');
680
obj.attr("type", content_type);
681
obj.attr("data", url);
682
obj.append('Could not load object');
685
var div = $('<div class="padding" />');
686
div.append('<h1>Preview</h1>');
689
$("#filesbody").append(div);
692
523
/* Enable or disable actions1 moreactions actions. Takes either a single
693
524
* name, or an array of them.*/
694
525
function set_action_state(names, which, allow_on_revision)
784
601
"return maybe_save('The last saved version will be served.')");
786
603
serve.setAttribute("href",
787
app_url(serve_app, current_path));
604
app_path(serve_app, current_path));
789
606
serve.setAttribute("href",
790
app_url(serve_app, current_path, filename));
607
app_path(serve_app, current_path, filename));
886
703
var pubcond = numsel <= 1 && file.isdir;
706
/* TODO: Work out of file is svn'd */
889
707
/* If this dir is already published, call it "Unpublish" */
890
708
if (file.published)
892
710
publish.setAttribute("value", "unpublish");
893
711
publish.setAttribute("title" ,"Make it so this directory "
894
712
+ "can not be seen by anyone on the web");
895
publish.firstChild.nodeValue = "Unpublish";
713
publish.textContent = "Unpublish";
897
715
publish.setAttribute("value", "publish");
898
716
publish.setAttribute("title","Make it so this directory "
899
717
+ "can be seen by anyone on the web");
900
publish.firstChild.nodeValue = "Publish";
718
publish.textContent = "Publish";
903
721
set_action_state(["publish", "submit"], pubcond);
924
742
/* Subversion actions */
925
743
/* These are only useful if we are in a versioned directory and have some
926
744
* files selected. */
927
set_action_state(["svnrename"], numsel == 1 && current_file.svnstatus);
928
set_action_state(["svnadd"], numsel >= 1 && current_file.svnstatus);
929
/* And these are only useful is ALL the selected files are versioned */
930
set_action_state(["svnremove", "svnrevert", "svncopy", "svncut"],
931
numsel >= 1 && current_file.svnstatus && svn_selection);
932
/* Commit is useful if ALL selected files are versioned, or the current
933
* directory is versioned */
934
set_action_state(["svncommit"], current_file.svnstatus &&
935
(numsel >= 1 && svn_selection || numsel == 0));
745
set_action_state(["svnadd", "svnremove", "svnrevert", "svncommit"], numsel >= 1 && current_file.svnstatus);
937
747
/* Diff, log and update only support one path at the moment, so we must
938
748
* have 0 or 1 versioned files selected. If 0, the directory must be
950
760
/* Log should be available for revisions as well. */
951
761
set_action_state("svnlog", single_versioned_path, true);
953
/* Cleanup should be available for revisions as well. */
954
set_action_state("svncleanup", single_versioned_path, true);
956
single_ivle_versioned_path = (
958
(numsel == 1 && (stat = file_listing[selected_files[0]])) ||
959
(numsel == 0 && (stat = current_file))
960
) && svnstatus_versioned(stat.svnstatus)
962
&& stat.svnurl.substr(0, svn_base.length) == svn_base);
963
set_action_state(["submit"], single_ivle_versioned_path);
965
763
/* There is currently nothing on the More Actions menu of use
966
764
* when the current file is not a directory. Hence, just remove
1011
814
action_unpublish(selected_files);
1014
window.open(public_app_url("~" + current_path, filename), 'share')
817
//alert("Not yet implemented: Sharing files");
818
window.open(public_app_path(serve_app, current_path, filename), 'share')
1017
if (selected_files.length == 1)
1018
stat = file_listing[selected_files[0]];
1020
stat = current_file;
1021
url = stat.svnurl.substr(svn_base.length); // URL-encoded
1022
path = decodeURIComponent(url);
1024
/* The working copy might not have an up-to-date version of the
1025
* directory. While submitting like this could yield unexpected
1026
* results, we should really submit the latest revision to minimise
1027
* terrible mistakes - so we run off and ask fileservice for the
1028
* latest revision.*/
1029
$.post(app_path(service_app, current_path),
1030
{"action": "svnrepostat", "path": path},
1033
window.location = path_join(app_path('+submit'), url) + '?revision=' + result.svnrevision;
822
alert("Not yet implemented: Submit");
1039
825
action_rename(filename);
1063
849
action_add(selected_files);
1065
851
case "svnremove":
1066
action_svnremove(selected_files);
1069
action_svnrename(selected_files);
852
action_remove(selected_files);
1071
854
case "svnrevert":
1072
855
action_revert(selected_files);
1075
window.location = path_join(app_url('diff'), current_path, selected_files[0] || '');
858
window.location = path_join(app_path('diff'), current_path, selected_files[0] || '');
1077
860
case "svnupdate":
1078
861
action_update(selected_files);