-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/kak/show tours#1109 #1144
Feature/kak/show tours#1109 #1144
Conversation
Add unimplemented tab for tours, with a divider before it.
Use polling to watch files from within vagrant VM. Fixes azavea#1036.
Not yet fully implemented.
Show tour as accessible if all its destinations are accessbile.
Preserve existing event destinations on change to complex related object.
Not yet used.
Limit destinations list on event details page to top four. Add JS button to show all (cannot toggle off again).
Test destination search endpoint results for places, events, and tours.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've explored this some and gotten partway through the code. It looks good. I like the code sharing between tours and events--seems clear and efficient.
Per the comment below, the change to Event.destinations
seemed wrong to me, but what I was going to suggest--making it a M2M to Destination
with through=EventDestination
--isn't actually very useful since it's apparently not possible to sort that type of relation based on properties of the through model.
Also, seeing that made me realize that the same structure was already in place on Tour
, which I didn't catch when I reviewed #1133. So I think the same argument applies there.
I'm going to pause on further review for now because I'm not sure how best to proceed and how extensive the code changes would be.
{% if not event.single_day %} | ||
<!-- only show dates for multi-day events --> | ||
<div class="info-event-date"> | ||
{{ event_dest.start_date|date:"D M j" }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what you mean by "the time range is backwards." If the end date/time precedes the start date/time, the admin interface will prevent saving the event destination with an error. What are the full start and end dates and times for this event destination? (If the end date is a different year, it would present this way in the interface.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That event did span the new year, but for a realistic example, take an event running from the evening of one day to the morning a few days later (like a music festival might). It looks like this in the admin:
And comes out like this in the front-end:
Showing only the start date for multi-day events makes it look like it's a one-day event that runs backwards in time. I think it should either show the range for both or not show the time range. Though the former, or some variation, seems better, since otherwise there's no indication that it's multi-day.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
python/cac_tripplanner/destinations/templatetags/destination_extras.py
Outdated
Show resolved
Hide resolved
@@ -194,13 +222,27 @@ class Meta: | |||
start_date = models.DateTimeField() | |||
end_date = models.DateTimeField() | |||
|
|||
destinations = models.ManyToManyField('Destination', blank=True) | |||
destinations = models.ManyToManyField('EventDestination', blank=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be
destinations = models.ManyToManyField(Destination, through=EventDestination, blank=True)
The EventDestination
model adds properties to the Event
<->Destination
relation, but that's still the relation we care about--i.e. event.destinations.first()
should return a Destination
, not an EventDestination
.
And there's already an event.event_destinations
related manager created by the ForeignKey
declaration on EventDestination
.
Though upon further investigation, event.destinations.all()
is apparently ordered by the ordering
of the target model, not the connecting model. Which probably makes sense for some purposes, but it seems like a bug here.
I think that might mean this destinations
property should just be removed. We don't need a M2M relation of Event
to EventDestination
, and having an Event.destinations
related manager that refuses to sort properly just seems like a recipe for error.
Remove unused field from Events and Tours (destinations are provided by back relationships.)
I've removed the unused |
Shorten query.
This should be ready for another look. I've addressed everything but the date range templating; it's not clear to me what's going on there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The handling of EventDestination
and TourDestination
looks good now. Still a bummer that we can't set them as through tables and have the ordering just work, but so it goes. This setup is still consistent and easy to follow.
A couple optimization comments below, but it all looks good and seems to be working well. The one thing I think needs to change somehow is the display of multi-day destinations within multi-day events, as discussed above.
def first_destination(self): | ||
if self.tour_destinations.count() > 0: | ||
return self.tour_destinations.order_by('order').first().destination | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like the one on Event
, this could avoid the count()
query:
@property
def first_destination(self):
try:
return self.tour_destinations.first().destination
except AttributeError:
return None
for td in self.tour_destinations.all(): | ||
if not td.destination.accessible: | ||
return False | ||
return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be written to use exists()
? I.e.
return not self.tour_destinations.filter(destination__accessible=False).exists()
The double negative is a little odd, but it seems like it would produce the same answer without having to load any destination instances into memory.
If that works for this, it should also work for watershed_alliance
below.
Refactor computed tour properties as queries on their destinations.
Okay, this should be ready for another look. |
</a> | ||
{% if event_dest.start_date and event_dest.end_date %} | ||
{% if event_dest.single_day %} | ||
<!-- only show dates for multi-day events --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a number of possible combinations of dates and times:
- Single-day event (for which the destinations obviously should be single-day as well)
- Multi-day destination on a multi-day event
- Single-day destination on a multi-day event
Here's an example of "everything on one day":
Nothing there is wrong or confusing, but the dates on the destinations are superflous--it could just show times.
Here's a multi-day event with one single-day and one multi-day destination:
This, too, is not incorrect but might look better if the single-day destination used the format that's being used for single-day events, i.e.
Thu Sep 12
6pm - 8pm
If the current setup is what's desired, that's fine--each of the labels is correct and complete. Some of them are just potentially a little less clear than they could be without repeated bits.
(Also, this "only show dates for multi-day events" comment doesn't quite match what's happening around it.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The single_day
Django helper method was returning inconsistent results because it wasn't timezone aware (it depended on the time range whether it seemed to work or not). It was misbehaving similarly for the overall event date/time range as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Looks good!
Overview
Demo
Homepage tour tab:
Tour detail page lists locations in cards:
Multi-day event:
Single day event:
Notes
For now, directions to tours or events goes to the first location. Also, filtering by event or tour categories on the map page is now broken (shows no results), but works on the homepage. These can both be addressed in #1111 or #1121.
There's no validation to check event destination times, if set, fall within range of the event times, or that they are ordered by time.
Testing Instructions
app
VM:cd /opt/app/src/ && npm run gulp
should build frontend and rebuild on JS or style file changegulp watch
rebuild should show change (there's no live reload)Checklist
Closes #1109
Fixes #1036
Closes #1110
Closes #1138