Skip to content

Commit

Permalink
Merge 6120396 into 90a2dea
Browse files Browse the repository at this point in the history
  • Loading branch information
hyunchel committed Jun 5, 2016
2 parents 90a2dea + 6120396 commit 8fec8bc
Showing 1 changed file with 42 additions and 11 deletions.
53 changes: 42 additions & 11 deletions analytics/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from __future__ import absolute_import
from __future__ import division
from typing import Any, Dict, List, Tuple
from typing import Any, Dict, List, Tuple, Optional, Sequence, Callable, Union

from django.db import connection
from django.db.models.query import QuerySet
from django.template import RequestContext, loader
from django.core import urlresolvers
from django.http import HttpResponseNotFound
from django.http import HttpResponseNotFound, HttpRequest, HttpResponse
from jinja2 import Markup as mark_safe

from zerver.decorator import has_request_variables, REQ, zulip_internal
Expand All @@ -27,9 +28,11 @@
from zproject.jinja2 import render_to_response

def make_table(title, cols, rows, has_row_class=False):
# type: (str, List[str], List[Any], bool) -> str

if not has_row_class:
def fix_row(row):
# type: (Any) -> Dict[str, Any]
return dict(cells=row, row_class=None)
rows = list(map(fix_row, rows))

Expand All @@ -43,6 +46,7 @@ def fix_row(row):
return content

def dictfetchall(cursor):
# type: (Any) -> List[Dict[str, Any]]
"Returns all rows from a cursor as a dict"
desc = cursor.description
return [
Expand All @@ -52,6 +56,7 @@ def dictfetchall(cursor):


def get_realm_day_counts():
# type: () -> Dict[str, Dict[str, str]]
query = '''
select
r.domain,
Expand Down Expand Up @@ -91,6 +96,7 @@ def get_realm_day_counts():
max_cnt = max(raw_cnts)

def format_count(cnt):
# type: (int) -> str
if cnt == min_cnt:
good_bad = 'bad'
elif cnt == max_cnt:
Expand All @@ -106,6 +112,7 @@ def format_count(cnt):
return result

def realm_summary_table(realm_minutes):
# type: (Dict[str, float]) -> str
query = '''
SELECT
realm.domain,
Expand Down Expand Up @@ -218,10 +225,10 @@ def realm_summary_table(realm_minutes):
row['history'] = ''

# augment data with realm_minutes
total_hours = 0
total_hours = 0.0
for row in rows:
domain = row['domain']
minutes = realm_minutes.get(domain, 0)
minutes = realm_minutes.get(domain, 0.0)
hours = minutes / 60.0
total_hours += hours
row['hours'] = str(int(hours))
Expand All @@ -236,6 +243,7 @@ def realm_summary_table(realm_minutes):

# Count active sites
def meets_goal(row):
# type: (Dict[str, int]) -> bool
return row['active_user_count'] >= 5

num_active_sites = len(list(filter(meets_goal, rows)))
Expand Down Expand Up @@ -269,6 +277,7 @@ def meets_goal(row):


def user_activity_intervals():
# type: () -> Tuple[mark_safe, Dict[str, float]]
day_end = timestamp_to_datetime(time.time())
day_start = day_end - timedelta(hours=24)

Expand Down Expand Up @@ -319,6 +328,7 @@ def user_activity_intervals():
return content, realm_minutes

def sent_messages_report(realm):
# type: (Realm) -> str
title = 'Recently sent messages for ' + realm

cols = [
Expand Down Expand Up @@ -386,14 +396,17 @@ def sent_messages_report(realm):
return make_table(title, cols, rows)

def ad_hoc_queries():
# type: () -> List[Dict[str, str]]
def get_page(query, cols, title):
# type: (str, List[str], str) -> Dict[str, str]
cursor = connection.cursor()
cursor.execute(query)
rows = cursor.fetchall()
rows = list(map(list, rows))
cursor.close()

def fix_rows(i, fixup_func):
# type: (int, Union[Callable[[Realm], mark_safe], Callable[[datetime], str]]) -> None
for row in rows:
row[i] = fixup_func(row[i])

Expand Down Expand Up @@ -556,8 +569,9 @@ def fix_rows(i, fixup_func):
@zulip_internal
@has_request_variables
def get_activity(request):
duration_content, realm_minutes = user_activity_intervals()
counts_content = realm_summary_table(realm_minutes)
# type: (HttpRequest) -> HttpResponse
duration_content, realm_minutes = user_activity_intervals() # type: Tuple[mark_safe, Dict[str, float]]
counts_content = realm_summary_table(realm_minutes) # type: str
data = [
('Counts', counts_content),
('Durations', duration_content),
Expand All @@ -574,6 +588,7 @@ def get_activity(request):
)

def get_user_activity_records_for_realm(realm, is_bot):
# type: (Realm, bool) -> QuerySet
fields = [
'user_profile__full_name',
'user_profile__email',
Expand All @@ -593,6 +608,7 @@ def get_user_activity_records_for_realm(realm, is_bot):
return records

def get_user_activity_records_for_email(email):
# type: (str) -> List[QuerySet]
fields = [
'user_profile__full_name',
'query',
Expand All @@ -609,6 +625,7 @@ def get_user_activity_records_for_email(email):
return records

def raw_user_activity_table(records):
# type: (List[QuerySet]) -> str
cols = [
'query',
'client',
Expand All @@ -617,6 +634,7 @@ def raw_user_activity_table(records):
]

def row(record):
# type: (QuerySet) -> List[Any]
return [
record.query,
record.client.name,
Expand All @@ -629,9 +647,10 @@ def row(record):
return make_table(title, cols, rows)

def get_user_activity_summary(records):
# type: (Any) -> Any
# type: (List[QuerySet]) -> Dict[str, Dict[str, Any]]
summary = {} # type: Dict[str, Dict[str, Any]]
def update(action, record):
# type: (str, QuerySet) -> None
if action not in summary:
summary[action] = dict(
count=record.count,
Expand Down Expand Up @@ -673,24 +692,28 @@ def update(action, record):
return summary

def format_date_for_activity_reports(date):
# type: (datetime) -> str
if date:
return date.astimezone(eastern_tz).strftime('%Y-%m-%d %H:%M')
else:
return ''

def user_activity_link(email):
# type: (str) -> mark_safe
url_name = 'analytics.views.get_user_activity'
url = urlresolvers.reverse(url_name, kwargs=dict(email=email))
email_link = '<a href="%s">%s</a>' % (url, email)
return mark_safe(email_link)

def realm_activity_link(realm):
# type: (Realm) -> mark_safe
url_name = 'analytics.views.get_realm_activity'
url = urlresolvers.reverse(url_name, kwargs=dict(realm=realm))
realm_link = '<a href="%s">%s</a>' % (url, realm)
return mark_safe(realm_link)

def realm_client_table(user_summaries):
# type: (Dict[str, Dict[str, Dict[str, Any]]]) -> str
exclude_keys = [
'internal',
'name',
Expand Down Expand Up @@ -735,6 +758,7 @@ def realm_client_table(user_summaries):
return make_table(title, cols, rows)

def user_activity_summary_table(user_summary):
# type: (Dict[str, Dict[str, Any]]) -> str
rows = []
for k, v in user_summary.items():
if k == 'name':
Expand All @@ -761,27 +785,32 @@ def user_activity_summary_table(user_summary):
return make_table(title, cols, rows)

def realm_user_summary_table(all_records, admin_emails):
# type: (List[QuerySet], Set[str]) -> Tuple[Any, str]
user_records = {}

def by_email(record):
# type: (QuerySet) -> str
return record.user_profile.email

for email, records in itertools.groupby(all_records, by_email):
user_records[email] = get_user_activity_summary(list(records))

def get_last_visit(user_summary, k):
# type: (Dict[str, Dict[str, Any]], str) -> Optional[datetime]
if k in user_summary:
return user_summary[k]['last_visit']
else:
return None

def get_count(user_summary, k):
# type: (Dict[str, Dict[str, Any]], str) -> str
if k in user_summary:
return user_summary[k]['count']
else:
return ''

def is_recent(val):
# type: (Any) -> bool
age = datetime.now(val.tzinfo) - val
return age.total_seconds() < 5 * 60

Expand All @@ -792,18 +821,19 @@ def is_recent(val):
cells = [user_summary['name'], email_link, sent_count]
row_class = ''
for field in ['use', 'send', 'pointer', 'desktop', 'ZulipiOS', 'Android']:
val = get_last_visit(user_summary, field)
visit = get_last_visit(user_summary, field)
if field == 'use':
if val and is_recent(val):
if visit and is_recent(visit):
row_class += ' recently_active'
if email in admin_emails:
row_class += ' admin'
val = format_date_for_activity_reports(val)
val = format_date_for_activity_reports(visit)
cells.append(val)
row = dict(cells=cells, row_class=row_class)
rows.append(row)

def by_used_time(row):
# type: (Dict[str, Sequence[str]]) -> str
return row['cells'][3]

rows = sorted(rows, key=by_used_time, reverse=True)
Expand All @@ -827,7 +857,7 @@ def by_used_time(row):

@zulip_internal
def get_realm_activity(request, realm):
# type: (Any, Any) -> Any
# type: (HttpRequest, Realm) -> HttpResponse
data = [] # type: List[Tuple[str, str]]
all_user_records = {} # type: Dict[str, Any]

Expand Down Expand Up @@ -869,6 +899,7 @@ def get_realm_activity(request, realm):

@zulip_internal
def get_user_activity(request, email):
# type: (HttpRequest, str) -> HttpResponse
records = get_user_activity_records_for_email(email)

data = [] # type: List[Tuple[str, str]]
Expand Down

0 comments on commit 8fec8bc

Please sign in to comment.