aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--wqflask/base/data_set.py2
-rw-r--r--wqflask/wqflask/collect.py287
-rw-r--r--wqflask/wqflask/static/new/javascript/search_results.js35
-rw-r--r--wqflask/wqflask/templates/base.html2
-rw-r--r--wqflask/wqflask/templates/collections/add.html3
-rw-r--r--wqflask/wqflask/templates/collections/list.html17
-rw-r--r--wqflask/wqflask/templates/collections/view.html6
-rw-r--r--wqflask/wqflask/user_manager.py66
8 files changed, 296 insertions, 122 deletions
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index d0ec3f3c..1b4e1195 100644
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -106,7 +106,7 @@ Publish or ProbeSet. E.g.
new_type = "Geno"
else:
new_type = "ProbeSet"
- self.datasets[short_dataset_name] = new_type
+ self.datasets[short_dataset_name] = new_type
logger.info("datasets",self.datasets)
def __call__(self, name):
diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py
index 4ea8407c..5484633b 100644
--- a/wqflask/wqflask/collect.py
+++ b/wqflask/wqflask/collect.py
@@ -15,35 +15,26 @@ import urlparse
import simplejson as json
-#from sqlalchemy import orm
-
-#from redis import StrictRedis
import redis
Redis = redis.StrictRedis()
-
from flask import (Flask, g, render_template, url_for, request, make_response,
redirect, flash, jsonify)
from wqflask import app
-
from pprint import pformat as pf
-
from wqflask.database import db_session
from wqflask import model
+from wqflask import user_manager
from utility import Bunch, Struct
from utility.formatting import numify
-from wqflask import user_manager
-
-
from base import trait
-
def get_collection():
if g.user_session.logged_in:
return UserCollection()
@@ -54,39 +45,112 @@ def get_collection():
class AnonCollection(object):
"""User is not logged in"""
- def __init__(self):
- self.anon_user = user_manager.AnonUser()
- self.key = "anon_collection:v5:{}".format(self.anon_user.anon_id)
-
- def add_traits(self, params, collection_name):
- assert collection_name == "Default", "Unexpected collection name for anonymous user"
- print("params[traits]:", params['traits'])
- traits = process_traits(params['traits'])
- print("traits is:", traits)
- print("self.key is:", self.key)
- len_before = len(Redis.smembers(self.key))
- Redis.sadd(self.key, *list(traits))
- Redis.expire(self.key, 60 * 60 * 24 * 3)
- print("currently in redis:", Redis.smembers(self.key))
- len_now = len(Redis.smembers(self.key))
- report_change(len_before, len_now)
+ def __init__(self, collection_name):
+ anon_user = user_manager.AnonUser()
+ self.key = anon_user.key
+ self.name = collection_name
+ self.id = None
+ self.created_timestamp = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
+ self.changed_timestamp = self.created_timestamp #ZS: will be updated when changes are made
+
+ #ZS: Find id and set it if the collection doesn't already exist
+ if Redis.get(self.key) == "None" or Redis.get(self.key) == None:
+ Redis.set(self.key, None) #ZS: For some reason I get the error "Operation against a key holding the wrong kind of value" if I don't do this
+ else:
+ collections_list = json.loads(Redis.get(self.key))
+ collection_position = 0 #ZS: Position of collection in collection_list, if it exists
+ collection_exists = False
+ for i, collection in enumerate(collections_list):
+ if collection['name'] == self.name:
+ collection_position = i
+ collection_exists = True
+ self.id = collection['id']
+ break
+ if self.id == None:
+ self.id = str(uuid.uuid4())
+
+ def get_members(self):
+ traits = []
+ collections_list = json.loads(Redis.get(self.key))
+ for collection in collections_list:
+ if collection['id'] == self.id:
+ traits = collection['members']
+ return traits
+
+ @property
+ def num_members(self):
+ num_members = 0
+ collections_list = json.loads(Redis.get(self.key))
+ for collection in collections_list:
+ if collection['id'] == self.id:
+ num_members = collection['num_members']
+ return num_members
+
+ def add_traits(self, params):
+ #assert collection_name == "Default", "Unexpected collection name for anonymous user"
+ self.traits = list(process_traits(params['traits']))
+ #len_before = len(Redis.smembers(self.key))
+ existing_collections = Redis.get(self.key)
+ print("existing_collections:", existing_collections)
+ if existing_collections != None and existing_collections != "None":
+ collections_list = json.loads(existing_collections)
+ collection_position = 0 #ZS: Position of collection in collection_list, if it exists
+ collection_exists = False
+ for i, collection in enumerate(collections_list):
+ if collection['id'] == self.id:
+ collection_position = i
+ collection_exists = True
+ break
+ if collection_exists:
+ collections_list[collection_position]['members'].extend(self.traits)
+ collections_list[collection_position]['num_members'] = len(collections_list[collection_position]['members'])
+ collections_list[collection_position]['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
+ else:
+ collection_dict = {"id" : self.id,
+ "name" : self.name,
+ "created_timestamp" : self.created_timestamp,
+ "changed_timestamp" : self.changed_timestamp,
+ "num_members" : len(self.traits),
+ "members" : self.traits}
+ collections_list.append(collection_dict)
+ else:
+ collections_list = []
+ collection_dict = {"id" : self.id,
+ "name" : self.name,
+ "created_timestamp" : self.created_timestamp,
+ "changed_timestamp" : self.changed_timestamp,
+ "num_members" : len(self.traits),
+ "members" : self.traits}
+ collections_list.append(collection_dict)
+
+ Redis.set(self.key, json.dumps(collections_list))
+ #Redis.sadd(self.key, *list(traits))
+ #Redis.expire(self.key, 60 * 60 * 24 * 5)
+ #len_now = len(Redis.smembers(self.key))
+ #report_change(len_before, len_now)
def remove_traits(self, params):
- traits_to_remove = params.getlist('traits[]')
- print("traits_to_remove:", process_traits(traits_to_remove))
- len_before = len(Redis.smembers(self.key))
- Redis.srem(self.key, traits_to_remove)
- print("currently in redis:", Redis.smembers(self.key))
- len_now = len(Redis.smembers(self.key))
+ traits_to_remove = [(":").join(trait.split(":")[:2]) for trait in params.getlist('traits[]')]
+ existing_collections = Redis.get(self.key)
+ collection_position = 0
+ collections_list = json.loads(existing_collections)
+ for i, collection in enumerate(collections_list):
+ if collection['id'] == self.id:
+ collection_position = i
+ collection_exists = True
+ break
+ collections_list[collection_position]['members'] = [trait for trait in collections_list[collection_position]['members'] if trait not in traits_to_remove]
+ collections_list[collection_position]['num_members'] = len(collections_list[collection_position]['members'])
+ collections_list[collection_position]['changed_timestamp'] = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
+ len_now = collections_list[collection_position]['num_members']
+ #print("before in redis:", json.loads(Redis.get(self.key)))
+ Redis.set(self.key, json.dumps(collections_list))
+ #print("currently in redis:", json.loads(Redis.get(self.key)))
# We need to return something so we'll return this...maybe in the future
# we can use it to check the results
return str(len_now)
- def get_traits(self):
- traits = Redis.smembers(self.key)
- print("traits:", traits)
- return traits
class UserCollection(object):
"""User is logged in"""
@@ -164,85 +228,103 @@ def collections_add():
user_collections = g.user_session.user_ob.user_collections
print("user_collections are:", user_collections)
return render_template("collections/add.html",
- traits=traits,
- user_collections = user_collections,
+ traits = traits,
+ collections = user_collections,
)
else:
- return render_template("collections/add_anonymous.html",
- traits=traits
- )
+ anon_collections = user_manager.AnonUser().get_collections()
+ collection_names = []
+ for collection in anon_collections:
+ print("COLLECTION:", collection)
+ collection_names.append({'id':collection['id'], 'name':collection['name']})
+ return render_template("collections/add.html",
+ traits = traits,
+ collections = collection_names,
+ )
@app.route("/collections/new")
def collections_new():
params = request.args
- print("request.args in collections_new are:", params)
+ #print("request.args in collections_new are:", params)
+ collection_name = params['new_collection']
+
if "anonymous_add" in params:
- AnonCollection().add_traits(params, "Default")
+ AnonCollection(name=collection_name).add_traits(params, "Default")
return redirect(url_for('view_collection'))
- elif "sign_in" in params:
+ if "sign_in" in params:
return redirect(url_for('login'))
- collection_name = params['new_collection']
-
if "create_new" in params:
print("in create_new")
return create_new(collection_name)
elif "add_to_existing" in params:
print("in add to existing")
- return UserCollection().add_traits(params, collection_name)
+ if g.user_session.logged_in:
+ return UserCollection().add_traits(params, collection_name)
+ else:
+ ac = AnonCollection(collection_name)
+ ac.add_traits(params)
+ return redirect(url_for('view_collection', collection_id=ac.id))
else:
print("ELSE")
CauseAnError
def process_traits(unprocessed_traits):
- print("unprocessed_traits are:", unprocessed_traits)
+ #print("unprocessed_traits are:", unprocessed_traits)
if isinstance(unprocessed_traits, basestring):
unprocessed_traits = unprocessed_traits.split(",")
traits = set()
for trait in unprocessed_traits:
- print("trait is:", trait)
+ #print("trait is:", trait)
data, _separator, hmac = trait.rpartition(':')
data = data.strip()
- print("data is:", data)
- print("hmac is:", hmac)
assert hmac==user_manager.actual_hmac_creation(data), "Data tampering?"
- traits.add(str(data))
+ traits.add (str(data))
return traits
def create_new(collection_name):
params = request.args
- uc = model.UserCollection()
- uc.name = collection_name
- print("user_session:", g.user_session.__dict__)
- uc.user = g.user_session.user_id
+
unprocessed_traits = params['traits']
-
traits = process_traits(unprocessed_traits)
-
- uc.members = json.dumps(list(traits))
- print("traits are:", traits)
-
- db_session.add(uc)
- db_session.commit()
-
- print("Created: " + uc.name)
- return redirect(url_for('view_collection', uc_id=uc.id))
+
+ if g.user_session.logged_in:
+ uc = model.UserCollection()
+ uc.name = collection_name
+ print("user_session:", g.user_session.__dict__)
+ uc.user = g.user_session.user_id
+ uc.members = json.dumps(list(traits))
+ db_session.add(uc)
+ db_session.commit()
+ return redirect(url_for('view_collection', uc_id=uc.id))
+ else:
+ current_collections = user_manager.AnonUser().get_collections()
+ ac = AnonCollection(collection_name)
+ ac.changed_timestamp = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p')
+ ac.add_traits(params)
+ print("Collection ID:", ac.id)
+ return redirect(url_for('view_collection', collection_id=ac.id))
@app.route("/collections/list")
def list_collections():
params = request.args
- try:
+ print("PARAMS:", params)
+ if g.user_session.logged_in:
user_collections = list(g.user_session.user_ob.user_collections)
print("user_collections are:", user_collections)
return render_template("collections/list.html",
params = params,
- user_collections = user_collections,
+ collections = user_collections,
)
- except:
- return redirect(url_for('view_collection'))
+ else:
+ anon_collections = user_manager.AnonUser().get_collections()
+ print("anon_collections are:", anon_collections)
+ return render_template("collections/list.html",
+ params = params,
+ collections = anon_collections)
@app.route("/collections/remove", methods=('POST',))
@@ -267,7 +349,8 @@ def remove_traits():
uc.changed_timestamp = datetime.datetime.utcnow()
db_session.commit()
else:
- members_now = AnonCollection().remove_traits(params)
+ collection_name = params['collection_name']
+ members_now = AnonCollection(collection_name).remove_traits(params)
# We need to return something so we'll return this...maybe in the future
@@ -279,32 +362,43 @@ def remove_traits():
def delete_collection():
params = request.form
print("params:", params)
- uc_id = params['uc_id']
- uc = model.UserCollection.query.get(uc_id)
- # Todo: For now having the id is good enough since it's so unique
- # But might want to check ownership in the future
- collection_name = uc.name
- db_session.delete(uc)
- db_session.commit()
- flash("We've deletet the collection: {}.".format(collection_name), "alert-info")
+ if g.user_session.logged_in:
+ uc_id = params['uc_id']
+ uc = model.UserCollection.query.get(uc_id)
+ # Todo: For now having the id is good enough since it's so unique
+ # But might want to check ownership in the future
+ collection_name = uc.name
+ db_session.delete(uc)
+ db_session.commit()
+ else:
+ collection_name = params['collection_name']
+ user_manager.AnonUser().delete_collection(collection_name)
+
+ flash("We've deleted the collection: {}.".format(collection_name), "alert-info")
return redirect(url_for('list_collections'))
-
@app.route("/collections/view")
def view_collection():
params = request.args
print("PARAMS in view collection:", params)
- #if "uc_id" in params:
- uc_id = params['uc_id']
- uc = model.UserCollection.query.get(uc_id)
- traits = json.loads(uc.members)
- print("traits are:", traits)
- #else:
- # traits = AnonCollection().get_traits()
-
+ if "uc_id" in params:
+ uc_id = params['uc_id']
+ uc = model.UserCollection.query.get(uc_id)
+ traits = json.loads(uc.members)
+ print("traits are:", traits)
+ else:
+ user_collections = json.loads(Redis.get(user_manager.AnonUser().key))
+ this_collection = {}
+ for collection in user_collections:
+ if collection['id'] == params['collection_id']:
+ this_collection = collection
+ break
+ #this_collection = user_collections[params['collection_id']]
+ traits = this_collection['members']
+
print("in view_collection traits are:", traits)
trait_obs = []
@@ -312,29 +406,22 @@ def view_collection():
for atrait in traits:
print("atrait is:", atrait)
- name, dataset_name = atrait.split(':')
-
+ name, dataset_name = atrait.split(':')
+
trait_ob = trait.GeneralTrait(name=name, dataset_name=dataset_name)
trait_ob.retrieve_info(get_qtl_info=True)
trait_obs.append(trait_ob)
json_version.append(trait_ob.jsonable())
- #json_version.append(dict(name=trait_ob.name,
- # description=trait_ob.description_display,
- # location=trait_ob.location_repr,
- # mean=trait_ob.mean,
- # lrs_score=trait_ob.LRS_score_repr,
- # lrs_location=trait_ob.LRS_location_repr))
- # dis=trait_ob.description))
- #json_version.append(trait_ob.__dict__th)
print("trait_obs:", trait_obs)
if "uc_id" in params:
collection_info = dict(trait_obs=trait_obs,
- uc = uc)
+ uc = uc)
else:
- collection_info = dict(trait_obs=trait_obs)
+ collection_info = dict(trait_obs=trait_obs,
+ collection_name=this_collection['name'])
if "json" in params:
print("json_version:", json_version)
return json.dumps(json_version)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index 4218fdbb..746564fd 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -130,17 +130,30 @@ $(function() {
}).get();
console.log("checked length is:", traits.length);
console.log("checked is:", traits);
- uc_id = $("#uc_id").val();
- console.log("uc.id is:", uc_id);
- return $.ajax({
- type: "POST",
- url: "/collections/remove",
- data: {
- uc_id: uc_id,
- traits: traits
- },
- success: removed_traits
- });
+ if ( $("#uc_id").length ) {
+ uc_id = $("#uc_id").val();
+ return $.ajax({
+ type: "POST",
+ url: "/collections/remove",
+ data: {
+ uc_id: uc_id,
+ traits: traits
+ },
+ success: removed_traits
+ });
+ }
+ else {
+ collection_name = $("#collection_name").val();
+ return $.ajax({
+ type: "POST",
+ url: "/collections/remove",
+ data: {
+ collection_name: collection_name,
+ traits: traits
+ },
+ success: removed_traits
+ });
+ }
};
$("#select_all").click(select_all);
$("#deselect_all").click(deselect_all);
diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html
index 759c4a8d..6af07edc 100644
--- a/wqflask/wqflask/templates/base.html
+++ b/wqflask/wqflask/templates/base.html
@@ -43,6 +43,8 @@
<a href="/collections/list">Collections
{% if g.user_session.user_ob %}
<span class="badge badge-info">{{ g.user_session.user_ob.display_num_collections() }}</span>
+ {% else %}
+ <span class="badge badge-info">{{ g.cookie_session.display_num_collections() }}</span>
{% endif %}
</a>
</li>
diff --git a/wqflask/wqflask/templates/collections/add.html b/wqflask/wqflask/templates/collections/add.html
index 07fcba22..f4a69423 100644
--- a/wqflask/wqflask/templates/collections/add.html
+++ b/wqflask/wqflask/templates/collections/add.html
@@ -16,7 +16,6 @@
<hr />
-->
-
<input type="hidden" name="traits" value="{{ traits }}" />
<fieldset>
<legend>Create a new named collection</legend>
@@ -33,7 +32,7 @@
<label>Existing collection name</label>
<select name="existing_collection" class="form-control">
- {% for col in user_collections %}
+ {% for col in collections %}
<option value="{{ col.id }}">{{ col.name }}</option>
{% endfor %}
</select>
diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html
index 0e7612aa..a26e77ef 100644
--- a/wqflask/wqflask/templates/collections/list.html
+++ b/wqflask/wqflask/templates/collections/list.html
@@ -8,13 +8,22 @@
{% endblock %}
{% block content %}
<!-- Start of body -->
+ {% if g.user_session.user_ob %}
{{ header("Your Collections",
- 'You have {}.'.format(numify(user_collections|count, "collection", "collections"))) }}
+ 'You have {}.'.format(numify(collections|count, "collection", "collections"))) }}
+ {% else %}
+ {{ header("Your Collections",
+ 'You have {}.'.format(numify(collections|count, "collection", "collections"))) }}
+ {% endif %}
<div class="container">
<div class="page-header">
+ {% if g.user_session.user_ob %}
<h1>Collections owned by {{ g.user_session.user_ob.full_name }}</h1>
+ {% else %}
+ <h1>Your Collections</h1>
+ {% endif %}
</div>
<div id="collections_list">
@@ -30,10 +39,14 @@
</thead>
<tbody>
- {% for uc in user_collections %}
+ {% for uc in collections %}
<tr class="collection_line">
<td>{{ loop.index }}
+ {% if g.user_session.user_ob %}
<td><a class="collection_name" href="{{ url_for('view_collection', uc_id=uc.id) }}">{{ uc.name }}</a></td>
+ {% else %}
+ <td><a class="collection_name" href="{{ url_for('view_collection', collection_id=uc.id) }}">{{ uc.name }}</a></td>
+ {% endif %}
<td>{{ timeago(uc.created_timestamp.isoformat() + "Z") }}</td>
<td>{{ timeago(uc.changed_timestamp.isoformat() + "Z") }}</td>
<td>{{ uc.num_members }}</td>
diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html
index 288207e7..68d2886f 100644
--- a/wqflask/wqflask/templates/collections/view.html
+++ b/wqflask/wqflask/templates/collections/view.html
@@ -14,23 +14,23 @@
<h2>{{ uc.name }}</h2>
<h3>{{ 'This collection has {}.'.format(numify(trait_obs|count, "record", "records")) }}</h3>
{% else %}
- <h2>Your Collection</h2>
+ <h2> {{ collection_name }}</h2>
<h3>{{ 'This collection has {}.'.format(numify(trait_obs|count, "record", "records")) }}</h3>
{% endif %}
</div>
<div class="container">
<div>
- {% if uc %}
<form action="/collections/delete" method="post">
{% if uc %}
<input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" />
+ {% else %}
+ <input type="hidden" name="collection_name" id="collection_name" value="{{ collection_name }}" />
{% endif %}
<div class="col-xs-3 controls">
<input type="submit" class="btn btn-danger" value="Delete this collection" />
</div>
</form>
- {% endif %}
<form action="/corr_matrix" method="post">
{% if uc %}
<input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" />
diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py
index 10fac06d..4ff3e79c 100644
--- a/wqflask/wqflask/user_manager.py
+++ b/wqflask/wqflask/user_manager.py
@@ -62,21 +62,80 @@ def timestamp():
class AnonUser(object):
- cookie_name = 'anon_user_v1'
+ cookie_name = 'anon_user_v8'
def __init__(self):
self.cookie = request.cookies.get(self.cookie_name)
if self.cookie:
logger.debug("already is cookie")
self.anon_id = verify_cookie(self.cookie)
+
else:
logger.debug("creating new cookie")
self.anon_id, self.cookie = create_signed_cookie()
+ self.key = "anon_collection:v1:{}".format(self.anon_id)
@after.after_this_request
def set_cookie(response):
response.set_cookie(self.cookie_name, self.cookie)
-
+
+ def add_collection(self, new_collection):
+ collection_dict = dict(name = new_collection.name,
+ created_timestamp = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p'),
+ changed_timestamp = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p'),
+ num_members = new_collection.num_members,
+ members = new_collection.get_members())
+
+ Redis.set(self.key, json.dumps(collection_dict))
+ Redis.expire(self.key, 60 * 60 * 24 * 5)
+
+ def delete_collection(self, collection_name):
+ existing_collections = self.get_collections()
+ updated_collections = []
+ for i, collection in enumerate(existing_collections):
+ if collection['name'] == collection_name:
+ continue
+ else:
+ this_collection = {}
+ this_collection['id'] = collection['id']
+ this_collection['name'] = collection['name']
+ this_collection['created_timestamp'] = collection['created_timestamp'].strftime('%b %d %Y %I:%M%p')
+ this_collection['changed_timestamp'] = collection['changed_timestamp'].strftime('%b %d %Y %I:%M%p')
+ this_collection['num_members'] = collection['num_members']
+ this_collection['members'] = collection['members']
+ updated_collections.append(this_collection)
+
+ Redis.set(self.key, json.dumps(updated_collections))
+
+ def get_collections(self):
+ json_collections = Redis.get(self.key)
+ if json_collections == None or json_collections == "None":
+ return []
+ else:
+ collections = json.loads(json_collections)
+ for collection in collections:
+ collection['created_timestamp'] = datetime.datetime.strptime(collection['created_timestamp'], '%b %d %Y %I:%M%p')
+ collection['changed_timestamp'] = datetime.datetime.strptime(collection['changed_timestamp'], '%b %d %Y %I:%M%p')
+ return collections
+
+ def display_num_collections(self):
+ """
+ Returns the number of collections or a blank string if there are zero.
+
+ Because this is so unimportant...we wrap the whole thing in a try/expect...last thing we
+ want is a webpage not to be displayed because of an error here
+
+ Importand TODO: use redis to cache this, don't want to be constantly computing it
+ """
+ try:
+ num = len(self.get_collections())
+ if num > 0:
+ return num
+ else:
+ return ""
+ except Exception as why:
+ print("Couldn't display_num_collections:", why)
+ return ""
def verify_cookie(cookie):
the_uuid, separator, the_signature = cookie.partition(':')
@@ -164,7 +223,8 @@ class UserSession(object):
@app.before_request
def before_request():
g.user_session = UserSession()
-
+ g.cookie_session = AnonUser()
+
class UsersManager(object):
def __init__(self):
self.users = model.User.query.all()