aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Magorsch <max@magorsch.de>2019-10-18 21:33:54 +0200
committerMax Magorsch <max@magorsch.de>2019-10-18 21:33:54 +0200
commit8efe1d0c7adc971e7ff7c2353e5f18e9cf7f5b92 (patch)
treebfbe185cb965d2693627e75eb76d304ade092ced
parentMove the query documentation to a new page (diff)
downloadpackages-5-8efe1d0c7adc971e7ff7c2353e5f18e9cf7f5b92.tar.gz
packages-5-8efe1d0c7adc971e7ff7c2353e5f18e9cf7f5b92.tar.bz2
packages-5-8efe1d0c7adc971e7ff7c2353e5f18e9cf7f5b92.zip
Add a generator for advanced search queries
So far, advanced search queries can be run by writing them manually. Now advanced search queries can be composed using a set of predefined forms. Similar to other advanced search interfaces. Signed-off-by: Max Magorsch <max@magorsch.de>
-rw-r--r--app/assets/javascripts/index/query_generator.js93
-rw-r--r--app/views/index/index.html.erb228
2 files changed, 156 insertions, 165 deletions
diff --git a/app/assets/javascripts/index/query_generator.js b/app/assets/javascripts/index/query_generator.js
new file mode 100644
index 0000000..17cb798
--- /dev/null
+++ b/app/assets/javascripts/index/query_generator.js
@@ -0,0 +1,93 @@
+function updateDropdown(self) {
+ getThirdParent(self).querySelector('button > span:first-child').innerHTML = self.innerHTML;
+}
+
+function buildAdvancedQuery(){
+ var query = ""
+ document.querySelectorAll('#search-container > .row').forEach(function(element) {
+ var term = element.querySelector('.form-control').value;
+
+ if(!term.replace(/\s/g, '').length){
+ return;
+ }else{
+ term = parseSearchTerm(term);
+ }
+
+ var operator = parseOperator(element.querySelector('.pgo-query-operator > span:first-child').innerHTML);
+ var field = element.querySelector('.pgo-query-field > span:first-child').innerHTML;
+
+ query += operator + field + ":" + term + " ";
+ });
+ document.getElementById('q').value = query;
+}
+
+function parseOperator(operator){
+ switch(operator) {
+ case "should match":
+ return "";
+ case "must match":
+ return "+";
+ case "must not match":
+ return "-";
+ default:
+ return "";
+ }
+}
+
+function parseSearchTerm(term){
+ if (/\s/.test(term) && !/^\".*\"$/.test(term)) {
+ return "\"" + term + "\""
+ }else{
+ return term
+ }
+}
+
+function addInput(self){
+ var new_input = document.querySelector('#search-container > .row').cloneNode(true);
+ resetInput(new_input);
+ document.querySelector('#search-container').append(new_input);
+ checkDeleteButtons();
+ checkAddButtons();
+}
+
+function resetInput(input) {
+ input.querySelector('.form-control').value = '';
+ input.querySelector('.pgo-query-operator > span:first-child').innerHTML = 'should match';
+ input.querySelector('.pgo-query-field > span:first-child').innerHTML = 'name';
+}
+
+function deleteInput(self){
+ getThirdParent(self).removeChild(getSecondParent(self));
+ checkDeleteButtons();
+ checkAddButtons();
+}
+
+function checkDeleteButtons(){
+ if(document.querySelectorAll('#search-container > .row').length == 1){
+ document.querySelectorAll('.pgo-query-delete-btn').forEach(function(element) {
+ element.style.display = 'none';
+ });
+ }else{
+ document.querySelectorAll('.pgo-query-delete-btn').forEach(function(element) {
+ element.style.display = 'block';
+ });
+ }
+}
+
+function checkAddButtons(){
+ document.querySelectorAll('.pgo-query-add-btn').forEach(function(element) {
+ element.style.display = 'none';
+ });
+
+ document.querySelectorAll('.pgo-query-add-btn')[document.querySelectorAll('.pgo-query-add-btn').length - 1].style.display = 'block';
+}
+
+function getThirdParent(self) {
+ return self.parentElement.parentElement.parentElement;
+}
+
+function getSecondParent(self) {
+ return self.parentElement.parentElement;
+}
+
+checkDeleteButtons(); \ No newline at end of file
diff --git a/app/views/index/index.html.erb b/app/views/index/index.html.erb
index e54eb74..ee2bd7f 100644
--- a/app/views/index/index.html.erb
+++ b/app/views/index/index.html.erb
@@ -60,181 +60,79 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
- <h3 class="modal-title" id="searchHelpTitle"><span class="fa fa-info" style="font-size: 15px;"></span>&nbsp; Package Search Syntax</h3>
+ <h3 class="modal-title" id="searchHelpTitle"><span class="fa fa-info" style="font-size: 15px;"></span>&nbsp; Advanced Search Queries</h3>
</div>
<div class="modal-body">
- The search can be used to find Gentoo packages. You can search in two different ways:
- <ul >
- <li>Keywords</li>
- <li>Field/Value pairs</li>
- </ul>
- <h4 style="margin-top:35px;">Keywords</h4>
- You can use simple keywords to find packages. For instance, if you search for <i>gentoo-sources</i> you will find the package <i>sys-kernel/gentoo-sources</i>.
- When searching for keywords, the
- <ul >
- <li><b>name</b></li>
- <li> and the <b>atom</b>
- </ul>
- fields are searched for the keyword.
- <h4 style="margin-top:35px;">Field/Value pairs</h4>
- If you, however, like to run advanced queries, you can use field/value pairs combined with operators. The possible fields and operators are summarized in the following tables.
- <table class="table">
- <thead>
- <tr>
- <th scope="col">Field</th>
- <th scope="col">Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <th scope="row">atom</th>
- <td>The unique identifier of a package <br> <i style="padding-left:2em">e.g. sys-kernel/gentoo-sources</i></td>
- </tr>
- <tr>
- <th scope="row">category</th>
- <td>The category of a package <br> <i style="padding-left:2em">e.g. sys-kernel</i></td>
- </tr>
- <tr>
- <th scope="row">name</th>
- <td>The name of a package <br> <i style="padding-left:2em">e.g. gentoo-sources</i></td>
- </tr>
- <tr>
- <th scope="row">description</th>
- <td>The description of a package <br> <i style="padding-left:2em">e.g. A tiling window manager</i> </td>
- </tr>
- <tr>
- <th scope="row">longdescription</th>
- <td>The full descripiton of a package <br> <i style="padding-left:2em">e.g. xmonad is a tiling window manager for [...]</i></td>
- </tr>
- <tr>
- <th scope="row">homepage</th>
- <td>The homepage of a package <br> <i style="padding-left:2em">e.g. http://xmonad.org</i></td>
- </tr>
- <tr>
- <th scope="row">license</th>
- <td>The license of a package <br> <i style="padding-left:2em">e.g. BSD</i></td>
- </tr>
- <tr>
- <th scope="row">Maintainers</th>
- <td></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">maintainers.name</th>
- <td>The name of the maintainer <br> <i style="padding-left:2em">e.g. Gentoo Haskell</i></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">maintainers.description</th>
- <td>The description of the maintainers</td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">maintainers.type</th>
- <td>The type of maintainter <br> <i style="padding-left:2em">e.g. project</i></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">maintainers.restrict</th>
- <td></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">maintainers.email</th>
- <td>The email of the maintainer <br> <i style="padding-left:2em">e.g. haskell@gentoo.org</i></td>
- </tr>
- <tr>
- <th scope="row">Useflag</th>
- <td></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:1em">global</th>
- <td></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">useflags.global.name</th>
- <td>The name of the global useflag <br> <i style="padding-left:2em">e.g. hscolour</i></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">useflags.global.description</th>
- <td>The description of the global useflag <br> <i style="padding-left:2em">e.g. Include coloured haskell sources to [...]</i></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:1em">local</th>
- <td></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">useflags.local.name</th>
- <td>The name of the local useflag</td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">useflags.local.description</th>
- <td>The description of the local useflag</td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:1em">use_expand</th>
- <td></td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">useflags.use_expand.name</th>
- <td>The name of the local use_expand</td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">useflags.use_expand.description</th>
- <td>The description of the use_expand</td>
- </tr>
- <tr>
- <th scope="row" style="padding-left:2em">useflags.use_expand.use_expand_prefix</th>
- <td>The use_expand prefix <br> <i style="padding-left:2em">e.g. python_targets</i></td>
- </tr>
- <tr>
- <th scope="row">metadata_hash</th>
- <td>The hash of the metadata <br> <i style="padding-left:2em">e.g. 5cd76e098f966b4edcd1848866dd9099</i></td>
- </tr>
- </tbody>
- </table>
- The following operators can be used to combine multiple field/value pairs:
- <table class="table">
- <thead>
- <tr>
- <th scope="col">Operator</th>
- <th scope="col">Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <th scope="row"></th>
- <td>The term <b>should</b> appear (default)</td>
- </tr>
- <tr>
- <th scope="row">+</th>
- <td>The term <b>must</b> appear</td>
- </tr>
- <tr>
- <th scope="row">-</th>
- <td>The term <b>must not</b> appear</td>
- </tr>
- <tr>
- <th scope="row">"..."</th>
- <td>Can be used to <b>group</b> phrases <br> <i style="padding-left:2em">e.g. +description:"window manager"</i></td>
- </tr>
- </tbody>
- </table>
+ Using the following forms you can compose advanced search queries instead of writing them manually.
- <h4>Examples</h4>
+ <div id="search-container" style="margin-bottom:25px;">
+ <div class="row" style="margin-top:25px;">
+ <div class="col-lg-2"></div>
+ <div class="col-lg-8">
+ <div class="input-group">
+ <div class="input-group-btn">
+ <div class="btn-group">
+ <button type="button" class="pgo-query-field btn btn-default dropdown-toggle" data-toggle="dropdown"><span>name</span>
+ <span class="caret"></span></button>
+ <ul class="dropdown-menu" role="menu">
+ <li><a onclick="updateDropdown(this);">name</a></li>
+ <li><a onclick="updateDropdown(this);">category</a></li>
+ <li><a onclick="updateDropdown(this);">atom</a></li>
+ <li><a onclick="updateDropdown(this);">description</a></li>
+ <li><a onclick="updateDropdown(this);">longdescription</a></li>
+ <li><a onclick="updateDropdown(this);">license</a></li>
+ <li class="divider"></li>
+ <li><a onclick="updateDropdown(this);">maintainers.name</a></li>
+ <li><a onclick="updateDropdown(this);">maintainers.description</a></li>
+ <li><a onclick="updateDropdown(this);">maintainers.type</a></li>
+ <li><a onclick="updateDropdown(this);">maintainers.restrict</a></li>
+ <li><a onclick="updateDropdown(this);">maintainers.email</a></li>
+ <li class="divider"></li>
+ <li><a onclick="updateDropdown(this);">useflags.global.name</a></li>
+ <li><a onclick="updateDropdown(this);">useflags.global.description</a></li>
+ <li><a onclick="updateDropdown(this);">useflags.local.name</a></li>
+ <li><a onclick="updateDropdown(this);">useflags.local.description</a></li>
+ <li><a onclick="updateDropdown(this);">useflags.use_expand.name</a></li>
+ <li><a onclick="updateDropdown(this);">useflags.use_expand.description</a></li>
+ <li><a onclick="updateDropdown(this);">useflags.use_expand.use_expand_prefix</a></li>
+ <li class="divider"></li>
+ <li><a onclick="updateDropdown(this);">metadata_hash</a></li>
+ </ul>
+ </div>
+ <div class="btn-group">
+ <button type="button" class="pgo-query-operator btn btn-default dropdown-toggle" data-toggle="dropdown"><span>should match</span>
+ <span class="caret"></span></button>
+ <ul class="dropdown-menu" role="menu">
+ <li><a onclick="updateDropdown(this);">should match</a></li>
+ <li><a onclick="updateDropdown(this);">must match</a></li>
+ <li><a onclick="updateDropdown(this);">must not match</a></li>
+ </ul>
+ </div>
+ </div><!-- /btn-group -->
+ <input type="text" class="form-control" placeholder="e.g. gentoo-sources">
+ </div><!-- /input-group -->
- <ul>
- <li>Find all packages named git: <br><code style="margin-left:2em">+name:git</code></li>
- <li>Find all packages in the category sys-kernel: <br><code style="margin-left:2em">+category:sys-kernel</code></li>
- <li>Find all packages with a BSD license: <br><code style="margin-left:2em">+license:BSD</code></li>
- <li>Find all packages that neither have a BSD license nor a MIT license: <br><code style="margin-left:2em">-license:BSD -license:MIT</code></li>
- <li>Find all packages maintained by the Haskell Team: <br><code style="margin-left:2em">+maintainer.email:haskell@gentoo.org</code></li>
- <li>Find all packages maintained by the Haskell Team but that aren't in the 'dev-haskell' category: <br><code style="margin-left:2em">+maintainer.email:haskell@gentoo.org -category:dev-haskell</code></li>
- <li>Find all packages those description contains 'window manager': <br><code style="margin-left:2em">+description:"window manager"</code></li>
- <li>Find all packages that contain the use_expand 'python_targets': <br><code style="margin-left:2em">+useflags.use_expand.use_expand_prefix:python_targets</code></li>
- </ul>
+ </div><!-- /.col-lg-6 -->
+ <div class="col-lg-2">
+ <span class="pgo-query-delete-btn fa fa-trash pull-right" style="font-size: 20px;margin-top:5px;" onclick="deleteInput(this);"></span>
+ <span class="pgo-query-add-btn fa fa-plus pull-right" style="font-size: 20px;margin-top:5px;" onclick="addInput();"></span>
+ </div>
+
+ </div><!-- /.row -->
+
+ </div>
+
+ Please refer to <a href="/about/queries">this page</a> for further information on advanced search queries and examples.
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ <button type="button" class="btn btn-primary" onclick="buildAdvancedQuery();" data-dismiss="modal">Apply</button>
</div>
</div>
</div>
</div>
+<%= javascript_include_tag 'index/query_generator.js' %>
+
<%= javascript_include_tag 'index/typeahead.js' %>