Skip to content

Commit

Permalink
feat(app): add course search
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominik Imrich authored and jonbiemond committed Nov 3, 2023
1 parent bfc2b8f commit 50fbd84
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 4 deletions.
17 changes: 15 additions & 2 deletions bcitflex/app_functions/course_query.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Filter courses."""
from enum import Enum
from typing import Type

from functional import seq
Expand All @@ -7,6 +8,11 @@
from bcitflex.model import Base, Course, Subject


class Match(Enum):
EXACT = "EXACT"
PARTIAL = "PARTIAL"


def coerce_to_column_type(model_column: Column, value: str | int) -> str | int:
"""Coerce a value to the type of the given model column."""
column_data_type = model_column.type.python_type
Expand All @@ -30,7 +36,11 @@ def __repr__(self) -> str:
return f"{self.__class__.__name__}({self.conditions})"

def add_condition(
self, attr: str, value: str | int | None, relation: Type[Base] | None = None
self,
attr: str,
value: str | int | None,
relation: Type[Base] | None = None,
match: Match = Match.EXACT,
):
"""Return a function that returns True if the given model attribute
matches the given value.
Expand Down Expand Up @@ -64,7 +74,10 @@ def condition(obj: Type[Base]) -> bool:

def condition(obj: Type[Base]) -> bool:
model_attr = getattr(obj, attr)
return model_attr == value
if match is Match.EXACT:
return model_attr == value
else:
return value.lower() in model_attr.lower()

self.conditions.append(condition)

Expand Down
2 changes: 2 additions & 0 deletions bcitflex/course.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from werkzeug.datastructures import ImmutableMultiDict

from bcitflex.app_functions import ModelFilter
from bcitflex.app_functions.course_query import Match
from bcitflex.db import DBSession
from bcitflex.model import Course, Meeting, Offering, Subject, Term

Expand All @@ -18,6 +19,7 @@ def filters_from_form(form: ImmutableMultiDict) -> ModelFilter:
filters.add_condition("subject_id", form.get("subject"))
filters.add_condition("campus", form.get("campus"), Offering)
filters.add_condition("code", form.get("code"))
filters.add_condition("name", form.get("name"), None, Match.PARTIAL)
filters.add_condition("is_available", form.get("available") == "True" or None)
return filters

Expand Down
3 changes: 3 additions & 0 deletions bcitflex/templates/courses/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ <h1>{% block title %}Courses{% endblock %}</h1>
<label for="code">Code:</label>
<input type="text" id="code" name="code" placeholder="Enter code">

<label for="name">Name:</label>
<input type="text" id="name" name="name" placeholder="Enter name">

<label for="available">Available:</label>
<input type="checkbox" id="available" name="available" value="true">

Expand Down
32 changes: 30 additions & 2 deletions tests/app_functions/test_course_query.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
"""Tests for the CourseFilter class and course query function."""
import pytest

from bcitflex.app_functions.course_query import ModelFilter, coerce_to_column_type
from bcitflex.app_functions.course_query import (
Match,
ModelFilter,
coerce_to_column_type,
)
from bcitflex.model import Course, Offering, Subject


Expand All @@ -15,10 +19,11 @@ def course_filter():
def courses():
"""Return a list of Course instances."""
return [
Course(code="1234", subject=Subject(subject_id="COMP")),
Course(code="1234", name="Test Course", subject=Subject(subject_id="COMP")),
Course(
code="5678",
subject=Subject(subject_id="COMP"),
name="Second Course",
offerings=[Offering(term_id="202101")],
),
]
Expand Down Expand Up @@ -84,3 +89,26 @@ def test_filter_rel_collection(self, course_filter: ModelFilter, courses):
filtered_courses = course_filter.filter(courses)
assert len(filtered_courses) == 1
assert filtered_courses[0].offerings[0].term_id == "202101"

def test_filter_name_course(self, course_filter: ModelFilter, courses):
"""Test the filter method with a relationship."""
course_filter.add_condition("name", "Test Course")
filtered_courses = course_filter.filter(courses)
assert len(filtered_courses) == 1
assert filtered_courses[0].name == "Test Course"

def test_filter_exact_match(self, course_filter: ModelFilter, courses):
"""Test the filter method with a relationship."""
course_filter.add_condition("name", "cours")
filtered_courses = course_filter.filter(courses)
assert len(filtered_courses) == 0

def test_filter_partial_match(self, course_filter: ModelFilter, courses):
"""Test the filter method with a relationship."""
course_filter.add_condition("name", "cours", None, Match.PARTIAL)
filtered_courses = course_filter.filter(courses)
assert len(filtered_courses) == 2
assert list(map(lambda x: x.name, filtered_courses)) == [
"Test Course",
"Second Course",
]

0 comments on commit 50fbd84

Please sign in to comment.