Compare commits

..

2 Commits

2 changed files with 103 additions and 72 deletions

View File

@@ -1,4 +1,17 @@
# Keep all imports and previous classes up to RideCreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.views.generic import UpdateView
from companies.models import Manufacturer
from designers.models import Designer
from moderation.mixins import EditSubmissionMixin
from apps.parks.mixins.base import ParkContextRequired # type: ignore
from moderation.models import EditSubmission
from parks.models import Park
from rides.forms import RideForm # type: ignore
from .models import Ride, RideModel
class RideUpdateView(LoginRequiredMixin, ParkContextRequired, EditSubmissionMixin, UpdateView):
"""View for updating an existing ride"""

View File

@@ -52,28 +52,7 @@ document.addEventListener('alpine:init', () => {
const savedFilters = localStorage.getItem('rideFilters');
// Set up destruction handler
this.$cleanup = () => {
// Remove all bound event listeners
this.boundHandlers.forEach((handler, event) => {
if (event === 'popstate') {
window.removeEventListener(event, handler);
} else {
document.body.removeEventListener(event, handler);
}
});
this.boundHandlers.clear();
// Cancel any pending requests
if (this.currentRequest) {
this.currentRequest.abort();
this.currentRequest = null;
}
// Clear any pending timeouts
if (this.suggestionTimeout) {
clearTimeout(this.suggestionTimeout);
}
};
this.$cleanup = this.performCleanup.bind(this);
if (savedFilters) {
const filters = JSON.parse(savedFilters);
Object.entries(filters).forEach(([key, value]) => {
@@ -137,6 +116,19 @@ document.addEventListener('alpine:init', () => {
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5s timeout
try {
const response = await this.fetchSuggestions(controller, requestId);
await this.handleSuggestionResponse(response, requestId);
} catch (error) {
this.handleSuggestionError(error, requestId);
} finally {
clearTimeout(timeoutId);
if (this.currentRequest === controller) {
this.currentRequest = null;
}
}
},
async fetchSuggestions(controller, requestId) {
const parkSlug = document.querySelector('input[name="park_slug"]')?.value;
const url = `/rides/search-suggestions/?q=${encodeURIComponent(this.searchQuery)}${parkSlug ? '&park_slug=' + parkSlug : ''}`;
@@ -150,16 +142,22 @@ document.addEventListener('alpine:init', () => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response;
},
async handleSuggestionResponse(response, requestId) {
const html = await response.text();
// Only update if this is still the most recent request
if (requestId === this.lastRequestId && this.searchQuery === document.getElementById('search').value) {
const suggestionsEl = document.getElementById('search-suggestions');
suggestionsEl.innerHTML = html;
this.showSuggestions = html.trim() ? true : false;
this.showSuggestions = Boolean(html.trim());
// Set proper ARIA attributes
this.updateAriaAttributes(suggestionsEl);
}
},
updateAriaAttributes(suggestionsEl) {
const searchInput = document.getElementById('search');
searchInput.setAttribute('aria-expanded', this.showSuggestions.toString());
searchInput.setAttribute('aria-controls', 'search-suggestions');
@@ -169,11 +167,14 @@ document.addEventListener('alpine:init', () => {
btn.setAttribute('role', 'option');
});
}
}
} catch (error) {
},
handleSuggestionError(error, requestId) {
if (error.name === 'AbortError') {
console.warn('Search suggestion request timed out or cancelled');
} else {
return;
}
console.error('Error fetching suggestions:', error);
if (requestId === this.lastRequestId) {
const suggestionsEl = document.getElementById('search-suggestions');
@@ -183,13 +184,6 @@ document.addEventListener('alpine:init', () => {
</div>`;
this.showSuggestions = true;
}
}
} finally {
clearTimeout(timeoutId);
if (this.currentRequest === controller) {
this.currentRequest = null;
}
}
},
// Handle input changes with debounce
@@ -297,6 +291,34 @@ document.addEventListener('alpine:init', () => {
}
}
}));
});
},
performCleanup() {
// Remove all bound event listeners
this.boundHandlers.forEach(this.removeEventHandler.bind(this));
this.boundHandlers.clear();
// Cancel any pending requests
if (this.currentRequest) {
this.currentRequest.abort();
this.currentRequest = null;
}
// Clear any pending timeouts
if (this.suggestionTimeout) {
clearTimeout(this.suggestionTimeout);
}
},
removeEventHandler(handler, event) {
if (event === 'popstate') {
window.removeEventListener(event, handler);
} else {
document.body.removeEventListener(event, handler);
}
}
}));
});
</script>
@@ -316,10 +338,6 @@ document.addEventListener('alpine:init', () => {
bottom: 1rem;
right: 1rem;
z-index: 50;
padding: 0.5rem 1rem;
background: rgba(37, 99, 235, 0.95);
border-radius: 0.5rem;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
gap: 0.5rem;