From 178102c304e5ad1da2af5b2ab0af2484edb8a609 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Mon, 19 Mar 2018 17:08:05 +0300
Subject: * Add mapping tests. Fix link-checker tests.
* Add tests for the R/qtl and CIM mapping tools.
* Fix tests for in-page links.
---
test/requests/link_checker.py | 16 ++++++++++++----
test/requests/mapping_tests.py | 35 ++++++++++++++++++++++-------------
2 files changed, 34 insertions(+), 17 deletions(-)
diff --git a/test/requests/link_checker.py b/test/requests/link_checker.py
index 256bf6ef..a75327f0 100644
--- a/test/requests/link_checker.py
+++ b/test/requests/link_checker.py
@@ -16,6 +16,10 @@ def is_internal_link(link):
pattern = re.compile("^/.*")
return pattern.match(link)
+def is_in_page_link(link):
+ pattern = re.compile("^#.*")
+ return pattern.match(link)
+
def get_links(doc):
return filter(
lambda x: not (
@@ -32,17 +36,21 @@ def verify_link(link):
else:
print("ERROR: link `"+link+"` failed with status "
, result.status_code)
- except ConnectionError as ex:
- print("ERROR: ", link, ex)
+ except Exception as ex:
+ print("ERROR: ("+link+")", ex)
def check_page(host, start_url):
print("")
print("Checking links in page `"+start_url+"`")
doc = parse(start_url).getroot()
links = get_links(doc)
+ in_page_links = filter(is_in_page_link, links)
internal_links = filter(is_internal_link, links)
- external_links = filter(lambda x: not is_internal_link(x), links)
- external_links.append("http://somenon-existentsite.brr")
+ external_links = filter(lambda x: not (is_internal_link(x) or is_in_page_link(x)), links)
+
+ for link in in_page_links:
+ verify_link(start_url+link)
+
for link in internal_links:
verify_link(host+link)
diff --git a/test/requests/mapping_tests.py b/test/requests/mapping_tests.py
index fd20df11..8eb19de7 100644
--- a/test/requests/mapping_tests.py
+++ b/test/requests/mapping_tests.py
@@ -1,17 +1,10 @@
from __future__ import print_function
import re
+import copy
import json
import requests
from lxml.html import fromstring
-def get_data(list_item):
- try:
- value = list_item[1]
- except:
- value = None
- #print("list_item:", list_item, "==>", value)
- return value
-
def load_data_from_file():
filename = "../test/data/input/mapping/1435395_s_at_HC_M2_0606_P.json"
file_handle = open(filename, "r")
@@ -19,6 +12,8 @@ def load_data_from_file():
return file_data
def check_pylmm_tool_selection(host, data):
+ print("")
+ print("pylmm mapping tool selection")
data["method"] = "pylmm"
page = requests.post(host+"/marker_regression", data=data)
doc = fromstring(page.text)
@@ -27,10 +22,24 @@ def check_pylmm_tool_selection(host, data):
assert form.fields["value:BXD1"] == "15.034" # Check value in the file
def check_R_qtl_tool_selection(host, data):
- pass
+ print("")
+ print("R/qtl mapping tool selection")
+ headers = {"Content-Type": "application/x-www-form-urlencoded"}
+ page = requests.post(host+"/marker_regression", data=data, headers=headers)
+ doc = fromstring(page.text)
+ form = doc.forms[1]
+ assert form.fields["dataset"] == "HC_M2_0606_P"
+ assert form.fields["value:BXD1"] == "15.034"
def check_CIM_tool_selection(host, data):
- pass
+ print("")
+ print("CIM mapping tool selection (using reaper)")
+ data["method"] = "reaper"
+ page = requests.post(host+"/marker_regression", data=data)
+ doc = fromstring(page.text)
+ form = doc.forms[1]
+ assert form.fields["dataset"] == "HC_M2_0606_P"
+ assert form.fields["value:BXD1"] == "15.034"
def check_mapping(args_obj, parser):
print("")
@@ -38,6 +47,6 @@ def check_mapping(args_obj, parser):
host = args_obj.host
data = load_data_from_file()
- check_pylmm_tool_selection(host, data)
- check_R_qtl_tool_selection(host, data)
- check_CIM_tool_selection(host, data)
+ check_pylmm_tool_selection(host, copy.deepcopy(data))
+ check_R_qtl_tool_selection(host, copy.deepcopy(data)) ## Why does this fail?
+ check_CIM_tool_selection(host, copy.deepcopy(data))
--
cgit v1.2.3
From 883bcc257a38240de7de8888f78bac4406b5d027 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Mon, 19 Mar 2018 17:49:39 +0300
Subject: Initialise navigation tests.
* Start working on navigation tests.
---
test/requests/navigation_tests.py | 15 +++++++++++++++
test/requests/test-website.py | 7 ++++---
2 files changed, 19 insertions(+), 3 deletions(-)
create mode 100644 test/requests/navigation_tests.py
diff --git a/test/requests/navigation_tests.py b/test/requests/navigation_tests.py
new file mode 100644
index 00000000..eda27324
--- /dev/null
+++ b/test/requests/navigation_tests.py
@@ -0,0 +1,15 @@
+from __future__ import print_function
+import re
+import requests
+from lxml.html import parse
+
+def check_navigation(args_obj, parser):
+ print("")
+ print("Checking navigation.")
+
+ host = args_obj.host
+ url = host + "/show_trait?trait_id=1435395_s_at&dataset=HC_M2_0606_P"
+ print("URL: ", url)
+ page = requests.get(url)
+ # Page is built by the javascript, hence using requests fails for this.
+ # Investigate use of selenium maybe?
diff --git a/test/requests/test-website.py b/test/requests/test-website.py
index 2bef6eb1..dbf3b822 100755
--- a/test/requests/test-website.py
+++ b/test/requests/test-website.py
@@ -7,6 +7,7 @@ from __future__ import print_function
import argparse
from link_checker import check_links
from mapping_tests import check_mapping
+from navigation_tests import check_navigation
from main_web_functionality import check_main_web_functionality
print("Mechanical Rob firing up...")
@@ -57,9 +58,9 @@ parser.add_argument("-m", "--mapping", dest="accumulate"
, action="store_const", const=check_mapping, default=print_help
, help="Checks for mapping.")
-# parser.add_argument("-n", "--navigation", dest="accumulate"
-# , action="store_const", const=check_navigation, default=print_help
-# , help="Checks for navigation.")
+parser.add_argument("-n", "--navigation", dest="accumulate"
+ , action="store_const", const=check_navigation, default=print_help
+ , help="Checks for navigation.")
# parser.add_argument("-s", "--skip-broken", dest="accumulate"
# , action="store_const", const=dummy, default=print_help
--
cgit v1.2.3
From a20004e25d0143a14763180359e8266e31f9766f Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Wed, 21 Mar 2018 11:22:48 +0300
Subject: Deactivate navigation tests
* Navigation depends on Javascript to render the elements being tested.
That would require selenium and its ilk to run such tests, meaning
such packages would need to be defined for Guix first.
---
test/requests/test-website.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/test/requests/test-website.py b/test/requests/test-website.py
index dbf3b822..f03c148a 100755
--- a/test/requests/test-website.py
+++ b/test/requests/test-website.py
@@ -58,9 +58,10 @@ parser.add_argument("-m", "--mapping", dest="accumulate"
, action="store_const", const=check_mapping, default=print_help
, help="Checks for mapping.")
-parser.add_argument("-n", "--navigation", dest="accumulate"
- , action="store_const", const=check_navigation, default=print_help
- , help="Checks for navigation.")
+# Navigation tests deactivated since system relies on Javascript
+# parser.add_argument("-n", "--navigation", dest="accumulate"
+# , action="store_const", const=check_navigation, default=print_help
+# , help="Checks for navigation.")
# parser.add_argument("-s", "--skip-broken", dest="accumulate"
# , action="store_const", const=dummy, default=print_help
--
cgit v1.2.3
From 4c2ce5580a0891d89fc35c48da06d25fb4c8df76 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Thu, 22 Mar 2018 06:09:39 +0300
Subject: Fix 'def' statement
* End the 'def' statement with a colon (:)
* Add an empty line between lines at different indentation levels for
clarity.
---
wqflask/base/anon_collection.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/wqflask/base/anon_collection.py b/wqflask/base/anon_collection.py
index 8ee73296..dd1aa27f 100644
--- a/wqflask/base/anon_collection.py
+++ b/wqflask/base/anon_collection.py
@@ -1,6 +1,6 @@
class AnonCollection(TraitCollection):
- def __init__(self, anon_id)
+ def __init__(self, anon_id):
self.anon_id = anon_id
self.collection_members = Redis.smembers(self.anon_id)
print("self.collection_members is:", self.collection_members)
@@ -12,6 +12,7 @@ class AnonCollection(TraitCollection):
print("traits_to_remove:", traits_to_remove)
for trait in traits_to_remove:
Redis.srem(self.anon_id, trait)
+
members_now = self.collection_members - traits_to_remove
print("members_now:", members_now)
print("Went from {} to {} members in set.".format(len(self.collection_members), len(members_now)))
--
cgit v1.2.3
From cfce6d80be4fb38573c37d1943db2687d54cf2fc Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Thu, 22 Mar 2018 06:28:01 +0300
Subject: Change raise statement
* Change the raise statement to use an Exception object rather than
using a string for compatibility with Python3.
---
wqflask/utility/svg.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/wqflask/utility/svg.py b/wqflask/utility/svg.py
index 512bc9e6..db13b9d1 100644
--- a/wqflask/utility/svg.py
+++ b/wqflask/utility/svg.py
@@ -1029,7 +1029,7 @@ class drawing:
try:
xv.feed(svg)
except:
- raise "SVG is not well formed, see messages above"
+ raise Exception("SVG is not well formed, see messages above")
else:
print "SVG well formed"
if __name__=='__main__':
--
cgit v1.2.3
From d03fc330cd91d376045d0dd028955619d914dc7e Mon Sep 17 00:00:00 2001
From: Pjotr Prins
Date: Sat, 7 Apr 2018 10:22:33 +0000
Subject: Dear @zsloan,
This patch removes TableTools. I don't think we use it. I have compared the look and feel
of below pages and I see no difference. If that is correct we can simply ditch it by
merging this PR. Note that if we are using such functionality this package is considered
obsolete by the authors.
According to https://datatables.net/extensions/tabletools/:
This extension has now been retired and has been replaced by the
Buttons and Select extensions. The documentation is retained for
legacy reference only. New projects should use Buttons and Select in
preference to TableTools. Moving Tabletools CSS
--- a/wqflask/wqflask/static/packages/TableTools/media/css/TableTools.css
+++ b/wqflask/wqflask/static/packages/TableTools/media/css/TableTools.css
@@ -319,3 +319,8 @@ div.DTTT_collection a.DTTT_button {
line-height: 20px;
}
+.no-sort::after { display: none!important; }
+.no-sort { pointer-events: none!important;
+ cursor: default!important;
+}
+
wqflask/wqflask/templates/correlation_matrix.html:
wqflask/wqflask/templates/collections/list.html:
wqflask/wqflask/templates/search_error.html:
wqflask/wqflask/templates/corr_scatterplot.html:
wqflask/wqflask/templates/pair_scan_results.html:
---
MANIFEST.in | 9 -
.../static/packages/TableTools/alt_init.html | 520 ----
.../static/packages/TableTools/alter_buttons.html | 505 ----
.../static/packages/TableTools/bootstrap.html | 551 -----
.../static/packages/TableTools/button_text.html | 531 -----
.../static/packages/TableTools/collection.html | 522 -----
.../static/packages/TableTools/defaults.html | 503 ----
.../wqflask/static/packages/TableTools/index.html | 499 ----
.../packages/TableTools/media/as3/ZeroClipboard.as | 221 --
.../TableTools/media/as3/ZeroClipboardPdf.as | 310 ---
.../packages/TableTools/media/as3/lib/AlivePDF.swc | Bin 131230 -> 0 bytes
.../packages/TableTools/media/css/TableTools.css | 326 ---
.../TableTools/media/css/TableTools_JUI.css | 185 --
.../TableTools/media/images/background.png | Bin 944 -> 0 bytes
.../TableTools/media/images/collection.png | Bin 1166 -> 0 bytes
.../TableTools/media/images/collection_hover.png | Bin 1194 -> 0 bytes
.../packages/TableTools/media/images/copy.png | Bin 2184 -> 0 bytes
.../TableTools/media/images/copy_hover.png | Bin 2797 -> 0 bytes
.../packages/TableTools/media/images/csv.png | Bin 1607 -> 0 bytes
.../packages/TableTools/media/images/csv_hover.png | Bin 1854 -> 0 bytes
.../packages/TableTools/media/images/pdf.png | Bin 4325 -> 0 bytes
.../packages/TableTools/media/images/pdf_hover.png | Bin 2786 -> 0 bytes
.../packages/TableTools/media/images/print.png | Bin 2123 -> 0 bytes
.../TableTools/media/images/print_hover.png | Bin 2230 -> 0 bytes
.../TableTools/media/images/psd/collection.psd | Bin 25792 -> 0 bytes
.../TableTools/media/images/psd/copy document.psd | Bin 104729 -> 0 bytes
.../TableTools/media/images/psd/file_types.psd | Bin 1090645 -> 0 bytes
.../TableTools/media/images/psd/printer.psd | Bin 119952 -> 0 bytes
.../packages/TableTools/media/images/xls.png | Bin 1641 -> 0 bytes
.../packages/TableTools/media/images/xls_hover.png | Bin 2061 -> 0 bytes
.../packages/TableTools/media/js/TableTools.js | 2476 --------------------
.../packages/TableTools/media/js/TableTools.min.js | 77 -
.../TableTools/media/js/TableTools.min.js.gz | Bin 8785 -> 0 bytes
.../packages/TableTools/media/js/ZeroClipboard.js | 367 ---
.../packages/TableTools/media/swf/copy_csv_xls.swf | Bin 2165 -> 0 bytes
.../TableTools/media/swf/copy_csv_xls_pdf.swf | Bin 58824 -> 0 bytes
.../static/packages/TableTools/multi_instance.html | 499 ----
.../packages/TableTools/multiple_tables.html | 296 ---
.../static/packages/TableTools/pdf_message.html | 524 -----
.../static/packages/TableTools/plug-in.html | 539 -----
.../static/packages/TableTools/select_multi.html | 507 ----
.../static/packages/TableTools/select_single.html | 505 ----
.../static/packages/TableTools/swf_path.html | 505 ----
.../wqflask/static/packages/TableTools/tabs.html | 348 ---
.../wqflask/static/packages/TableTools/theme.html | 524 -----
wqflask/wqflask/templates/search_error.html | 2 -
46 files changed, 11851 deletions(-)
delete mode 100644 wqflask/wqflask/static/packages/TableTools/alt_init.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/alter_buttons.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/bootstrap.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/button_text.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/collection.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/defaults.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/index.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/as3/ZeroClipboard.as
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/as3/ZeroClipboardPdf.as
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/as3/lib/AlivePDF.swc
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/css/TableTools.css
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/css/TableTools_JUI.css
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/background.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/collection.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/collection_hover.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/copy.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/copy_hover.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/csv.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/csv_hover.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/pdf.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/pdf_hover.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/print.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/print_hover.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/psd/collection.psd
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/psd/copy document.psd
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/psd/file_types.psd
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/psd/printer.psd
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/xls.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/images/xls_hover.png
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/js/TableTools.js
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/js/TableTools.min.js
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/js/TableTools.min.js.gz
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/js/ZeroClipboard.js
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/swf/copy_csv_xls.swf
delete mode 100644 wqflask/wqflask/static/packages/TableTools/media/swf/copy_csv_xls_pdf.swf
delete mode 100644 wqflask/wqflask/static/packages/TableTools/multi_instance.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/multiple_tables.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/pdf_message.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/plug-in.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/select_multi.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/select_single.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/swf_path.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/tabs.html
delete mode 100644 wqflask/wqflask/static/packages/TableTools/theme.html
diff --git a/MANIFEST.in b/MANIFEST.in
index 25beb977..0e0b4bd4 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -52,15 +52,6 @@ include wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold
include wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/6_delayed_rendering/*
include wqflask/wqflask/static/new/packages/DataTables/unit_testing/tests_onhold/1_dom/*
include wqflask/wqflask/static/packages/*
-include wqflask/wqflask/static/packages/TableTools/*
-include wqflask/wqflask/static/packages/TableTools/media/*
-include wqflask/wqflask/static/packages/TableTools/media/images/*
-include wqflask/wqflask/static/packages/TableTools/media/images/psd/*
-include wqflask/wqflask/static/packages/TableTools/media/swf/*
-include wqflask/wqflask/static/packages/TableTools/media/js/*
-include wqflask/wqflask/static/packages/TableTools/media/css/*
-include wqflask/wqflask/static/packages/TableTools/media/as3/*
-include wqflask/wqflask/static/packages/TableTools/media/as3/lib/*
include wqflask/wqflask/static/packages/underscore/*
include wqflask/wqflask/static/packages/bootstrap/*
include wqflask/wqflask/static/packages/bootstrap/fonts/*
diff --git a/wqflask/wqflask/static/packages/TableTools/alt_init.html b/wqflask/wqflask/static/packages/TableTools/alt_init.html
deleted file mode 100644
index 73853150..00000000
--- a/wqflask/wqflask/static/packages/TableTools/alt_init.html
+++ /dev/null
@@ -1,520 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - initialisation with 'new TableTools()'
-
-
-
Preamble
-
Typically when working with TableTools, the initialisation and insertion into the DOM will be done automatically by DataTables, through the use of the sDom parameter. However, it is also possible to initialise TableTools manually as shown in the example below. Once initialised you can insert the TableTools tool bar node anywhere you wish into the DOM using the instance.dom.container parameter.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/alter_buttons.html b/wqflask/wqflask/static/packages/TableTools/alter_buttons.html
deleted file mode 100644
index 771b0b86..00000000
--- a/wqflask/wqflask/static/packages/TableTools/alter_buttons.html
+++ /dev/null
@@ -1,505 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - button arrangement
-
-
-
Preamble
-
TableTools makes it very simple to arrange the buttons in the toolbar as you see fit. Using the aButtons parameter you can use any of the predefined buttons or customised buttons. The example below shows how TableTools can be initialised to provide only the 'copy-to-clipboard' and 'print view' options (i.e. no save to local file option is available).
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/bootstrap.html b/wqflask/wqflask/static/packages/TableTools/bootstrap.html
deleted file mode 100644
index 664bde3d..00000000
--- a/wqflask/wqflask/static/packages/TableTools/bootstrap.html
+++ /dev/null
@@ -1,551 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
-
-
-
- TableTools with Twitter Bootstrap
-
-
-
Preamble
-
Twitter Bootstrap is a very powerful design framework for allowing you to very quickly create applications with a unified look and feel. DataTables integrates well with Bootstrap, and so does TableTools.
-
This example shows the default Bootstrap theme being used with a Bootstrap styled DataTable. sDom is supplied to the DataTable with a setup suitable for Bootstrap styling, and a TableTools collection is used to show how it can be used in this environment.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/button_text.html b/wqflask/wqflask/static/packages/TableTools/button_text.html
deleted file mode 100644
index 6828eb94..00000000
--- a/wqflask/wqflask/static/packages/TableTools/button_text.html
+++ /dev/null
@@ -1,531 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - customised button text
-
-
-
Preamble
-
You may wish to set your own text for the buttons in the TableTools toolbar, rather than relying on the default built-in text. This is done by overriding the sButtonText parameter of whatever button you wish to alter. The way TableTools allows you to alter a predefined button is by 'extending' it (using the sExtends parameter) and then setting the overriding parameter. A full list of the parameters which can be used is available on the DataTables.net web-site. This example shows how to set the button text as required.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/collection.html b/wqflask/wqflask/static/packages/TableTools/collection.html
deleted file mode 100644
index 4eb3141b..00000000
--- a/wqflask/wqflask/static/packages/TableTools/collection.html
+++ /dev/null
@@ -1,522 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - button collections
-
-
-
Preamble
-
TableTools provides the ability to group buttons into a hidden drop down list, which is activated by clicking on a top-level button. This is achieved by extending the 'collection' predefined button type and setting it's aButtons parameter with the same options as the top level buttons (note that you cannot currently use a collection within a collection).
-
The example below shows the file save buttons grouped into a collection, while the copy and print buttons are left on the top level.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/defaults.html b/wqflask/wqflask/static/packages/TableTools/defaults.html
deleted file mode 100644
index 5ef74a68..00000000
--- a/wqflask/wqflask/static/packages/TableTools/defaults.html
+++ /dev/null
@@ -1,503 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - changing the initialisation defaults
-
-
-
Preamble
-
TableTools provides the ability to override the default initialisation parameters that are used when creating a new instance. This this particularly useful if you have multiple tables which you want to have the same TableTools behaviour - rather than declaring the structure multiple times, you can just set the defaults once. This example shows how to alter the default buttons.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/index.html b/wqflask/wqflask/static/packages/TableTools/index.html
deleted file mode 100644
index 06a2442d..00000000
--- a/wqflask/wqflask/static/packages/TableTools/index.html
+++ /dev/null
@@ -1,499 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example
-
-
-
Preamble
-
This example shows the basic initialisation of TableTools by simply including the 'T' marker in DataTables' sDom parameter. This tell DataTables to insert the TableTools toolbar in that location. Remember to include the Javascript and CSS source files as well!
-
It is worth noting that you might need to set the sSwfPath parameter to tell TableTools where to find the SWF file for copy and file save.
Please use your browser's print function to print this table. Press escape when finished.",sMessage:null,bShowAll:!0,sToolTip:"View print view",sButtonClass:"DTTT_button_print",sButtonText:"Print",fnClick:function(a,b){this.fnPrint(!0,b)}}),text:e.extend({},TableTools.buttonBase),select:e.extend({},TableTools.buttonBase,{sButtonText:"Select button",fnSelect:function(a){0!==this.fnGetSelected().length?e(a).removeClass(this.classes.buttons.disabled):e(a).addClass(this.classes.buttons.disabled)},
-fnInit:function(a){e(a).addClass(this.classes.buttons.disabled)}}),select_single:e.extend({},TableTools.buttonBase,{sButtonText:"Select button",fnSelect:function(a){1==this.fnGetSelected().length?e(a).removeClass(this.classes.buttons.disabled):e(a).addClass(this.classes.buttons.disabled)},fnInit:function(a){e(a).addClass(this.classes.buttons.disabled)}}),select_all:e.extend({},TableTools.buttonBase,{sButtonText:"Select all",fnClick:function(){this.fnSelectAll()},fnSelect:function(a){this.fnGetSelected().length==
-this.s.dt.fnRecordsDisplay()?e(a).addClass(this.classes.buttons.disabled):e(a).removeClass(this.classes.buttons.disabled)}}),select_none:e.extend({},TableTools.buttonBase,{sButtonText:"Deselect all",fnClick:function(){this.fnSelectNone()},fnSelect:function(a){0!==this.fnGetSelected().length?e(a).removeClass(this.classes.buttons.disabled):e(a).addClass(this.classes.buttons.disabled)},fnInit:function(a){e(a).addClass(this.classes.buttons.disabled)}}),ajax:e.extend({},TableTools.buttonBase,{sAjaxUrl:"/xhr.php",
-sButtonText:"Ajax button",fnClick:function(a,b){var c=this.fnGetTableData(b);e.ajax({url:b.sAjaxUrl,data:[{name:"tableData",value:c}],success:b.fnAjaxComplete,dataType:"json",type:"POST",cache:!1,error:function(){alert("Error detected when sending table data to server")}})},fnAjaxComplete:function(){alert("Ajax complete")}}),div:e.extend({},TableTools.buttonBase,{sAction:"div",sTag:"div",sButtonClass:"DTTT_nonbutton",sButtonText:"Text button"}),collection:e.extend({},TableTools.buttonBase,{sAction:"collection",
-sButtonClass:"DTTT_button_collection",sButtonText:"Collection",fnClick:function(a,b){this._fnCollectionShow(a,b)}})};TableTools.classes={container:"DTTT_container",buttons:{normal:"DTTT_button",disabled:"DTTT_disabled"},collection:{container:"DTTT_collection",background:"DTTT_collection_background",buttons:{normal:"DTTT_button",disabled:"DTTT_disabled"}},select:{table:"DTTT_selectable",row:"DTTT_selected"},print:{body:"DTTT_Print",info:"DTTT_print_info",message:"DTTT_PrintMessage"}};TableTools.classes_themeroller=
-{container:"DTTT_container ui-buttonset ui-buttonset-multi",buttons:{normal:"DTTT_button ui-button ui-state-default"},collection:{container:"DTTT_collection ui-buttonset ui-buttonset-multi"}};TableTools.DEFAULTS={sSwfPath:"media/swf/copy_csv_xls_pdf.swf",sRowSelect:"none",sSelectedClass:null,fnPreRowSelect:null,fnRowSelected:null,fnRowDeselected:null,aButtons:["copy","csv","xls","pdf","print"],oTags:{container:"div",button:"a",liner:"span",collection:{container:"div",button:"a",liner:"span"}}};TableTools.prototype.CLASS=
-"TableTools";TableTools.VERSION="2.1.5";TableTools.prototype.VERSION=TableTools.VERSION;"function"==typeof e.fn.dataTable&&"function"==typeof e.fn.dataTableExt.fnVersionCheck&&e.fn.dataTableExt.fnVersionCheck("1.9.0")?e.fn.dataTableExt.aoFeatures.push({fnInit:function(a){a=new TableTools(a.oInstance,"undefined"!=typeof a.oInit.oTableTools?a.oInit.oTableTools:{});TableTools._aInstances.push(a);return a.dom.container},cFeature:"T",sFeature:"TableTools"}):alert("Warning: TableTools 2 requires DataTables 1.9.0 or newer - www.datatables.net/download");
-e.fn.DataTable.TableTools=TableTools})(jQuery,window,document);
diff --git a/wqflask/wqflask/static/packages/TableTools/media/js/TableTools.min.js.gz b/wqflask/wqflask/static/packages/TableTools/media/js/TableTools.min.js.gz
deleted file mode 100644
index 01ce7c04..00000000
Binary files a/wqflask/wqflask/static/packages/TableTools/media/js/TableTools.min.js.gz and /dev/null differ
diff --git a/wqflask/wqflask/static/packages/TableTools/media/js/ZeroClipboard.js b/wqflask/wqflask/static/packages/TableTools/media/js/ZeroClipboard.js
deleted file mode 100644
index ff87ecd8..00000000
--- a/wqflask/wqflask/static/packages/TableTools/media/js/ZeroClipboard.js
+++ /dev/null
@@ -1,367 +0,0 @@
-// Simple Set Clipboard System
-// Author: Joseph Huckaby
-
-var ZeroClipboard_TableTools = {
-
- version: "1.0.4-TableTools2",
- clients: {}, // registered upload clients on page, indexed by id
- moviePath: '', // URL to movie
- nextId: 1, // ID of next movie
-
- $: function(thingy) {
- // simple DOM lookup utility function
- if (typeof(thingy) == 'string') thingy = document.getElementById(thingy);
- if (!thingy.addClass) {
- // extend element with a few useful methods
- thingy.hide = function() { this.style.display = 'none'; };
- thingy.show = function() { this.style.display = ''; };
- thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; };
- thingy.removeClass = function(name) {
- this.className = this.className.replace( new RegExp("\\s*" + name + "\\s*"), " ").replace(/^\s+/, '').replace(/\s+$/, '');
- };
- thingy.hasClass = function(name) {
- return !!this.className.match( new RegExp("\\s*" + name + "\\s*") );
- }
- }
- return thingy;
- },
-
- setMoviePath: function(path) {
- // set path to ZeroClipboard.swf
- this.moviePath = path;
- },
-
- dispatch: function(id, eventName, args) {
- // receive event from flash movie, send to client
- var client = this.clients[id];
- if (client) {
- client.receiveEvent(eventName, args);
- }
- },
-
- register: function(id, client) {
- // register new client to receive events
- this.clients[id] = client;
- },
-
- getDOMObjectPosition: function(obj) {
- // get absolute coordinates for dom element
- var info = {
- left: 0,
- top: 0,
- width: obj.width ? obj.width : obj.offsetWidth,
- height: obj.height ? obj.height : obj.offsetHeight
- };
-
- if ( obj.style.width != "" )
- info.width = obj.style.width.replace("px","");
-
- if ( obj.style.height != "" )
- info.height = obj.style.height.replace("px","");
-
- while (obj) {
- info.left += obj.offsetLeft;
- info.top += obj.offsetTop;
- obj = obj.offsetParent;
- }
-
- return info;
- },
-
- Client: function(elem) {
- // constructor for new simple upload client
- this.handlers = {};
-
- // unique ID
- this.id = ZeroClipboard_TableTools.nextId++;
- this.movieId = 'ZeroClipboard_TableToolsMovie_' + this.id;
-
- // register client with singleton to receive flash events
- ZeroClipboard_TableTools.register(this.id, this);
-
- // create movie
- if (elem) this.glue(elem);
- }
-};
-
-ZeroClipboard_TableTools.Client.prototype = {
-
- id: 0, // unique ID for us
- ready: false, // whether movie is ready to receive events or not
- movie: null, // reference to movie object
- clipText: '', // text to copy to clipboard
- fileName: '', // default file save name
- action: 'copy', // action to perform
- handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor
- cssEffects: true, // enable CSS mouse effects on dom container
- handlers: null, // user event handlers
- sized: false,
-
- glue: function(elem, title) {
- // glue to DOM element
- // elem can be ID or actual DOM element object
- this.domElement = ZeroClipboard_TableTools.$(elem);
-
- // float just above object, or zIndex 99 if dom element isn't set
- var zIndex = 99;
- if (this.domElement.style.zIndex) {
- zIndex = parseInt(this.domElement.style.zIndex) + 1;
- }
-
- // find X/Y position of domElement
- var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);
-
- // create floating DIV above element
- this.div = document.createElement('div');
- var style = this.div.style;
- style.position = 'absolute';
- style.left = '0px';
- style.top = '0px';
- style.width = (box.width) + 'px';
- style.height = box.height + 'px';
- style.zIndex = zIndex;
-
- if ( typeof title != "undefined" && title != "" ) {
- this.div.title = title;
- }
- if ( box.width != 0 && box.height != 0 ) {
- this.sized = true;
- }
-
- // style.backgroundColor = '#f00'; // debug
- if ( this.domElement ) {
- this.domElement.appendChild(this.div);
- this.div.innerHTML = this.getHTML( box.width, box.height );
- }
- },
-
- positionElement: function() {
- var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);
- var style = this.div.style;
-
- style.position = 'absolute';
- //style.left = (this.domElement.offsetLeft)+'px';
- //style.top = this.domElement.offsetTop+'px';
- style.width = box.width + 'px';
- style.height = box.height + 'px';
-
- if ( box.width != 0 && box.height != 0 ) {
- this.sized = true;
- } else {
- return;
- }
-
- var flash = this.div.childNodes[0];
- flash.width = box.width;
- flash.height = box.height;
- },
-
- getHTML: function(width, height) {
- // return HTML for movie
- var html = '';
- var flashvars = 'id=' + this.id +
- '&width=' + width +
- '&height=' + height;
-
- if (navigator.userAgent.match(/MSIE/)) {
- // IE gets an OBJECT tag
- var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
- html += '';
- }
- else {
- // all other browsers get an EMBED tag
- html += '';
- }
- return html;
- },
-
- hide: function() {
- // temporarily hide floater offscreen
- if (this.div) {
- this.div.style.left = '-2000px';
- }
- },
-
- show: function() {
- // show ourselves after a call to hide()
- this.reposition();
- },
-
- destroy: function() {
- // destroy control and floater
- if (this.domElement && this.div) {
- this.hide();
- this.div.innerHTML = '';
-
- var body = document.getElementsByTagName('body')[0];
- try { body.removeChild( this.div ); } catch(e) {;}
-
- this.domElement = null;
- this.div = null;
- }
- },
-
- reposition: function(elem) {
- // reposition our floating div, optionally to new container
- // warning: container CANNOT change size, only position
- if (elem) {
- this.domElement = ZeroClipboard_TableTools.$(elem);
- if (!this.domElement) this.hide();
- }
-
- if (this.domElement && this.div) {
- var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);
- var style = this.div.style;
- style.left = '' + box.left + 'px';
- style.top = '' + box.top + 'px';
- }
- },
-
- clearText: function() {
- // clear the text to be copy / saved
- this.clipText = '';
- if (this.ready) this.movie.clearText();
- },
-
- appendText: function(newText) {
- // append text to that which is to be copied / saved
- this.clipText += newText;
- if (this.ready) { this.movie.appendText(newText) ;}
- },
-
- setText: function(newText) {
- // set text to be copied to be copied / saved
- this.clipText = newText;
- if (this.ready) { this.movie.setText(newText) ;}
- },
-
- setCharSet: function(charSet) {
- // set the character set (UTF16LE or UTF8)
- this.charSet = charSet;
- if (this.ready) { this.movie.setCharSet(charSet) ;}
- },
-
- setBomInc: function(bomInc) {
- // set if the BOM should be included or not
- this.incBom = bomInc;
- if (this.ready) { this.movie.setBomInc(bomInc) ;}
- },
-
- setFileName: function(newText) {
- // set the file name
- this.fileName = newText;
- if (this.ready) this.movie.setFileName(newText);
- },
-
- setAction: function(newText) {
- // set action (save or copy)
- this.action = newText;
- if (this.ready) this.movie.setAction(newText);
- },
-
- addEventListener: function(eventName, func) {
- // add user event listener for event
- // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
- eventName = eventName.toString().toLowerCase().replace(/^on/, '');
- if (!this.handlers[eventName]) this.handlers[eventName] = [];
- this.handlers[eventName].push(func);
- },
-
- setHandCursor: function(enabled) {
- // enable hand cursor (true), or default arrow cursor (false)
- this.handCursorEnabled = enabled;
- if (this.ready) this.movie.setHandCursor(enabled);
- },
-
- setCSSEffects: function(enabled) {
- // enable or disable CSS effects on DOM container
- this.cssEffects = !!enabled;
- },
-
- receiveEvent: function(eventName, args) {
- // receive event from flash
- eventName = eventName.toString().toLowerCase().replace(/^on/, '');
-
- // special behavior for certain events
- switch (eventName) {
- case 'load':
- // movie claims it is ready, but in IE this isn't always the case...
- // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
- this.movie = document.getElementById(this.movieId);
- if (!this.movie) {
- var self = this;
- setTimeout( function() { self.receiveEvent('load', null); }, 1 );
- return;
- }
-
- // firefox on pc needs a "kick" in order to set these in certain cases
- if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
- var self = this;
- setTimeout( function() { self.receiveEvent('load', null); }, 100 );
- this.ready = true;
- return;
- }
-
- this.ready = true;
- this.movie.clearText();
- this.movie.appendText( this.clipText );
- this.movie.setFileName( this.fileName );
- this.movie.setAction( this.action );
- this.movie.setCharSet( this.charSet );
- this.movie.setBomInc( this.incBom );
- this.movie.setHandCursor( this.handCursorEnabled );
- break;
-
- case 'mouseover':
- if (this.domElement && this.cssEffects) {
- //this.domElement.addClass('hover');
- if (this.recoverActive) this.domElement.addClass('active');
- }
- break;
-
- case 'mouseout':
- if (this.domElement && this.cssEffects) {
- this.recoverActive = false;
- if (this.domElement.hasClass('active')) {
- this.domElement.removeClass('active');
- this.recoverActive = true;
- }
- //this.domElement.removeClass('hover');
- }
- break;
-
- case 'mousedown':
- if (this.domElement && this.cssEffects) {
- this.domElement.addClass('active');
- }
- break;
-
- case 'mouseup':
- if (this.domElement && this.cssEffects) {
- this.domElement.removeClass('active');
- this.recoverActive = false;
- }
- break;
- } // switch eventName
-
- if (this.handlers[eventName]) {
- for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
- var func = this.handlers[eventName][idx];
-
- if (typeof(func) == 'function') {
- // actual function reference
- func(this, args);
- }
- else if ((typeof(func) == 'object') && (func.length == 2)) {
- // PHP style object + method, i.e. [myObject, 'myMethod']
- func[0][ func[1] ](this, args);
- }
- else if (typeof(func) == 'string') {
- // name of function
- window[func](this, args);
- }
- } // foreach event handler defined
- } // user defined handler for event
- }
-
-};
diff --git a/wqflask/wqflask/static/packages/TableTools/media/swf/copy_csv_xls.swf b/wqflask/wqflask/static/packages/TableTools/media/swf/copy_csv_xls.swf
deleted file mode 100644
index 082c7acb..00000000
Binary files a/wqflask/wqflask/static/packages/TableTools/media/swf/copy_csv_xls.swf and /dev/null differ
diff --git a/wqflask/wqflask/static/packages/TableTools/media/swf/copy_csv_xls_pdf.swf b/wqflask/wqflask/static/packages/TableTools/media/swf/copy_csv_xls_pdf.swf
deleted file mode 100644
index 063131df..00000000
Binary files a/wqflask/wqflask/static/packages/TableTools/media/swf/copy_csv_xls_pdf.swf and /dev/null differ
diff --git a/wqflask/wqflask/static/packages/TableTools/multi_instance.html b/wqflask/wqflask/static/packages/TableTools/multi_instance.html
deleted file mode 100644
index 14e1e63e..00000000
--- a/wqflask/wqflask/static/packages/TableTools/multi_instance.html
+++ /dev/null
@@ -1,499 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - multiple toolbars
-
-
-
Preamble
-
Like all DataTables control elements, TableTools can have multiple instances specified in the sDom parameter of DataTables. This will create two TableTools toolbars next to the table, providing the same functions. An example of when this might be useful is to show the toolbar both above and below the table - as is done in this example.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/multiple_tables.html b/wqflask/wqflask/static/packages/TableTools/multiple_tables.html
deleted file mode 100644
index 8cd8aef9..00000000
--- a/wqflask/wqflask/static/packages/TableTools/multiple_tables.html
+++ /dev/null
@@ -1,296 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - multiple tables
-
-
-
Preamble
-
This example shows how multiple tables can be initialised with DataTables and TableTools in a single call to the $().dataTable() function. Basically it works as you would expect - no special considerations need be made!
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/pdf_message.html b/wqflask/wqflask/static/packages/TableTools/pdf_message.html
deleted file mode 100644
index e8f66e12..00000000
--- a/wqflask/wqflask/static/packages/TableTools/pdf_message.html
+++ /dev/null
@@ -1,524 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example
-
-
-
Preamble
-
This example shows how you can add a message to the saved PDF using the 'sPdfMessage' parameter. It also shows that the orientation of the output PDF can be changed to landscape which is useful if you have a lot of columns.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/plug-in.html b/wqflask/wqflask/static/packages/TableTools/plug-in.html
deleted file mode 100644
index 08a055bf..00000000
--- a/wqflask/wqflask/static/packages/TableTools/plug-in.html
+++ /dev/null
@@ -1,539 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - plug-ins
-
-
-
Preamble
-
Plug-ins in TableTools take the form of additional buttons types, which provide extra options and flexibility for TableTools. This example shows how a plug-in button type can be defined and then used in the TableTools initialisation. Note that the TableTools.buttonBase object is extended with our required parameters - this base object provides default values for all of the options TableTools can work with, so they don't all have to be defined in our button.
-
Additional plug-ins for TableTools can be found on the DataTables.net site. The example plug-in here shows a button which is used to insert the data from the table into a given element.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/select_multi.html b/wqflask/wqflask/static/packages/TableTools/select_multi.html
deleted file mode 100644
index ee94789c..00000000
--- a/wqflask/wqflask/static/packages/TableTools/select_multi.html
+++ /dev/null
@@ -1,507 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - multi-row select
-
-
-
Preamble
-
As well as providing a button toolbar, TableTools provides everything needed to have selectable rows in the table. Row selection is turned off by default in TableTools, but can be enabled using the sRowSelect parameter, set to either 'multi' or 'single'. When set the end user can select rows by simply clicking on them. TableTools provides a set of API methods and callbacks for controlling and monitoring the row selection in TableTools. There are also a number of pre-defined buttons to provide functions such as select-all and select-none, as shown in this example.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/select_single.html b/wqflask/wqflask/static/packages/TableTools/select_single.html
deleted file mode 100644
index 94a47893..00000000
--- a/wqflask/wqflask/static/packages/TableTools/select_single.html
+++ /dev/null
@@ -1,505 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - single row selection
-
-
-
Preamble
-
As well as providing a button toolbar, TableTools provides everything needed to have selectable rows in the table. Row selection is turned off by default in TableTools, but can be enabled using the sRowSelect parameter, set to either 'multi' or 'single'. When set the end user can select rows by simply clicking on them. TableTools provides a set of API methods and callbacks for controlling and monitoring the row selection in TableTools. This example shows single row selection enabled.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/swf_path.html b/wqflask/wqflask/static/packages/TableTools/swf_path.html
deleted file mode 100644
index c82633b4..00000000
--- a/wqflask/wqflask/static/packages/TableTools/swf_path.html
+++ /dev/null
@@ -1,505 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - setting SWF path
-
-
-
Preamble
-
TableTools uses a Flash SWF file to provide the ability to copy text to the system clipboard and save files locally. TableTools must be able to load the SWF file in order to provide these facilities. If you aren't using the same directory structure as the TableTools package, you will need to set this parameter.
-
Note that TableTools ships with two different SWF files - the only difference between them is that one of them provides the ability to save PDF files while the other doesn't. The trade off is that the PDF capable file is significantly larger in size (56K v 2K).
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/tabs.html b/wqflask/wqflask/static/packages/TableTools/tabs.html
deleted file mode 100644
index 915cc821..00000000
--- a/wqflask/wqflask/static/packages/TableTools/tabs.html
+++ /dev/null
@@ -1,348 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
-
- TableTools example
-
-
-
Preamble
-
This example shows the basic initialisation of TableTools by simply including the 'T' marker in DataTables' sDom parameter. This tell DataTables to insert the TableTools toolbar in that location. Remember to include the Javascript and CSS source files as well!
-
It is worth noting that you might need to set the sSwfPath parameter to tell TableTools where to find the SWF file for copy and file save.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/static/packages/TableTools/theme.html b/wqflask/wqflask/static/packages/TableTools/theme.html
deleted file mode 100644
index fcda07a0..00000000
--- a/wqflask/wqflask/static/packages/TableTools/theme.html
+++ /dev/null
@@ -1,524 +0,0 @@
-
-
-
-
-
-
- TableTools example
-
-
-
-
-
-
-
-
-
-
- TableTools example - jQuery UI theming
-
-
-
Preamble
-
Like DataTables, TableTools can be styled by a jQuery UI theme. The required classes for the theming with TableTools are added automatically when the bJQueryUI option is detected from DataTables. This example shows that in action, and also defines a button collection to show the themeing there.
-
-
\ No newline at end of file
diff --git a/wqflask/wqflask/templates/search_error.html b/wqflask/wqflask/templates/search_error.html
index 22416580..7394c9f9 100644
--- a/wqflask/wqflask/templates/search_error.html
+++ b/wqflask/wqflask/templates/search_error.html
@@ -2,8 +2,6 @@
{% block title %}Search Results{% endblock %}
{% block css %}
-
-
{% endblock %}
{% block content %}
--
cgit v1.2.3
From 518be96a310963a4127a0b569a73c91187c02b64 Mon Sep 17 00:00:00 2001
From: Pjotr Prins
Date: Thu, 12 Apr 2018 08:20:30 +0000
Subject: README and docs
---
README.md | 13 ++++++++-----
bin/genenetwork2 | 15 ++++++++-------
wqflask/maintenance/gen_select_dataset.py | 3 ---
3 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
index 8221ad65..3e7e64d0 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,11 @@ Once installed GN2 can be run online through a browser interface
./bin/genenetwork2
```
-(default is http://localhost:5003/). We are building up automated
+(default is http://localhost:5003/). For more examples, including running scripts and a Python REPL
+see the startup script [./bin/genenetwork2](https://github.com/genenetwork/genenetwork2/blob/testing/bin/genenetwork2).
+
+
+We are building up automated
testing using [mechanize](https://github.com/genenetwork/genenetwork2/tree/master/test/lib) which can be run with
```sh
@@ -70,16 +74,15 @@ For more information visit http://www.genenetwork.org/
[![JOSS](http://joss.theoj.org/papers/10.21105/joss.00025/status.svg)](http://joss.theoj.org/papers/10.21105/joss.00025)
-GeneNetwork was published in the Journal of Open Source Software as 'GeneNetwork: framework for web-based genetics' by Zachary Sloan, Danny Arends, Karl W. Broman, Arthur Centeno, Nicholas Furlotte, Harm Nijveen, Lei Yan, Xiang Zhou, Robert W. WIlliams and Pjotr Prins
+GeneNetwork was published in the Journal of Open Source Software as 'GeneNetwork: framework for web-based genetics' by Zachary Sloan, Danny Arends, Karl W. Broman, Arthur Centeno, Nicholas Furlotte, Harm Nijveen, Lei Yan, Xiang Zhou, Robert W. WIlliams and Pjotr Prins
You may also cite the software using
-[![DOI](https://zenodo.org/badge/5591/genenetwork/genenetwork2.svg)](https://zenodo.org/badge/latestdoi/5591/genenetwork/genenetwork2).
+[![DOI](https://zenodo.org/badge/5591/genenetwork/genenetwork2.svg)](https://zenodo.org/badge/latestdoi/5591/genenetwork/genenetwork2).
## Contact
IRC on #genenetwork on irc.freenode.net.
Code and primary web service managed by Dr. Robert W. Williams and the
-University of Tennessee Health Science Center, Memphis TN, USA.
-
+University of Tennessee Health Science Center, Memphis TN, USA.
diff --git a/bin/genenetwork2 b/bin/genenetwork2
index 18e02388..b3a8d8c2 100755
--- a/bin/genenetwork2
+++ b/bin/genenetwork2
@@ -15,28 +15,29 @@
# installation path of genenetwork). Say your profile is in
# ~/opt/gn-latest-guix
#
-# env GN2_PROFILE=~/opt/gn-latest-guix ./bin/genenetwork2
+# env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2
#
# You can pass in your own settings file, e.g.
#
-# env GN2_PROFILE=~/opt/gn-latest-guix ./bin/genenetwork2 ~/my_settings.py
+# env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2 ~/my_settings.py
#
# To run a maintenance python script with settings (instead of the
-# webserver) add that with a -c switch, e.g.
+# webserver) run from the base-dir with settings file and add that
+# script with a -c switch, e.g.
#
-# env GN2_PROFILE=~/opt/gn-latest-guix ./bin/genenetwork2 -c ./wqflask/maintenance/gen_select_dataset.py
+# env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2 ./etc/default_settings.py -c ./maintenance/gen_select_dataset.py
#
# To run any script in the environment
#
-# env GN2_PROFILE=~/opt/gn-latest-guix ./bin/genenetwork2 ./etc/default_settings.py -cli echo "HELLO WORLD"
+# env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2 ./etc/default_settings.py -cli echo "HELLO WORLD"
#
# To get a python REPL(!)
#
-# env GN2_PROFILE=~/opt/gn-latest-guix ./bin/genenetwork2 ./etc/default_settings.py -cli python
+# env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2 ./etc/default_settings.py -cli python
#
# For development you may want to run
#
-# env GN2_PROFILE=~/opt/gn-latest-guix WEBSERVER_MODE=DEBUG LOG_LEVEL=DEBUG ./bin/genenetwork2
+# env GN2_PROFILE=~/opt/gn-latest WEBSERVER_MODE=DEBUG LOG_LEVEL=DEBUG ./bin/genenetwork2
#
# For staging and production we use gunicorn. Run with something like
# (note you have to provide the server port). Provide a settings file!
diff --git a/wqflask/maintenance/gen_select_dataset.py b/wqflask/maintenance/gen_select_dataset.py
index f62d0cc1..79242661 100644
--- a/wqflask/maintenance/gen_select_dataset.py
+++ b/wqflask/maintenance/gen_select_dataset.py
@@ -63,9 +63,6 @@ from pprint import pformat as pf
#conn = Engine.connect()
-print('WARNING: This conversion is now OBSOLETE as the menu gets built from the database in Javascript using GN_SERVER instead!')
-
-
def parse_db_uri(db_uri):
"""Converts a database URI to the db name, host name, user name, and password"""
--
cgit v1.2.3
From 55cc4c63478de9587e282522540334e5375aebf1 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Fri, 13 Apr 2018 15:33:39 +0300
Subject: Use single entry-point for tests
* Remove the run-integration-tests.py, and use the test-website.py as
the entry point for all tests. This simplifies running the tests for
the site.
---
test/requests/run-integration-tests.py | 34 -----------------------------
test/requests/test-website.py | 40 ++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 34 deletions(-)
delete mode 100644 test/requests/run-integration-tests.py
diff --git a/test/requests/run-integration-tests.py b/test/requests/run-integration-tests.py
deleted file mode 100644
index 5e816549..00000000
--- a/test/requests/run-integration-tests.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import sys
-from test_login_local import TestLoginLocal
-from test_login_orcid import TestLoginOrcid
-from test_login_github import TestLoginGithub
-from test_registration import TestRegistration
-from unittest import TestSuite, TextTestRunner, TestLoader
-
-test_cases = [
- TestRegistration
- , TestLoginLocal
- , TestLoginGithub
- , TestLoginOrcid
-]
-
-def suite(gn2_url, es_url):
- the_suite = TestSuite()
- for case in test_cases:
- the_suite.addTests(initTest(case, gn2_url, es_url))
- return the_suite
-
-def initTest(klass, gn2_url, es_url):
- loader = TestLoader()
- methodNames = loader.getTestCaseNames(klass)
- return [klass(mname, gn2_url, es_url) for mname in methodNames]
-
-def main(gn2_url, es_url):
- runner = TextTestRunner()
- runner.run(suite(gn2_url, es_url))
-
-if __name__ == "__main__":
- if len(sys.argv) < 3:
- raise Exception("Required arguments missing:\n\tTry running `run-integration-test.py `")
- else:
- main(sys.argv[1], sys.argv[2])
diff --git a/test/requests/test-website.py b/test/requests/test-website.py
index a33fe708..b2e09bc4 100755
--- a/test/requests/test-website.py
+++ b/test/requests/test-website.py
@@ -12,6 +12,15 @@ from main_web_functionality import check_main_web_functionality
import link_checker
import sys
+# Imports for integration tests
+from wqflask import app
+from test_login_local import TestLoginLocal
+from test_login_orcid import TestLoginOrcid
+from test_login_github import TestLoginGithub
+from test_registration import TestRegistration
+from test_forgot_password import TestForgotPassword
+from unittest import TestSuite, TextTestRunner, TestLoader
+
print("Mechanical Rob firing up...")
def run_all(args_obj, parser):
@@ -30,6 +39,33 @@ def print_help(args_obj, parser):
def dummy(args_obj, parser):
print("Not implemented yet.")
+def integration_tests(args_obj, parser):
+ gn2_url = args_obj.host
+ es_url = app.config.get("ELASTICSEARCH_HOST")+":"+str(app.config.get("ELASTICSEARCH_PORT"))
+ run_integration_tests(gn2_url, es_url)
+
+def initTest(klass, gn2_url, es_url):
+ loader = TestLoader()
+ methodNames = loader.getTestCaseNames(klass)
+ return [klass(mname, gn2_url, es_url) for mname in methodNames]
+
+def integration_suite(gn2_url, es_url):
+ test_cases = [
+ TestRegistration
+ , TestLoginLocal
+ , TestLoginGithub
+ , TestLoginOrcid
+ , TestForgotPassword
+ ]
+ the_suite = TestSuite()
+ for case in test_cases:
+ the_suite.addTests(initTest(case, gn2_url, es_url))
+ return the_suite
+
+def run_integration_tests(gn2_url, es_url):
+ runner = TextTestRunner()
+ runner.run(integration_suite(gn2_url, es_url))
+
desc = """
This is Mechanical-Rob - an automated web server tester for
@@ -64,6 +100,10 @@ parser.add_argument("-m", "--mapping", dest="accumulate"
, action="store_const", const=check_mapping, default=print_help
, help="Checks for mapping.")
+parser.add_argument("-i", "--integration-tests", dest="accumulate"
+ , action="store_const", const=integration_tests, default=print_help
+ , help="Runs integration tests.")
+
# Navigation tests deactivated since system relies on Javascript
# parser.add_argument("-n", "--navigation", dest="accumulate"
# , action="store_const", const=check_navigation, default=print_help
--
cgit v1.2.3
From 90da7aa5028d64437f3fcaf903075cbda293b575 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Fri, 13 Apr 2018 15:39:47 +0300
Subject: Fix logging in tests
* Use the LOG_LEVEL provided by the application settings to enable easy
control of logging when running tests. It helps avoid a lot of
verbosity when running tests.
---
test/requests/parametrized_test.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/test/requests/parametrized_test.py b/test/requests/parametrized_test.py
index abf98fce..c585e910 100644
--- a/test/requests/parametrized_test.py
+++ b/test/requests/parametrized_test.py
@@ -1,5 +1,6 @@
import logging
import unittest
+from wqflask import app
from elasticsearch import Elasticsearch, TransportError
class ParametrizedTest(unittest.TestCase):
@@ -14,6 +15,7 @@ class ParametrizedTest(unittest.TestCase):
self.es_cleanup = []
es_logger = logging.getLogger("elasticsearch")
+ es_logger.setLevel(app.config.get("LOG_LEVEL"))
es_logger.addHandler(
logging.FileHandler("/tmp/es_TestRegistrationInfo.log"))
es_trace_logger = logging.getLogger("elasticsearch.trace")
--
cgit v1.2.3
From 9396ba78aa204a7f9474c314ca5a519c48ba042c Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Fri, 13 Apr 2018 15:41:31 +0300
Subject: Check email provided on forgot password
* Ensure that the user actually provides an email address when they try
to use the forgot password feature.
---
wqflask/wqflask/user_manager.py | 32 +++++++++++++++++---------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py
index 5f6c818e..9d09dbf6 100644
--- a/wqflask/wqflask/user_manager.py
+++ b/wqflask/wqflask/user_manager.py
@@ -727,31 +727,33 @@ def logout():
return response
-@app.route("/n/forgot_password")
+@app.route("/n/forgot_password", methods=['GET'])
def forgot_password():
"""Entry point for forgotten password"""
- return render_template("new_security/forgot_password.html")
+ print("ARGS: ", request.args)
+ errors = {"no-email": request.args.get("no-email")}
+ print("ERRORS: ", errors)
+ return render_template("new_security/forgot_password.html", errors=errors)
@app.route("/n/forgot_password_submit", methods=('POST',))
def forgot_password_submit():
"""When a forgotten password form is submitted we get here"""
params = request.form
email_address = params['email_address']
- logger.debug("Wants to send password E-mail to ",email_address)
- es = get_elasticsearch_connection()
- user_details = get_user_by_unique_column(es, "email_address", email_address)
- if user_details:
- ForgotPasswordEmail(user_details["email_address"])
- # try:
- # user = model.User.query.filter_by(email_address=email_address).one()
- # except orm.exc.NoResultFound:
- # flash("Couldn't find a user associated with the email address {}. Sorry.".format(
- # email_address))
- # return redirect(url_for("login"))
- # ForgotPasswordEmail(user)
- return render_template("new_security/forgot_password_step2.html",
+ next_page = None
+ if email_address != "":
+ logger.debug("Wants to send password E-mail to ",email_address)
+ es = get_elasticsearch_connection()
+ user_details = get_user_by_unique_column(es, "email_address", email_address)
+ if user_details:
+ ForgotPasswordEmail(user_details["email_address"])
+ return render_template("new_security/forgot_password_step2.html",
subject=ForgotPasswordEmail.subject)
+ else:
+ flash("You MUST provide an email", "alert-danger")
+ return redirect(url_for("forgot_password"))
+
@app.errorhandler(401)
def unauthorized(error):
return redirect(url_for('login'))
--
cgit v1.2.3
From ea099c2820fbca3f935fb8dc657b88e71224cded Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Sun, 15 Apr 2018 09:53:21 +0300
Subject: Fix issue with indentation
* Ensure the return is at the correct indentation level so that it is
executed correctly.
---
wqflask/wqflask/user_manager.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py
index 9d09dbf6..d652f2e9 100644
--- a/wqflask/wqflask/user_manager.py
+++ b/wqflask/wqflask/user_manager.py
@@ -747,8 +747,9 @@ def forgot_password_submit():
user_details = get_user_by_unique_column(es, "email_address", email_address)
if user_details:
ForgotPasswordEmail(user_details["email_address"])
- return render_template("new_security/forgot_password_step2.html",
- subject=ForgotPasswordEmail.subject)
+
+ return render_template("new_security/forgot_password_step2.html",
+ subject=ForgotPasswordEmail.subject)
else:
flash("You MUST provide an email", "alert-danger")
--
cgit v1.2.3
From e3e98b0533460837c4ea2eac67c4281eb0ba0012 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Sun, 15 Apr 2018 11:48:06 +0300
Subject: Use existing code. Delay after delete.
* Use existing code to get the elasticsearch connection. This should
prevent tests from failing in case the way connections to
elasticsearch are made change.
* Delay a while after deleting to allow elasticsearch to re-index the
data, thus preventing subtle bugs in the test.
---
test/requests/parametrized_test.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/test/requests/parametrized_test.py b/test/requests/parametrized_test.py
index c585e910..50003850 100644
--- a/test/requests/parametrized_test.py
+++ b/test/requests/parametrized_test.py
@@ -1,6 +1,7 @@
import logging
import unittest
from wqflask import app
+from utility.elasticsearch_tools import get_elasticsearch_connection, get_user_by_unique_column
from elasticsearch import Elasticsearch, TransportError
class ParametrizedTest(unittest.TestCase):
@@ -11,7 +12,7 @@ class ParametrizedTest(unittest.TestCase):
self.es_url = es_url
def setUp(self):
- self.es = Elasticsearch([self.es_url])
+ self.es = get_elasticsearch_connection()
self.es_cleanup = []
es_logger = logging.getLogger("elasticsearch")
@@ -23,7 +24,9 @@ class ParametrizedTest(unittest.TestCase):
logging.FileHandler("/tmp/es_TestRegistrationTrace.log"))
def tearDown(self):
+ from time import sleep
self.es.delete_by_query(
index="users"
, doc_type="local"
, body={"query":{"match":{"email_address":"test@user.com"}}})
+ sleep(1)
--
cgit v1.2.3
From 9ac9f94f3b1409ae3a47c8a9e890f578a69b020f Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Sun, 15 Apr 2018 11:56:00 +0300
Subject: Add tests for Forgot Password feature
* Add tests to ensure the "Forgot Password" feature works appropriately.
---
test/requests/test_forgot_password.py | 52 +++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
create mode 100644 test/requests/test_forgot_password.py
diff --git a/test/requests/test_forgot_password.py b/test/requests/test_forgot_password.py
new file mode 100644
index 00000000..2bf34c5c
--- /dev/null
+++ b/test/requests/test_forgot_password.py
@@ -0,0 +1,52 @@
+import requests
+from wqflask import user_manager
+from utility.elasticsearch_tools import get_user_by_unique_column
+from parameterized import parameterized
+from parametrized_test import ParametrizedTest
+
+passwork_reset_link = ''
+forgot_password_page = None
+
+class TestForgotPassword(ParametrizedTest):
+
+ def setUp(self):
+ super(TestForgotPassword, self).setUp()
+ self.forgot_password_url = self.gn2_url+"/n/forgot_password_submit"
+ def send_email(to_addr, msg, fromaddr="no-reply@genenetwork.org"):
+ print("CALLING: send_email_mock()")
+ email_data = {
+ "to_addr": to_addr
+ , "msg": msg
+ , "fromaddr": from_addr}
+
+ data = {
+ "es_connection": self.es,
+ "email_address": "test@user.com",
+ "full_name": "Test User",
+ "organization": "Test Organisation",
+ "password": "test_password",
+ "password_confirm": "test_password"
+ }
+ user_manager.basic_info = lambda : { "basic_info": "basic" }
+ user_manager.RegisterUser(data)
+
+ def testWithoutEmail(self):
+ data = {"email_address": ""}
+ error_notification = '
You MUST provide an email
'
+ result = requests.post(self.forgot_password_url, data=data)
+ self.assertEqual(result.url, self.gn2_url+"/n/forgot_password")
+ self.assertTrue(
+ result.content.find(error_notification) >= 0
+ , "Error message should be displayed but was not")
+
+ def testWithNonExistingEmail(self):
+ # Monkey patching doesn't work, so simply test that getting by email
+ # returns the correct data
+ user = get_user_by_unique_column(self.es, "email_address", "non-existent@domain.com")
+ self.assertTrue(user is None, "Should not find non-existent user")
+
+ def testWithExistingEmail(self):
+ # Monkey patching doesn't work, so simply test that getting by email
+ # returns the correct data
+ user = get_user_by_unique_column(self.es, "email_address", "test@user.com")
+ self.assertTrue(user is not None, "Should find user")
--
cgit v1.2.3
From fdd28defcaf3326f3c6b6507124708d83a1da119 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Sun, 15 Apr 2018 11:57:09 +0300
Subject: Deactivate analysis of email_address field
* Prevent elasticsearch from analysing and tokenising the email_address
field so as to avoid issue with getting back all email addresses with
the same domain as the one being searched for.
---
wqflask/utility/elasticsearch_tools.py | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/wqflask/utility/elasticsearch_tools.py b/wqflask/utility/elasticsearch_tools.py
index d35cb5ee..7d2ee8c9 100644
--- a/wqflask/utility/elasticsearch_tools.py
+++ b/wqflask/utility/elasticsearch_tools.py
@@ -24,6 +24,8 @@ def get_elasticsearch_connection():
"host": ELASTICSEARCH_HOST, "port": ELASTICSEARCH_PORT
}]) if (ELASTICSEARCH_HOST and ELASTICSEARCH_PORT) else None
+ setup_users_index(es)
+
es_logger = logging.getLogger("elasticsearch")
es_logger.setLevel(logging.INFO)
es_logger.addHandler(logging.NullHandler())
@@ -33,6 +35,17 @@ def get_elasticsearch_connection():
return es
+def setup_users_index(es_connection):
+ if es_connection:
+ index_settings = {
+ "properties": {
+ "email_address": {
+ "type": "string"
+ , "index": "not_analyzed"}}}
+
+ es_connection.indices.create(index='users', ignore=400)
+ es_connection.indices.put_mapping(body=index_settings, index="users", doc_type="local")
+
def get_user_by_unique_column(es, column_name, column_value, index="users", doc_type="local"):
return get_item_by_unique_column(es, column_name, column_value, index=index, doc_type=doc_type)
--
cgit v1.2.3
From dda4697505aea2cd950533dfb3a0dfb0e66ec018 Mon Sep 17 00:00:00 2001
From: Pjotr Prins
Date: Mon, 16 Apr 2018 09:00:52 +0000
Subject: Docs on elasticsearch use
---
README.md | 24 ++++++++++++++------
bin/test-website | 2 +-
wqflask/utility/elasticsearch_tools.py | 41 ++++++++++++++++++++++++++++++++++
3 files changed, 59 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index 3e7e64d0..59645994 100644
--- a/README.md
+++ b/README.md
@@ -17,25 +17,35 @@ deploy GN2 and dependencies as a self contained unit on any machine.
The database can be run separately as well as the source tree (for
developers). See the [installation docs](doc/README.org).
-## Test
+## Run
Once installed GN2 can be run online through a browser interface
```sh
-./bin/genenetwork2
+genenetwork2
```
-(default is http://localhost:5003/). For more examples, including running scripts and a Python REPL
-see the startup script [./bin/genenetwork2](https://github.com/genenetwork/genenetwork2/blob/testing/bin/genenetwork2).
+(default is http://localhost:5003/). For full examples (you'll need to
+set a number of environment variables), including running scripts and
+a Python REPL, see the startup script
+[./bin/genenetwork2](https://github.com/genenetwork/genenetwork2/blob/testing/bin/genenetwork2).
+## Testing
-We are building up automated
-testing using [mechanize](https://github.com/genenetwork/genenetwork2/tree/master/test/lib) which can be run with
+We are building 'Mechanical Rob' automated testing using Python
+[requests](https://github.com/genenetwork/genenetwork2/tree/master/test/lib)
+which can be run with something like
```sh
-./bin/test-website
+env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2 ./etc/default_settings.py -c ../test/requests/test-website.py -a http://localhost:5003
```
+The GN2_PROFILE is the Guix profile that contains all
+dependencies. The ./bin/genenetwork2 script sets up the environment
+and executes test-website.py in a Python interpreter. The -a switch
+says to run all tests and the URL points to the running GN2 http
+server.
+
## Documentation
User documentation can be found
diff --git a/bin/test-website b/bin/test-website
index 5935f016..7fbcfd2f 100755
--- a/bin/test-website
+++ b/bin/test-website
@@ -2,6 +2,6 @@
if [ -z $GN2_PROFILE ]; then
echo "Run request tests with something like"
- echo env GN2_PROFILE=/home/wrk/opt/gn-latest ./bin/genenetwork2 ./etc/default_settings.py -c ../test/requests/test-website.py http://localhost:5003
+ echo env GN2_PROFILE=/home/wrk/opt/gn-latest ./bin/genenetwork2 ./etc/default_settings.py -c ../test/requests/test-website.py -a http://localhost:5003
exit 1
fi
diff --git a/wqflask/utility/elasticsearch_tools.py b/wqflask/utility/elasticsearch_tools.py
index 7d2ee8c9..4d4a9844 100644
--- a/wqflask/utility/elasticsearch_tools.py
+++ b/wqflask/utility/elasticsearch_tools.py
@@ -1,3 +1,44 @@
+# Elasticsearch support
+#
+# Some helpful commands to view the database:
+#
+# You can test the server being up with
+#
+# curl -H 'Content-Type: application/json' http://localhost:9200
+#
+# List all indices
+#
+# curl -H 'Content-Type: application/json' 'localhost:9200/_cat/indices?v'
+#
+# To see the users index 'table'
+#
+# curl http://localhost:9200/users
+#
+# To list all user ids
+#
+# curl -H 'Content-Type: application/json' http://localhost:9200/users/local/_search?pretty=true -d '
+# {
+# "query" : {
+# "match_all" : {}
+# },
+# "stored_fields": []
+# }'
+#
+# To view a record
+#
+# curl -H 'Content-Type: application/json' http://localhost:9200/users/local/_search?pretty=true -d '
+# {
+# "query" : {
+# "match" : { "email_address": "pjotr2017@thebird.nl"}
+# }
+# }'
+#
+#
+# To delete the users index and data (dangerous!)
+#
+# curl -XDELETE -H 'Content-Type: application/json' 'localhost:9200/users'
+
+
from elasticsearch import Elasticsearch, TransportError
import logging
--
cgit v1.2.3
From bc1672f8617c56684ae3aeda7018362e818c46d6 Mon Sep 17 00:00:00 2001
From: Muriithi Frederick Muriuki
Date: Mon, 16 Apr 2018 17:25:14 +0300
Subject: Update mappings for Elasticsearch 6.2. Update logger
* Update the indexes mappings to be compatible with the newer
Elasticsearch 6.2.* series.
Close the index before updating it, and reopen it after to help with
the re-indexing of the data.
* Update the error logger to include the exception that was thrown.
---
wqflask/utility/elasticsearch_tools.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/wqflask/utility/elasticsearch_tools.py b/wqflask/utility/elasticsearch_tools.py
index 7d2ee8c9..0dc59d43 100644
--- a/wqflask/utility/elasticsearch_tools.py
+++ b/wqflask/utility/elasticsearch_tools.py
@@ -29,8 +29,8 @@ def get_elasticsearch_connection():
es_logger = logging.getLogger("elasticsearch")
es_logger.setLevel(logging.INFO)
es_logger.addHandler(logging.NullHandler())
- except:
- logger.error("Failed to get elasticsearch connection")
+ except Exception as e:
+ logger.error("Failed to get elasticsearch connection", e)
es = None
return es
@@ -40,11 +40,12 @@ def setup_users_index(es_connection):
index_settings = {
"properties": {
"email_address": {
- "type": "string"
- , "index": "not_analyzed"}}}
+ "type": "keyword"}}}
es_connection.indices.create(index='users', ignore=400)
+ es_connection.indices.close(index="users")
es_connection.indices.put_mapping(body=index_settings, index="users", doc_type="local")
+ es_connection.indices.open(index="users")
def get_user_by_unique_column(es, column_name, column_value, index="users", doc_type="local"):
return get_item_by_unique_column(es, column_name, column_value, index=index, doc_type=doc_type)
--
cgit v1.2.3
From ebbc8c67c13b44df98ea3c2b355e86f77572543b Mon Sep 17 00:00:00 2001
From: Pjotr Prins
Date: Mon, 16 Apr 2018 15:02:16 +0000
Subject: login messages improved
---
wqflask/wqflask/templates/new_security/login_user.html | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/wqflask/wqflask/templates/new_security/login_user.html b/wqflask/wqflask/templates/new_security/login_user.html
index 4a857c60..27b20ebf 100644
--- a/wqflask/wqflask/templates/new_security/login_user.html
+++ b/wqflask/wqflask/templates/new_security/login_user.html
@@ -31,16 +31,19 @@