From d1e5a1d4c64167d2284df3a71f08d16c053f9d37 Mon Sep 17 00:00:00 2001 From: mpl Date: Wed, 14 Nov 2012 00:02:12 +0100 Subject: [PATCH] search UI: find all roots This change allows to find all roots (permanodes with the "camliRoot" attribute) from the search.html ui page. To achieve that, func (x *Index) SearchPermanodesWithAttr now uses a prefix string without the query part if the query is "". http://code.google.com/p/camlistore/issues/detail?id=35 Change-Id: I396fba683e6e7b2296d1f0df8009c07e3c2cd09d --- pkg/index/index.go | 9 +++- pkg/search/handler.go | 2 +- pkg/search/search.go | 5 +++ server/camlistored/ui/search.html | 5 +++ server/camlistored/ui/search.js | 42 ++++++++++-------- server/camlistored/ui/zembed_search.html.go | 7 ++- server/camlistored/ui/zembed_search.js.go | 48 +++++++++++++-------- 7 files changed, 79 insertions(+), 39 deletions(-) diff --git a/pkg/index/index.go b/pkg/index/index.go index 58590a5d3..b770c406a 100644 --- a/pkg/index/index.go +++ b/pkg/index/index.go @@ -337,6 +337,7 @@ func (x *Index) PermanodeOfSignerAttrValue(signer *blobref.BlobRef, attr, val st } // This is just like PermanodeOfSignerAttrValue except we return multiple and dup-suppress. +// If request.Query is "", it is not used in the prefix search. func (x *Index) SearchPermanodesWithAttr(dest chan<- *blobref.BlobRef, request *search.PermanodeByAttrRequest) (err error) { defer close(dest) if request.FuzzyMatch { @@ -355,7 +356,13 @@ func (x *Index) SearchPermanodesWithAttr(dest chan<- *blobref.BlobRef, request * return err } seen := make(map[string]bool) - it := x.queryPrefix(keySignerAttrValue, keyId, request.Attribute, request.Query) + var it *prefixIter + // TODO(mpl): test this case in particular when making a test for that method. + if request.Query == "" { + it = x.queryPrefix(keySignerAttrValue, keyId, request.Attribute) + } else { + it = x.queryPrefix(keySignerAttrValue, keyId, request.Attribute, request.Query) + } defer closeIterator(it, &err) for it.Next() { pn := blobref.Parse(it.Value()) diff --git a/pkg/search/handler.go b/pkg/search/handler.go index c27091218..ac7e74f1a 100644 --- a/pkg/search/handler.go +++ b/pkg/search/handler.go @@ -195,7 +195,7 @@ func (sh *Handler) servePermanodesWithAttr(rw http.ResponseWriter, req *http.Req defer setPanicError(ret) signer := blobref.MustParse(mustGet(req, "signer")) - value := mustGet(req, "value") + value := req.FormValue("value") fuzzy := req.FormValue("fuzzy") // exact match if empty fuzzyMatch := false if fuzzy != "" { diff --git a/pkg/search/search.go b/pkg/search/search.go index 912f77a1a..315cb5aec 100644 --- a/pkg/search/search.go +++ b/pkg/search/search.go @@ -119,6 +119,8 @@ type PermanodeByAttrRequest struct { // The attribute value to find exactly (or roughly, if // FuzzyMatch is set) + // If blank, the permanodes with Attribute as an attribute + // (set to any value) are searched. Query string FuzzyMatch bool // by default, an exact match is required @@ -153,6 +155,9 @@ type Index interface { // In particular, if request.FuzzyMatch is true, a fulltext // search is performed (if supported by the attribute(s)) // instead of an exact match search. + // If request.Query is blank, the permanodes which have + // request.Attribute as an attribute (regardless of its value) + // are searched. // Additionally, if request.Attribute is blank, all attributes // are searched (as fulltext), otherwise the search is // restricted to the named attribute. diff --git a/server/camlistored/ui/search.html b/server/camlistored/ui/search.html index 40ff83c3a..254b82e4d 100644 --- a/server/camlistored/ui/search.html +++ b/server/camlistored/ui/search.html @@ -13,6 +13,11 @@

Search

+

Find all roots

+
+ +
+

In all attributes

diff --git a/server/camlistored/ui/search.js b/server/camlistored/ui/search.js index 061a6ac7d..e6383aca2 100644 --- a/server/camlistored/ui/search.js +++ b/server/camlistored/ui/search.js @@ -20,15 +20,9 @@ function getSearchParams() { CamliSearch.query = ""; CamliSearch.type = ""; CamliSearch.fuzzy = ""; - CamliSearch.query = getQueryParam('q'); - CamliSearch.type = getQueryParam('t'); - CamliSearch.fuzzy = getQueryParam('f'); - if (CamliSearch.type == null) { - CamliSearch.type = ""; - } - if (CamliSearch.fuzzy == null) { - CamliSearch.fuzzy = ""; - } + CamliSearch.query = getQueryParam('q') || ""; + CamliSearch.type = getQueryParam('t') || ""; + CamliSearch.fuzzy = getQueryParam('f') || ""; } function hideAllResThings() { @@ -38,6 +32,13 @@ function hideAllResThings() { CamliSearch.formAddToCollec.style.visibility = 'hidden'; } +function handleFormGetRoots(e) { + e.stopPropagation(); + e.preventDefault(); + + document.location.href = "search.html?&t=camliRoot" +} + function handleFormGetTagged(e) { e.stopPropagation(); e.preventDefault(); @@ -97,8 +98,13 @@ function doSearch() { case "title": camliGetPermanodesWithAttr(sigconf.publicKeyBlobRef, "title", CamliSearch.query, "true", tagcb); break; + case "camliRoot": + camliGetPermanodesWithAttr(sigconf.publicKeyBlobRef, "camliRoot", CamliSearch.query, "false", tagcb); + break; case "": - camliGetPermanodesWithAttr(sigconf.publicKeyBlobRef, "", CamliSearch.query, "true", tagcb); + if (CamliSearch.query !== "") { + camliGetPermanodesWithAttr(sigconf.publicKeyBlobRef, "", CamliSearch.query, "true", tagcb); + } break; } }; @@ -146,16 +152,18 @@ function showPermanodes(searchRes, type) { if (results.length > 0) { switch(type) { case "tag": - CamliSearch.titleRes.innerHTML = "Tagged with \""; + CamliSearch.titleRes.innerHTML = "Tagged with \"" + CamliSearch.query + "\""; break; case "title": - CamliSearch.titleRes.innerHTML = "Titled with \""; + CamliSearch.titleRes.innerHTML = "Titled with \"" + CamliSearch.query + "\""; + break; + case "camliRoot": + CamliSearch.titleRes.innerHTML = "All roots"; break; case "": - CamliSearch.titleRes.innerHTML = "General search for \""; + CamliSearch.titleRes.innerHTML = "General search for \"" + CamliSearch.query + "\""; break; } - CamliSearch.titleRes.innerHTML += CamliSearch.query + "\""; CamliSearch.titleRes.style.visibility = 'visible'; CamliSearch.btnNewCollec.disabled = false; CamliSearch.btnNewCollec.style.visibility = 'visible'; @@ -246,6 +254,8 @@ function addToCollection(createNew) { function indexOnLoad(e) { + var formRoots = document.getElementById("formRoots"); + formRoots.addEventListener("submit", handleFormGetRoots); var formTags = document.getElementById("formTags"); formTags.addEventListener("submit", handleFormGetTagged); var formTitles = document.getElementById("formTitles"); @@ -259,9 +269,7 @@ function indexOnLoad(e) { CamliSearch.formAddToCollec.addEventListener("submit", handleAddToCollection); hideAllResThings(); getSearchParams(); - if (CamliSearch.query != "") { - doSearch(); - } + doSearch(); } window.addEventListener("load", indexOnLoad); diff --git a/server/camlistored/ui/zembed_search.html.go b/server/camlistored/ui/zembed_search.html.go index 9464ac272..f3c1bd829 100644 --- a/server/camlistored/ui/zembed_search.html.go +++ b/server/camlistored/ui/zembed_search.html.go @@ -20,6 +20,11 @@ func init() { "\n"+ "

Search

\n"+ "\n"+ + "

Find all roots

\n"+ + " \n"+ + " \n"+ + "
\n"+ + "\n"+ "

In all attributes

\n"+ "
\n"+ " \n"+ @@ -51,5 +56,5 @@ func init() { "\n"+ "\n"+ "\n"+ - "", time.Unix(0, 1330389504169976807)) + "", time.Unix(0, 1352847761019584970)) } diff --git a/server/camlistored/ui/zembed_search.js.go b/server/camlistored/ui/zembed_search.js.go index 4a9ead48c..102f6beb8 100644 --- a/server/camlistored/ui/zembed_search.js.go +++ b/server/camlistored/ui/zembed_search.js.go @@ -27,15 +27,9 @@ func init() { " CamliSearch.query = \"\";\n"+ " CamliSearch.type = \"\";\n"+ " CamliSearch.fuzzy = \"\";\n"+ - " CamliSearch.query = getQueryParam('q');\n"+ - " CamliSearch.type = getQueryParam('t');\n"+ - " CamliSearch.fuzzy = getQueryParam('f');\n"+ - " if (CamliSearch.type == null) {\n"+ - " CamliSearch.type = \"\";\n"+ - " }\n"+ - " if (CamliSearch.fuzzy == null) {\n"+ - " CamliSearch.fuzzy = \"\";\n"+ - " }\n"+ + " CamliSearch.query = getQueryParam('q') || \"\";\n"+ + " CamliSearch.type = getQueryParam('t') || \"\";\n"+ + " CamliSearch.fuzzy = getQueryParam('f') || \"\";\n"+ "}\n"+ "\n"+ "function hideAllResThings() {\n"+ @@ -45,6 +39,13 @@ func init() { " CamliSearch.formAddToCollec.style.visibility = 'hidden';\n"+ "}\n"+ "\n"+ + "function handleFormGetRoots(e) {\n"+ + " e.stopPropagation();\n"+ + " e.preventDefault();\n"+ + "\n"+ + " document.location.href = \"search.html?&t=camliRoot\"\n"+ + "}\n"+ + "\n"+ "function handleFormGetTagged(e) {\n"+ " e.stopPropagation();\n"+ " e.preventDefault();\n"+ @@ -106,9 +107,15 @@ func init() { " camliGetPermanodesWithAttr(sigconf.publicKeyBlobRef, \"title\", CamliSearch.quer"+ "y, \"true\", tagcb);\n"+ " break;\n"+ + " case \"camliRoot\":\n"+ + " camliGetPermanodesWithAttr(sigconf.publicKeyBlobRef, \"camliRoot\", CamliSearch."+ + "query, \"false\", tagcb);\n"+ + " break;\n"+ " case \"\":\n"+ - " camliGetPermanodesWithAttr(sigconf.publicKeyBlobRef, \"\", CamliSearch.query, \"t"+ - "rue\", tagcb);\n"+ + " if (CamliSearch.query !== \"\") {\n"+ + " camliGetPermanodesWithAttr(sigconf.publicKeyBlobRef, \"\", CamliSearch.query, \""+ + "true\", tagcb);\n"+ + " }\n"+ " break;\n"+ " }\n"+ " };\n"+ @@ -156,16 +163,19 @@ func init() { " if (results.length > 0) {\n"+ " switch(type) {\n"+ " case \"tag\":\n"+ - " CamliSearch.titleRes.innerHTML = \"Tagged with \\\"\";\n"+ + " CamliSearch.titleRes.innerHTML = \"Tagged with \\\"\" + CamliSearch.query + \"\\\"\";\n"+ " break;\n"+ " case \"title\":\n"+ - " CamliSearch.titleRes.innerHTML = \"Titled with \\\"\";\n"+ + " CamliSearch.titleRes.innerHTML = \"Titled with \\\"\" + CamliSearch.query + \"\\\"\";\n"+ + " break;\n"+ + " case \"camliRoot\":\n"+ + " CamliSearch.titleRes.innerHTML = \"All roots\";\n"+ " break;\n"+ " case \"\":\n"+ - " CamliSearch.titleRes.innerHTML = \"General search for \\\"\";\n"+ + " CamliSearch.titleRes.innerHTML = \"General search for \\\"\" + CamliSearch.query +"+ + " \"\\\"\";\n"+ " break;\n"+ " }\n"+ - " CamliSearch.titleRes.innerHTML += CamliSearch.query + \"\\\"\";\n"+ " CamliSearch.titleRes.style.visibility = 'visible';\n"+ " CamliSearch.btnNewCollec.disabled = false;\n"+ " CamliSearch.btnNewCollec.style.visibility = 'visible';\n"+ @@ -257,6 +267,8 @@ func init() { "\n"+ "function indexOnLoad(e) {\n"+ "\n"+ + " var formRoots = document.getElementById(\"formRoots\");\n"+ + " formRoots.addEventListener(\"submit\", handleFormGetRoots);\n"+ " var formTags = document.getElementById(\"formTags\");\n"+ " formTags.addEventListener(\"submit\", handleFormGetTagged);\n"+ " var formTitles = document.getElementById(\"formTitles\");\n"+ @@ -270,11 +282,9 @@ func init() { " CamliSearch.formAddToCollec.addEventListener(\"submit\", handleAddToCollection);\n"+ " hideAllResThings();\n"+ " getSearchParams();\n"+ - " if (CamliSearch.query != \"\") {\n"+ - " doSearch();\n"+ - " }\n"+ + " doSearch();\n"+ "}\n"+ "\n"+ "window.addEventListener(\"load\", indexOnLoad);\n"+ - "", time.Unix(0, 1352107488430325498)) + "", time.Unix(0, 1352847747010347886)) }