mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-28 07:27:01 -05:00
Compare commits
2 Commits
52514e5cbc
...
cf47ddd8bf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf47ddd8bf | ||
|
|
3d2361b937 |
@@ -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"""
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user