Skip to content

Conditional 1.2 #85

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Oct 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f74eaf8
Address design concerns raised by #53
mbillow Oct 18, 2016
cc2ce48
Removed Housing Evals Submition Model
mbillow Oct 19, 2016
e851d7d
Updated DB Models as reqested in #57
mbillow Oct 19, 2016
9ab116d
Change dashboard for inactive members #34
mbillow Oct 19, 2016
5276f37
Created and styled intro evals slideshow
RamZallan Oct 17, 2016
dc789f5
Merge pull request #81 from RamZallan/develop
stevenmirabito Oct 20, 2016
d3cc62c
Stop Duplication of OnFloorStatusAssigned Objects
liam-middlebrook Oct 20, 2016
2403184
Add redundant check for the code reading clarity
liam-middlebrook Oct 20, 2016
1c2dd20
Add vote count to dashboard for eboard memebrs #67
mbillow Oct 20, 2016
322e7f3
Restyle LDAP Imports for Member Management
liam-middlebrook Oct 20, 2016
eed5e4b
Created spring evals slideshow
RamZallan Oct 20, 2016
6add04c
Stop using magic method notation in ldap util
mbillow Oct 20, 2016
41eaa3f
Merge pull request #82 from liam-middlebrook/fix-onfloor-status
mbillow Oct 20, 2016
6ceb9a3
Remove Housing Points from Spring Evals Review
liam-middlebrook Oct 20, 2016
3341b4c
Hasn't broken yet!
liam-middlebrook Oct 20, 2016
efab997
Fix House Meeting Attendance Race Condition
liam-middlebrook Oct 20, 2016
81fd1c9
Merge pull request #83 from RamZallan/develop
mbillow Oct 20, 2016
cd36248
Moved old DB migration out of main setup in README
stevenmirabito Oct 23, 2016
d3d1fbe
Fix Coop username uid mismatch
liam-middlebrook Oct 25, 2016
99d9e32
Remove static_old, no longer required
stevenmirabito Oct 26, 2016
6d2aa76
Add Intro Project Results management
stevenmirabito Oct 26, 2016
6ebe141
Merge pull request #88 from stevenmirabito/develop
mbillow Oct 26, 2016
b34b3bc
Freshmen need 10 CMs not 25
mbillow Oct 26, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .sass-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ files:
include: 'frontend/stylesheets/**/*.s+(a|c)ss'
ignore:
- 'frontend/stylesheets/components/sweet-alert/**'
- 'frontend/stylesheets/components/reveal/**'
- 'frontend/stylesheets/presentations.scss'
rules:
# Extends
extends-before-mixins: 1
Expand Down Expand Up @@ -93,4 +95,4 @@ rules:

# Final Items
trailing-semicolon: 1
final-newline: 1
final-newline: 1
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Conditional
===========

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

A comprehensive membership evaluations solution for Computer Science House.

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

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):
Expand All @@ -30,12 +31,7 @@ Then, install the pipeline and frontend dependencies:
npm install
```

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:

```
pip install pymysql
flask zoo
```
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.

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

Expand All @@ -62,3 +58,12 @@ flask db migrate
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.

For more information, refer to the [Flask-Migrate](https://flask-migrate.readthedocs.io/) documentation.

### Old Evals DB Migration

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:

```
pip install pymysql
flask zoo
```
2 changes: 1 addition & 1 deletion conditional/blueprints/attendance.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def get_non_alumni_non_coop(internal=False):
# Only Members Who Have Paid Dues Are Required to
# go to house meetings
non_alumni_members = ldap_get_active_members()
coop_members = [u.username for u in CurrentCoops.query.all()]
coop_members = [u.uid for u in CurrentCoops.query.all()]

named_members = [
{
Expand Down
5 changes: 5 additions & 0 deletions conditional/blueprints/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
from conditional.models.models import HouseMeeting
from conditional.models.models import CommitteeMeeting

from conditional.blueprints.member_management import get_members_info

from conditional.util.housing import get_queue_length, get_queue_position
from conditional.util.flask import render_template

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

active_list = get_members_info()[0]
data['voting_count'] = {"Voting Members": len(can_vote),
"Active Members": len(active_list)}
# freshman shit
if ldap_is_intromember(user_name):
data['freshman'] = get_freshman_data(user_name)
Expand Down
3 changes: 2 additions & 1 deletion conditional/blueprints/intro_evals.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ def get_fid_cm_count(member_id):

if freshman_data is None:
continue
elif freshman_data.freshman_eval_result != "Pending":
continue

# Add continue for if freshman_data.status != Pending
h_meetings = [m.meeting_id for m in
MemberHouseMeetingAttendance.query.filter(
MemberHouseMeetingAttendance.uid == uid
Expand Down
100 changes: 83 additions & 17 deletions conditional/blueprints/member_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import uuid

from datetime import datetime
from functools import lru_cache

import structlog

from flask import Blueprint, request, jsonify
from flask import Blueprint, request, jsonify, abort

from conditional.models.models import FreshmanAccount
from conditional.models.models import FreshmanEvalData
Expand All @@ -23,6 +24,7 @@

from conditional.blueprints.cache_management import clear_active_members_cache
from conditional.blueprints.cache_management import clear_onfloor_members_cache
from conditional.blueprints.intro_evals import display_intro_evals

from conditional.util.ldap import ldap_is_eval_director
from conditional.util.ldap import ldap_is_financial_director
Expand All @@ -37,8 +39,9 @@
from conditional.util.ldap import ldap_get_name
from conditional.util.ldap import ldap_is_active
from conditional.util.ldap import ldap_is_onfloor
from conditional.util.ldap import __ldap_add_member_to_group__ as ldap_add_member_to_group
from conditional.util.ldap import __ldap_remove_member_from_group__ as ldap_remove_member_from_group
from conditional.util.ldap import _ldap_add_member_to_group as ldap_add_member_to_group
from conditional.util.ldap import _ldap_remove_member_from_group as ldap_remove_member_from_group
from conditional.util.ldap import _ldap_is_member_of_group as ldap_is_member_of_group

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


def get_members_info(members):
@lru_cache(maxsize=1024)
def get_members_info():
members = [m['uid'] for m in ldap_get_current_students()]
member_list = []
number_onfloor = 0

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

members = [m['uid'] for m in ldap_get_current_students()]
member_list, onfloor_number = get_members_info(members)
member_list, onfloor_number = get_members_info()

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


def edit_uid(uid, user_name, post_data):
active_member = post_data['activeMember']

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

ldap_set_roomnumber(uid, room_number)
if onfloor_status:
db.session.add(OnFloorStatusAssigned(uid, datetime.now()))
ldap_add_member_to_group(uid, "onfloor")
# If a OnFloorStatusAssigned object exists, don't make another
if not ldap_is_member_of_group(uid, "onfloor"):
db.session.add(OnFloorStatusAssigned(uid, datetime.now()))
ldap_add_member_to_group(uid, "onfloor")
else:
for ofs in OnFloorStatusAssigned.query.filter(OnFloorStatusAssigned.uid == uid):
db.session.delete(ofs)
db.session.flush()
db.session.commit()

ldap_remove_member_from_group(uid, "onfloor")
if ldap_is_member_of_group(uid, "onfloor"):
ldap_remove_member_from_group(uid, "onfloor")
ldap_set_housingpoints(uid, housing_points)

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

def edit_fid(uid, post_data):
logger.info('backend', action="edit freshman account %s room: %s onfloor: %s eval_date: %s sig_missed %s" %
(uid, post_data['roomNumber'], post_data['onfloorStatus'],
post_data['evalDate'], post_data['sigMissed']))
(uid, post_data['roomNumber'], post_data['onfloorStatus'],
post_data['evalDate'], post_data['sigMissed']))

name = post_data['name']

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

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

for fhm in FreshmanHouseMeetingAttendance.query.filter(FreshmanHouseMeetingAttendance.fid == fid):
db.session.add(MemberHouseMeetingAttendance(
uid, fhm.meeting_id, fhm.excuse, fhm.attendance_status))
# XXX this might fail horribly #yoloswag
# Don't duplicate HM attendance records
mhm = MemberHouseMeetingAttendance.query.filter(
MemberHouseMeetingAttendance.meeting_id == fhm.meeting_id).first()
if mhm is None:
db.session.add(MemberHouseMeetingAttendance(
uid, fhm.meeting_id, fhm.excuse, fhm.attendance_status))
else:
logger.info('backend', action="duplicate house meeting attendance! fid: %s, uid: %s, id: %s" %
(fid, uid, fhm.meeting_id))
db.session.delete(fhm)

if acct.onfloor_status:
Expand All @@ -478,7 +490,6 @@ def member_management_upgrade_user():
if acct.room_number:
ldap_set_roomnumber(uid, acct.room_number)

# XXX this might fail horribly #yoloswag
db.session.delete(acct)

db.session.flush()
Expand All @@ -487,3 +498,58 @@ def member_management_upgrade_user():
clear_onfloor_members_cache()

return jsonify({"success": True}), 200


@member_management_bp.route('/manage/intro_project', methods=['GET'])
def introductory_project():
log = logger.new(user_name=request.headers.get("x-webauth-user"),
request_id=str(uuid.uuid4()))
log.info('api', action='show introductory project management')

user_name = request.headers.get('x-webauth-user')

if not ldap_is_eval_director(user_name):
return "must be eval director", 403

return render_template(request,
'introductory_project.html',
username=user_name,
intro_members=display_intro_evals(internal=True))


@member_management_bp.route('/manage/intro_project', methods=['POST'])
def introductory_project_submit():
log = logger.new(user_name=request.headers.get("x-webauth-user"),
request_id=str(uuid.uuid4()))
log.info('api', action='submit introductory project results')

user_name = request.headers.get('x-webauth-user')

if not ldap_is_eval_director(user_name):
return "must be eval director", 403

post_data = request.get_json()

if not isinstance(post_data, list):
abort(400)

for intro_member in post_data:
if not isinstance(intro_member, dict):
abort(400)

if 'uid' not in intro_member or 'status' not in intro_member:
abort(400)

if intro_member['status'] not in ['Passed', 'Pending', 'Failed']:
abort(400)

log.info('debug', action='setting status "' + intro_member['status'] + '" for ' + intro_member['uid'])

FreshmanEvalData.query.filter(FreshmanEvalData.uid == intro_member['uid']).update({
'freshman_project': intro_member['status']
})

db.session.flush()
db.session.commit()

return jsonify({"success": True}), 200
14 changes: 1 addition & 13 deletions conditional/blueprints/slideshow.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def slideshow_spring_review():
post_data = request.get_json()
uid = post_data['uid']
status = post_data['status']
# points = post_data['points']

logger.info("backend", action="submit spring eval for %s status: %s" % (uid, status))

SpringEval.query.filter(
Expand All @@ -138,18 +138,6 @@ def slideshow_spring_review():
'status': status
})

# points are handeled automagically through constitutional override
# HousingEvalsSubmission.query.filter(
# HousingEvalsSubmission.uid == uid and
# HousingEvalsSubmission.active).\
# update(
# {
# 'points': points
# })

# current_points = ldap_get_housing_points(uid)
# ldap_set_housingpoints(uid, current_points + points)

db.session.flush()
db.session.commit()
return jsonify({"success": True}), 200
16 changes: 2 additions & 14 deletions conditional/blueprints/spring_evals.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from conditional.models.models import MajorProject
from conditional.models.models import HouseMeeting
from conditional.models.models import SpringEval
from conditional.models.models import HousingEvalsSubmission

from conditional.util.flask import render_template

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

eval_data = None
if internal:
eval_data = HousingEvalsSubmission.query.filter(
HousingEvalsSubmission.uid == uid).first()

if HousingEvalsSubmission.query.filter(HousingEvalsSubmission.uid == uid).count() > 0:
eval_data = \
{
'social_attended': eval_data.social_attended,
'social_hosted': eval_data.social_hosted,
'seminars_attended': eval_data.technical_attended,
'seminars_hosted': eval_data.technical_hosted,
'projects': eval_data.projects,
'comments': eval_data.comments
}
h_meetings = [m.meeting_id for m in
MemberHouseMeetingAttendance.query.filter(
MemberHouseMeetingAttendance.uid == uid
Expand Down
Loading