aboutsummaryrefslogtreecommitdiff
path: root/wqflask
diff options
context:
space:
mode:
Diffstat (limited to 'wqflask')
-rw-r--r--wqflask/base/data_set.py113
-rw-r--r--wqflask/base/webqtlCaseData.py41
-rw-r--r--wqflask/base/webqtlConfig.py2
-rw-r--r--wqflask/tests/base/data.py110
-rw-r--r--wqflask/tests/base/test_data_set.py135
-rw-r--r--wqflask/tests/base/test_webqtl_case_data.py39
-rw-r--r--wqflask/utility/authentication_tools.py5
-rw-r--r--wqflask/wqflask/static/gif/error/m001.gifbin0 -> 273531 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/m002.gifbin0 -> 1799777 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/m003.gifbin0 -> 2238947 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/m004.gifbin0 -> 2090274 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/m005.gifbin0 -> 947565 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/m006.gifbin0 -> 121116 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/m007.gifbin0 -> 41670 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/m008.gifbin0 -> 732023 bytes
-rw-r--r--wqflask/wqflask/static/gif/error/mouse-wheel.gifbin0 -> 2001764 bytes
16 files changed, 340 insertions, 105 deletions
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index 5d562871..cfba9104 100644
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -93,7 +93,7 @@ Publish or ProbeSet. E.g.
"""
self.redis_instance = redis_instance
self.datasets = {}
- data = redis_instance.get("dataset_structure")
+ data = self.redis_instance.get("dataset_structure")
if data:
self.datasets = json.loads(data)
else: # ZS: I don't think this should ever run unless Redis is emptied
@@ -115,73 +115,58 @@ Publish or ProbeSet. E.g.
except:
pass
- redis_instance.set("dataset_structure", json.dumps(self.datasets))
+ self.redis_instance.set("dataset_structure", json.dumps(self.datasets))
- # Set LOG_LEVEL_DEBUG=5 to see the following:
- logger.debugf(5, "datasets", self.datasets)
+ def set_dataset_key(self, t, name):
+ """If name is not in the object's dataset dictionary, set it, and update
+ dataset_structure in Redis
+
+ args:
+ t: Type of dataset structure which can be: 'mrna_expr', 'pheno',
+ 'other_pheno', 'geno'
+ name: The name of the key to inserted in the datasets dictionary
+
+ """
+ sql_query_mapping = {
+ 'mrna_expr': ("""SELECT ProbeSetFreeze.Id FROM """ +
+ """ProbeSetFreeze WHERE ProbeSetFreeze.Name = "{}" """),
+ 'pheno': ("""SELECT InfoFiles.GN_AccesionId """ +
+ """FROM InfoFiles, PublishFreeze, InbredSet """ +
+ """WHERE InbredSet.Name = '{}' AND """ +
+ """PublishFreeze.InbredSetId = InbredSet.Id AND """ +
+ """InfoFiles.InfoPageName = PublishFreeze.Name"""),
+ 'other_pheno': ("""SELECT PublishFreeze.Name """ +
+ """FROM PublishFreeze, InbredSet """ +
+ """WHERE InbredSet.Name = '{}' AND """ +
+ """PublishFreeze.InbredSetId = InbredSet.Id"""),
+ 'geno': ("""SELECT GenoFreeze.Id FROM GenoFreeze WHERE """ +
+ """GenoFreeze.Name = "{}" """)
+ }
+
+ dataset_name_mapping = {
+ "mrna_expr": "ProbeSet",
+ "pheno": "Publish",
+ "other_pheno": "Publish",
+ "geno": "Geno",
+ }
+
+ if t in ['pheno', 'other_pheno']:
+ name = name.replace("Publish", "")
+ if bool(len(g.db.execute(sql_query_mapping[t].format(name)))):
+ self.datasets[name] = dataset_name_mapping[t]
+ self.redis_instance.set("dataset_structure", json.dumps(self.datasets))
+ return True
+
+ return None
def __call__(self, name):
+
if name not in self.datasets:
- mrna_expr_query = """
- SELECT
- ProbeSetFreeze.Id
- FROM
- ProbeSetFreeze
- WHERE
- ProbeSetFreeze.Name = "{0}"
- """.format(name)
-
- results = g.db.execute(mrna_expr_query).fetchall()
- if len(results):
- self.datasets[name] = "ProbeSet"
- redis_instance.set("dataset_structure", json.dumps(self.datasets))
- return self.datasets[name]
-
- group_name = name.replace("Publish", "")
-
- pheno_query = """SELECT InfoFiles.GN_AccesionId
- FROM InfoFiles, PublishFreeze, InbredSet
- WHERE InbredSet.Name = '{0}' AND
- PublishFreeze.InbredSetId = InbredSet.Id AND
- InfoFiles.InfoPageName = PublishFreeze.Name""".format(group_name)
-
- results = g.db.execute(pheno_query).fetchall()
- if len(results):
- self.datasets[name] = "Publish"
- redis_instance.set("dataset_structure", json.dumps(self.datasets))
- return self.datasets[name]
-
- # ZS: For when there isn't an InfoFiles ID; not sure if this and the preceding query are both necessary
- other_pheno_query = """SELECT PublishFreeze.Name
- FROM PublishFreeze, InbredSet
- WHERE InbredSet.Name = '{}' AND
- PublishFreeze.InbredSetId = InbredSet.Id""".format(group_name)
-
- results = g.db.execute(other_pheno_query).fetchall()
- if len(results):
- self.datasets[name] = "Publish"
- redis_instance.set("dataset_structure", json.dumps(self.datasets))
- return self.datasets[name]
-
- geno_query = """
- SELECT
- GenoFreeze.Id
- FROM
- GenoFreeze
- WHERE
- GenoFreeze.Name = "{0}"
- """.format(name)
-
- results = g.db.execute(geno_query).fetchall()
- if len(results):
- self.datasets[name] = "Geno"
- self.redis_instance.set("dataset_structure", json.dumps(self.datasets))
- return self.datasets[name]
-
- # ZS: It shouldn't ever reach this
- return None
- else:
- return self.datasets[name]
+ for t in ["mrna_expr", "pheno", "other_pheno", "geno"]:
+ # This has side-effects, with the end result being a truth-y value
+ if(self.set_dataset_key(t, name)):
+ break
+ return self.datasets.get(name, None) # Return None if name has not been set
# Do the intensive work at startup one time only
diff --git a/wqflask/base/webqtlCaseData.py b/wqflask/base/webqtlCaseData.py
index d8487f01..2844cedd 100644
--- a/wqflask/base/webqtlCaseData.py
+++ b/wqflask/base/webqtlCaseData.py
@@ -19,8 +19,7 @@
# This module is used by GeneNetwork project (www.genenetwork.org)
#
# Created by GeneNetwork Core Team 2010/08/10
-#
-# Last updated by GeneNetwork Core Team 2010/10/20
+
from utility.logger import getLogger
logger = getLogger(__name__)
@@ -29,7 +28,7 @@ import utility.tools
utility.tools.show_settings()
-class webqtlCaseData(object):
+class webqtlCaseData:
"""one case data in one trait"""
def __init__(self, name, value=None, variance=None, num_cases=None, name2=None):
@@ -43,44 +42,40 @@ class webqtlCaseData(object):
self.outlier = None # Not set to True/False until later
def __repr__(self):
- str = "<webqtlCaseData> "
- if self.value != None:
- str += "value=%2.3f" % self.value
- if self.variance != None:
- str += " variance=%2.3f" % self.variance
+ case_data_string = "<webqtlCaseData> "
+ if self.value is not None:
+ case_data_string += "value=%2.3f" % self.value
+ if self.variance is not None:
+ case_data_string += " variance=%2.3f" % self.variance
if self.num_cases:
- str += " ndata=%s" % self.num_cases
+ case_data_string += " ndata=%s" % self.num_cases
if self.name:
- str += " name=%s" % self.name
+ case_data_string += " name=%s" % self.name
if self.name2:
- str += " name2=%s" % self.name2
- return str
+ case_data_string += " name2=%s" % self.name2
+ return case_data_string
@property
def class_outlier(self):
"""Template helper"""
if self.outlier:
return "outlier"
- else:
- return ""
+ return ""
@property
def display_value(self):
- if self.value != None:
+ if self.value is not None:
return "%2.3f" % self.value
- else:
- return "x"
+ return "x"
@property
def display_variance(self):
- if self.variance != None:
+ if self.variance is not None:
return "%2.3f" % self.variance
- else:
- return "x"
+ return "x"
@property
def display_num_cases(self):
- if self.num_cases != None:
+ if self.num_cases is not None:
return "%s" % self.num_cases
- else:
- return "x"
+ return "x"
diff --git a/wqflask/base/webqtlConfig.py b/wqflask/base/webqtlConfig.py
index 3d86bc22..862ac881 100644
--- a/wqflask/base/webqtlConfig.py
+++ b/wqflask/base/webqtlConfig.py
@@ -85,7 +85,7 @@ assert_writable_dir(GENERATED_TEXT_DIR)
# Flat file directories
GENODIR = flat_files('genotype')+'/'
assert_dir(GENODIR)
-assert_dir(GENODIR+'bimbam') # for gemma
+# assert_dir(GENODIR+'bimbam') # for gemma
# JSON genotypes are OBSOLETE
JSON_GENODIR = flat_files('genotype/json')+'/'
diff --git a/wqflask/tests/base/data.py b/wqflask/tests/base/data.py
new file mode 100644
index 00000000..06a5a989
--- /dev/null
+++ b/wqflask/tests/base/data.py
@@ -0,0 +1,110 @@
+gen_menu_json = """
+{
+ "datasets": {
+ "human": {
+ "HLC": {
+ "Liver mRNA": [
+ [
+ "320",
+ "HLC_0311",
+ "GSE9588 Human Liver Normal (Mar11) Both Sexes"
+ ]
+ ],
+ "Phenotypes": [
+ [
+ "635",
+ "HLCPublish",
+ "HLC Published Phenotypes"
+ ]
+ ]
+ }
+ },
+ "mouse": {
+ "BXD": {
+ "Genotypes": [
+ [
+ "600",
+ "BXDGeno",
+ "BXD Genotypes"
+ ]
+ ],
+ "Hippocampus mRNA": [
+ [
+ "112",
+ "HC_M2_0606_P",
+ "Hippocampus Consortium M430v2 (Jun06) PDNN"
+ ]
+ ],
+ "Phenotypes": [
+ [
+ "602",
+ "BXDPublish",
+ "BXD Published Phenotypes"
+ ]
+ ]
+ }
+ }
+ },
+ "groups": {
+ "human": [
+ [
+ "HLC",
+ "Liver: Normal Gene Expression with Genotypes (Merck)",
+ "Family:None"
+ ]
+ ],
+ "mouse": [
+ [
+ "BXD",
+ "BXD",
+ "Family:None"
+ ]
+ ]
+ },
+ "species": [
+ [
+ "human",
+ "Human"
+ ],
+ [
+ "mouse",
+ "Mouse"
+ ]
+ ],
+ "types": {
+ "human": {
+ "HLC": [
+ [
+ "Phenotypes",
+ "Traits and Cofactors",
+ "Phenotypes"
+ ],
+ [
+ "Liver mRNA",
+ "Liver mRNA",
+ "Molecular Trait Datasets"
+ ]
+ ]
+ },
+ "mouse": {
+ "BXD": [
+ [
+ "Phenotypes",
+ "Traits and Cofactors",
+ "Phenotypes"
+ ],
+ [
+ "Genotypes",
+ "DNA Markers and SNPs",
+ "Genotypes"
+ ],
+ [
+ "Hippocampus mRNA",
+ "Hippocampus mRNA",
+ "Molecular Trait Datasets"
+ ]
+ ]
+ }
+ }
+}
+"""
diff --git a/wqflask/tests/base/test_data_set.py b/wqflask/tests/base/test_data_set.py
index 44a54c7e..94780a5d 100644
--- a/wqflask/tests/base/test_data_set.py
+++ b/wqflask/tests/base/test_data_set.py
@@ -1,25 +1,18 @@
+"""Tests for wqflask/base/data_set.py"""
+
import unittest
import mock
from wqflask import app
-
+from data import gen_menu_json
from base.data_set import DatasetType
-
-class TestDataSetTypes(unittest.TestCase):
- def setUp(self):
- self.app_context = app.app_context()
- self.app_context.push()
- def tearDown(self):
- self.app_context.pop()
+class TestDataSetTypes(unittest.TestCase):
+ """Tests for the DataSetType class"""
- @mock.patch('base.data_set.g')
- def test_data_set_type(self, db_mock):
- with app.app_context():
- db_mock.get = mock.Mock()
- r = mock.Mock()
- r.get.return_value = """
+ def setUp(self):
+ self.test_dataset = """
{
"AD-cases-controls-MyersGeno": "Geno",
"AD-cases-controls-MyersPublish": "Publish",
@@ -32,4 +25,116 @@ class TestDataSetTypes(unittest.TestCase):
"B139_K_1206_R": "ProbeSet"
}
"""
- self.assertEqual(DatasetType(r)("All Phenotypes"), "Publish")
+ self.app_context = app.app_context()
+ self.app_context.push()
+
+ def tearDown(self):
+ self.app_context.pop()
+
+ @mock.patch('base.data_set.g')
+ def test_data_set_type(self, db_mock):
+ """Test that DatasetType returns correctly if the Redis Instance is not empty
+ and the name variable exists in the dictionary
+
+ """
+ with app.app_context():
+ db_mock.get = mock.Mock()
+ redis_mock = mock.Mock()
+ redis_mock.get.return_value = self.test_dataset
+ self.assertEqual(DatasetType(redis_mock)
+ ("All Phenotypes"), "Publish")
+ redis_mock.get.assert_called_once_with("dataset_structure")
+
+ @mock.patch('base.data_set.requests.get')
+ def test_data_set_type_with_empty_redis(self, request_mock):
+ """Test that DatasetType returns correctly if the Redis Instance is empty and
+ the name variable exists in the dictionary
+
+ """
+ with app.app_context():
+ request_mock.return_value.content = gen_menu_json
+ redis_mock = mock.Mock()
+ redis_mock.get.return_value = None
+ data_set = DatasetType(redis_mock)
+ self.assertEqual(data_set("BXDGeno"), "Geno")
+ self.assertEqual(data_set("BXDPublish"), "Publish")
+ self.assertEqual(data_set("HLC_0311"), "ProbeSet")
+ redis_mock.set.assert_called_once_with(
+ "dataset_structure",
+ '{"BXDGeno": "Geno", "BXDPublish": "Publish", "HLCPublish": "Publish", "HLC_0311": "ProbeSet", "HC_M2_0606_P": "ProbeSet"}')
+
+ @mock.patch('base.data_set.g')
+ def test_set_dataset_key_mrna(self, db_mock):
+ with app.app_context():
+ db_mock.db.execute.return_value = [1, 2, 3]
+ redis_mock = mock.Mock()
+ redis_mock.get.return_value = self.test_dataset
+ data_set = DatasetType(redis_mock)
+ data_set.set_dataset_key("mrna_expr", "Test")
+ self.assertEqual(data_set("Test"), "ProbeSet")
+ redis_mock.set.assert_called_once_with(
+ "dataset_structure",
+ '{"Aging-Brain-UCIPublish": "Publish", "AKXDGeno": "Geno", "B139_K_1206_M": "ProbeSet", "AD-cases-controls-MyersGeno": "Geno", "AD-cases-controls-MyersPublish": "Publish", "All Phenotypes": "Publish", "Test": "ProbeSet", "AXBXAPublish": "Publish", "B139_K_1206_R": "ProbeSet", "AXBXAGeno": "Geno"}')
+ expected_db_call = """"""
+ db_mock.db.execute.assert_called_with(
+ ("SELECT ProbeSetFreeze.Id FROM ProbeSetFreeze " +
+ "WHERE ProbeSetFreeze.Name = \"Test\" ")
+ )
+
+ @mock.patch('base.data_set.g')
+ def test_set_dataset_key_pheno(self, db_mock):
+ with app.app_context():
+ db_mock.db.execute.return_value = [1, 2, 3]
+ redis_mock = mock.Mock()
+ redis_mock.get.return_value = self.test_dataset
+ data_set = DatasetType(redis_mock)
+ data_set.set_dataset_key("pheno", "Test")
+ self.assertEqual(data_set("Test"), "Publish")
+ redis_mock.set.assert_called_once_with(
+ "dataset_structure",
+ '{"Aging-Brain-UCIPublish": "Publish", "AKXDGeno": "Geno", "B139_K_1206_M": "ProbeSet", "AD-cases-controls-MyersGeno": "Geno", "AD-cases-controls-MyersPublish": "Publish", "All Phenotypes": "Publish", "Test": "Publish", "AXBXAPublish": "Publish", "B139_K_1206_R": "ProbeSet", "AXBXAGeno": "Geno"}')
+ expected_db_call = """"""
+ db_mock.db.execute.assert_called_with(
+ ("SELECT InfoFiles.GN_AccesionId " +
+ "FROM InfoFiles, PublishFreeze, InbredSet " +
+ "WHERE InbredSet.Name = 'Test' AND "
+ "PublishFreeze.InbredSetId = InbredSet.Id AND " +
+ "InfoFiles.InfoPageName = PublishFreeze.Name")
+ )
+
+ @mock.patch('base.data_set.g')
+ def test_set_dataset_other_pheno(self, db_mock):
+ with app.app_context():
+ db_mock.db.execute.return_value = [1, 2, 3]
+ redis_mock = mock.Mock()
+ redis_mock.get.return_value = self.test_dataset
+ data_set = DatasetType(redis_mock)
+ data_set.set_dataset_key("other_pheno", "Test")
+ self.assertEqual(data_set("Test"), "Publish")
+ redis_mock.set.assert_called_once_with(
+ "dataset_structure",
+ '{"Aging-Brain-UCIPublish": "Publish", "AKXDGeno": "Geno", "B139_K_1206_M": "ProbeSet", "AD-cases-controls-MyersGeno": "Geno", "AD-cases-controls-MyersPublish": "Publish", "All Phenotypes": "Publish", "Test": "Publish", "AXBXAPublish": "Publish", "B139_K_1206_R": "ProbeSet", "AXBXAGeno": "Geno"}')
+ expected_db_call = """"""
+ db_mock.db.execute.assert_called_with(
+ ("SELECT PublishFreeze.Name " +
+ "FROM PublishFreeze, InbredSet " +
+ "WHERE InbredSet.Name = 'Test' AND "
+ "PublishFreeze.InbredSetId = InbredSet.Id")
+ )
+
+ @mock.patch('base.data_set.g')
+ def test_set_dataset_geno(self, db_mock):
+ with app.app_context():
+ db_mock.db.execute.return_value = [1, 2, 3]
+ redis_mock = mock.Mock()
+ redis_mock.get.return_value = self.test_dataset
+ data_set = DatasetType(redis_mock)
+ data_set.set_dataset_key("geno", "Test")
+ self.assertEqual(data_set("Test"), "Geno")
+ redis_mock.set.assert_called_once_with(
+ "dataset_structure",
+ '{"Aging-Brain-UCIPublish": "Publish", "AKXDGeno": "Geno", "B139_K_1206_M": "ProbeSet", "AD-cases-controls-MyersGeno": "Geno", "AD-cases-controls-MyersPublish": "Publish", "All Phenotypes": "Publish", "Test": "Geno", "AXBXAPublish": "Publish", "B139_K_1206_R": "ProbeSet", "AXBXAGeno": "Geno"}')
+ expected_db_call = """"""
+ db_mock.db.execute.assert_called_with(
+ ("SELECT GenoFreeze.Id FROM GenoFreeze WHERE GenoFreeze.Name = \"Test\" ")
+ )
diff --git a/wqflask/tests/base/test_webqtl_case_data.py b/wqflask/tests/base/test_webqtl_case_data.py
new file mode 100644
index 00000000..8e8ba482
--- /dev/null
+++ b/wqflask/tests/base/test_webqtl_case_data.py
@@ -0,0 +1,39 @@
+"""Tests for wqflask/base/webqtlCaseData.py"""
+import unittest
+
+from wqflask import app # Required because of utility.tools in webqtlCaseData.py
+from base.webqtlCaseData import webqtlCaseData
+
+class TestWebqtlCaseData(unittest.TestCase):
+ """Tests for WebqtlCaseData class"""
+
+ def setUp(self):
+ self.w = webqtlCaseData(name="Test",
+ value=0,
+ variance=0.0,
+ num_cases=10,
+ name2="Test2")
+
+ def test_webqtl_case_data_repr(self):
+ self.assertEqual(
+ repr(self.w),
+ "<webqtlCaseData> value=0.000 variance=0.000 ndata=10 name=Test name2=Test2"
+ )
+
+ def test_class_outlier(self):
+ self.assertEqual(self.w.class_outlier, "")
+
+ def test_display_value(self):
+ self.assertEqual(self.w.display_value, "0.000")
+ self.w.value = None
+ self.assertEqual(self.w.display_value, "x")
+
+ def test_display_variance(self):
+ self.assertEqual(self.w.display_variance, "0.000")
+ self.w.variance = None
+ self.assertEqual(self.w.display_variance, "x")
+
+ def test_display_num_cases(self):
+ self.assertEqual(self.w.display_num_cases, "10")
+ self.w.num_cases = None
+ self.assertEqual(self.w.display_num_cases, "x")
diff --git a/wqflask/utility/authentication_tools.py b/wqflask/utility/authentication_tools.py
index deddaec3..9a2a5ccd 100644
--- a/wqflask/utility/authentication_tools.py
+++ b/wqflask/utility/authentication_tools.py
@@ -45,7 +45,7 @@ def check_resource_availability(dataset, trait_id=None):
def add_new_resource(dataset, trait_id=None):
resource_ob = {
- 'owner_id' : "None",
+ 'owner_id' : "none", # webqtlConfig.DEFAULT_OWNER_ID,
'default_mask': webqtlConfig.DEFAULT_PRIVILEGES,
'group_masks' : {}
}
@@ -84,6 +84,7 @@ def check_admin(resource_id=None):
try:
response = json.loads(requests.get(the_url).content)['admin']
except:
+ logger.debug(resource_info)
response = resource_info['default_mask']['admin']
if 'edit-admins' in response:
@@ -124,4 +125,4 @@ def check_owner_or_admin(dataset=None, trait_id=None, resource_id=None):
else:
return check_admin(resource_id)
- return "not-admin" \ No newline at end of file
+ return "not-admin"
diff --git a/wqflask/wqflask/static/gif/error/m001.gif b/wqflask/wqflask/static/gif/error/m001.gif
new file mode 100644
index 00000000..81c8ba26
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/m001.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/m002.gif b/wqflask/wqflask/static/gif/error/m002.gif
new file mode 100644
index 00000000..7232c58b
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/m002.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/m003.gif b/wqflask/wqflask/static/gif/error/m003.gif
new file mode 100644
index 00000000..2384ceb6
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/m003.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/m004.gif b/wqflask/wqflask/static/gif/error/m004.gif
new file mode 100644
index 00000000..d77c708d
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/m004.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/m005.gif b/wqflask/wqflask/static/gif/error/m005.gif
new file mode 100644
index 00000000..1b2de7ec
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/m005.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/m006.gif b/wqflask/wqflask/static/gif/error/m006.gif
new file mode 100644
index 00000000..f354a4cc
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/m006.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/m007.gif b/wqflask/wqflask/static/gif/error/m007.gif
new file mode 100644
index 00000000..ba2eeb37
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/m007.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/m008.gif b/wqflask/wqflask/static/gif/error/m008.gif
new file mode 100644
index 00000000..4cdec5cb
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/m008.gif
Binary files differ
diff --git a/wqflask/wqflask/static/gif/error/mouse-wheel.gif b/wqflask/wqflask/static/gif/error/mouse-wheel.gif
new file mode 100644
index 00000000..164220e7
--- /dev/null
+++ b/wqflask/wqflask/static/gif/error/mouse-wheel.gif
Binary files differ