diff --git a/agenda/add_new_conference.py b/agenda/add_new_conference.py index e74455c..71c12ce 100644 --- a/agenda/add_new_conference.py +++ b/agenda/add_new_conference.py @@ -16,7 +16,7 @@ import pycountry import requests import yaml -from agenda.conference import ConferenceSeries, conference_date_fields, load_series +from agenda.conference import conference_date_fields USER_AGENT = "add-new-conference/0.1" COORDINATE_PATTERNS = ( @@ -36,139 +36,58 @@ def read_api_key() -> str: return parser["openai"]["api_key"] -def conference_yaml_format_description() -> str: - """Return the conference YAML format description for LLM prompts.""" - return """ -Use this YAML format for one conference entry. - -Required fields: -- `name`: event name. -- `topic`: topic/category. -- `location`: city or location label. Use `TBC` if the page confirms a future - event but not a city. -- Date information in nested `dates`. - -Preferred date shape: -- `dates.status`: one of `exact`, `tentative`, or `approximate`. -- For `exact`: use when the page confirms specific dates/times. Include - `dates.start` and `dates.end` as YAML dates or timezone-aware datetimes. -- For `tentative`: use when specific dates are guessed or explicitly - unconfirmed. Include `dates.start`, `dates.end`, and preferably `dates.label` - and `dates.basis`. -- For `approximate`: use when only a broad date phrase is known. Include - `dates.label`, `dates.earliest`, and `dates.latest`. Examples: `March 2027` - should become earliest `2027-03-01`, latest `2027-03-31`; `mid-April 2027` - should become a sensible bounded range such as `2027-04-11` to `2027-04-20`. - -Important date rule: -- If the source page contains exact dates, output `dates.status: exact` even if - the existing agenda entry or conference announcement previously had only - approximate dates. -- Always include an end date for `exact` and `tentative`. For a single-day - event, `dates.end` can be the same as `dates.start`. -- Do not output legacy top-level `start`, `end`, or `date_status`. - -Common optional fields: -- `series`: a key from the known conference series list, when this event belongs - to a listed series. -- `country`: valid ISO 3166-1 alpha-2 country code in lowercase, for example - `ca`, `gb`, `us`. Do not output country names. -- `venue`, `address`, `latitude`, `longitude`, `url`, `cfp_url`, `cfp_end`, - `hashtag`, `description`. -- `free`, `price`, `currency`, `hackathon`, `online`, `attendees`. -- Do not include `going`, `registered`, `accommodation_booked`, - `transport_booked`, or `trip` unless the source explicitly says they apply to - my attendance. -""" - - -def yaml_example_text() -> str: - """Return examples of the conference YAML format.""" - return """ +def build_prompt( + url: str, + source_text: str, + detected_coordinates: tuple[float, float] | None, +) -> str: + """Build prompt with embedded YAML examples.""" + examples = """ - name: Geomob London - series: geomob-london topic: Maps location: London country: gb - dates: - status: exact - start: 2026-01-28 18:00:00+00:00 - end: 2026-01-28 22:00:00+00:00 + start: 2026-01-28 18:00:00+00:00 + end: 2026-01-28 23:00:00+00:00 url: https://thegeomob.com/post/jan-28th-2026-geomoblon-details venue: Geovation Hub address: Sutton Yard, 65 Goswell Rd, London EC1V 7EN latitude: 51.5242464 longitude: -0.0997024 free: true + going: true hashtag: '#geomobLON' - name: DebConf 25 - series: debconf topic: Debian - location: Plouzane + location: Plouzané (Breast) country: fr - dates: - status: exact - start: 2025-07-07 - end: 2025-07-20 + start: 2025-07-07 + end: 2025-07-20 url: https://wiki.debian.org/DebConf/25 + going: true cfp_url: https://debconf25.debconf.org/talks/new/ - venue: Ecole nationale superieure Mines-Telecom Atlantique Bretagne Pays de la Loire + venue: École nationale supérieure Mines-Télécom Atlantique Bretagne Pays de la Loire campus de Brest latitude: 48.35934 longitude: -4.569889 - name: Wikimedia Hackathon - series: wikimedia-hackathon topic: Wikimedia - location: Albania - country: al - dates: - status: approximate - label: mid-April 2027 - earliest: 2027-04-11 - latest: 2027-04-20 - url: https://www.mediawiki.org/wiki/Wikimedia_Hackathon_2027 + location: Istanbul + country: tr + start: 2025-05-02 + end: 2025-05-04 + venue: Renaissance Polat Istanbul Hotel + address: Yeşilyurt, Sahil Yolu Cd. No:2, 34149 Bakırköy/İstanbul + latitude: 40.959946 + longitude: 28.838763 + url: https://www.mediawiki.org/wiki/Wikimedia_Hackathon_2025 + going: true + free: true hackathon: true - -- name: PyCascades - series: pycascades - topic: Python - location: Seattle, Washington - country: us - dates: - status: approximate - label: March 2027 - earliest: 2027-03-01 - latest: 2027-03-31 + registered: true """ - - -def series_prompt_text(series: dict[str, ConferenceSeries]) -> str: - """Return compact known series text for the LLM prompt.""" - if not series: - return "No known conference series loaded." - - lines = ["Known conference series IDs:"] - for series_id, item in sorted(series.items()): - details = [item["name"]] - if topic := item.get("topic"): - details.append(f"topic: {topic}") - if location := item.get("usual_location"): - details.append(f"usual location: {location}") - if country := item.get("country"): - details.append(f"country: {country}") - lines.append(f"- {series_id}: " + "; ".join(details)) - return "\n".join(lines) - - -def build_prompt( - url: str, - source_text: str, - detected_coordinates: tuple[float, float] | None, - series: dict[str, ConferenceSeries] | None = None, -) -> str: - """Build prompt with embedded YAML format details and examples.""" coordinate_note = "" if detected_coordinates is not None: coordinate_note = ( @@ -180,26 +99,28 @@ def build_prompt( prompt = f""" I keep a record of interesting conferences in a YAML file. -Format rules: - -{conference_yaml_format_description()} - -{series_prompt_text(series or {})} - Here are some examples of the format I use: -{yaml_example_text()} +{examples} Now here is a new conference of interest: Conference URL: {url} -Return the YAML representation for this conference following the same style and -keys as the examples. Only include keys if the information is available. Do not -invent details. +Return the YAML representation for this conference following the +same style and keys as the examples. Only include keys if the +information is available. Do not invent details. -Important: if this is a Geomob event, use a `dates.end` datetime of 22:00 local -time on the event date unless the page explicitly provides a different end time. +Important: the `country` field must always be a valid ISO 3166-1 alpha-2 +country code (two lowercase letters, e.g. `ca` for Canada, `gb` for United Kingdom). +Do not output full country names. + +Important: always include an `end` field. If the event is a single-day event, +the `end` can be the same date as `start`, or a same-day datetime if the page +provides an end time. + +Important: if this is a Geomob event, use an `end` datetime of 22:00 local time +on the event date unless the page explicitly provides a different end time. {coordinate_note} Wrap your answer in a JSON object with a single key "yaml". @@ -340,26 +261,9 @@ def parse_date(date_str: str) -> datetime: return dt -def data_dir_from_conferences_path(yaml_path: str) -> str: - """Return personal-data directory from a conferences.yaml path.""" - return os.path.dirname(os.path.abspath(yaml_path)) - - def url_has_year_component(url: str) -> bool: - """Return True if the URL contains a year or edition path component.""" - parsed = urlparse(url) - components = [part for part in parsed.path.split("/") if part] - if parsed.netloc: - components.extend(part for part in parsed.netloc.split(".") if part) - - for component in components: - if re.fullmatch(r"20\d{2}", component): - return True - if re.search(r"(?:^|[-_/])20\d{2}(?:$|[-_/])", component): - return True - if re.fullmatch(r"\d{1,2}x", component, flags=re.IGNORECASE): - return True - return False + """Return True if the URL contains any digit.""" + return any(ch.isdigit() for ch in url) def insert_sorted( @@ -369,13 +273,6 @@ def insert_sorted( new_url = new_conf.get("url") new_start = conference_sort_datetime(new_conf) new_year = new_start.year - update_idx = find_inexact_existing_conference(conferences, new_conf) - if update_idx is not None: - existing = conferences.pop(update_idx) - merged = dict(existing) - merged.update(new_conf) - print(f"Updating inexact conference entry: {existing.get('name')}") - return insert_sorted(conferences, merged) if new_url: for conf in conferences: @@ -402,56 +299,6 @@ def insert_sorted( return conferences -def date_ranges_overlap( - first: dict[str, typing.Any], second: dict[str, typing.Any] -) -> bool: - """Return True if two conference date ranges overlap.""" - first_fields = conference_date_fields(first) - second_fields = conference_date_fields(second) - return typing.cast(date, first_fields["start_date"]) <= typing.cast( - date, second_fields["end_date"] - ) and typing.cast(date, second_fields["start_date"]) <= typing.cast( - date, first_fields["end_date"] - ) - - -def same_conference_identity( - existing: dict[str, typing.Any], new_conf: dict[str, typing.Any] -) -> bool: - """Return True if two entries appear to represent the same conference.""" - existing_url = existing.get("url") - new_url = new_conf.get("url") - if existing_url and new_url and existing_url == new_url: - return True - - existing_series = existing.get("series") - new_series = new_conf.get("series") - if existing_series and new_series and existing_series == new_series: - return date_ranges_overlap(existing, new_conf) - - return str(existing.get("name", "")).casefold() == str( - new_conf.get("name", "") - ).casefold() and date_ranges_overlap(existing, new_conf) - - -def find_inexact_existing_conference( - conferences: list[dict[str, typing.Any]], new_conf: dict[str, typing.Any] -) -> int | None: - """Return index of an inexact existing entry that exact new data can update.""" - new_fields = conference_date_fields(new_conf) - if new_fields["date_status"] != "exact": - return None - - for idx, existing in enumerate(conferences): - existing_fields = conference_date_fields(existing) - if existing_fields["date_status"] == "exact": - continue - if same_conference_identity(existing, new_conf): - return idx - - return None - - def conference_sort_datetime(conf: dict[str, typing.Any]) -> datetime: """Return conference sort date as a datetime.""" sort_date = conference_date_fields(conf)["sort_date"] @@ -502,42 +349,6 @@ def parse_yaml_datetime(value: typing.Any) -> datetime | None: return None -def parse_yaml_date_value(value: typing.Any) -> date | datetime | None: - """Convert YAML date/datetime strings to date-like values.""" - if isinstance(value, datetime): - return value - - if isinstance(value, date): - return value - - if not isinstance(value, str): - return None - - try: - if " " in value or "T" in value: - return datetime.fromisoformat(value) - return date.fromisoformat(value) - except ValueError: - return None - - -def normalize_date_values(conf: dict[str, typing.Any]) -> None: - """Normalize quoted ISO date/datetime values produced by the LLM.""" - dates = conf.get("dates") - if isinstance(dates, dict): - for field in ("start", "end", "earliest", "latest"): - if field in dates: - parsed = parse_yaml_date_value(dates[field]) - if parsed is not None: - dates[field] = parsed - - for field in ("start", "end"): - if field in conf: - parsed = parse_yaml_date_value(conf[field]) - if parsed is not None: - conf[field] = parsed - - def same_type_as_start( start_value: typing.Any, new_dt: datetime, @@ -563,46 +374,6 @@ def same_type_as_start( return new_dt -def normalize_dates_field(conf: dict[str, typing.Any]) -> None: - """Move legacy top-level date fields into the nested dates mapping.""" - normalize_date_values(conf) - raw_dates = conf.get("dates") - dates = raw_dates if isinstance(raw_dates, dict) else None - - if dates is None and ("start" in conf or "end" in conf): - start = conf.pop("start", None) - end = conf.pop("end", start) - status = str(conf.pop("date_status", "exact")) - conf["dates"] = {"status": status, "start": start, "end": end} - return - - if dates is not None: - if "start" in conf and "start" not in dates: - dates["start"] = conf["start"] - if "end" in conf and "end" not in dates: - dates["end"] = conf["end"] - if "date_status" in conf and "status" not in dates: - dates["status"] = conf["date_status"] - - conf.pop("start", None) - conf.pop("end", None) - conf.pop("date_status", None) - normalize_date_values(conf) - - -def validate_generated_conference(conf: dict[str, typing.Any]) -> None: - """Validate generated conference YAML before inserting it.""" - try: - conference_date_fields(conf) - except ValueError as exc: - generated_yaml = yaml.dump(conf, sort_keys=False, allow_unicode=True).strip() - raise ValueError( - "Generated conference YAML is missing valid date information. " - "Expected nested `dates:` with exact/tentative start/end or " - f"approximate earliest/latest.\n\nGenerated YAML:\n{generated_yaml}" - ) from exc - - def maybe_extract_explicit_end_time(source_text: str) -> int | None: """Extract an explicit 12-hour clock end time for Geomob-style pages.""" lowered = source_text.lower() @@ -664,14 +435,6 @@ def load_conferences(yaml_path: str) -> list[dict[str, typing.Any]]: return typing.cast(list[dict[str, typing.Any]], loaded) -def load_conference_series_for_path(yaml_path: str) -> dict[str, ConferenceSeries]: - """Load conference series next to the target conferences YAML file.""" - return typing.cast( - dict[str, ConferenceSeries], - load_series(data_dir_from_conferences_path(yaml_path)), - ) - - def dump_conferences(yaml_path: str, conferences: list[dict[str, typing.Any]]) -> None: """Write conference YAML.""" with open(yaml_path, "w") as file: @@ -687,9 +450,6 @@ def add_new_conference(url: str, yaml_path: str) -> bool: if url_has_year_component(url): for conf in conferences: if conf.get("url") == url: - fields = conference_date_fields(conf) - if fields["date_status"] != "exact": - continue print( "⚠️ Conference already exists in YAML " + f"(url={url}), skipping before API call." @@ -699,8 +459,7 @@ def add_new_conference(url: str, yaml_path: str) -> bool: soup = fetch_webpage(url) source_text = webpage_to_text(soup) detected_coordinates = detect_page_coordinates(soup) - series = load_conference_series_for_path(yaml_path) - prompt = build_prompt(url, source_text, detected_coordinates, series) + prompt = build_prompt(url, source_text, detected_coordinates) new_yaml_text = get_from_open_ai(prompt)["yaml"] new_conf = yaml.safe_load(new_yaml_text) @@ -709,10 +468,7 @@ def add_new_conference(url: str, yaml_path: str) -> bool: assert isinstance(new_conf, dict) validate_country(new_conf) - normalize_dates_field(new_conf) normalise_end_field(new_conf, source_text) - normalize_dates_field(new_conf) - validate_generated_conference(new_conf) if detected_coordinates is not None: new_conf["latitude"] = detected_coordinates[0] diff --git a/agenda/conference.py b/agenda/conference.py index 89f43fe..f9e15b4 100644 --- a/agenda/conference.py +++ b/agenda/conference.py @@ -2,7 +2,6 @@ import dataclasses import decimal -import os import typing from datetime import date, datetime @@ -17,18 +16,6 @@ DATE_STATUSES = {"exact", "approximate", "tentative"} DATED_STATUSES = {"exact", "tentative"} -class ConferenceSeries(typing.TypedDict, total=False): - """Conference series metadata.""" - - name: str - topic: str - url: str - notes: str - cadence: str - usual_location: str - country: str - - @dataclasses.dataclass class Conference: """Conference.""" @@ -36,7 +23,6 @@ class Conference: name: str topic: str location: str - series: str | None = None start: date | datetime | None = None end: date | datetime | None = None trip: date | None = None @@ -180,20 +166,6 @@ def validate_conference_date_fields(item: StrDict) -> StrDict: return fields -def load_series(data_dir: str) -> dict[str, ConferenceSeries]: - """Load conference series metadata.""" - filepath = os.path.join(data_dir, "conference_series.yaml") - if not os.path.exists(filepath): - return {} - - loaded = yaml.safe_load(open(filepath, "r")) - if loaded is None: - return {} - if not isinstance(loaded, dict): - raise ValueError("conference_series.yaml must be a mapping") - return typing.cast(dict[str, ConferenceSeries], loaded) - - def get_list(filepath: str) -> list[Event]: """Read conferences from a YAML file and return a list of Event objects.""" events: list[Event] = [] diff --git a/agenda/trip.py b/agenda/trip.py index 2561094..6ab69ff 100644 --- a/agenda/trip.py +++ b/agenda/trip.py @@ -11,7 +11,7 @@ import flask import pycountry import yaml -from agenda import conference, ical, travel, trip_schengen +from agenda import ical, travel, trip_schengen from agenda.types import StrDict, Trip, TripElement from agenda.utils import as_date, as_datetime, depart_datetime @@ -333,18 +333,12 @@ def build_trip_list( yaml_trip_list = travel.parse_yaml("trips", data_dir) flight_bookings = load_flight_bookings(data_dir) - conferences = travel.parse_yaml("conferences", data_dir) - for conf in conferences: - date_fields = conference.conference_date_fields(conf) - if "start" in date_fields: - conf["start"] = date_fields["start"] - conf["end"] = date_fields["end"] data = { "flight_bookings": flight_bookings, "travel": collect_travel_items(flight_bookings, data_dir, route_distances), "accommodation": travel.parse_yaml("accommodation", data_dir), - "conferences": conferences, + "conferences": travel.parse_yaml("conferences", data_dir), "events": travel.parse_yaml("events", data_dir), } @@ -473,10 +467,10 @@ def conference_free_days(trip: Trip) -> dict[str, tuple[int, int]]: return {} def conf_attend_start(c: StrDict) -> date: - return typing.cast(date, as_date(c.get("attend_start") or c["start"])) + return as_date(c.get("attend_start") or c["start"]) def conf_attend_end(c: StrDict) -> date: - return typing.cast(date, as_date(c.get("attend_end") or c["end"])) + return as_date(c.get("attend_end") or c["end"]) sorted_confs = sorted(trip.conferences, key=conf_attend_start) result: dict[str, tuple[int, int]] = {} @@ -870,7 +864,7 @@ def _trip_element_label(element: TripElement) -> str: return start_loc if isinstance(end_loc, str): return end_loc - return typing.cast(str, element.title) + return element.title def _trip_element_summary(trip: Trip, element: TripElement) -> str: diff --git a/docs/personal-data-yaml.md b/docs/personal-data-yaml.md index 08c391e..a538fff 100644 --- a/docs/personal-data-yaml.md +++ b/docs/personal-data-yaml.md @@ -283,7 +283,6 @@ Legacy fields: Common optional fields: -- Series: `series`, a key from `conference_series.yaml`. - Trip/location: `trip`, `country`, `venue`, `address`, `latitude`, `longitude`. - Attendance: `going`, `registered`, `speaking`, `online`, `accommodation_booked`, `transport_booked`. - Partial attendance: `attend_start`, `attend_end`. These may be dates or timezone-aware datetimes and are used on trip pages instead of official dates. @@ -295,7 +294,6 @@ Exact example: ```yaml - name: FOSDEM - series: fosdem topic: FOSDEM location: Brussels country: be @@ -321,7 +319,6 @@ Tentative example: ```yaml - name: FOSDEM - series: fosdem topic: FOSDEM location: Brussels country: be @@ -338,7 +335,6 @@ Approximate examples: ```yaml - name: Wikimedia Hackathon 2027 - series: wikimedia-hackathon topic: Wikimedia location: Albania country: al @@ -350,7 +346,6 @@ Approximate examples: hackathon: true - name: PyCascades 2027 - series: pycascades topic: Python location: TBC dates: @@ -360,46 +355,6 @@ Approximate examples: latest: 2027-03-31 ``` -## `conference_series.yaml` - -Top-level shape: mapping from stable series ID to series metadata. - -Used by: conference list pages, conference series index/detail pages, and validation of `conferences.yaml` `series` references. - -Required fields for each series: - -- `name`: display name for the series. - -Common optional fields: - -- `topic`: default topic/category. -- `cadence`: for example `annual` or `recurring`. -- `usual_location`: common city/place when the event usually stays in one place. -- `country`: common lowercase country code when stable. -- `url`: series homepage. -- `notes`: free-text generation or scheduling notes. - -Example: - -```yaml -fosdem: - name: FOSDEM - topic: FOSDEM - cadence: annual - usual_location: Brussels - country: be - url: https://fosdem.org/ - notes: Usually the weekend where Sunday is the first Sunday in February. - -geomob-london: - name: Geomob London - topic: Maps - cadence: recurring - usual_location: London - country: gb - url: https://thegeomob.com/ -``` - ## `entities.yaml` Top-level shape: list of people/entities. diff --git a/templates/conference_list.html b/templates/conference_list.html index e20b154..6529b22 100644 --- a/templates/conference_list.html +++ b/templates/conference_list.html @@ -134,7 +134,7 @@ tr.conf-hl > td { {% if item_list %} {% set count = item_list | length %} - {{ heading }} {{ count }} conference{{ "" if count == 1 else "s" }} + {{ heading }} {{ count }} conference{{ "" if count == 1 else "s" }} {% set ns = namespace(prev_month="") %} {% for item in item_list %} @@ -142,7 +142,7 @@ tr.conf-hl > td { {% if month_label != ns.prev_month %} {% set ns.prev_month = month_label %} - {{ month_label }} + {{ month_label }} {% endif %} @@ -176,13 +176,6 @@ tr.conf-hl > td { {% endif %} {{ item.topic }} - - {% if item.series and item.series_detail %} - {{ item.series_detail.name }} - {% elif item.series %} - {{ item.series }} - {% endif %} - {% set country = get_country(item.country) if item.country else None %} {% if country %}{{ country.flag }} {{ item.location }} @@ -220,7 +213,6 @@ tr.conf-hl > td { - @@ -229,7 +221,6 @@ tr.conf-hl > td { Dates Conference Topic - Series Location CFP ends Price diff --git a/templates/conference_series.html b/templates/conference_series.html deleted file mode 100644 index 10bfdb7..0000000 --- a/templates/conference_series.html +++ /dev/null @@ -1,85 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{{ series.name }} - Edward Betts{% endblock %} - -{% block content %} -
-

{{ series.name }}

- -
- {% if series.topic %} -
Topic
-
{{ series.topic }}
- {% endif %} - {% if series.usual_location or series.country %} -
Usual location
-
- {% set country = get_country(series.country) if series.country else None %} - {% if country %}{{ country.flag }} {% endif %}{{ series.usual_location or "" }} -
- {% endif %} - {% if series.cadence %} -
Cadence
-
{{ series.cadence }}
- {% endif %} - {% if series.url %} -
Website
-
{{ series.url }}
- {% endif %} - {% if series.notes %} -
Notes
-
{{ series.notes }}
- {% endif %} -
- -

Editions

- - - - - - - - - - - {% for item in conferences %} - - - - - - - {% endfor %} - -
DatesConferenceLocationAttendance
- {{ item.display_date }} - {% if item.date_status == "tentative" %} - tentative - {% elif item.date_status == "approximate" %} - approximate - {% endif %} - - {% if item.url %}{{ item.name }} - {% else %}{{ item.name }}{% endif %} - - {% set country = get_country(item.country) if item.country else None %} - {% if country %}{{ country.flag }} {% endif %}{{ item.location }} - - {% if item.going %} - going - {% endif %} - {% if item.registered %} - registered - {% endif %} - {% if item.linked_trip %} - {% set trip = item.linked_trip %} - - trip{% if trip.title != item.name %}: {{ trip.title }}{% endif %} - - {% endif %} -
-
-{% endblock %} diff --git a/templates/conference_series_list.html b/templates/conference_series_list.html deleted file mode 100644 index f9ccc5f..0000000 --- a/templates/conference_series_list.html +++ /dev/null @@ -1,47 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Conference Series - Edward Betts{% endblock %} - -{% block content %} -
-

Conference Series

- - - - - - - - - - - - - {% for item in series_list %} - - - - - - - - {% endfor %} - -
SeriesTopicUsual locationConferencesNext
- {{ item.name }} - {% if item.attended %} - attended - {% endif %} - {% if item.url %} - - {% endif %} - {{ item.topic or "" }} - {% set country = get_country(item.country) if item.country else None %} - {% if country %}{{ country.flag }} {% endif %}{{ item.usual_location or "" }} - {{ item.count }} - {% if item.next_conf %} - {{ item.next_conf.display_date }} · {{ item.next_conf.name }} - {% endif %} -
-
-{% endblock %} diff --git a/templates/navbar.html b/templates/navbar.html index 373c053..fe5b98a 100644 --- a/templates/navbar.html +++ b/templates/navbar.html @@ -28,7 +28,6 @@ {% set conference_pages = [ {"endpoint": "conference_list", "label": "Conferences" }, {"endpoint": "past_conference_list", "label": "Past conferences" }, - {"endpoint": "conference_series_list", "label": "Conference series" }, ] %} @@ -64,7 +63,7 @@ - {% set conference_active = request.endpoint in ['conference_list', 'past_conference_list', 'conference_series_list', 'conference_series_page'] %} + {% set conference_active = request.endpoint in ['conference_list', 'past_conference_list'] %}