Skip to content

Commit

Permalink
backend: minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
slaporte committed Sep 30, 2017
1 parent bc05f37 commit 15b7f7e
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 39 deletions.
62 changes: 30 additions & 32 deletions montage/admin_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,8 @@ def unpublish_report(user_dao, campaign_id):


def make_admin_round_details(rnd, rnd_stats):
"""
Same as juror, but with: quorum, total_entries, jurors
"""
# TODO: This should be depricated in favor of rnd.to_details_dict(), which
# is similar except for the stats dict structure.
ret = {'id': rnd.id,
'name': rnd.name,
'directions': rnd.directions,
Expand All @@ -186,8 +185,8 @@ def make_admin_round_details(rnd, rnd_stats):
'percent_tasks_open': rnd_stats['percent_tasks_open'],
'total_disqualified_entries': rnd_stats['total_disqualified_entries'],
'campaign': rnd.campaign.to_info_dict(),
'stats': rnd_stats,
'jurors': [rj.to_details_dict() for rj in rnd.round_jurors]}
# TODO: add total num of entries, total num of uploaders, round source info
return ret


Expand Down Expand Up @@ -226,7 +225,7 @@ def create_campaign(user_dao, request_dict):

url = request_dict['url']

series_id = request_dict.get('series_id', 0)
series_id = request_dict.get('series_id', 1)

coord_names = request_dict.get('coordinators')

Expand All @@ -248,7 +247,6 @@ def create_campaign(user_dao, request_dict):


def get_campaign_report(user_dao, campaign_id):
# TODO: docs
coord_dao = CoordinatorDAO.from_campaign(user_dao, campaign_id)
summary = coord_dao.get_campaign_report()
ctx = summary.summary
Expand All @@ -262,9 +260,12 @@ def get_campaign_report_raw(user_dao, campaign_id):
return {'data': data}


def get_campaign_log(user_dao, campaign_id):
def get_campaign_log(user_dao, campaign_id, request_dict):
limit = request_dict.get('limit', 100)
offset = request_dict.get('offset', 0)

coord_dao = CoordinatorDAO.from_campaign(user_dao, campaign_id)
audit_logs = coord_dao.get_audit_log() # TODO: should this paginate?
audit_logs = coord_dao.get_audit_log()
ret = [a.to_info_dict() for a in audit_logs]
return {'data': ret}

Expand Down Expand Up @@ -300,7 +301,6 @@ def import_entries(user_dao, round_id, request_dict):
"""
coord_dao = CoordinatorDAO.from_round(user_dao, round_id)
import_method = request_dict['import_method']
warnings = []

if import_method == GISTCSV_METHOD:
gist_url = request_dict['gist_url']
Expand All @@ -323,31 +323,27 @@ def import_entries(user_dao, round_id, request_dict):
else:
raise NotImplementedError()

new_entries = coord_dao.add_round_entries(round_id, entries,
method=import_method,
params=params)
rnd = coord_dao.get_round(round_id) # TODO: The stats below should
# returned by
# add_round_entries
new_entry_stats = coord_dao.add_round_entries(round_id, entries,
method=import_method,
params=params)

# loader warnings
new_entry_stats['warnings'] = list()
if not entries:
warnings.append({'empty import': 'no entries imported'})
elif not new_entries:
warnings.append({'duplicate import': 'no new entries imported'})
new_entry_stats['warnings'].append({'empty import':
'no entries imported'})
elif not new_entry_stats.get('new_entry_count'):
new_entry_stats['warnings'].append({'duplicate import':
'no new entries imported'})

# automatically disqualify entries based on round config
auto_dq = autodisqualify(user_dao, round_id, request_dict={})
dqed = auto_dq['data']
if len(dqed) >= len(entries):
warnings.append({'all disqualified':
'all entries disqualified by round settings'})
data = {'round_id': rnd.id,
'new_entry_count': len(entries),
'new_round_entry_count': len(new_entries),
'total_entries': len(rnd.entries),
'disqualified': dqed,
'warnings': warnings}
new_entry_stats['disqualified'] = auto_dq['data']
if len(new_entry_stats['disqualified']) >= len(entries):
new_entry_stats['warnings'].append({'all disqualified':
'all entries disqualified by round settings'})

return {'data': data}
return {'data': new_entry_stats}


def activate_round(user_dao, round_id, request_dict):
Expand Down Expand Up @@ -489,12 +485,14 @@ def get_round_results_preview(user_dao, round_id):
try:
data['thresholds'] = get_threshold_map(data['ratings'])
except:
import pdb;pdb.post_mortem()
# import pdb;pdb.post_mortem()
raise
elif rnd.vote_method == 'ranking':
if not is_closeable:
# TODO: should this sort of check apply to ratings as well?
import pdb;pdb.set_trace()
# TODO: What should this return for ranking rounds? The ranking
# round is sorta an all-or-nothing deal, unlike the rating rounds
# where you can take a peek at in-progress results
# import pdb;pdb.set_trace()
raise InvalidAction('round must be closeable to preview results')

rankings = coord_dao.get_round_ranking_list(round_id)
Expand Down
17 changes: 17 additions & 0 deletions montage/docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ Get the audit log for a campaign

### Parameters
- `campaign_id` (in path)
- `limit` (optional, default 100)
- `offset` (optional, default 0)

### Response
- `data`: list of [`audit log entry`](#audit-log-entry) dictionaries
Expand Down Expand Up @@ -711,6 +713,21 @@ Downloads a csv file, with columns similar to the [MediaWiki image table](https:
- 403: not a coordinator for this campaign
- 404: round does not exist

## /v1/admin/campaign/`<campaign_id:int>`/report
Download a structured report from a finalized campaign.

- Function: [get_campaign_report_raw](https://github.com/hatnote/montage/blob/master/montage/admin_endpoints.py#L258) (admin_endpoints.py)
- Method: GET

### Parameters
- `campaign_id` (in path)

### Response
[TODO]

### Errors
- 403: not a coordinator for this campaign
- 404: campaign report does not exist

## /v1/juror
Return details from any jurored rounds
Expand Down
30 changes: 23 additions & 7 deletions montage/rdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
TIMESTAMP,
ForeignKey,
inspect)
from sqlalchemy.sql import func, asc
from sqlalchemy.sql import func, asc, distinct
from sqlalchemy.orm import relationship, joinedload
from sqlalchemy.sql.expression import select
from sqlalchemy.ext.declarative import declarative_base
Expand Down Expand Up @@ -320,18 +320,26 @@ def get_count_map(self):
.filter_by(round_id=self.id)\
.filter(RoundEntry.dq_reason != None)\
.count()
all_mimes = rdb_session.query(Entry.mime_minor)\
.join(RoundEntry)\
.distinct(Entry.mime_minor)\
.filter_by(round_id=self.id)\
.filter(RoundEntry.dq_reason == None)\
.all()

if task_count:
percent_open = round((100.0 * open_task_count) / task_count, 3)
else:
percent_open = 0.0

return {'total_round_entries': re_count,
return {'total_round_entries': re_count, # TODO: sync with total_entries
'total_tasks': task_count,
'total_open_tasks': open_task_count,
'percent_tasks_open': percent_open,
'total_cancelled_tasks': cancelled_task_count,
'total_disqualified_entries': dq_entry_count,
'total_uploaders': len(self.get_uploaders())}
'total_uploaders': len(self.get_uploaders()),
'all_mimes': all_mimes}

def get_uploaders(self):
# TODO: order by and maybe include count per?
Expand Down Expand Up @@ -378,11 +386,13 @@ def to_info_dict(self):
'deadline_date': format_date(self.deadline_date),
'jurors': [rj.to_info_dict() for rj in self.round_jurors],
'status': self.status,
'config': self.config}
'config': self.config,
'round_sources': []}
return ret

def to_details_dict(self):
ret = self.to_info_dict()
ret['campaign'] = self.campaign.to_info_dict()
ret['quorum'] = self.quorum
ret['total_round_entries'] = len(self.round_entries)
ret['stats'] = self.get_count_map()
Expand Down Expand Up @@ -1520,7 +1530,7 @@ def add_round_entries(self, round_id, entries, method, params):
in unique_iter(entries, key=lambda e: e.name)
if e.name not in existing_names]
if not new_entries:
return new_entries
return dict()
round_source = self.get_or_create_round_source(round_id, method, params)
self.rdb_session.flush()
for new_entry in new_entries:
Expand All @@ -1533,7 +1543,11 @@ def add_round_entries(self, round_id, entries, method, params):
if method:
msg += ' (from %s)' % (method,)
self.log_action('add_round_entries', message=msg, round=rnd)
return new_entries
new_entry_stats = {'round_id': rnd.id,
'new_entry_count': len(entries),
'new_round_entry_count': len(new_entries),
'total_entries': len(rnd.entries)}
return new_entry_stats

def cancel_round(self, round_id):
rnd = self.get_round(round_id)
Expand Down Expand Up @@ -1637,10 +1651,12 @@ def get_campaign_report(self):
.one_or_none()
return summary

def get_audit_log(self):
def get_audit_log(self, limit=100, offset=0):
audit_logs = (self.query(AuditLogEntry)
.filter_by(campaign_id=self.campaign.id)
.order_by(AuditLogEntry.create_date.asc())
.limit(limit)
.offset(offset)
.all())
return audit_logs

Expand Down

0 comments on commit 15b7f7e

Please sign in to comment.