diff --git a/cgi-bin/download.cgi b/cgi-bin/download.cgi
new file mode 100755
index 0000000..b412043
--- /dev/null
+++ b/cgi-bin/download.cgi
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+import cgitb; cgitb.enable()
+import os, sys, cgi
+from project import Project
+from zipfile import ZipFile
+
+
+method = os.environ.get("REQUEST_METHOD", "")
+fs = cgi.FieldStorage()
+project = fs.getvalue("p", "")
+paths = fs.getlist("f[]")
+
+if paths:
+ proj = Project(project)
+ zippath = os.path.join(proj.fullpath, "{0}.zip".format(project))
+ with ZipFile(zippath, 'w') as zzip:
+ for p in paths:
+ fp = os.path.join(proj.fullpath, p)
+ # print >> sys.stderr, "*** rm", fp
+ _, base = os.path.split(fp)
+ zzip.write(fp, project+"/"+base)
+ # serve zippath
+ print "Content-type: application/zip"
+ print "Content-disposition: attachment; filename={0}.zip".format(project)
+ print "Content-length: {0}".format(os.path.getsize(zippath))
+ print
+ with open(zippath) as f:
+ while True:
+ data = f.read()
+ if data == "":
+ break
+ sys.stdout.write(data)
+ os.unlink(zippath)
+
diff --git a/cgi-bin/hype.cgi b/cgi-bin/hype.cgi
index c27db96..801844e 100755
--- a/cgi-bin/hype.cgi
+++ b/cgi-bin/hype.cgi
@@ -1,4 +1,12 @@
#!/usr/bin/env python
+#
+# (c) 2014 Michael Murtaugh and contributors to the Digital Publishing Toolkit
+
+# License: GPL3
+
+# This code has been developed as part of the [Digital Publishing Toolkit](http://digitalpublishingtoolkit.org).
+# with the support of Institute for [Network Cultures](http://networkcultures.org)
+# and [Creating 010](http://creating010.com).
import cgitb; cgitb.enable()
import os, sys, cgi, mimetypes
@@ -33,11 +41,13 @@ print """
+
+
diff --git a/editor.css b/editor.css
index 6dd95a7..a446531 100644
--- a/editor.css
+++ b/editor.css
@@ -101,6 +101,23 @@ a:hover {
width: auto;
}
+#listing div.item a {
+ text-decoration: none;
+}
+
+#listing div.item.active a {
+ font-weight: bold;
+}
+
+#listing div.item.active a::after {
+ content: " \2192";
+ font-weight: bold;
+}
+
+#listing div.item a:hover {
+ text-decoration: underline;
+}
+
#listing div.item a.normal {
color: black;
}
@@ -126,6 +143,10 @@ a:hover {
display: none;
}
+#listing button, #listing select {
+ margin-right: 2px;
+}
+
/* *** */
#editor {
@@ -158,6 +179,10 @@ a:hover {
font-size: 12px;
}
+.editorfoot button, .editorfoot select {
+ margin-right: 6px;
+}
+
#editor .preview {
position: absolute;
left: 0; right: 0;
diff --git a/editor.js b/editor.js
index 0a819e3..5dafc6a 100644
--- a/editor.js
+++ b/editor.js
@@ -1,3 +1,16 @@
+/*
+
+(c) 2014 Michael Murtaugh and contributors to the Digital Publishing Toolkit
+
+License: GPL3
+
+This code has been developed as part of the [Digital Publishing Toolkit](http://digitalpublishingtoolkit.org).
+with the support of Institute for [Network Cultures](http://networkcultures.org)
+and [Creating 010](http://creating010.com).
+
+*/
+
+
var editor_factory = aa_aceeditor(window.ace),
editor = editor_factory.get_editor(),
editor_elt = d3.select(editor.elt),
@@ -21,6 +34,7 @@ var editor_factory = aa_aceeditor(window.ace),
.append("div")
.attr("class", "gear");
+
function url_for (script) {
return cgi_url+script+"?p=" + encodeURIComponent(project);
}
@@ -92,17 +106,30 @@ aa_frames(document.getElementById("split"));
document.getElementById("editor").appendChild(editor.elt);
-function edit (url) {
- editor.href(url);
+var activeURL;
+
+function updateActiveItem () {
+ var item = d3.selectAll("#listing div.item")
+ .classed("active", function (d) {
+ return d.url == activeURL;
+ });
+}
+
+function edit (url, done, forceReload) {
+ activeURL = url;
+ editor.href(url, done, forceReload);
+ editor.aceeditor.focus();
editor_elt
.style("display", "block");
preview_div
.style("display", "none");
close_make();
+ updateActiveItem();
// make_div.style("display", "none");
}
function preview (url) {
+ activeURL = url;
preview_div
.style("display", "block");
editor_elt
@@ -110,6 +137,7 @@ function preview (url) {
preview_iframe
.attr("src", url);
close_make();
+ updateActiveItem();
// make_div.style("display", "none");
}
@@ -143,18 +171,11 @@ function make (path, done) {
function make_busy (val) {
make_div.classed("busy", val);
}
-/*
+
function select_all () {
- var checkboxes = d3.selectAll(".itemcheckbox"),
- checked = d3.selectAll(".itemcheckbox:checked");
- if (checkboxes.size() == checked.size()) {
- checkboxes.property("checked", false);
- } else {
- checkboxes.property("checked", true);
- }
+ d3.selectAll("#listing div.item").each(item_select);
update_selection();
}
-*/
function delete_selection () {
var items_selected = d3.selectAll("#listing div.selected"),
@@ -181,6 +202,25 @@ function delete_selection () {
}
}
+function download_selection () {
+ var items_selected = d3.selectAll("#listing div.selected"),
+ num_selected = items_selected.size(),
+ paths = items_selected.data().map(function (d) { return d.path });
+
+ if (num_selected == 0) return;
+ var ok = true; //confirm("Download "+num_selected+" selected file"+((num_selected==1)?"":"s") + "?");
+ if (ok) {
+ var url = url_for("download.cgi");
+ url += paths.map(function(x) { return "&f[]="+encodeURIComponent(x); }).join("");
+ // console.log("download", url);
+ preview_iframe
+ .attr("src", url);
+
+ items_selected.each(item_deselect);
+ update_selection();
+ }
+}
+
var longclick_begin;
function item_select (d) {
@@ -256,7 +296,7 @@ function rename () {
$("#listing .listing_rename_buttons").hide();
return;
}
- var ok = confirm("Rename "+ss.size()+" file"+((ss==1)?"":"s") + "?");
+ var ok = true; // confirm("Rename "+ss.size()+" file"+((ss==1)?"":"s") + "?");
if (ok) {
ss.each(function (d) {
var newpath = d3.select(this.parentNode).select("input.rename").property("value");
@@ -320,12 +360,16 @@ function refresh_listing(done) {
}
if (d.remake) {
// alert("make");
+ activeURL = d.url;
+ updateActiveItem();
make(d.path, function () {
// re-get the d in case of change!
var d = d3.select(that).datum();
// console.log("d", d, d.binary, d.url);
if (!d.binary) {
- edit(d.url);
+ // force reload!
+ console.log("force reload")
+ edit(d.url, null, true);
} else {
preview(d.url);
}
@@ -364,8 +408,10 @@ refresh_listing();
$("#listing .body").niceScroll({cursorcolor:"#0F0"});
$("#editor .make .body").niceScroll({cursorcolor:"#0F0"});
+$("#listing_select_all").click(select_all);
$("#listing_refresh").click(refresh_listing);
$("#listing_delete").click(delete_selection);
+$("#listing_download").click(download_selection);
$("#listing_rename").click(rename);
$("#listing_cancel").click(listing_cancel);
// $("#listing_select_all").click(select_all);
diff --git a/lib/aa/ace-editor.js b/lib/aa/ace-editor.js
index 1378b7a..bda8e20 100644
--- a/lib/aa/ace-editor.js
+++ b/lib/aa/ace-editor.js
@@ -26,7 +26,7 @@ function aa_aceeditor (ace) {
current_href,
highlightLineStart,
highlightLineEnd,
- _save;
+ _save, _reload;
editor.elt = document.createElement("div");
@@ -42,6 +42,9 @@ function aa_aceeditor (ace) {
editor.save = function (callback) {
_save = callback;
}
+ editor.reload = function (callback) {
+ _reload = callback;
+ }
// a bit of a brutal solution but...
$(document).bind("resize", function (e) {
@@ -79,6 +82,24 @@ function aa_aceeditor (ace) {
}
});
+ var reload = foot
+ .append("button")
+ .text("reload")
+ .on("click", function () {
+ var text;
+ if (_reload) {
+ text = editor.aceeditor.getValue();
+ _reload.call(editor, {
+ text: text,
+ href: current_href
+ });
+ } else {
+ editor.href(current_href, null, true);
+ aceeditor.focus();
+ }
+ });
+
+
function highlight(s, e) {
var session = editor.aceeditor.getSession();
if (highlightLineStart) {
@@ -111,9 +132,9 @@ function aa_aceeditor (ace) {
if (session == "loading") {
return false;
}
- /*
- todo, improve this.. now commented out to force reload
- if (session != undefined) {
+
+ // todo, improve this.. now commented out to force reload
+ if (!forceReload && (session != undefined)) {
if (done) {
window.setTimeout(function () {
done.call(session);
@@ -128,7 +149,6 @@ function aa_aceeditor (ace) {
return true;
}
- */
sessionsByHref[href.nofrag] = "loading";
$.ajax({
url: href.nofrag,