Skip to content
Merged
12 changes: 8 additions & 4 deletions labconnect/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,20 @@ def format_credits(credit_1, credit_2, credit_3, credit_4):
credits_output.append("4")

# Handle different cases
if len(credits_output) == 0:
return None
if len(credits_output) == 4:
return "1-4 Credits"
elif len(credits_output) == 1:
return (
f"{credits_output[0]} Credit"
if credit_1
else f"{credits_output[0]} Credits"
)
elif len(credits_output) == 4:
return "1-4 Credits"
elif credits_output == ["1", "2", "3"]:
return "1-3 Credits"
elif credits_output == ["2", "3", "4"]:
return "2-4 Credits"
elif len(credits_output) == 0:
return None
else:
return f"{','.join(credits_output)} Credits"

Expand Down
183 changes: 80 additions & 103 deletions labconnect/main/opportunity_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from flask import abort, request
from flask_jwt_extended import get_jwt_identity, jwt_required
from sqlalchemy import func
from sqlalchemy import func, case

from labconnect import db
from labconnect.helpers import (
Expand Down Expand Up @@ -143,31 +143,6 @@ def packageIndividualOpportunity(opportunityInfo):
return data


def packageOpportunityCard(opportunity):
# get professor and department by getting Leads and LabManager
query = db.session.execute(
db.select(Leads, LabManager, User.first_name, User.last_name)
.where(Leads.opportunity_id == opportunity.id)
.join(LabManager, Leads.lab_manager_id == LabManager.id)
.join(User, LabManager.id == User.lab_manager_id)
)

data = query.all()

professorInfo = ", ".join(item[1].getName() for item in data)

card = {
"id": opportunity.id,
"title": opportunity.name,
"professor": professorInfo,
"season": opportunity.semester,
"location": "TBA",
"year": opportunity.year,
}

return card


@main_blueprint.get("/getOpportunity/<int:opp_id>")
def getOpportunity(opp_id: int):
# query database for opportunity and recommended class years
Expand Down Expand Up @@ -200,86 +175,94 @@ def getOpportunity(opp_id: int):


@main_blueprint.get("/opportunity/filter")
def getOpportunities():
# Handle GET requests for fetching default active opportunities
data = db.session.execute(
db.select(Opportunities)
.where(Opportunities.active)
.limit(20)
.order_by(Opportunities.last_updated.desc())
.distinct()
).scalars()
result = [serialize_opportunity(opportunity) for opportunity in data]
return result


@main_blueprint.post("/opportunity/filter")
@jwt_required()
def filterOpportunities():
# Handle POST requests for filtering opportunities
json_request_data = request.get_json()

if not json_request_data:
abort(400)

filters = json_request_data.get("filters", None)

# Handle GET requests for filtering opportunities using query parameters
filters = request.args.to_dict(flat=False)
user_id = get_jwt_identity()
data = None

if filters is None:
data = db.session.execute(db.select(Opportunities).limit(20)).scalars()

elif not isinstance(filters, list):
abort(400)

else:
where_conditions = []
query = (
db.select(Opportunities)
.where(Opportunities.active)
.limit(20)
.order_by(Opportunities.last_updated)
.distinct()
query = (
db.select(
Opportunities,
func.json_agg(
func.json_build_object(
"first_name",
User.first_name,
"last_name",
User.last_name,
"preferred_name",
User.preferred_name,
)
).label("lab_managers"),
case((UserSavedOpportunities.user_id.isnot(None), True), else_=False).label(
"is_saved"
),
)
.join(Leads, Opportunities.id == Leads.opportunity_id)
.join(LabManager, Leads.lab_manager_id == LabManager.id)
.join(User, LabManager.id == User.lab_manager_id)
.outerjoin(
RecommendsMajors, Opportunities.id == RecommendsMajors.opportunity_id
)
for given_filter in filters:
field = given_filter.get("field", None)
value = given_filter.get("value", None)
.outerjoin(
UserSavedOpportunities,
db.and_(
Opportunities.id == UserSavedOpportunities.opportunity_id,
UserSavedOpportunities.user_id == user_id, # filter for current user
),
)
.where(Opportunities.active)
.group_by(Opportunities.id, UserSavedOpportunities.user_id)
.order_by(Opportunities.last_updated)
.limit(20)
)

if filters is not None or filters != {}:
where_conditions = []
for field, value in filters.items():
if field and value:
field = field.lower()
value = value[0].split(",")

# Location filter
# not in use yet
if field == "location":
if value.lower() == "remote":
where_conditions.append(Opportunities.location == "REMOTE")
else:
where_conditions.append(Opportunities.location != "REMOTE")
for location in value:
if location.lower() == "remote":
where_conditions.append(Opportunities.location == "REMOTE")
else:
where_conditions.append(Opportunities.location != "REMOTE")

# Class year filter
elif field == "class_year":
elif field == "years":
if not isinstance(value, list):
abort(400)
years = list(map(int, filter(str.isdigit, value)))
if len(years) == 0:
abort(400)
query = query.join(
RecommendsClassYears,
Opportunities.id == RecommendsClassYears.opportunity_id,
).where(RecommendsClassYears.class_year.in_(value))
).where(RecommendsClassYears.class_year.in_(years))

# Credits filter
elif field == "credits":
if not isinstance(value, list):
abort(400)
credit_conditions = []
for credit in value:
if credit == 1:
if credit == "1":
credit_conditions.append(Opportunities.one_credit.is_(True))
elif credit == 2:
elif credit == "2":
credit_conditions.append(
Opportunities.two_credits.is_(True)
)
elif credit == 3:
elif credit == "3":
credit_conditions.append(
Opportunities.three_credits.is_(True)
)
elif credit == 4:
elif credit == "4":
credit_conditions.append(
Opportunities.four_credits.is_(True)
)
Expand All @@ -291,12 +274,10 @@ def filterOpportunities():
elif field == "majors":
if not isinstance(value, list):
abort(400)
query = query.join(
RecommendsMajors,
Opportunities.id == RecommendsMajors.opportunity_id,
).where(RecommendsMajors.major_code.in_(value))
where_conditions.append(RecommendsMajors.major_code.in_(value))

# Departments filter
# not currently in use
elif field == "departments":
if not isinstance(value, list):
abort(400)
Expand All @@ -307,16 +288,11 @@ def filterOpportunities():
)

# Pay filter
elif field == "pay":
if not isinstance(value, dict):
elif field == "hourlypay":
pay = value[0]
if not pay.isnumeric():
abort(400)
min_pay = value.get("min")
max_pay = value.get("max")
if min_pay is None:
min_pay = 0
if max_pay is None:
max_pay = float("inf")
where_conditions.append(Opportunities.pay.between(min_pay, max_pay))
where_conditions.append(Opportunities.pay >= float(pay))

# Other fields
else:
Expand All @@ -328,29 +304,29 @@ def filterOpportunities():
abort(400)

query = query.where(*where_conditions)
data = db.session.execute(query).scalars()

data = db.session.execute(query).all()

if not data:
abort(404)

result = [serialize_opportunity(opportunity) for opportunity in data]
result = [
serialize_opportunity(
opportunity[0],
lab_managers=", ".join(
[
f"{name.get('preferred_name', None) or name.get('first_name')} {name.get('last_name')}"
for name in opportunity[1]
]
),
saved=opportunity[2],
)
for opportunity in data
]

return result


# Jobs page
@main_blueprint.get("/getOpportunityCards")
def getOpportunityCards():
# query database for opportunity
query = db.session.execute(db.select(Opportunities).where(Opportunities.active))

data = query.fetchall()
# return data in the below format if opportunity is found
cards = {"data": [packageOpportunityCard(opportunity[0]) for opportunity in data]}

return cards


@main_blueprint.get("/staff/opportunities/<string:rcs_id>")
def getLabManagerOpportunityCards(rcs_id: str) -> list[dict[str, str]]:
query = (
Expand Down Expand Up @@ -388,6 +364,7 @@ def getLabManagerOpportunityCards(rcs_id: str) -> list[dict[str, str]]:


@main_blueprint.get("/profile/opportunities/<string:rcs_id>")
@jwt_required()
def getProfileOpportunities(rcs_id: str) -> list[dict[str, str]]:
query = (
db.select(
Expand Down
2 changes: 0 additions & 2 deletions labconnect/main/routes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# from typing import Any

from typing import NoReturn
from flask import abort, request
from flask_jwt_extended import get_jwt_identity, jwt_required
Expand Down
6 changes: 5 additions & 1 deletion labconnect/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ def serialize_course(course: Courses) -> str:
return f"{course.code} {course.name}"


def serialize_opportunity(opportunity: Opportunities) -> dict:
def serialize_opportunity(
opportunity: Opportunities, lab_managers: str = "", saved: bool = False
) -> dict:
return {
"id": opportunity.id,
"name": opportunity.name,
Expand All @@ -25,4 +27,6 @@ def serialize_opportunity(opportunity: Opportunities) -> dict:
"active": opportunity.active,
"last_updated": opportunity.last_updated,
"location": opportunity.location,
"lab_managers": lab_managers,
"saved": saved,
}
Binary file modified misc/LabConnect_Logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading