+3
src/filtering/hydration.rs
+3
src/filtering/hydration.rs
+59
-7
src/http/handle_filter_events.rs
+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
+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
+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
+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
+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
+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>