From f865e6b64649a4b692492f07a84b7d2a6d9fae00 Mon Sep 17 00:00:00 2001 From: Patrick McDonagh Date: Thu, 16 Feb 2017 16:41:54 -0600 Subject: [PATCH] Adds time slider with AJAX reloading of graphs --- www/pocwww/pocwww/__init__.py | 3 + www/pocwww/pocwww/json.py | 53 ++++++ www/pocwww/pocwww/static/theme.css | 104 +++++++++++ www/pocwww/pocwww/templates/layout.jinja2 | 1 + www/pocwww/pocwww/templates/valuesall.jinja2 | 183 ++++++++++++++----- www/pocwww/pocwww/view_helpers.py | 23 --- www/pocwww/pocwww/views.py | 11 +- 7 files changed, 304 insertions(+), 74 deletions(-) diff --git a/www/pocwww/pocwww/__init__.py b/www/pocwww/pocwww/__init__.py index 9ed06eb..019d116 100644 --- a/www/pocwww/pocwww/__init__.py +++ b/www/pocwww/pocwww/__init__.py @@ -130,6 +130,9 @@ def main(global_config, **settings): # JSON-ONLY ROUTES config.add_route('json_lastcard', "/json/lastcard") + config.add_route('json_valuesbetween_wparams', "/json/values/between/{startdt}/{enddt}") + config.add_route('json_valuesbetween', "/json/values/between") + config.add_route("json_valuesdaterange", "/json/values/daterange") config.scan() return config.make_wsgi_app() diff --git a/www/pocwww/pocwww/json.py b/www/pocwww/pocwww/json.py index 8739856..bcd7bbc 100644 --- a/www/pocwww/pocwww/json.py +++ b/www/pocwww/pocwww/json.py @@ -7,3 +7,56 @@ from bson import json_util @view_config(route_name="json_lastcard", renderer="prettyjson") def json_lastcard(request): return get_latest_card(request) + + +@view_config(route_name="json_valuesbetween", renderer="prettyjson") +@view_config(route_name="json_valuesbetween_wparams", renderer="prettyjson") +def json_valuesbetween(request): + end = datetime.now() + try: # Attempt to get a value from the request. + end = request.matchdict['enddt'] + end = end.replace("T", " ") + end = datetime.strptime(end, "%Y-%m-%d %H:%M:%S.%fZ") + except KeyError: + pass + + start = end - timedelta(days=7) + try: # Attempt to get a value from the request. + start = request.matchdict['startdt'] + start = start.replace("T", " ") + start = datetime.strptime(start, "%Y-%m-%d %H:%M:%S.%fZ") + except KeyError: + pass + + tag_data = [] + grouped_tags = request.db['wellData'].aggregate([ + { + '$match': {"timestamp": {"$gt": start, "$lte": end}} + }, + { + '$sort': {"tagname": 1, "timestamp": 1} + }, + { + '$group': { + '_id': "$tagname", + 'timestamps': {'$push': "$timestamp"}, + 'currentValues': {'$push': "$currentValue"} + } + } + ]) + + for t in grouped_tags: + tag_data.append({"tagname": t['_id'], "timestamps": list(map(lambda a: a.strftime("%Y-%m-%d %H:%M:%S.%fZ"), t['timestamps'])), "currentValues": t['currentValues']}) + return {'values': tag_data, 'start': start, 'end': end} + + +@view_config(route_name="json_valuesdaterange", renderer="prettyjson") +def json_valuesdaterange(request): + date_limits = list(request.db['wellData'].aggregate([ + {"$group": { + "_id": 'null', + "last": {"$max": "$timestamp"}, + "first": {"$min": "$timestamp"} + }} + ]))[0] + return {'first_date': date_limits['first'], 'last_date': date_limits['last']} diff --git a/www/pocwww/pocwww/static/theme.css b/www/pocwww/pocwww/static/theme.css index 9f2ad39..ad1982c 100644 --- a/www/pocwww/pocwww/static/theme.css +++ b/www/pocwww/pocwww/static/theme.css @@ -146,3 +146,107 @@ body { fill: none; stroke-width: 2.5px; } + +#time-range p { + font-family:"Arial", sans-serif; + font-size:14px; + color:#333; +} +.ui-slider-horizontal { + height: 8px; + background: #D7D7D7; + border: 1px solid #BABABA; + box-shadow: 0 1px 0 #FFF, 0 1px 0 #CFCFCF inset; + clear: both; + margin: 8px 0; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; + border-radius: 6px; +} +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider-horizontal .ui-slider-range { + top: -1px; + height: 100%; +} +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + height: 8px; + font-size: .7em; + display: block; + border: 1px solid #5BA8E1; + box-shadow: 0 1px 0 #AAD6F6 inset; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + -khtml-border-radius: 6px; + border-radius: 6px; + background: #81B8F3; + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgi…pZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); + background-size: 100%; + background-image: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(0%, #A0D4F5), color-stop(100%, #81B8F3)); + background-image: -webkit-linear-gradient(top, #A0D4F5, #81B8F3); + background-image: -moz-linear-gradient(top, #A0D4F5, #81B8F3); + background-image: -o-linear-gradient(top, #A0D4F5, #81B8F3); + background-image: linear-gradient(top, #A0D4F5, #81B8F3); +} +.ui-slider .ui-slider-handle { + border-radius: 50%; + background: #F9FBFA; + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgi…pZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); + background-size: 100%; + background-image: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(0%, #C7CED6), color-stop(100%, #F9FBFA)); + background-image: -webkit-linear-gradient(top, #C7CED6, #F9FBFA); + background-image: -moz-linear-gradient(top, #C7CED6, #F9FBFA); + background-image: -o-linear-gradient(top, #C7CED6, #F9FBFA); + background-image: linear-gradient(top, #C7CED6, #F9FBFA); + width: 22px; + height: 22px; + -webkit-box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.6), 0 -1px 0 1px rgba(0, 0, 0, 0.15) inset, 0 1px 0 1px rgba(255, 255, 255, 0.9) inset; + -moz-box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.6), 0 -1px 0 1px rgba(0, 0, 0, 0.15) inset, 0 1px 0 1px rgba(255, 255, 255, 0.9) inset; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.6), 0 -1px 0 1px rgba(0, 0, 0, 0.15) inset, 0 1px 0 1px rgba(255, 255, 255, 0.9) inset; + -webkit-transition: box-shadow .3s; + -moz-transition: box-shadow .3s; + -o-transition: box-shadow .3s; + transition: box-shadow .3s; +} +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 22px; + height: 22px; + cursor: default; + border: none; + cursor: pointer; +} +.ui-slider .ui-slider-handle:after { + content:""; + position: absolute; + width: 8px; + height: 8px; + border-radius: 50%; + top: 50%; + margin-top: -4px; + left: 50%; + margin-left: -4px; + background: #30A2D2; + -webkit-box-shadow: 0 1px 1px 1px rgba(22, 73, 163, 0.7) inset, 0 1px 0 0 #FFF; + -moz-box-shadow: 0 1px 1px 1px rgba(22, 73, 163, 0.7) inset, 0 1px 0 0 white; + box-shadow: 0 1px 1px 1px rgba(22, 73, 163, 0.7) inset, 0 1px 0 0 #FFF; +} +.ui-slider-horizontal .ui-slider-handle { + top: -.5em; + margin-left: -.6em; +} +.ui-slider a:focus { + outline:none; +} + +.slider-time { + + +} diff --git a/www/pocwww/pocwww/templates/layout.jinja2 b/www/pocwww/pocwww/templates/layout.jinja2 index 1584faf..ab1febc 100644 --- a/www/pocwww/pocwww/templates/layout.jinja2 +++ b/www/pocwww/pocwww/templates/layout.jinja2 @@ -27,6 +27,7 @@ + diff --git a/www/pocwww/pocwww/templates/valuesall.jinja2 b/www/pocwww/pocwww/templates/valuesall.jinja2 index 3174ebd..306fb2a 100644 --- a/www/pocwww/pocwww/templates/valuesall.jinja2 +++ b/www/pocwww/pocwww/templates/valuesall.jinja2 @@ -10,19 +10,23 @@ Name - Value - Timestamp + Max + Min + Average + Total + Last Stored {% for t in current_tag_values %} {{t._id}} - - - {{t.value | round(3)}} + {{t.max | round(3)}} + {{t.min | round(3)}} + {{t.average | round(3)}} + {{t.total | round(3)}} {{t.timestamp | datetime('medium')}} {% endfor %} @@ -34,60 +38,157 @@
-
+            
         
- +
+

+
+
+
+
+
+ +
- + {% endblock content %} diff --git a/www/pocwww/pocwww/view_helpers.py b/www/pocwww/pocwww/view_helpers.py index 39ea811..45e227e 100644 --- a/www/pocwww/pocwww/view_helpers.py +++ b/www/pocwww/pocwww/view_helpers.py @@ -3,7 +3,6 @@ from math import ceil from .pagination import Pagination - def get_lastest_tag_values(request): latest_tag_values = [] latesttag_agg = request.db['wellData'].aggregate([ @@ -30,8 +29,6 @@ def get_lastest_tag_values(request): def get_latest_card(request): try: latest_card = list(request.db['cards'].find().sort("timestamp", -1).limit(1))[0] - for x in latest_card: - print("{} = {}".format(x, type(latest_card[x]))) return latest_card except IndexError: return [] @@ -58,23 +55,3 @@ def card_page(request): cards = request.db['cards'].find({'timestamp': {'$lt': cards_date_end, '$gte': cards_date_start}}).sort("timestamp", -1).skip(num_per_page * (page_num - 1)).limit(num_per_page) return {'cards': list(cards), 'pagination': Pagination(page_num, num_per_page, num_cards), 'cards_date': cards_date_start.strftime("%Y-%m-%d"), 'navgroup': 'cards'} - - -def get_all_tags_between(request): - tag_data = [] - grouped_tags = request.db['wellData'].aggregate([ - { - '$sort': {"tagname": 1, "timestamp": 1} - }, - { - '$group': { - '_id': "$tagname", - 'timestamps': {'$push': "$timestamp"}, - 'currentValues': {'$push': "$currentValue"} - } - } - ]) - - for t in grouped_tags: - tag_data.append({"tagname": t['_id'], "timestamps": list(map(lambda a: a.strftime("%Y-%m-%d %H:%M:%S.%fZ"), t['timestamps'])), "currentValues": t['currentValues']}) - return tag_data diff --git a/www/pocwww/pocwww/views.py b/www/pocwww/pocwww/views.py index a7dd99d..52f75dd 100644 --- a/www/pocwww/pocwww/views.py +++ b/www/pocwww/pocwww/views.py @@ -54,16 +54,7 @@ def card_single(request): @view_config(route_name='values_all', renderer="templates/valuesall.jinja2") @view_config(route_name='json_values_all', renderer='prettyjson') def values_all(request): - # all_dates = list(request.db['wellData'].distinct('timestamp')) - all_dates = request.db['wellData'].aggregate([ - {"$group": { - "_id": {"$dateToString": {'format': "%Y-%m-%d %H:%M:%S.000Z", 'date': "$timestamp"}}, - "count": {"$sum": 1} - }}, - {"$sort": {"_id": -1}} - ]) - all_dates_formatted = list(map(lambda x: {'count': x['count'], 'timestamp': datetime.strptime(x['_id'], "%Y-%m-%d %H:%M:%S.000Z")}, all_dates)) - return {'navgroup': 'values', 'current_tag_values': get_lastest_tag_values(request), 'all_dates': all_dates_formatted, 'tag_history': get_all_tags_between(request)} + return {'navgroup': 'values', 'current_tag_values': get_lastest_tag_values(request)} @view_config(route_name="values_tag", renderer="templates/values_single.jinja2")