Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
b2a1d94
working nav
BigSpaceships Mar 27, 2026
3118e37
Fixing dashboard
BigSpaceships Mar 27, 2026
a71fc10
fix webpack stuff
BigSpaceships Mar 27, 2026
1778140
fixing more dashboard
BigSpaceships Mar 27, 2026
3e8af9e
more updating dashboard
BigSpaceships Mar 27, 2026
49ac79f
major project stuff
BigSpaceships Mar 27, 2026
ad77d79
dashboard is done
BigSpaceships Mar 28, 2026
0ddf26c
reordered dashboard
BigSpaceships Mar 28, 2026
d164c3a
intro evals basic info
BigSpaceships Mar 29, 2026
b3d85b8
intro evals table stuff
BigSpaceships Mar 30, 2026
88fc6cf
table toggle
BigSpaceships Apr 1, 2026
c54efb8
made things more compact
BigSpaceships Apr 1, 2026
52f4e76
spring evals
BigSpaceships Apr 1, 2026
6584fe8
more fixing things
BigSpaceships Apr 1, 2026
8a9da9e
started working on conditionals
BigSpaceships Apr 1, 2026
c458ecd
more small fixes
BigSpaceships Apr 1, 2026
1c1554a
updated for updating from dev
BigSpaceships Apr 22, 2026
ed510e4
Merge branch 'develop' into bootstrap-5
BigSpaceships Apr 22, 2026
cd52fae
fix: spelling on dashboard
BigSpaceships Apr 23, 2026
399d21e
feat: update bootstrap
BigSpaceships Jun 13, 2026
ce0b773
fix: fixed broken bootstrap install, also swal2
BigSpaceships Jun 13, 2026
8e4a3b5
chore: consolidated nav and nav_protected and made everything inherit
BigSpaceships Jun 13, 2026
ebff7e5
fix: evals tables not showing up
BigSpaceships Jun 13, 2026
8bc611b
feat: styled spring evals table
BigSpaceships Jun 13, 2026
facca8c
feat: link icons for headers
BigSpaceships Jun 13, 2026
f760edb
csh bootstrap 5.3.10
BigSpaceships Jun 23, 2026
c68e1bd
feat: new bootstrap version
BigSpaceships Jun 23, 2026
59de3c7
feat: datepicker for conditional creation
BigSpaceships Jun 23, 2026
1f81512
feat: swal2 stuff for creating conditionals
BigSpaceships Jun 23, 2026
7162595
feat: cleanup fetch utils
BigSpaceships Jun 23, 2026
005bee8
fix: center active button
BigSpaceships Jun 23, 2026
1eefedf
Merge branch 'develop' into bootstrap-5
BigSpaceships Jun 28, 2026
6261e91
feat: cleanup intro and gatekeep evals stuff
BigSpaceships Jun 28, 2026
7eefb7d
feat: more major project stuff
BigSpaceships Jul 3, 2026
40f72aa
fix: better formatting the images
BigSpaceships Jul 3, 2026
48ee528
feat: coop form
BigSpaceships Jul 3, 2026
3b50b0f
feat: housing page
BigSpaceships Jul 4, 2026
fe28b48
feat: directorship attendance
BigSpaceships Jul 4, 2026
289be12
feat: more directorship attendance
BigSpaceships Jul 11, 2026
1232338
feat: ts attendance
BigSpaceships Jul 11, 2026
8f15197
feat: attendance history
BigSpaceships Jul 13, 2026
1126bc0
feat: styled attendance history
BigSpaceships Jul 23, 2026
dde8736
feat: hm attendance and history editing
BigSpaceships Jul 25, 2026
d9af474
fix: reviewing seminars and directorship bug
BigSpaceships Jul 25, 2026
2071d48
feat: coop management
BigSpaceships Jul 25, 2026
d57c749
feat: edit member modal
BigSpaceships Aug 1, 2026
d17f1a7
feat: member management cleaned up
BigSpaceships Aug 1, 2026
b71d732
fix: user group overrides
BigSpaceships Aug 1, 2026
b82550e
fix: active button shows up now
BigSpaceships Aug 1, 2026
128d6db
feat: financial member management
BigSpaceships Aug 5, 2026
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
106 changes: 80 additions & 26 deletions conditional/blueprints/attendance.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def get_all_members(user_dict=None):

named_members = [
{
'display': f.name,
'label': f.name,
'value': f.id,
'freshman': True
} for f in FreshmanAccount.query.filter(
Expand All @@ -49,7 +49,7 @@ def get_all_members(user_dict=None):
for account in members:
named_members.append(
{
'display': account['displayName'],
'label': account['displayName'],
'value': account['uid'],
'freshman': False
})
Expand Down Expand Up @@ -79,7 +79,7 @@ def get_non_alumni_non_coop(internal=False, user_dict=None):

eligible_members = [
{
'display': f.name,
'label': f.name,
'value': f.id,
'freshman': True
} for f in FreshmanAccount.query.filter(
Expand All @@ -92,7 +92,7 @@ def get_non_alumni_non_coop(internal=False, user_dict=None):

eligible_members.append(
{
'display': account['displayName'],
'label': account['displayName'],
'value': account['uid'],
'freshman': False
})
Expand All @@ -115,7 +115,7 @@ def get_non_alumni(user_dict=None):

eligible_members = [
{
'display': f.name,
'label': f.name,
'value': f.id,
'freshman': True
} for f in FreshmanAccount.query.filter(
Expand All @@ -124,7 +124,7 @@ def get_non_alumni(user_dict=None):
for account in current_students:
eligible_members.append(
{
'display': account['displayName'],
'label': account['displayName'],
'value': account['uid'],
'freshman': False
})
Expand Down Expand Up @@ -166,10 +166,14 @@ def display_attendance_hm(user_dict=None):
if not user_dict_is_eval_director(user_dict):
return redirect("/dashboard")

members = get_non_alumni_non_coop(internal=True)

print(members)

return render_template('attendance_hm.html',
username=user_dict['username'],
date=datetime.now().strftime("%Y-%m-%d"),
members=get_non_alumni_non_coop(internal=True))
members=members)


@attendance_bp.route('/attendance/submit/cm', methods=['POST'])
Expand Down Expand Up @@ -371,53 +375,73 @@ def alter_house_excuse(uid, hid, user_dict=None):
@auth.oidc_auth("default")
@get_user
def attendance_history(user_dict=None):
member_names = { member['uid']: member['displayName']
for member in ldap.get_group_member_attributes(groups=['current_student'],
attributes=['uid', 'displayName']) }

def get_member_name(uid):
if uid in member_names:
return member_names[uid]

name = ldap_get_member(uid).displayName
member_names[uid] = name
return name

def get_meeting_attendees(meeting_id):
attendees = [ldap_get_member(a.uid).displayName for a in
attendees = [get_member_name(a.uid) for a in
MemberCommitteeAttendance.query.filter(
MemberCommitteeAttendance.meeting_id == meeting_id).all()]

for freshman in [a.fid for a in
freshmen_attendees = [a.fid for a in
FreshmanCommitteeAttendance.query.filter(
FreshmanCommitteeAttendance.meeting_id == meeting_id).all()]:
FreshmanCommitteeAttendance.meeting_id == meeting_id).all()]

for freshman in freshmen_attendees:
attendees.append(FreshmanAccount.query.filter(
FreshmanAccount.id == freshman).first().name)

return attendees

def get_seminar_attendees(meeting_id):
attendees = [ldap_get_member(a.uid).displayName for a in
attendees = [get_member_name(a.uid) for a in
MemberSeminarAttendance.query.filter(
MemberSeminarAttendance.seminar_id == meeting_id).all()]

for freshman in [a.fid for a in
freshmen_attendees = [a.fid for a in
FreshmanSeminarAttendance.query.filter(
FreshmanSeminarAttendance.seminar_id == meeting_id).all()]:
FreshmanSeminarAttendance.seminar_id == meeting_id).all()]

for freshman in freshmen_attendees:
attendees.append(FreshmanAccount.query.filter(
FreshmanAccount.id == freshman).first().name)

return attendees

def get_seminar_hosts(meeting_id):
hosts = [ldap_get_member(a.uid).displayName for a in
hosts = [get_member_name(a.uid) for a in
MemberSeminarHost.query.filter(
MemberSeminarHost.seminar_id == meeting_id).all()]

for freshman in [a.fid for a in
freshmen_hosts = [a.fid for a in
FreshmanSeminarHost.query.filter(
FreshmanSeminarHost.seminar_id == meeting_id).all()]:
FreshmanSeminarHost.seminar_id == meeting_id).all()]

for freshman in freshmen_hosts:
hosts.append(FreshmanAccount.query.filter(
FreshmanAccount.id == freshman).first().name)

return hosts

log = logger.new(request=request, auth_dict=user_dict)

if not user_dict_is_eboard(user_dict):
return jsonify({"success": False, "error": "Not EBoard"}), 403


page = request.args.get('page', 1)
page_size = int(request.args.get('size', 10))

log.info('View Past Attendance Submitions')
offset = 0 if int(page) == 1 else ((int(page)-1)*10)
limit = int(page)*10
offset = 0 if int(page) == 1 else ((int(page) - 1) * 10)
limit = int(page) * page_size
all_cm = [{"id": m.id,
"name": m.committee,
"dt_obj": m.timestamp,
Expand All @@ -427,6 +451,7 @@ def get_seminar_hosts(meeting_id):
} for m in CommitteeMeeting.query.filter(
CommitteeMeeting.timestamp > start_of_year(),
CommitteeMeeting.approved).all()]

all_ts = [{"id": m.id,
"name": m.name,
"dt_obj": m.timestamp,
Expand All @@ -437,6 +462,7 @@ def get_seminar_hosts(meeting_id):
} for m in TechnicalSeminar.query.filter(
TechnicalSeminar.timestamp > start_of_year(),
TechnicalSeminar.approved).all()]

pend_cm = [{"id": m.id,
"name": m.committee,
"dt_obj": m.timestamp,
Expand All @@ -445,6 +471,7 @@ def get_seminar_hosts(meeting_id):
} for m in CommitteeMeeting.query.filter(
CommitteeMeeting.timestamp > start_of_year(),
CommitteeMeeting.approved == False).all()] # pylint: disable=singleton-comparison

pend_ts = [{"id": m.id,
"name": m.name,
"dt_obj": m.timestamp,
Expand All @@ -454,20 +481,47 @@ def get_seminar_hosts(meeting_id):
} for m in TechnicalSeminar.query.filter(
TechnicalSeminar.timestamp > start_of_year(),
TechnicalSeminar.approved == False).all()] # pylint: disable=singleton-comparison

all_meetings = sorted((all_cm + all_ts), key=lambda k: k['dt_obj'], reverse=True)[offset:limit]
if len(all_cm) % 10 != 0:
total_pages = int(len(all_cm) / 10) + 1
if len(all_cm) % page_size != 0:
total_pages = int(len(all_cm) / page_size) + 1
else:
total_pages = int(len(all_cm) / 10)
total_pages = int(len(all_cm) / page_size)

page_size_options = [
{
'value': 10,
'label': '10'
},
{
'value': 25,
'label': '25'
},
{
'value': 50,
'label': '50'
},
{
'value': 100,
'label': '100'
},
{
'value': -1,
'label': 'all'
}
]

selected_page_size = list(filter(lambda opt: opt['value'] == page_size, page_size_options))[0]

return render_template('attendance_history.html',
username=user_dict['username'],
history=all_meetings,
pending_cm=pend_cm,
pending_ts=pend_ts,
all_ts=all_ts,
num_pages=total_pages,
current_page=int(page))

page_size=selected_page_size,
current_page=int(page),
page_sizes=page_size_options)

@attendance_bp.route('/attendance/alter/cm/<cid>', methods=['POST'])
@auth.oidc_auth("default")
Expand Down
4 changes: 1 addition & 3 deletions conditional/blueprints/co_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ def submit_co_op_form(user_dict=None):
db.session.add(co_op)
db.session.flush()
db.session.commit()
req_cm.cache_clear()

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

Expand All @@ -84,7 +83,6 @@ def delete_co_op(uid, user_dict=None):

db.session.flush()
db.session.commit()
req_cm.cache_clear()

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

Expand All @@ -99,7 +97,7 @@ def display_co_op_management(user_dict=None):
if not user_dict_is_eval_director(user_dict):
return "must be eval director", 403

co_op_list = [(member.semester, member.uid)
co_op_list = [{ 'semester': member.semester, 'uid': member.uid}
for member in CurrentCoops.query.filter(
CurrentCoops.date_created > start_of_year(),
CurrentCoops.semester != "Neither")]
Expand Down
9 changes: 5 additions & 4 deletions conditional/blueprints/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ def display_dashboard(user_dict=None):
"Active Members": len(ldap_get_active_member_uids())}
# freshman shit
if user_dict_is_intromember(user_dict):
data['freshman'] = get_freshman_data(uid)
data['intro'] = get_freshman_data(uid)
else:
data['freshman'] = None
data['intro'] = None

spring = {}
c_meetings = get_cm(user_dict['account'])
Expand Down Expand Up @@ -162,8 +162,9 @@ def display_dashboard(user_dict=None):

data['cm_attendance'] = c_meetings
data['cm_attendance_len'] = len(c_meetings)
data['hm_attendance'] = hm_attendance
data['hm_attendance_len'] = len(hm_attendance)

data['missed_hm'] = hm_attendance
data['missed_hm_len'] = len(hm_attendance)

gatekeep_info = gatekeep_values(uid)
gatekeep_result = 'disenfranchised'
Expand Down
7 changes: 7 additions & 0 deletions conditional/blueprints/gatekeep.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,16 @@ def display_spring_evals(internal=False, user_dict=None):
if passing:
status = 'passed'

status_int = 0

if passing:
status_int = 1

member = {
'name': name,
'uid': uid,
'status': status,
'status_int': status_int,
'committee_meetings': cm_attended_count,
'technical_seminars': ts_attended_count,
'technical_seminars_hosted': ts_hosted_count,
Expand All @@ -136,6 +142,7 @@ def display_spring_evals(internal=False, user_dict=None):
gk_members.sort(key=lambda x: x['committee_meetings'], reverse=True)
gk_members.sort(key=lambda x: x['technical_seminars'], reverse=True)
gk_members.sort(key=lambda x: len(x['house_meetings_missed']))
gk_members.sort(key=lambda x: x['status_int'], reverse=True)
# return names in 'first last (username)' format
if internal:
return gk_members
Expand Down
32 changes: 20 additions & 12 deletions conditional/blueprints/housing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import structlog
from flask import Blueprint, request, jsonify

import ldap as python_ldap

from conditional import db, auth, ldap
from conditional.models.models import FreshmanAccount
from conditional.models.models import InHousingQueue
Expand Down Expand Up @@ -102,24 +104,30 @@ def change_room_numbers(rmnumber, user_dict=None):
if not user_dict_is_eval_director(user_dict):
return "must be eval director", 403

# Get the current list of people living on-floor.
current_students = ldap_get_current_students()
# Get the current list of people living in the room
# I'm sorry for the raw ldap
current_occupants_result = ldap.__con__.search_s(
"dc=csh,dc=rit,dc=edu",
python_ldap.SCOPE_SUBTREE,
f'roomNumber={rmnumber}',
['uid']
)

# Set the new room number for each person in the list.
current_occupants = [member[1]['uid'][0].decode('utf-8') for member in current_occupants_result]

# Remove all old occupants
for occupant in current_occupants:
if occupant not in update["occupants"]:
ldap_get_member(occupant).roomNumber = None

# Set the new room number for each person in the list.
for occupant in update["occupants"]:
if occupant != "":
account = ldap_get_member(occupant)
account.roomNumber = rmnumber
log.info(f'{occupant} assigned to room {rmnumber}')
ldap_set_active(account)
log.info(f'{occupant} marked as active because of room assignment')
# Delete any old occupants that are no longer in room.
for old_occupant in [account for account in current_students
if ldap_get_roomnumber(account) == str(rmnumber)
and account.uid not in update["occupants"]]:
log.info(f'{old_occupant.uid} removed from room {old_occupant.roomNumber}')
old_occupant.roomNumber = None

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

Expand All @@ -129,11 +137,11 @@ def change_room_numbers(rmnumber, user_dict=None):
def get_occupants(rmnumber):

# Get the current list of people living on-floor.
current_students = ldap_get_current_students()
current_students = ldap.get_group_member_attributes(groups=['current_student'], attributes=['uid', 'roomNumber', 'cn'])

# Find the current occupants of the specified room.
occupants = [account.uid for account in current_students
if ldap_get_roomnumber(account) == str(rmnumber)]
occupants = [account['uid'] for account in current_students
if 'roomNumber' in account and account['roomNumber'] == str(rmnumber)]
return jsonify({"room": rmnumber, "occupants": occupants}), 200


Expand Down
2 changes: 0 additions & 2 deletions conditional/blueprints/intro_evals.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,6 @@ def get_intro_members_without_accounts():
}
ie_members.append(freshman)

print(ie_members)

return ie_members

@intro_evals_bp.route('/intro_evals/')
Expand Down
Loading
Loading