Heavily customized version of smokesignal - https://whtwnd.com/kayrozen.com/3lpwe4ymowg2t

fix: correct RSVP status values in hydration queries

RSVP counts were showing as 0 on filter page due to mismatched
status values - database stores simple strings but queries expected

kayrozen 20bac033 e7def3f3

+3
src/filtering/hydration.rs
··· 192 192 193 193 let total = going + interested + not_going; 194 194 195 + tracing::debug!("RSVP counts for event {}: going={}, interested={}, not_going={}, total={}", 196 + event_aturi, going, interested, not_going, total); 197 + 195 198 Ok(RsvpCounts { 196 199 going, 197 200 interested,
+59 -7
src/http/handle_filter_events.rs
··· 48 48 use serde_json::Value; 49 49 use tracing::{instrument, warn}; 50 50 51 - use crate::filtering::{EventFilterCriteria, EventSortField, FilteringService, FilterOptions, SortOrder, HydratedEvent}; 51 + use crate::filtering::{EventFilterCriteria, EventSortField, FilteringService, FilterOptions, SortOrder, HydratedEvent, HydrationOptions}; 52 52 use crate::http::context::UserRequestContext; 53 53 use crate::http::errors::{CommonError, WebError}; 54 54 use crate::http::middleware_filter::{FilterCriteriaExtension, FilterQueryParams}; ··· 121 121 pub status: Option<String>, 122 122 /// Formatted address for display (optional) 123 123 pub address_display: Option<String>, 124 + /// Alias for address_display for template compatibility 125 + pub location: Option<String>, 124 126 125 127 // RSVP counts 126 128 /// Number of "going" RSVPs ··· 219 221 220 222 // Determine what data to include based on request type 221 223 let options = if is_htmx && !page_query.full.unwrap_or(false) { 222 - // For HTMX requests, include minimal data for faster responses 223 - FilterOptions::list_view() 224 + // For HTMX requests, include minimal data for faster responses but still include RSVP counts 225 + FilterOptions { 226 + include_facets: false, 227 + include_hydration: true, 228 + hydration_options: HydrationOptions { 229 + include_rsvp_counts: true, 230 + include_creator_handles: true, 231 + include_locations: false, 232 + max_events: Some(50), 233 + }, 234 + } 224 235 } else { 225 236 // For full page loads, include everything 226 - FilterOptions::detail_view() 237 + FilterOptions { 238 + include_facets: true, 239 + include_hydration: true, 240 + hydration_options: HydrationOptions { 241 + include_rsvp_counts: true, 242 + include_creator_handles: true, 243 + include_locations: true, 244 + max_events: None, 245 + }, 246 + } 227 247 }; 228 248 229 249 // Execute the filtering with locale support ··· 935 955 _ => None, // For other location types (Geo, Fsq, Hthree) 936 956 } 937 957 }), 958 + location: event_details.locations.first().and_then(|loc| { 959 + // Alias for address_display for template compatibility 960 + match loc { 961 + crate::atproto::lexicon::community::lexicon::calendar::event::EventLocation::Address(addr) => { 962 + Some(format!("{:?}", addr)) // Convert Address to string representation 963 + }, 964 + crate::atproto::lexicon::community::lexicon::calendar::event::EventLocation::Uri(named_uri) => { 965 + match named_uri { 966 + crate::atproto::lexicon::community::lexicon::calendar::event::NamedUri::Current { name, .. } => { 967 + name.clone() 968 + } 969 + } 970 + }, 971 + _ => None, // For other location types (Geo, Fsq, Hthree) 972 + } 973 + }), 938 974 939 975 count_going: hydrated.rsvp_counts.as_ref().map(|c| c.going as u32).unwrap_or(0), 940 976 count_interested: hydrated.rsvp_counts.as_ref().map(|c| c.interested as u32).unwrap_or(0), ··· 952 988 953 989 // Use EventView data if available for better formatting (overrides the basic data) 954 990 if let Some(ref event_view) = hydrated.event_view { 991 + tracing::debug!("Using EventView data for event {}, RSVP counts: going={}, interested={}, notgoing={}", 992 + event.aturi, event_view.count_going, event_view.count_interested, event_view.count_notgoing); 955 993 template_event.name = event_view.name.clone(); 956 994 template_event.description = event_view.description.as_ref().map(|desc| convert_urls_to_links(desc)); 957 995 template_event.description_short = event_view.description_short.clone(); ··· 963 1001 template_event.mode = event_view.mode.clone(); 964 1002 template_event.status = event_view.status.clone(); 965 1003 template_event.address_display = event_view.address_display.clone(); 966 - template_event.count_going = event_view.count_going; 967 - template_event.count_interested = event_view.count_interested; 968 - template_event.count_not_going = event_view.count_notgoing; // Note: EventView uses "count_notgoing" but template expects "count_not_going" 1004 + template_event.location = event_view.address_display.clone(); // Alias for template compatibility 1005 + 1006 + // Prefer hydrated RSVP counts over EventView counts if available 1007 + if let Some(ref rsvp_counts) = hydrated.rsvp_counts { 1008 + tracing::debug!("Using fresh RSVP counts from hydration instead of EventView for event {}", event.aturi); 1009 + template_event.count_going = rsvp_counts.going as u32; 1010 + template_event.count_interested = rsvp_counts.interested as u32; 1011 + template_event.count_not_going = rsvp_counts.not_going as u32; 1012 + } else { 1013 + tracing::debug!("Using EventView RSVP counts for event {}", event.aturi); 1014 + template_event.count_going = event_view.count_going; 1015 + template_event.count_interested = event_view.count_interested; 1016 + template_event.count_not_going = event_view.count_notgoing; // Note: EventView uses "count_notgoing" but TemplateEvent uses "count_not_going" 1017 + } 1018 + 969 1019 template_event.links = event_view.links.clone(); 970 1020 template_event.site_url = event_view.site_url.clone(); 971 1021 template_event.collection = event_view.collection.clone(); // Override collection from EventView 1022 + } else { 1023 + tracing::debug!("No EventView data available for event {}, using base hydrated data", event.aturi); 972 1024 } 973 1025 974 1026 // Determine user's role/relationship to this event
+6 -6
templates/event_list.fr-ca.incl.html
··· 389 389 390 390 <!-- Event Statistics --> 391 391 <div class="event-stats"> 392 - <div class="stat" title="{{ t('event-count-going', count=event.count_going) }}"> 392 + <div class="stat" title="{{ t('event-count-going', count=event.count_going | default(0)) }}"> 393 393 <i class="fas fa-star"></i> 394 - <span>{{ event.count_going }}</span> 394 + <span>{{ event.count_going | default(0) }}</span> 395 395 </div> 396 - <div class="stat" title="{{ t('event-count-interested', count=event.count_interested) }}"> 396 + <div class="stat" title="{{ t('event-count-interested', count=event.count_interested | default(0)) }}"> 397 397 <i class="fas fa-eye"></i> 398 - <span>{{ event.count_interested }}</span> 398 + <span>{{ event.count_interested | default(0) }}</span> 399 399 </div> 400 - <div class="stat" title="{{ t('event-count-not-going', count=event.count_not_going) }}"> 400 + <div class="stat" title="{{ t('event-count-not-going', count=event.count_not_going | default(0)) }}"> 401 401 <i class="fas fa-ban"></i> 402 - <span>{{ event.count_notgoing }}</span> 402 + <span>{{ event.count_not_going | default(0) }}</span> 403 403 </div> 404 404 </div> 405 405
+10 -18
templates/filter_events_results.fr-ca.incl.html
··· 162 162 </div> 163 163 </div> 164 164 165 - <div class="event-card-footer"> 165 + <!-- Event Statistics --> 166 166 <div class="event-stats"> 167 - {% if event.stats %} 168 - <div class="stat-item"> 169 - <span class="icon"> 170 - <i class="fas fa-eye"></i> 171 - </span> 172 - <span>{{ event.stats.views | default(0) }}</span> 167 + <div class="stat" title="{{ t('event-count-going', count=event.count_going) }}"> 168 + <i class="fas fa-star"></i> 169 + <span>{{ event.count_going }}</span> 173 170 </div> 174 - <div class="stat-item"> 175 - <span class="icon"> 176 - <i class="fas fa-calendar-check"></i> 177 - </span> 178 - <span>{{ event.stats.attendees | default(0) }}</span> 171 + <div class="stat" title="{{ t('event-count-interested', count=event.count_interested) }}"> 172 + <i class="fas fa-eye"></i> 173 + <span>{{ event.count_interested }}</span> 179 174 </div> 180 - <div class="stat-item"> 181 - <span class="icon"> 182 - <i class="fas fa-share"></i> 183 - </span> 184 - <span>{{ event.stats.shares | default(0) }}</span> 175 + <div class="stat" title="{{ t('event-count-not-going', count=event.count_not_going) }}"> 176 + <i class="fas fa-ban"></i> 177 + <span>{{ event.count_not_going }}</span> 185 178 </div> 186 - {% endif %} 187 179 </div> 188 180 189 181 <div class="event-actions">
+2 -2
templates/single_event.fr-ca.incl.html
··· 183 183 <i class="fas fa-eye"></i> 184 184 <span>{{ event.count_interested }}</span> 185 185 </div> 186 - <div class="stat" title="{{ t('event-count-not-going', count=event.count_not_going) }}"> 186 + <div class="stat" title="{{ t('event-count-not-going', count=event.count_not_going | default(0)) }}"> 187 187 <i class="fas fa-ban"></i> 188 - <span>{{ event.count_notgoing }}</span> 188 + <span>{{ event.count_not_going | default(0) }}</span> 189 189 </div> 190 190 </div> 191 191
+1 -1
templates/view_event.en-us.common.html
··· 417 417 <li {% if active_tab=="notgoing" %}class="is-active" {% endif %}> 418 418 <a href="?tab=notgoing&collection={{ fallback_collection if using_fallback_collection else collection }}" 419 419 rel="nofollow"> 420 - {{ t("not-going-count", count=event.count_notgoing | default("0")) }} 420 + {{ t("not-going-count", count=event.count_not_going | default("0")) }} 421 421 </a> 422 422 </li> 423 423 </ul>
+2 -2
templates/view_event.fr-ca.common.html
··· 337 337 </span> 338 338 <span>{{ t("rsvp-status-not-going") }}</span> 339 339 </p> 340 - <p class="title is-4 has-text-warning">{{ event.count_notgoing | default("0") }}</p> 340 + <p class="title is-4 has-text-warning">{{ event.count_not_going | default("0") }}</p> 341 341 </div> 342 342 </div> 343 343 </div> ··· 592 592 <li {% if active_tab=="notgoing" %}class="is-active" {% endif %}> 593 593 <a href="?tab=notgoing&collection={{ fallback_collection if using_fallback_collection else collection }}" 594 594 rel="nofollow"> 595 - {{ t("not-going-count", count=event.count_notgoing | default("0")) }} 595 + {{ t("not-going-count", count=event.count_not_going | default("0")) }} 596 596 </a> 597 597 </li> 598 598 </ul>