Example #1
0
def on_date_availability_request(data):
    """
    Called whenever the reservation form is first loaded
    Returns a list of dates that are not fully booked or otherwise unavailable
    """
    print("Got an event for date input with data:", data)
    date = datetime.datetime.strptime(data[DATE_KEY], DATE_FORMAT)
    user_role = _current_user_role()
    if user_role == models.UserRole.LIBRARIAN:
        available_dates = db_utils.get_available_dates_for_month(date)
    elif user_role == models.UserRole.PROFESSOR:
        available_dates = db_utils.get_available_dates_after_date(
            date=date,
            date_range=PROFESSOR_DATE_AVAILABILITY_RANGE,
        )
    elif user_role == models.UserRole.STUDENT:
        available_dates = db_utils.get_available_dates_after_date(
            date=date,
            date_range=STUDENT_DATE_AVAILABILITY_RANGE,
        )
    else:
        return
    available_date_timestamps = [
        available_date.timestamp() * 1000.0
        for available_date in available_dates
    ]
    SOCKET.emit(
        DATE_AVAILABILITY_RESPONSE_CHANNEL,
        {ALL_DATES_KEY: available_date_timestamps},
        room=flask.request.sid,
    )
def on_time_availability_request(data):
    """
    Called whenever a user clicks on a date in the reservation form
    Checks to see what timeslots are available and sends them to the client
    """
    assert data is not None
    assert all([
        isinstance(data, dict),
        DATE_KEY in data,
    ])
    assert isinstance(data[DATE_KEY], str)
    print("Got an event for time input with data:", data)
    if _current_user_role() is None:
        return
    date = datetime.datetime.strptime(data[DATE_KEY], DATE_FORMAT)
    available_times = db_utils.get_available_times_for_date(date=date.date())
    # TODO: jlh29, extend this for timeslots that are not 2 hours
    all_times = [{
        TIMESLOT_KEY: f"{hour}:00-{hour+2}:00",
        AVAILABLE_ROOMS_KEY: available_times[hour],
        TIME_AVAILABILITY_KEY: available_times[hour] != 0,
    } for hour in sorted(available_times)]
    SOCKET.emit(
        TIME_AVAILABILITY_RESPONSE_CHANNEL,
        {ALL_TIMES_KEY: all_times},
        room=flask.request.sid,
    )
Example #3
0
def on_new_user_login(data):
    """
    Called whenever a user successfully passes through the Google OAuth login
    Sends the user's name and role back to the client so that the webpage
    is rendered correctly
    """
    print(f"Got an event for new user login")
    auth_user = login_utils.get_user_from_google_token(
        data[USER_LOGIN_TOKEN_KEY])
    if auth_user is None:
        SOCKET.emit(
            FAILED_LOGIN_CHANNEL,
            room=flask.request.sid,
        )
        return
    CONNECTED_USERS[flask.request.sid] = auth_user
    SOCKET.emit(
        SUCCESSFUL_LOGIN_CHANNEL,
        {
            USER_LOGIN_NAME_KEY: auth_user.name,
            USER_LOGIN_ROLE_KEY: auth_user.role.value,
        },
        room=flask.request.sid,
    )
    emit_all_dates(DISABLE_CHANNEL)
Example #4
0
def on_check_in(data):
    """
    Called whenever the librarian checks in a group via their check-in code
    """
    if not _current_user_role() == models.UserRole.LIBRARIAN:
        return
    check_in_code = data[CHECK_IN_CODE_KEY]
    result = db_utils.check_in_with_code(check_in_code)
    SOCKET.emit(
        CHECK_IN_RESPONSE_CHANNEL,
        {CHECK_IN_SUCCESS_KEY: result},
        room=flask.request.sid,
    )
Example #5
0
def on_request_rooms():
    """
    Called whenever the Librarian Overview UI loads the Room Overview section
    Returns a list of all BreakoutRooms
    """
    if not _current_user_role() == models.UserRole.LIBRARIAN:
        return
    rooms = db_utils.get_all_room_objs(True)
    SOCKET.emit(
        ROOMS_RESPONSE_CHANNEL,
        {ROOMS_KEY: rooms},
        room=flask.request.sid,
    )
Example #6
0
def on_request_users():
    """
    Called whenever the Librarian Overview UI loads the User Overview section
    Returns a list of all AuthUsers
    """
    if not _current_user_role() == models.UserRole.LIBRARIAN:
        return
    users = db_utils.get_all_user_objs(True)
    SOCKET.emit(
        USERS_RESPONSE_CHANNEL,
        {USERS_KEY: users},
        room=flask.request.sid,
    )
def emit_all_dates(channel):
    """
    Send all disable dates to the client
    """
    all_unavailable = db_utils.get_disable_date()

    SOCKET.emit(
        channel,
        {
            ALL_DATES_KEY: all_unavailable,
        },
    )
    print("Data sent to client")
Example #8
0
def on_request_appointments(data):
    """
    Called whenever the librarian clicks on a date in the Librarian Overview
    UI
    Returns a list of all Appointments for a given date
    """
    if not _current_user_role() == models.UserRole.LIBRARIAN:
        return
    date = datetime.datetime.strptime(data[DATE_KEY], DATE_FORMAT)
    appointments = db_utils.get_all_appointments_for_date(date, True)
    SOCKET.emit(
        APPOINTMENTS_RESPONSE_CHANNEL,
        {APPOINTMENTS_KEY: appointments},
        room=flask.request.sid,
    )
Example #9
0
def emit_all_dates(channel):
    """
    Send all disable dates to the client 
    """
    all_start_dates, all_end_dates, all_notes = db_utils.get_disable_date()

    all_start_dates = [str(x.date()) for x in all_start_dates]
    all_end_dates = [str(x.date()) for x in all_end_dates]

    date_range = list(list(x) for x in zip(all_start_dates, all_end_dates))

    SOCKET.emit(
        channel, {
            DATE_RANGE: date_range,
            START_DATE: all_start_dates,
            END_DATE: all_end_dates,
            NOTE: all_notes,
        })
    print("Data sent to client")
Example #10
0
def on_reservation_submit(data):
    """
    Called whenever a user submits the reservation form
    Creates a new Appointment (if possible) and returns its details
    """
    mobile_number = data['phoneNumber']
    print(data)
    user_role = _current_user_role()
    date = datetime.datetime.fromtimestamp(data[DATE_KEY] / 1000.0)
    date_difference = (date - datetime.datetime.utcnow()).days
    if user_role is None:
        return
    if (user_role == models.UserRole.STUDENT
            and date_difference > STUDENT_DATE_AVAILABILITY_RANGE):
        return
    if (user_role == models.UserRole.PROFESSOR
            and date_difference > PROFESSOR_DATE_AVAILABILITY_RANGE):
        return
    attendee_ids = db_utils.get_attendee_ids_from_ucids(data[ATTENDEES_KEY])
    # TODO: jlh29, actually allow the user to choose a room
    available_rooms_by_time = db_utils.get_available_room_ids_for_date(
        date.date())
    # TODO: jlh29, fix this messy messy messy code for Sprint 2
    selected_hour = int(data[TIME_KEY].split(":")[0])
    if len(available_rooms_by_time[selected_hour]) == 0:
        return
    room_id = available_rooms_by_time[selected_hour][0]
    # TODO: jlh29, fix this time/date mess
    start_time_string, end_time_string = data[TIME_KEY].split("-")
    start_time = datetime.datetime(
        date.year,
        date.month,
        date.day,
        int(start_time_string.split(":")[0]),
        0,
        0,
    )
    end_time = datetime.datetime(
        date.year,
        date.month,
        date.day,
        int(end_time_string.split(":")[0]),
        0,
        0,
    )
    organizer_id = CONNECTED_USERS[flask.request.sid].id
    (
        reservation_success,
        reservation_code,
        reservation_dict,
    ) = db_utils.create_reservation(
        room_id=room_id,
        start_time=start_time,
        end_time=end_time,
        organizer_id=organizer_id,
        attendee_ids=attendee_ids,
    )

    ucid = CONNECTED_USERS[flask.request.sid].ucid
    send_confirmation(mobile_number, ucid, date.date(), data['time'],
                      data['attendees'], reservation_code)

    SOCKET.emit(
        RESERVATION_RESPONSE_CHANNEL,
        {
            RESERVATION_SUCCESS_KEY: reservation_success,
            CHECK_IN_CODE_KEY: reservation_code,
            RESERVATION_KEY: reservation_dict,
        },
        room=flask.request.sid,
    )
Example #11
0
    Called whenever the librarian makes an edit to a room in the Librarian Overview
    """
    if not _current_user_role() == models.UserRole.LIBRARIAN:
        return
    assert isinstance(data.get("id", None), int) and isinstance(
        data.get("role", None), str)

    try:
        role = models.UserRole(data["role"].lower())
    except ValueError:
        print("Invalid value of 'role' passed to server when updating a user")

    db_utils.update_user_role(
        user_id=data["id"],
        role=role,
    )

    on_request_users()


if __name__ == "__main__":
    db_instance.init_db(APP)
    socket_utils.init_socket(APP)
    scheduled_tasks.start_tasks()
    SOCKET.run(
        APP,
        host=os.getenv("IP", "0.0.0.0"),
        port=int(os.getenv("PORT", "8080")),
        debug=True,
    )
def send_refresh_to_client(sid):
    assert isinstance(sid, str)
    assert sid in CONNECTED_USERS
    SOCKET.emit(REFRESH_CHANNEL, room=sid)
def on_reservation_submit(data):
    """
    Called whenever a user submits the reservation form
    Creates a new Appointment (if possible) and returns its details
    """
    print("running")
    assert data is not None
    assert all([
        isinstance(data, dict),
        DATE_KEY in data,
        TIME_KEY in data,
        PHONE_NUMBER_KEY in data,
        ATTENDEES_KEY in data,
    ])
    assert all([
        isinstance(data[DATE_KEY], (float, int)),
        isinstance(data[TIME_KEY], str),
        isinstance(data[PHONE_NUMBER_KEY], (str, int)),
        data[ATTENDEES_KEY] is None
        or (isinstance(data[ATTENDEES_KEY], list) and all(
            [isinstance(attendee, str) for attendee in data[ATTENDEES_KEY]])),
    ])
    user_role = _current_user_role()
    date = datetime.datetime.fromtimestamp(data[DATE_KEY] / 1000.0)
    date_difference = (date - datetime.datetime.utcnow()).days
    if user_role is None:
        return
    if (user_role == models.UserRole.STUDENT
            and date_difference > STUDENT_DATE_AVAILABILITY_RANGE):
        return
    if (user_role == models.UserRole.PROFESSOR
            and date_difference > PROFESSOR_DATE_AVAILABILITY_RANGE):
        return
    attendee_ids = db_utils.get_attendee_ids_from_ucids(data[ATTENDEES_KEY])
    # TODO: jlh29, actually allow the user to choose a room
    available_rooms_by_time = db_utils.get_available_room_ids_for_date(
        date.date())
    # TODO: jlh29, fix this messy messy messy code for Sprint 2
    selected_hour = int(data[TIME_KEY].split(":")[0])
    if len(available_rooms_by_time[selected_hour]) == 0:
        return
    room_id = available_rooms_by_time[selected_hour][0]
    # TODO: jlh29, fix this time/date mess
    start_time_string, end_time_string = data[TIME_KEY].split("-")
    start_time = datetime.datetime(
        date.year,
        date.month,
        date.day,
        int(start_time_string.split(":")[0]),
        0,
        0,
        tzinfo=EST_TZ_OFFSET,
    )
    end_time = datetime.datetime(
        date.year,
        date.month,
        date.day,
        int(end_time_string.split(":")[0]),
        0,
        0,
        tzinfo=EST_TZ_OFFSET,
    )
    organizer_id = CONNECTED_USERS[flask.request.sid].id
    (
        reservation_success,
        reservation_code,
        reservation_dict,
    ) = db_utils.create_reservation(
        room_id=room_id,
        start_time=start_time,
        end_time=end_time,
        organizer_id=organizer_id,
        attendee_ids=attendee_ids,
    )

    ucid = CONNECTED_USERS[flask.request.sid].ucid
    if reservation_success:
        send_confirmation(
            number=data[PHONE_NUMBER_KEY],
            ucid=ucid,
            date=date.date(),
            time=data[TIME_KEY],
            attendees=data[ATTENDEES_KEY],
            confirmation=reservation_code,
        )

    SOCKET.emit(
        RESERVATION_RESPONSE_CHANNEL,
        {
            RESERVATION_SUCCESS_KEY: reservation_success,
            CHECK_IN_CODE_KEY: reservation_code,
            RESERVATION_KEY: reservation_dict,
        },
        room=flask.request.sid,
    )