diff --git a/agenda/__init__.py b/agenda/__init__.py index 97d4863..61692d5 100644 --- a/agenda/__init__.py +++ b/agenda/__init__.py @@ -23,7 +23,7 @@ from dateutil.relativedelta import FR, relativedelta from agenda import thespacedevs -from . import fx, gwr, markets, sun, waste_schedule +from . import calendar, fx, gwr, markets, sun, waste_schedule from .types import Event warnings.simplefilter(action="ignore", category=FutureWarning) @@ -49,26 +49,8 @@ assert os.path.exists(config_filename) config = configparser.ConfigParser() config.read(config_filename) -access_key = config.get("exchangerate", "access_key") data_dir = config.get("data", "dir") -colors = { - "primary-subtle": "#cfe2ff", - "secondary-subtle": "#e2e3e5", - "success-subtle": "#d1e7dd", - "info-subtle": "#cff4fc", - "warning-subtle": "#fff3cd", - "danger-subtle": "#f8d7da", -} - -event_type_color_map = { - "bank_holiday": "success-subtle", - "conference": "primary-subtle", - "us_holiday": "secondary-subtle", - "birthday": "info-subtle", - "waste_schedule": "danger-subtle", -} - def next_uk_mothers_day(input_date: date) -> date: """Calculate the date of the next UK Mother's Day from the current date.""" @@ -288,7 +270,7 @@ def as_date(d: date | datetime) -> date: return d.date() if isinstance(d, datetime) else d -def get_conferences(input_date: date, filepath: str) -> List[Event]: +def get_conferences(filepath: str) -> List[Event]: """Read conferences from a YAML file and return a list of Event objects.""" with open(filepath, "r") as f: data = yaml.safe_load(f) @@ -299,8 +281,6 @@ def get_conferences(input_date: date, filepath: str) -> List[Event]: end_date = conf["end"] # Skip the conference if it is before the input date. - if as_date(end_date) < input_date: - continue event = Event( name="conference", date=start_date, @@ -448,60 +428,6 @@ def bristol_waste_collection_events(start_date: date) -> list[Event]: return waste_schedule.get_bristol_gov_uk(start_date, data_dir, uprn) -def build_events_for_calendar(events: list[Event]) -> list[dict[str, typing.Any]]: - """Build list of events for FullCalendar.""" - items: list[dict[str, typing.Any]] = [] - - one_day = timedelta(days=1) - - for e in events: - if e.name == "accommodation": - assert e.title and e.end_date - item = { - "allDay": True, - "title": e.display_title, - "start": e.as_date.isoformat(), - "end": (e.end_as_date + one_day).isoformat(), - "url": e.url, - } - items.append(item) - - item = { - "allDay": False, - "title": "checkin: " + e.title, - "start": e.date.isoformat(), - "url": e.url, - } - items.append(item) - item = { - "allDay": False, - "title": "checkout: " + e.title, - "start": e.end_date.isoformat(), - "url": e.url, - } - items.append(item) - - continue - - if e.has_time: - end = e.end_date or e.date + timedelta(hours=1) - else: - end = (e.end_as_date if e.end_date else e.as_date) + one_day - item = { - "allDay": not e.has_time, - "title": e.display_title, - "start": e.date.isoformat(), - "end": end.isoformat(), - } - if e.name in event_type_color_map: - item["color"] = colors[event_type_color_map[e.name]] - item["textColor"] = "black" - if e.url: - item["url"] = e.url - items.append(item) - return items - - def get_data(now: datetime) -> typing.Mapping[str, str | object]: """Get data to display on agenda dashboard.""" rocket_dir = os.path.join(data_dir, "thespacedevs") @@ -554,7 +480,7 @@ def get_data(now: datetime) -> typing.Mapping[str, str | object]: events += get_birthdays(today, os.path.join(my_data, "entities.yaml")) events += get_accommodation(today, os.path.join(my_data, "accommodation.yaml")) events += get_all_travel_events(today) - events += get_conferences(today, os.path.join(my_data, "conferences.yaml")) + events += get_conferences(os.path.join(my_data, "conferences.yaml")) events += waste_collection_events() + bristol_waste_collection_events(today) next_up_series = Event( @@ -568,6 +494,6 @@ def get_data(now: datetime) -> typing.Mapping[str, str | object]: reply["events"] = events - reply["fullcalendar_events"] = build_events_for_calendar(events) + reply["fullcalendar_events"] = calendar.build_events(events) return reply diff --git a/agenda/calendar.py b/agenda/calendar.py new file mode 100644 index 0000000..8cbd58a --- /dev/null +++ b/agenda/calendar.py @@ -0,0 +1,77 @@ +"""Calendar.""" + +import typing +from datetime import timedelta + +from .types import Event + +event_type_color_map = { + "bank_holiday": "success-subtle", + "conference": "primary-subtle", + "us_holiday": "secondary-subtle", + "birthday": "info-subtle", + "waste_schedule": "danger-subtle", +} + +colors = { + "primary-subtle": "#cfe2ff", + "secondary-subtle": "#e2e3e5", + "success-subtle": "#d1e7dd", + "info-subtle": "#cff4fc", + "warning-subtle": "#fff3cd", + "danger-subtle": "#f8d7da", +} + + +def build_events(events: list[Event]) -> list[dict[str, typing.Any]]: + """Build list of events for FullCalendar.""" + items: list[dict[str, typing.Any]] = [] + + one_day = timedelta(days=1) + + for e in events: + if e.name == "accommodation": + assert e.title and e.end_date + item = { + "allDay": True, + "title": e.display_title, + "start": e.as_date.isoformat(), + "end": (e.end_as_date + one_day).isoformat(), + "url": e.url, + } + items.append(item) + + item = { + "allDay": False, + "title": "checkin: " + e.title, + "start": e.date.isoformat(), + "url": e.url, + } + items.append(item) + item = { + "allDay": False, + "title": "checkout: " + e.title, + "start": e.end_date.isoformat(), + "url": e.url, + } + items.append(item) + + continue + + if e.has_time: + end = e.end_date or e.date + timedelta(hours=1) + else: + end = (e.end_as_date if e.end_date else e.as_date) + one_day + item = { + "allDay": not e.has_time, + "title": e.display_title, + "start": e.date.isoformat(), + "end": end.isoformat(), + } + if e.name in event_type_color_map: + item["color"] = colors[event_type_color_map[e.name]] + item["textColor"] = "black" + if e.url: + item["url"] = e.url + items.append(item) + return items