gui/html: Now files/action browsing is complete
File browsing for now lists all files in the folder **without**
directories. We probably would need to implement normal browsing at
some point, but it requires modification of FileState.
File restoring is coming soon. Stay tuned.
Change-Id: I273366e04164716bfb53e92585cdf02808e4d06a
diff --git a/gui/html/chronoshare-helpers.js b/gui/html/chronoshare-helpers.js
new file mode 100644
index 0000000..ed95925
--- /dev/null
+++ b/gui/html/chronoshare-helpers.js
@@ -0,0 +1,58 @@
+function number_format( number, decimals, dec_point, thousands_sep ) {
+ // http://kevin.vanzonneveld.net
+ // + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + bugfix by: Michael White (http://crestidg.com)
+ // + bugfix by: Benjamin Lupton
+ // + bugfix by: Allan Jensen (http://www.winternet.no)
+ // + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
+ // * example 1: number_format(1234.5678, 2, '.', '');
+ // * returns 1: 1234.57
+
+ var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals;
+ var d = dec_point == undefined ? "," : dec_point;
+ var t = thousands_sep == undefined ? "." : thousands_sep, s = n < 0 ? "-" : "";
+ var i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
+
+ return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
+}
+
+function SegNumToFileSize (segNum) {
+ filesize = segNum * 1024;
+
+ if (filesize >= 1073741824) {
+ filesize = number_format(filesize / 1073741824, 2, '.', '') + ' Gb';
+ } else {
+ if (filesize >= 1048576) {
+ filesize = number_format(filesize / 1048576, 2, '.', '') + ' Mb';
+ } else {
+ if (filesize > 1024) {
+ filesize = number_format(filesize / 1024, 0) + ' Kb';
+ } else {
+ filesize = '< 1 Kb';
+ };
+ };
+ };
+ return filesize;
+};
+
+/**
+ * @brief Convert binary data represented as non-escaped hex string to Uint8Array
+ * @param str String like ba0cb43e4b9639c114a0487d5faa7c70452533963fc8beb37d1b67c09a48a21d
+ *
+ * Note that if string length is odd, null will be returned
+ */
+StringHashToUint8Array = function (str) {
+ if (str.length % 2 != 0) {
+ return null;
+ }
+
+ var buf = new Uint8Array (str.length / 2);
+
+ for (var i = 0; i < str.length; i+=2) {
+ value = parseInt (str.substring (i, i+2), 16);
+ buf[i/2] = value;
+ }
+
+ return buf;
+};
diff --git a/gui/html/chronoshare-navigation.js b/gui/html/chronoshare-navigation.js
new file mode 100644
index 0000000..7dafd71
--- /dev/null
+++ b/gui/html/chronoshare-navigation.js
@@ -0,0 +1,70 @@
+var CHRONOSHARE;
+
+var PAGE; // no default page anymore (no reason to have)
+var PARAMS = [ ];
+var URIPARAMS = "";
+
+function nav_anchor (aurl) {
+ aurl = aurl.split('#');
+ if (aurl[1])
+ {
+ aurl_split = aurl[1].split ('&');
+ page = aurl_split[0];
+
+ vars = [ ];
+ for (var i = 1; i < aurl_split.length; i++)
+ {
+ hash = aurl_split[i].split('=');
+ vars.push(hash[0]);
+ // there is strange double-encoding problem...
+ vars[hash[0]] = decodeURIComponent (decodeURIComponent (hash[1]));
+ }
+
+ if (page != PAGE)
+ {
+ PAGE = page;
+ PARAMS = vars;
+ URIPARAMS = aurl[1];
+
+ if (CHRONOSHARE) {
+ CHRONOSHARE.run ();
+ }
+ }
+ else if (aurl[1] != URIPARAMS)
+ {
+ PARAMS = vars;
+ URIPARAMS = aurl[1];
+
+ if (CHRONOSHARE) {
+ CHRONOSHARE.run ();
+ }
+ }
+ }
+}
+
+$(document).ready (function () {
+ nav_anchor (window.location.href);
+
+ if (!PARAMS.user || !PARAMS.folder)
+ {
+ $("#error").html ("user and folder must be be specified in the URL");
+ $("#error").removeClass ("hidden");
+ return;
+ }
+ else {
+ // update in-page URLs
+ $(".needs-get-url").each (function (index,element) {
+ this.href += "&user="+encodeURIComponent (encodeURIComponent (PARAMS.user))
+ + "&folder="+encodeURIComponent (encodeURIComponent (PARAMS.folder));
+ });
+ $(".needs-get-url").removeClass ("needs-get-url");
+ }
+
+ CHRONOSHARE = new ChronoShare (PARAMS.user, PARAMS.folder);
+ CHRONOSHARE.run ();
+
+ $(window).on('hashchange', function() {
+ nav_anchor (window.location.href);
+ });
+});
+
diff --git a/gui/html/chronoshare.js b/gui/html/chronoshare.js
index ffd9724..bf8b4a1 100644
--- a/gui/html/chronoshare.js
+++ b/gui/html/chronoshare.js
@@ -1,94 +1,78 @@
-var CHRONOSHARE;
+$.Class ("ChronoShare", { },
+ {
+ init: function (username, foldername) {
+ $("#folder-name").text (foldername);
+ $("#user-name").text (username);
-var PAGE = "folderHistory";
-var PARAMS = [ ];
-var URIPARAMS = "";
+ this.username = new Name (username);
+ this.files = new Name ("/localhost").add (this.username).add ("chronoshare").add (foldername).add ("info").add ("files").add ("folder");
-function nav_anchor (aurl) {
- aurl = aurl.split('#');
- if (aurl[1])
- {
- aurl_split = aurl[1].split ('&');
- page = aurl_split[0];
+ this.actions = new Name ("/localhost").add (this.username).add ("chronoshare").add (foldername).add ("info").add ("actions");
- vars = [ ];
- for (var i = 1; i < aurl_split.length; i++)
- {
- hash = aurl_split[i].split('=');
- vars.push(hash[0]);
- // there is strange double-encoding problem...
- vars[hash[0]] = decodeURIComponent (decodeURIComponent (hash[1]));
- }
+ this.restore = new Name ("/localhost").add (this.username).add ("chronoshare").add (foldername).add ("cmd").add ("restore").add ("file");
- if (page != PAGE)
- {
- PAGE = page;
- PARAMS = vars;
- URIPARAMS = aurl[1];
+ this.ndn = new NDN ({host:"127.0.0.1"});
+ },
- if (CHRONOSHARE) {
- CHRONOSHARE.run ();
- }
- }
- else if (aurl != URIPARAMS)
- {
- PARAMS = vars;
- URIPARAMS = aurl[1];
+ run: function () {
+ console.log ("RUN page: " + PAGE);
+ $("#loader").fadeIn (500);
+ $("#error").addClass ("hidden");
- if (CHRONOSHARE) {
- CHRONOSHARE.run ();
- }
- }
- }
-}
+ cmd = {};
+ if (PAGE == "fileList") {
+ cmd = this.info_files (PARAMS.item);
+ }
+ else if (PAGE == "folderHistory") {
+ cmd = this.info_actions ("folder", PARAMS.item);
+ }
+ else if (PAGE == "fileHistory") {
+ cmd = this.info_actions ("file", PARAMS.item);
+ }
-$(document).ready (function () {
- nav_anchor (window.location.href);
+ if (cmd.request && cmd.callback) {
+ console.log (cmd.request.to_uri ());
+ this.ndn.expressInterest (cmd.request, cmd.callback);
+ }
+ else {
+ $("#loader").fadeOut (500); // ("hidden");
+ $("#content").empty ();
+ if (cmd.error) {
+ $("#error").html (cmd.error);
+ }
+ else {
+ $("#error").html ("Unknown error with " + PAGE);
+ }
+ $("#error").removeClass ("hidden");
+ }
+ },
- if (!PARAMS.user || !PARAMS.folder)
- {
- $("#error").html ("user and folder must be be specified in the URL");
- $("#error").removeClass ("hidden");
- return;
- }
- else {
- // update in-page URLs
- $(".needs-get-url").each (function (index,element) {
- this.href += "&user="+encodeURIComponent (encodeURIComponent (PARAMS.user))
- + "&folder="+encodeURIComponent (encodeURIComponent (PARAMS.folder));
- });
- $(".needs-get-url").removeClass ("needs-get-url");
- }
+ info_files: function(folder) {
+ request = new Name ().add (this.files)./*add (folder_in_question).*/addSegment (PARAMS.offset?PARAMS.offset:0);
+ return { request:request, callback: new FilesClosure (this) };
+ },
- CHRONOSHARE = new ChronoShare (PARAMS.user, PARAMS.folder);
- CHRONOSHARE.run ();
+ info_actions: function (type/*"file" or "folder"*/, fileOrFolder /*file or folder name*/) {
+ if (type=="file" && !fileOrFolder) {
+ return { error: "info_actions: fileOrFolder parameter is missing" };
+ }
- $(window).on('hashchange', function() {
- nav_anchor (window.location.href);
- });
-});
+ request = new Name ().add (this.actions).add (type);
+ if (fileOrFolder) {
+ request.add (fileOrFolder);
+ }
+ request.addSegment (PARAMS.offset?PARAMS.offset:0);
+ return { request: request, callback: new HistoryClosure (this) };
+ },
-/**
- * @brief Convert binary data represented as non-escaped hex string to Uint8Array
- * @param str String like ba0cb43e4b9639c114a0487d5faa7c70452533963fc8beb37d1b67c09a48a21d
- *
- * Note that if string length is odd, null will be returned
- */
-StringHashToUint8Array = function (str) {
- if (str.length % 2 != 0) {
- return null;
- }
-
- var buf = new Uint8Array (str.length / 2);
-
- for (var i = 0; i < str.length; i+=2) {
- value = parseInt (str.substring (i, i+2), 16);
- buf[i/2] = value;
- }
-
- return buf;
-};
-
+ cmd_restore_file: function (filename, version, hash) {
+ request = new Name ().add (this.restore)
+ .add (filename)
+ .addSegment (version)
+ .add (hash);
+ console.log (request.to_uri ());
+ }
+ });
$.Class ("FilesClosure", {}, {
init: function (chronoshare) {
@@ -105,21 +89,24 @@
}
data = JSON.parse (convertedData);
+ tbody = $("<tbody />", { "id": "file-list-files" });
+
// error handling?
- table = $("#content").append (
+ newcontent = $("<div />", { "id": "content" }).append (
$("<table />", { "class": "item-list" })
.append ($("<thead />")
.append ($("<tr />")
.append ($("<th />", { "class": "filename border-left", "scope": "col" }).text ("Filename"))
.append ($("<th />", { "class": "version", "scope": "col" }).text ("Version"))
+ .append ($("<th />", { "class": "size", "scope": "col" }).text ("Size"))
.append ($("<th />", { "class": "modified", "scope": "col" }).text ("Modified"))
.append ($("<th />", { "class": "modified-by border-right", "scope": "col" }).text ("Modified By"))))
- .append ($("<tbody />", { "id": "file-list-files" }))
+ .append (tbody)
.append ($("<tfoot />")
.append ($("<tr />")
- .append ($("<td />", { "colspan": "4", "class": "border-right border-left" })))));
+ .append ($("<td />", { "colspan": "5", "class": "border-right border-left" })))));
+ newcontent.hide ();
- var html = $("#file-list-files");
for (var i = 0; i < data.files.length; i++) {
file = data.files[i];
@@ -130,28 +117,71 @@
$(this).toggleClass('highlighted');
});
- row.attr ("filename", encodeURIComponent(encodeURIComponent(file.filename)));
+ row.attr ("filename", file.filename); //encodeURIComponent(encodeURIComponent(file.filename)));
+
row.bind('click', function (e) {
- url = "#fileHistory";
- url += "&item=" + $(this).attr ("filename");
- pos = URIPARAMS.indexOf ("&");
- if (pos >= 0) {
- url += URIPARAMS.substring (pos)
- }
+ url = new HistoryClosure (null).base_url ("fileHistory")
+ url += "&item=" + encodeURIComponent (encodeURIComponent ($(this).attr ("filename")));
document.location = url;
});
- row.append ($("<td />", {"class": "border-left"}).text (file.filename));
- row.append ($("<td />").text (file.version));
- row.append ($("<td />").text (new Date (file.timestamp)));
- row.append ($("<td />", {"class": "border-right"})
+ row.append ($("<td />", { "class": "filename border-left" }).text (file.filename));
+ row.append ($("<td />", { "class": "version" }).text (file.version));
+ row.append ($("<td />", { "class": "size" }).text (SegNumToFileSize (file.segNum)));
+ row.append ($("<td />", { "class": "modified" }).text (new Date (file.timestamp)));
+ row.append ($("<td />", { "class": "modified-by border-right"})
.append ($("<userName />").text (file.owner.userName))
.append ($("<seqNo> /").text (file.owner.seqNo)));
- html = html.append (row);
+ tbody = tbody.append (row);
}
+
+ // if (!PARAMS.offset || PARAMS.offset==0)
+ // {
+ $("#content").fadeOut ("fast", function () {
+ $(this).replaceWith (newcontent);
+ $("#content").fadeIn ("fast");
+ });
+
+ self = this; // small "cheat"
+ $("#content-nav").fadeOut ("fast", function () {
+ $("#content-nav a").hide ();
+
+ if (PARAMS.offset !== undefined || data.more !== undefined) {
+ $("#content-nav").fadeIn ("fast");
+
+ if (data.more !== undefined) {
+ $("#get-more").show ();
+
+ $("#get-more").unbind ('click').click (function () {
+ url = self.base_url ();
+ url += "&offset="+data.more;
+
+ document.location = url;
+ });
+ }
+ if (PARAMS.offset > 0) {
+ $("#get-less").show ();
+
+ $("#get-less").unbind ('click').click (function () {
+ url = self.base_url ();
+ if (PARAMS.offset > 1) {
+ url += "&offset="+(PARAMS.offset - 1);
+ }
+
+ document.location = url;
+ });
+ }
+ }
+ });
+ // }
+ // else {
+ // tbody.children ().each (function (index, row) {
+ // $("#history-list-actions").append (row);
+ // });
+ // }
}
else if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
$("#error").html ("Interest timed out");
@@ -161,6 +191,16 @@
$("#error").html ("Unknown error happened");
$("#error").removeClass ("hidden");
}
+ },
+
+ base_url: function () {
+ url = "#fileList"+
+ "&user="+encodeURIComponent (encodeURIComponent (PARAMS.user)) +
+ "&folder="+encodeURIComponent (encodeURIComponent (PARAMS.folder));
+ if (PARAMS.item !== undefined) {
+ url += "&item="+encodeURIComponent (encodeURIComponent (PARAMS.item));
+ }
+ return url;
}
});
@@ -180,8 +220,9 @@
}
data = JSON.parse (convertedData);
- // error handling?
- table = $("#content").append (
+ tbody = $("<tbody />", { "id": "history-list-actions" });
+
+ newcontent = $("<div />", { "id": "content" }).append (
$("<table />", { "class": "item-list" })
.append ($("<thead />")
.append ($("<tr />")
@@ -189,44 +230,90 @@
.append ($("<th />", { "class": "version", "scope": "col" }).text ("Version"))
.append ($("<th />", { "class": "modified", "scope": "col" }).text ("Modified"))
.append ($("<th />", { "class": "modified-by border-right", "scope": "col" }).text ("Modified By"))))
- .append ($("<tbody />", { "id": "history-list-actions" }))
+ .append (tbody)
.append ($("<tfoot />")
.append ($("<tr />")
.append ($("<td />", { "colspan": "4", "class": "border-right border-left" })))));
- var html = $("#history-list-actions");
for (var i = 0; i < data.actions.length; i++) {
action = data.actions[i];
row = $("<tr />");
if (i%2) { row.addClass ("odd"); }
+ if (action.action=="DELETE") { row.addClass ("delete"); }
row.bind('mouseenter mouseleave', function() {
$(this).toggleClass('highlighted');
});
- row.attr ("filename", encodeURIComponent(encodeURIComponent(action.filename)));
+ // row.attr ("filename", );//encodeURIComponent(encodeURIComponent(action.filename)));
+ // row.attr ("version",
- row.bind('click', function (e) {
- url = "#fileHistory";
- url += "&item=" + $(this).attr ("filename");
- pos = URIPARAMS.indexOf ("&");
- if (pos >= 0) {
- url += URIPARAMS.substring (pos)
- }
+ // row.bind('click', function (e) {
+ // url = "#fileHistory";
+ // url += "&item=" + $(this).attr ("filename");
+ // pos = URIPARAMS.indexOf ("&");
+ // if (pos >= 0) {
+ // url += URIPARAMS.substring (pos)
+ // }
- document.location = url;
- });
+ // document.location = url;
+ // });
- row.append ($("<td />", {"class": "border-left"}).text (action.filename));
- row.append ($("<td />").text (action.version));
- row.append ($("<td />").text (new Date (action.timestamp)));
- row.append ($("<td />")
+ row.append ($("<td />", { "class": "filename border-left" }).text (action.filename));
+ row.append ($("<td />", { "class": "version" }).text (action.version));
+ row.append ($("<td />", { "class": "timestamp" }).text (new Date (action.timestamp)));
+ row.append ($("<td />", { "class": "modified-by border-right" })
.append ($("<userName />").text (action.id.userName))
.append ($("<seqNo> /").text (action.id.seqNo)));
- html = html.append (row);
+ tbody = tbody.append (row);
}
+
+ // if (!PARAMS.offset || PARAMS.offset==0)
+ // {
+ $("#content").fadeOut ("fast", function () {
+ $(this).replaceWith (newcontent);
+ $("#content").fadeIn ("fast");
+ });
+
+ self = this; // small "cheat"
+ $("#content-nav").fadeOut ("fast", function () {
+ $("#content-nav a").hide ();
+
+ if (PARAMS.offset !== undefined || data.more !== undefined) {
+ $("#content-nav").fadeIn ("fast");
+
+ if (data.more !== undefined) {
+ $("#get-more").show ();
+
+ $("#get-more").unbind ('click').click (function () {
+ url = self.base_url (PAGE);
+ url += "&offset="+data.more;
+
+ document.location = url;
+ });
+ }
+ if (PARAMS.offset > 0) {
+ $("#get-less").show ();
+
+ $("#get-less").unbind ('click').click (function () {
+ url = self.base_url (PAGE);
+ if (PARAMS.offset > 1) {
+ url += "&offset="+(PARAMS.offset - 1);
+ }
+
+ document.location = url;
+ });
+ }
+ }
+ });
+ // }
+ // else {
+ // tbody.children ().each (function (index, row) {
+ // $("#history-list-actions").append (row);
+ // });
+ // }
}
else if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
$("#error").html ("Interest timed out");
@@ -236,52 +323,19 @@
$("#error").html ("Unknown error happened");
$("#error").removeClass ("hidden");
}
+ },
+
+ base_url: function (page) {
+ url = "#"+page+
+ "&user="+encodeURIComponent (encodeURIComponent (PARAMS.user)) +
+ "&folder="+encodeURIComponent (encodeURIComponent (PARAMS.folder));
+ if (PARAMS.item !== undefined) {
+ url += "&item="+encodeURIComponent (encodeURIComponent (PARAMS.item));
+ }
+ return url;
}
});
-$.Class ("ChronoShare", { },
- {
- init: function (username, foldername) {
- this.username = new Name (username);
- this.files = new Name ("/localhost").add (this.username).add ("chronoshare").add (foldername).add ("info").add ("files").add ("folder");
-
- this.actions = new Name ("/localhost").add (this.username).add ("chronoshare").add (foldername).add ("info").add ("actions");
-
- this.restore = new Name ("/localhost").add (this.username).add ("chronoshare").add (foldername).add ("cmd").add ("restore").add ("file");
-
- // this.ndn = new NDN ({host:"127.0.0.1", getHostAndPort: function() { return {host: "127.0.0.1", port: 9696}}});
- this.ndn = new NDN ({host:"127.0.0.1"});
- },
-
-
- run: function () {
- $("#content").empty ();
- $("#loader").fadeIn (500);
- $("#error").addClass ("hidden");
-
- if (PAGE == "fileList") {
- request = new Name ().add (this.files)./*add (folder_in_question).*/add ("nonce").addSegment (0);
- console.log (request.to_uri ());
- this.ndn.expressInterest (request, new FilesClosure (this));
- }
- else if (PAGE == "folderHistory") {
- request = new Name ().add (this.actions).add ("folder")./*add (folder_in_question).*/add ("nonce").addSegment (0);
- console.log (request.to_uri ());
- this.ndn.expressInterest (request, new HistoryClosure (this));
- }
- else if (PAGE == "fileHistory") {
- if (!PARAMS.item) {
- $("#loader").fadeOut (500); // ("hidden");
- $("#error").html ("incorrect input for fileHistory command");
- $("#error").removeClass ("hidden");
- return;
- }
- request = new Name ().add (this.actions).add ("file").add (PARAMS.item).add ("nonce").addSegment (0);
- console.log (request.to_uri ());
- this.ndn.expressInterest (request, new HistoryClosure (this));
- }
- }
- });
diff --git a/gui/html/index.html b/gui/html/index.html
index 24de8ca..ffa46a0 100644
--- a/gui/html/index.html
+++ b/gui/html/index.html
@@ -17,22 +17,29 @@
<body>
<header>
- <h1>ChronoShare</h1>
+ <h1>ChronoShare <green id="folder-name"></green> for <grey id="user-name"></grey></h1>
<h2 id="folderName"></h2>
<nav>
<ul>
- <li><a class="needs-get-url" href="#fileList">File list</a></li>
- <li><a class="needs-get-url" href="#folderHistory">Folder history</a></li>
+ <li><a class="needs-get-url" href="#fileList">All files</a></li>
+ <li><a class="needs-get-url" href="#folderHistory">Recent actions</a></li>
</ul>
</nav>
</header>
<article>
- <!-- <img id="loader" src="load.gif" /> -->
<div id="content" class="hidden">
</div>
+ <content-nav id="content-nav" style="display: none">
+ <ul>
+ <li><a id="get-less" class="ajax-action"><< Previous</a></li>
+ <li><a id="get-more" class="ajax-action">Next >></a></li>
+ </ul>
+
+ </content-nav>
+
<div class="hidden" id="loader">
<img src="load.gif" />
</div>
@@ -57,6 +64,8 @@
</footer>
<script src="detect.js"></script>
+ <script type="text/javascript" src="chronoshare-helpers.js"></script>
+ <script type="text/javascript" src="chronoshare-navigation.js"></script>
<script type="text/javascript" src="chronoshare.js"></script>
<script type="text/javascript">
$(window).ready (function () {
diff --git a/gui/html/style.css b/gui/html/style.css
index cd16f8c..cc3face 100644
--- a/gui/html/style.css
+++ b/gui/html/style.css
@@ -28,8 +28,9 @@
}
article {
- margin: 20px auto 0;
+ margin: 20px auto 20px;
width: 90%;
+ padding-bottom: 20px;
}
footer {
@@ -64,9 +65,7 @@
min-width: 587px;
width: 100%;
height: 40px;
-}
-nav {
background-color: #EAF4EF;
-moz-border-radius: 6px;
border-radius: 6px;
@@ -189,9 +188,22 @@
.filename {
width: 50%;
}
+
+.highlighted .filename {
+ font-weight: bold;
+}
+
+.delete .filename {
+ color: red;
+}
+
.version {
width: 5%;
}
+.size {
+ width: 5%;
+ whitespace: nowrap;
+}
.modified {
width: 20%;
}
@@ -227,4 +239,46 @@
seqNo {
display: inline-block;
margin-left: 5px;
-}
\ No newline at end of file
+}
+
+.ajax-action {
+ cursor: pointer;
+}
+
+
+
+/* Navigation menu */
+content-nav {
+ display: inline-block;
+ margin: 0;
+ /* width: 100%; */
+ height: 24px;
+
+ background-color: #EAF4EF;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ border: 1px solid #99CCB2;
+}
+
+content-nav ul {
+ margin: 0;
+ padding: 0px;
+}
+
+content-nav li {
+ list-style-type: none;
+ display: inline;
+ margin: 0;
+}
+
+content-nav li a {
+ display: inline-block;
+ color: #727272;
+ font-size: 14px;
+ line-height: 14px;
+ font-family: sans-serif;
+ text-decoration: none;
+ padding: 5px 30px 5px 30px;
+}
+
+content-nav li a.active, content-nav a:hover { color: #2D9A65; }
diff --git a/src/action-log.cc b/src/action-log.cc
index 71ee782..0a05dd2 100644
--- a/src/action-log.cc
+++ b/src/action-log.cc
@@ -701,9 +701,10 @@
action.set_action (static_cast<ActionItem_ActionType> (sqlite3_column_int (stmt, 2)));
action.set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 3)), sqlite3_column_bytes (stmt, 3));
std::string directory (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 4)), sqlite3_column_bytes (stmt, 4));
+ action.set_version (sqlite3_column_int64 (stmt, 5));
+
if (action.action () == 0)
{
- action.set_version (sqlite3_column_int64 (stmt, 5));
action.set_timestamp (sqlite3_column_int64 (stmt, 6));
action.set_file_hash (sqlite3_column_blob (stmt, 7), sqlite3_column_bytes (stmt, 7));
action.set_mtime (sqlite3_column_int (stmt, 8));
@@ -772,9 +773,10 @@
action.set_action (static_cast<ActionItem_ActionType> (sqlite3_column_int (stmt, 2)));
action.set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 3)), sqlite3_column_bytes (stmt, 3));
std::string directory (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 4)), sqlite3_column_bytes (stmt, 4));
+ action.set_version (sqlite3_column_int64 (stmt, 5));
+
if (action.action () == 0)
{
- action.set_version (sqlite3_column_int64 (stmt, 5));
action.set_timestamp (sqlite3_column_int64 (stmt, 6));
action.set_file_hash (sqlite3_column_blob (stmt, 7), sqlite3_column_bytes (stmt, 7));
action.set_mtime (sqlite3_column_int (stmt, 8));
diff --git a/src/state-server.cc b/src/state-server.cc
index 43f15e3..89b6095 100644
--- a/src/state-server.cc
+++ b/src/state-server.cc
@@ -77,11 +77,11 @@
// currently supporting limited number of command.
// will be extended to support all planned commands later
- // <PREFIX_INFO>/"actions"/"all"/<nonce>/<segment> get list of all actions
+ // <PREFIX_INFO>/"actions"/"all"/<segment> get list of all actions
m_ccnx->setInterestFilter (Name (m_PREFIX_INFO)("actions")("folder"), bind(&StateServer::info_actions_folder, this, _1));
m_ccnx->setInterestFilter (Name (m_PREFIX_INFO)("actions")("file"), bind(&StateServer::info_actions_file, this, _1));
- // <PREFIX_INFO>/"filestate"/"all"/<nonce>/<segment>
+ // <PREFIX_INFO>/"filestate"/"all"/<segment>
m_ccnx->setInterestFilter (Name (m_PREFIX_INFO)("files")("folder"), bind(&StateServer::info_files_folder, this, _1));
// <PREFIX_CMD>/"restore"/"file"/<one-component-relative-file-name>/<version>/<file-hash>
@@ -174,8 +174,8 @@
void
StateServer::info_actions_folder (const Name &interest)
{
- if (interest.size () - m_PREFIX_INFO.size () != 4 &&
- interest.size () - m_PREFIX_INFO.size () != 5)
+ if (interest.size () - m_PREFIX_INFO.size () != 3 &&
+ interest.size () - m_PREFIX_INFO.size () != 4)
{
_LOG_DEBUG ("Invalid interest: " << interest);
return;
@@ -188,8 +188,8 @@
void
StateServer::info_actions_file (const Name &interest)
{
- if (interest.size () - m_PREFIX_INFO.size () != 4 &&
- interest.size () - m_PREFIX_INFO.size () != 5)
+ if (interest.size () - m_PREFIX_INFO.size () != 3 &&
+ interest.size () - m_PREFIX_INFO.size () != 4)
{
_LOG_DEBUG ("Invalid interest: " << interest);
return;
@@ -203,7 +203,7 @@
void
StateServer::info_actions_fileOrFolder_Execute (const Ccnx::Name &interest, bool isFolder/* = true*/)
{
- // <PREFIX_INFO>/"actions"/"folder|file"/<folder|file>/<nonce>/<offset> get list of all actions
+ // <PREFIX_INFO>/"actions"/"folder|file"/<folder|file>/<offset> get list of all actions
try
{
@@ -212,9 +212,9 @@
/// @todo !!! add security checking
string fileOrFolderName;
- if (interest.size () - m_PREFIX_INFO.size () == 5)
- fileOrFolderName = interest.getCompFromBackAsString (2);
- else // == 4
+ if (interest.size () - m_PREFIX_INFO.size () == 4)
+ fileOrFolderName = interest.getCompFromBackAsString (1);
+ else // == 3
fileOrFolderName = "";
/*
* {
@@ -234,13 +234,13 @@
bool more;
if (isFolder)
{
- m_actionLog->LookupActionsInFolderRecursively
+ more = m_actionLog->LookupActionsInFolderRecursively
(boost::bind (StateServer::formatActionJson, boost::ref(actions), _1, _2, _3),
fileOrFolderName, offset*10, 10);
}
else
{
- m_actionLog->LookupActionsForFile
+ more = m_actionLog->LookupActionsForFile
(boost::bind (StateServer::formatActionJson, boost::ref(actions), _1, _2, _3),
fileOrFolderName, offset*10, 10);
}
@@ -249,8 +249,9 @@
if (more)
{
- Ccnx::Name more = Name (interest.getPartialName (0, interest.size () - 1))(offset + 1);
- json.push_back (Pair ("more", lexical_cast<string> (more)));
+ json.push_back (Pair ("more", lexical_cast<string> (offset + 1)));
+ // Ccnx::Name more = Name (interest.getPartialName (0, interest.size () - 1))(offset + 1);
+ // json.push_back (Pair ("more", lexical_cast<string> (more)));
}
ostringstream os;
@@ -324,8 +325,8 @@
void
StateServer::info_files_folder (const Ccnx::Name &interest)
{
- if (interest.size () - m_PREFIX_INFO.size () != 4 &&
- interest.size () - m_PREFIX_INFO.size () != 5)
+ if (interest.size () - m_PREFIX_INFO.size () != 3 &&
+ interest.size () - m_PREFIX_INFO.size () != 4)
{
_LOG_DEBUG ("Invalid interest: " << interest << ", " << interest.size () - m_PREFIX_INFO.size ());
return;
@@ -339,7 +340,7 @@
void
StateServer::info_files_folder_Execute (const Ccnx::Name &interest)
{
- // <PREFIX_INFO>/"filestate"/"folder"/<one-component-relative-folder-name>/<nonce>/<offset>
+ // <PREFIX_INFO>/"filestate"/"folder"/<one-component-relative-folder-name>/<offset>
try
{
int offset = interest.getCompFromBackAsInt (0);
@@ -347,9 +348,9 @@
// /// @todo !!! add security checking
string folder;
- if (interest.size () - m_PREFIX_INFO.size () == 5)
- folder = interest.getCompFromBackAsString (2);
- else // == 4
+ if (interest.size () - m_PREFIX_INFO.size () == 4)
+ folder = interest.getCompFromBackAsString (1);
+ else // == 3
folder = "";
/*
@@ -377,8 +378,9 @@
if (more)
{
- Ccnx::Name more = Name (interest.getPartialName (0, interest.size () - 1))(offset + 1);
- json.push_back (Pair ("more", lexical_cast<string> (more)));
+ json.push_back (Pair ("more", lexical_cast<string> (offset + 1)));
+ // Ccnx::Name more = Name (interest.getPartialName (0, interest.size () - 1))(offset + 1);
+ // json.push_back (Pair ("more", lexical_cast<string> (more)));
}
ostringstream os;
diff --git a/src/state-server.h b/src/state-server.h
index 22caf89..8809b7f 100644
--- a/src/state-server.h
+++ b/src/state-server.h
@@ -50,15 +50,15 @@
*
* - state: get list of SyncNodes, their sequence numbers, and forwarding hint (almost the same as RECOVERY interest)
*
- * <PREFIX_INFO>/"state" (nonce should probably be the authentification code or authentication code should in addition somewhere)
+ * <PREFIX_INFO>/"state" (@todo: authentification code or authentication code should in addition somewhere)
*
* - action
*
* Get list of actions for a folder (for all files under this folder)
*
- * <PREFIX_INFO>/"actions"/"folder"/<nonce>/<offset> (all actions)
+ * <PREFIX_INFO>/"actions"/"folder"/<offset> (all actions)
* or
- * <PREFIX_INFO>/"actions"/"folder"/<one-component-relative-file-name>/<nonce>/<offset>
+ * <PREFIX_INFO>/"actions"/"folder"/<one-component-relative-file-name>/<offset>
*
* Actions are ordered in decreasing order (latest will go first).
*
@@ -98,15 +98,15 @@
* },
*
* // only if there are more actions available
- * "more": "<NDN-NAME-OF-NEXT-SEGMENT-OF-ACTION>"
+ * "more": "next segment number"
* }
*
*
* - file
*
- * <PREFIX_INFO>/"files"/"folder"/<nonce>/<offset> (full filestate)
+ * <PREFIX_INFO>/"files"/"folder"/<offset> (full filestate)
* or
- * <PREFIX_INFO>/"files"/"folder"/<one-component-relative-folder-name>/<nonce>/<offset>
+ * <PREFIX_INFO>/"files"/"folder"/<one-component-relative-folder-name>/<offset>
*
* Each Data packets contains a list of up to 100 files.
* If more items are available, application data will specify URL for the next packet
@@ -132,7 +132,7 @@
* ]
*
* // only if there are more actions available
- * "more": "<NDN-NAME-OF-NEXT-SEGMENT-OF-FILESTATE>"
+ * "more": "next segment number"
* }
*
* Commands available: