Skip to content

Commit 7e87b67

Browse files
Merge pull request #85 from ComputerScienceHouse/develop
Conditional 1.2
2 parents 68e7f4f + b34b3bc commit 7e87b67

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1166
-19513
lines changed

.sass-lint.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ files:
44
include: 'frontend/stylesheets/**/*.s+(a|c)ss'
55
ignore:
66
- 'frontend/stylesheets/components/sweet-alert/**'
7+
- 'frontend/stylesheets/components/reveal/**'
8+
- 'frontend/stylesheets/presentations.scss'
79
rules:
810
# Extends
911
extends-before-mixins: 1
@@ -93,4 +95,4 @@ rules:
9395

9496
# Final Items
9597
trailing-semicolon: 1
96-
final-newline: 1
98+
final-newline: 1

README.md

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Conditional
22
===========
33

4-
[![Build Status](https://travis-ci.org/ComputerScienceHouse/conditional.svg?branch=travis-ci)](https://travis-ci.org/ComputerScienceHouse/conditional)
4+
[![Build Status](https://travis-ci.org/ComputerScienceHouse/conditional.svg)](https://travis-ci.org/ComputerScienceHouse/conditional)
55

66
A comprehensive membership evaluations solution for Computer Science House.
77

@@ -14,6 +14,7 @@ To run the application, you must have the latest version of [Python 3](https://w
1414
virtualenv .conditionalenv -p `which python3`
1515
source .conditionalenv/bin/activate
1616
pip install -r requirements.txt
17+
export FLASK_APP=app.py
1718
```
1819

1920
In addition, you must have Node, NPM, and Gulp CLI installed to properly execute the asset pipeline. If you don't have Node installed, we recommending installing with [NVM](https://github.com/creationix/nvm):
@@ -30,12 +31,7 @@ Then, install the pipeline and frontend dependencies:
3031
npm install
3132
```
3233

33-
You must create `config.py` in the top-level directory with the appropriate credentials for the application to run. See `config.sample.py` for an example. To perform the initial database migration, run the following commands before starting the application:
34-
35-
```
36-
pip install pymysql
37-
flask zoo
38-
```
34+
You must create `config.py` in the top-level directory with the appropriate credentials for the application to run. See `config.sample.py` for an example.
3935

4036
Once you have all of the dependencies installed, simply run:
4137

@@ -62,3 +58,12 @@ flask db migrate
6258
The new migration script in `migrations/versions` should be verified before being committed, as Alembic may not detect every change you make to the models.
6359

6460
For more information, refer to the [Flask-Migrate](https://flask-migrate.readthedocs.io/) documentation.
61+
62+
### Old Evals DB Migration
63+
64+
Conditional includes a utility to facilitate data migrations from the old Evals DB. This isn't necessary to run Conditional. To perform this migration, run the following commands before starting the application:
65+
66+
```
67+
pip install pymysql
68+
flask zoo
69+
```

conditional/blueprints/attendance.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def get_non_alumni_non_coop(internal=False):
7474
# Only Members Who Have Paid Dues Are Required to
7575
# go to house meetings
7676
non_alumni_members = ldap_get_active_members()
77-
coop_members = [u.username for u in CurrentCoops.query.all()]
77+
coop_members = [u.uid for u in CurrentCoops.query.all()]
7878

7979
named_members = [
8080
{

conditional/blueprints/dashboard.py

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
from conditional.models.models import HouseMeeting
2323
from conditional.models.models import CommitteeMeeting
2424

25+
from conditional.blueprints.member_management import get_members_info
26+
2527
from conditional.util.housing import get_queue_length, get_queue_position
2628
from conditional.util.flask import render_template
2729

@@ -106,6 +108,9 @@ def display_dashboard():
106108
# Voting Status
107109
data['voting'] = bool(user_name in can_vote)
108110

111+
active_list = get_members_info()[0]
112+
data['voting_count'] = {"Voting Members": len(can_vote),
113+
"Active Members": len(active_list)}
109114
# freshman shit
110115
if ldap_is_intromember(user_name):
111116
data['freshman'] = get_freshman_data(user_name)

conditional/blueprints/intro_evals.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,9 @@ def get_fid_cm_count(member_id):
107107

108108
if freshman_data is None:
109109
continue
110+
elif freshman_data.freshman_eval_result != "Pending":
111+
continue
110112

111-
# Add continue for if freshman_data.status != Pending
112113
h_meetings = [m.meeting_id for m in
113114
MemberHouseMeetingAttendance.query.filter(
114115
MemberHouseMeetingAttendance.uid == uid

conditional/blueprints/member_management.py

+83-17
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
import uuid
44

55
from datetime import datetime
6+
from functools import lru_cache
67

78
import structlog
89

9-
from flask import Blueprint, request, jsonify
10+
from flask import Blueprint, request, jsonify, abort
1011

1112
from conditional.models.models import FreshmanAccount
1213
from conditional.models.models import FreshmanEvalData
@@ -23,6 +24,7 @@
2324

2425
from conditional.blueprints.cache_management import clear_active_members_cache
2526
from conditional.blueprints.cache_management import clear_onfloor_members_cache
27+
from conditional.blueprints.intro_evals import display_intro_evals
2628

2729
from conditional.util.ldap import ldap_is_eval_director
2830
from conditional.util.ldap import ldap_is_financial_director
@@ -37,8 +39,9 @@
3739
from conditional.util.ldap import ldap_get_name
3840
from conditional.util.ldap import ldap_is_active
3941
from conditional.util.ldap import ldap_is_onfloor
40-
from conditional.util.ldap import __ldap_add_member_to_group__ as ldap_add_member_to_group
41-
from conditional.util.ldap import __ldap_remove_member_from_group__ as ldap_remove_member_from_group
42+
from conditional.util.ldap import _ldap_add_member_to_group as ldap_add_member_to_group
43+
from conditional.util.ldap import _ldap_remove_member_from_group as ldap_remove_member_from_group
44+
from conditional.util.ldap import _ldap_is_member_of_group as ldap_is_member_of_group
4245

4346
from conditional.util.flask import render_template
4447
from conditional.models.models import attendance_enum
@@ -50,7 +53,9 @@
5053
member_management_bp = Blueprint('member_management_bp', __name__)
5154

5255

53-
def get_members_info(members):
56+
@lru_cache(maxsize=1024)
57+
def get_members_info():
58+
members = [m['uid'] for m in ldap_get_current_students()]
5459
member_list = []
5560
number_onfloor = 0
5661

@@ -88,8 +93,7 @@ def display_member_management():
8893
if not ldap_is_eval_director(user_name) and not ldap_is_financial_director(user_name):
8994
return "must be eval director", 403
9095

91-
members = [m['uid'] for m in ldap_get_current_students()]
92-
member_list, onfloor_number = get_members_info(members)
96+
member_list, onfloor_number = get_members_info()
9397

9498
freshmen = FreshmanAccount.query
9599
freshmen_list = []
@@ -238,6 +242,7 @@ def member_management_edituser(uid):
238242
db.session.commit()
239243
return jsonify({"success": True}), 200
240244

245+
241246
def edit_uid(uid, user_name, post_data):
242247
active_member = post_data['activeMember']
243248

@@ -251,15 +256,18 @@ def edit_uid(uid, user_name, post_data):
251256

252257
ldap_set_roomnumber(uid, room_number)
253258
if onfloor_status:
254-
db.session.add(OnFloorStatusAssigned(uid, datetime.now()))
255-
ldap_add_member_to_group(uid, "onfloor")
259+
# If a OnFloorStatusAssigned object exists, don't make another
260+
if not ldap_is_member_of_group(uid, "onfloor"):
261+
db.session.add(OnFloorStatusAssigned(uid, datetime.now()))
262+
ldap_add_member_to_group(uid, "onfloor")
256263
else:
257264
for ofs in OnFloorStatusAssigned.query.filter(OnFloorStatusAssigned.uid == uid):
258265
db.session.delete(ofs)
259266
db.session.flush()
260267
db.session.commit()
261268

262-
ldap_remove_member_from_group(uid, "onfloor")
269+
if ldap_is_member_of_group(uid, "onfloor"):
270+
ldap_remove_member_from_group(uid, "onfloor")
263271
ldap_set_housingpoints(uid, housing_points)
264272

265273
# Only update if there's a diff
@@ -284,8 +292,8 @@ def edit_uid(uid, user_name, post_data):
284292

285293
def edit_fid(uid, post_data):
286294
logger.info('backend', action="edit freshman account %s room: %s onfloor: %s eval_date: %s sig_missed %s" %
287-
(uid, post_data['roomNumber'], post_data['onfloorStatus'],
288-
post_data['evalDate'], post_data['sigMissed']))
295+
(uid, post_data['roomNumber'], post_data['onfloorStatus'],
296+
post_data['evalDate'], post_data['sigMissed']))
289297

290298
name = post_data['name']
291299

@@ -458,18 +466,22 @@ def member_management_upgrade_user():
458466
db.session.add(new_acct)
459467
for fca in FreshmanCommitteeAttendance.query.filter(FreshmanCommitteeAttendance.fid == fid):
460468
db.session.add(MemberCommitteeAttendance(uid, fca.meeting_id))
461-
# XXX this might fail horribly #yoloswag
462469
db.session.delete(fca)
463470

464471
for fts in FreshmanSeminarAttendance.query.filter(FreshmanSeminarAttendance.fid == fid):
465472
db.session.add(MemberSeminarAttendance(uid, fts.seminar_id))
466-
# XXX this might fail horribly #yoloswag
467473
db.session.delete(fts)
468474

469475
for fhm in FreshmanHouseMeetingAttendance.query.filter(FreshmanHouseMeetingAttendance.fid == fid):
470-
db.session.add(MemberHouseMeetingAttendance(
471-
uid, fhm.meeting_id, fhm.excuse, fhm.attendance_status))
472-
# XXX this might fail horribly #yoloswag
476+
# Don't duplicate HM attendance records
477+
mhm = MemberHouseMeetingAttendance.query.filter(
478+
MemberHouseMeetingAttendance.meeting_id == fhm.meeting_id).first()
479+
if mhm is None:
480+
db.session.add(MemberHouseMeetingAttendance(
481+
uid, fhm.meeting_id, fhm.excuse, fhm.attendance_status))
482+
else:
483+
logger.info('backend', action="duplicate house meeting attendance! fid: %s, uid: %s, id: %s" %
484+
(fid, uid, fhm.meeting_id))
473485
db.session.delete(fhm)
474486

475487
if acct.onfloor_status:
@@ -478,7 +490,6 @@ def member_management_upgrade_user():
478490
if acct.room_number:
479491
ldap_set_roomnumber(uid, acct.room_number)
480492

481-
# XXX this might fail horribly #yoloswag
482493
db.session.delete(acct)
483494

484495
db.session.flush()
@@ -487,3 +498,58 @@ def member_management_upgrade_user():
487498
clear_onfloor_members_cache()
488499

489500
return jsonify({"success": True}), 200
501+
502+
503+
@member_management_bp.route('/manage/intro_project', methods=['GET'])
504+
def introductory_project():
505+
log = logger.new(user_name=request.headers.get("x-webauth-user"),
506+
request_id=str(uuid.uuid4()))
507+
log.info('api', action='show introductory project management')
508+
509+
user_name = request.headers.get('x-webauth-user')
510+
511+
if not ldap_is_eval_director(user_name):
512+
return "must be eval director", 403
513+
514+
return render_template(request,
515+
'introductory_project.html',
516+
username=user_name,
517+
intro_members=display_intro_evals(internal=True))
518+
519+
520+
@member_management_bp.route('/manage/intro_project', methods=['POST'])
521+
def introductory_project_submit():
522+
log = logger.new(user_name=request.headers.get("x-webauth-user"),
523+
request_id=str(uuid.uuid4()))
524+
log.info('api', action='submit introductory project results')
525+
526+
user_name = request.headers.get('x-webauth-user')
527+
528+
if not ldap_is_eval_director(user_name):
529+
return "must be eval director", 403
530+
531+
post_data = request.get_json()
532+
533+
if not isinstance(post_data, list):
534+
abort(400)
535+
536+
for intro_member in post_data:
537+
if not isinstance(intro_member, dict):
538+
abort(400)
539+
540+
if 'uid' not in intro_member or 'status' not in intro_member:
541+
abort(400)
542+
543+
if intro_member['status'] not in ['Passed', 'Pending', 'Failed']:
544+
abort(400)
545+
546+
log.info('debug', action='setting status "' + intro_member['status'] + '" for ' + intro_member['uid'])
547+
548+
FreshmanEvalData.query.filter(FreshmanEvalData.uid == intro_member['uid']).update({
549+
'freshman_project': intro_member['status']
550+
})
551+
552+
db.session.flush()
553+
db.session.commit()
554+
555+
return jsonify({"success": True}), 200

conditional/blueprints/slideshow.py

+1-13
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def slideshow_spring_review():
127127
post_data = request.get_json()
128128
uid = post_data['uid']
129129
status = post_data['status']
130-
# points = post_data['points']
130+
131131
logger.info("backend", action="submit spring eval for %s status: %s" % (uid, status))
132132

133133
SpringEval.query.filter(
@@ -138,18 +138,6 @@ def slideshow_spring_review():
138138
'status': status
139139
})
140140

141-
# points are handeled automagically through constitutional override
142-
# HousingEvalsSubmission.query.filter(
143-
# HousingEvalsSubmission.uid == uid and
144-
# HousingEvalsSubmission.active).\
145-
# update(
146-
# {
147-
# 'points': points
148-
# })
149-
150-
# current_points = ldap_get_housing_points(uid)
151-
# ldap_set_housingpoints(uid, current_points + points)
152-
153141
db.session.flush()
154142
db.session.commit()
155143
return jsonify({"success": True}), 200

conditional/blueprints/spring_evals.py

+2-14
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from conditional.models.models import MajorProject
1212
from conditional.models.models import HouseMeeting
1313
from conditional.models.models import SpringEval
14-
from conditional.models.models import HousingEvalsSubmission
1514

1615
from conditional.util.flask import render_template
1716

@@ -53,22 +52,11 @@ def get_cm_count(member_id):
5352
db.session.commit()
5453
# something bad happened to get here
5554
print("User did not have existing spring eval data")
55+
elif spring_entry.status != "Pending":
56+
continue
5657

5758
eval_data = None
58-
if internal:
59-
eval_data = HousingEvalsSubmission.query.filter(
60-
HousingEvalsSubmission.uid == uid).first()
6159

62-
if HousingEvalsSubmission.query.filter(HousingEvalsSubmission.uid == uid).count() > 0:
63-
eval_data = \
64-
{
65-
'social_attended': eval_data.social_attended,
66-
'social_hosted': eval_data.social_hosted,
67-
'seminars_attended': eval_data.technical_attended,
68-
'seminars_hosted': eval_data.technical_hosted,
69-
'projects': eval_data.projects,
70-
'comments': eval_data.comments
71-
}
7260
h_meetings = [m.meeting_id for m in
7361
MemberHouseMeetingAttendance.query.filter(
7462
MemberHouseMeetingAttendance.uid == uid

0 commit comments

Comments
 (0)