Add testing pages and update component attributes for enhanced interactivity

Integrates Django Cotton components with new test pages, updating button and input component templates to correctly handle `x_data` and `x_on` attributes for improved interactivity.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: eff39de1-3afa-446d-a965-acaf61837fc7
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/d6d61dac-164d-45dd-929f-7dcdfd771b64/eff39de1-3afa-446d-a965-acaf61837fc7/J3NgjVS
This commit is contained in:
pac7
2025-09-21 13:51:06 +00:00
committed by pacnpal
parent 1294b3009e
commit cb944485b8
6 changed files with 567 additions and 7 deletions

View File

@@ -13,8 +13,8 @@ Converts existing button component to use Django Cotton's component system
type="type|default:'button'"
disabled="disabled|default:''"
onclick="onclick|default:''"
x_data="x_data|default:''"
x_on="x_on|default:''"
x_data="x_data"
x_on="x_on"
hx_get="hx_get|default:''"
hx_post="hx_post|default:''"
hx_target="hx_target|default:''"
@@ -60,7 +60,7 @@ Converts existing button component to use Django Cotton's component system
{% if hx_post %}hx-post="{{ hx_post }}"{% endif %}
{% if hx_target %}hx-target="{{ hx_target }}"{% endif %}
{% if hx_swap %}hx-swap="{{ hx_swap }}"{% endif %}
{% if x_data and x_data != '' %}x-data="{{ x_data }}"{% endif %}
{% if x_data and x_data != 'x_data' %}x-data="{{ x_data }}"{% endif %}
{% if x_on %}{{ x_on }}{% endif %}
{% if disabled and disabled != '' %}disabled{% endif %}
{{ attrs }}

View File

@@ -14,9 +14,9 @@ Converts existing input component to use Django Cotton's component system
disabled="disabled|default:''"
required="required|default:''"
readonly="readonly|default:''"
x_model="x_model|default:''"
x_data="x_data|default:''"
x_on="x_on|default:''"
x_model="x_model"
x_data="x_data"
x_on="x_on"
hx_get="hx_get|default:''"
hx_post="hx_post|default:''"
hx_target="hx_target|default:''"
@@ -41,7 +41,7 @@ Converts existing input component to use Django Cotton's component system
{% if required %}required{% endif %}
{% if readonly %}readonly{% endif %}
{% if x_model %}x-model="{{ x_model }}"{% endif %}
{% if x_data %}x-data="{{ x_data }}"{% endif %}
{% if x_data and x_data != 'x_data' %}x-data="{{ x_data }}"{% endif %}
{% if x_on %}{{ x_on }}{% endif %}
{% if hx_get %}hx-get="{{ hx_get }}"{% endif %}
{% if hx_post %}hx-post="{{ hx_post }}"{% endif %}

View File

@@ -0,0 +1,21 @@
{% extends 'base/base.html' %}
{% load cotton %}
{% block title %}Minimal Cotton Test - ThrillWiki{% endblock %}
{% block content %}
<div class="max-w-4xl mx-auto p-8">
<h1 class="text-3xl font-bold mb-8">Minimal Cotton Test</h1>
<!-- Copy exact working syntax from enhanced_header.html -->
<div class="space-y-4">
<h2 class="text-xl font-semibold">Working Cotton Button (from enhanced_header.html):</h2>
<c-ui.button variant="default" size="sm" text="Search" />
<c-ui.button variant="outline" size="sm" text="Login" />
</div>
<div class="mt-8 p-4 bg-green-100 rounded">
<p>If you see buttons above, Cotton components are working correctly!</p>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,64 @@
{% extends 'base/base.html' %}
{% load static %}
{% load cotton %}
{% block title %}Simple Cotton Test - ThrillWiki{% endblock %}
{% block content %}
<div class="max-w-4xl mx-auto space-y-8">
<div class="text-center">
<h1 class="text-3xl font-bold text-gray-900 dark:text-white mb-4">
Simple Cotton Components Test
</h1>
<p class="text-lg text-gray-600 dark:text-gray-400">
Basic test of Cotton components
</p>
</div>
<!-- Test 1: Simple Button -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm border">
<h2 class="text-xl font-semibold mb-4">1. Button Component</h2>
<div class="space-y-3">
<c-ui.button text="Test Button" />
<c-ui.button variant="outline" text="Outline Button" />
</div>
</section>
<!-- Test 2: Simple Card -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm border">
<h2 class="text-xl font-semibold mb-4">2. Card Component</h2>
<c-ui.card title="Test Card" description="This is a test card">
<c-slot:content>
<p>Card content goes here.</p>
</c-slot:content>
</c-ui.card>
</section>
<!-- Test 3: Simple Input -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm border">
<h2 class="text-xl font-semibold mb-4">3. Input Component</h2>
<c-ui.input placeholder="Test input field" />
</section>
<!-- Test 4: Simple Status Badge -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm border">
<h2 class="text-xl font-semibold mb-4">4. Status Badge Component</h2>
<c-ui.status_badge status="OPERATIONAL" />
</section>
<!-- Success indicator -->
<section class="bg-green-50 dark:bg-green-900/20 rounded-lg p-6 border border-green-200 dark:border-green-700">
<h2 class="text-xl font-semibold mb-4 text-green-800 dark:text-green-200">
<i class="fas fa-check-circle mr-2"></i>
Basic Cotton Test Complete
</h2>
<p class="text-green-700 dark:text-green-300">
If you can see this page without errors, basic Cotton components are working.
</p>
</section>
</div>
{% endblock %}

View File

@@ -0,0 +1,460 @@
{% extends 'base/base.html' %}
{% load static %}
{% load cotton %}
{% block title %}Cotton Components Test - ThrillWiki{% endblock %}
{% block content %}
<div class="max-w-6xl mx-auto space-y-12">
<div class="text-center">
<h1 class="text-4xl font-bold text-gray-900 dark:text-white mb-4">
Cotton Components Test Suite
</h1>
<p class="text-xl text-gray-600 dark:text-gray-400">
Testing all 9 Phase 1 Cotton Components
</p>
</div>
<!-- Component 1: Button Tests -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-sm border">
<h2 class="text-2xl font-semibold mb-6 text-gray-900 dark:text-white">
<i class="fas fa-mouse-pointer mr-3 text-blue-500"></i>
1. Button Component Tests
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Button Variants -->
<div class="space-y-4">
<h3 class="text-lg font-medium">Variants</h3>
<div class="space-y-3">
<c-ui.button variant="default" text="Default Button" />
<c-ui.button variant="outline" text="Outline Button" />
<c-ui.button variant="ghost" text="Ghost Button" />
<c-ui.button variant="destructive" text="Destructive" />
<c-ui.button variant="secondary" text="Secondary" />
</div>
</div>
<!-- Button Sizes -->
<div class="space-y-4">
<h3 class="text-lg font-medium">Sizes</h3>
<div class="space-y-3">
<c-ui.button size="sm" text="Small Button" />
<c-ui.button size="default" text="Default Size" />
<c-ui.button size="lg" text="Large Button" />
<c-ui.button size="icon" icon_left="fas fa-heart" />
</div>
</div>
<!-- Interactive Features -->
<div class="space-y-4">
<h3 class="text-lg font-medium">Interactive</h3>
<div class="space-y-3">
<c-ui.button
text="Alpine.js Click"
x_data="{clicked: false}"
x_on="@click='clicked = !clicked; $el.textContent = clicked ? \"Clicked!\" : \"Alpine.js Click\"'"
/>
<c-ui.button
text="HTMX Test"
hx_get="/"
hx_target="#htmx-result"
hx_swap="innerHTML"
/>
<div id="htmx-result" class="text-sm text-gray-600 dark:text-gray-400 p-2 border rounded">
HTMX result will appear here
</div>
</div>
</div>
</div>
</section>
<!-- Component 2: Card Tests -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-sm border">
<h2 class="text-2xl font-semibold mb-6 text-gray-900 dark:text-white">
<i class="fas fa-square mr-3 text-green-500"></i>
2. Card Component Tests
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Basic Card -->
<c-ui.card
title="Test Card Title"
description="This is a test description for the card component."
>
<c-slot:content>
<p class="text-gray-600 dark:text-gray-400">
This is the main content area of the card component.
</p>
</c-slot:content>
<c-slot:footer>
<div class="flex justify-end space-x-2">
<c-ui.button variant="outline" size="sm" text="Cancel" />
<c-ui.button size="sm" text="Save" />
</div>
</c-slot:footer>
</c-ui.card>
<!-- Complex Card -->
<c-ui.card>
<c-slot:header>
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold">Complex Card</h3>
<c-ui.status_badge status="OPERATIONAL" />
</div>
</c-slot:header>
<c-slot:content>
<div class="space-y-3">
<c-ui.input placeholder="Test input in card" />
<p class="text-sm text-gray-600 dark:text-gray-400">
Testing nested components within cards.
</p>
</div>
</c-slot:content>
</c-ui.card>
</div>
</section>
<!-- Component 3: Input Tests -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-sm border">
<h2 class="text-2xl font-semibold mb-6 text-gray-900 dark:text-white">
<i class="fas fa-keyboard mr-3 text-purple-500"></i>
3. Input Component Tests
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-4">
<h3 class="text-lg font-medium">Input Types</h3>
<c-ui.input type="text" placeholder="Text input" name="test-text" />
<c-ui.input type="email" placeholder="Email input" name="test-email" />
<c-ui.input type="password" placeholder="Password input" name="test-password" />
<c-ui.input type="number" placeholder="Number input" name="test-number" />
</div>
<div class="space-y-4" x-data="{inputValue: 'Hello Alpine!'}">
<h3 class="text-lg font-medium">Alpine.js Integration</h3>
<c-ui.input
placeholder="Alpine.js x-model"
x_model="inputValue"
/>
<p class="text-sm text-gray-600 dark:text-gray-400">
Value: <span x-text="inputValue"></span>
</p>
<c-ui.input
placeholder="HTMX trigger"
hx_post="/"
hx_target="#input-result"
hx_trigger="keyup changed delay:500ms"
/>
<div id="input-result" class="text-sm text-gray-600 dark:text-gray-400 p-2 border rounded">
HTMX input result
</div>
</div>
</div>
</section>
<!-- Component 4: Status Badge Tests -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-sm border">
<h2 class="text-2xl font-semibold mb-6 text-gray-900 dark:text-white">
<i class="fas fa-tag mr-3 text-yellow-500"></i>
4. Status Badge Component Tests
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="space-y-3">
<h3 class="text-lg font-medium">Statuses</h3>
<div class="space-y-2">
<c-ui.status_badge status="OPERATIONAL" />
<c-ui.status_badge status="TEMPORARILY_CLOSED" />
<c-ui.status_badge status="PERMANENTLY_CLOSED" />
<c-ui.status_badge status="UNKNOWN" />
</div>
</div>
<div class="space-y-3">
<h3 class="text-lg font-medium">Sizes</h3>
<div class="space-y-2">
<c-ui.status_badge status="OPERATIONAL" size="sm" />
<c-ui.status_badge status="OPERATIONAL" size="default" />
<c-ui.status_badge status="OPERATIONAL" size="lg" />
</div>
</div>
<div class="space-y-3">
<h3 class="text-lg font-medium">Custom Content</h3>
<c-ui.status_badge status="OPERATIONAL">
<c-slot:status-text>Custom Status Text</c-slot:status-text>
</c-ui.status_badge>
</div>
</div>
</section>
<!-- Component 5: Pagination Tests -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-sm border">
<h2 class="text-2xl font-semibold mb-6 text-gray-900 dark:text-white">
<i class="fas fa-list mr-3 text-indigo-500"></i>
5. Pagination Component Tests
</h2>
<div class="space-y-6">
<p class="text-gray-600 dark:text-gray-400">
Testing pagination with mock page object data:
</p>
<!-- Mock pagination object for testing -->
<div class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
{% with mock_paginator=page_obj %}
<script>
// Mock page object for testing
const mockPageObj = {
has_previous: true,
has_next: true,
previous_page_number: 1,
next_page_number: 3,
number: 2,
start_index: 11,
end_index: 20,
paginator: {
count: 100,
page_range: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
};
</script>
<!-- Note: This would normally use Django's paginator, showing static layout for visual testing -->
<div class="flex items-center justify-between px-2">
<div class="flex-1 flex justify-between sm:hidden">
<a href="?page=1" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50">
Previous
</a>
<a href="?page=3" class="ml-3 relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50">
Next
</a>
</div>
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700 dark:text-gray-300">
Showing <span class="font-medium">11</span> to <span class="font-medium">20</span> of <span class="font-medium">100</span> results
</p>
</div>
<div>
<nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px">
<a href="?page=1" class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
<i class="fas fa-chevron-left h-5 w-5"></i>
</a>
<a href="?page=1" class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">1</a>
<span class="relative inline-flex items-center px-4 py-2 border border-blue-500 bg-blue-50 text-sm font-medium text-blue-600">2</span>
<a href="?page=3" class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">3</a>
<a href="?page=3" class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
<i class="fas fa-chevron-right h-5 w-5"></i>
</a>
</nav>
</div>
</div>
</div>
{% endwith %}
</div>
</div>
</section>
<!-- Component 6: Search Form Tests -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-sm border">
<h2 class="text-2xl font-semibold mb-6 text-gray-900 dark:text-white">
<i class="fas fa-search mr-3 text-red-500"></i>
6. Search Form Component Tests
</h2>
<div class="space-y-6">
<c-ui.search_form
placeholder="Search parks and rides..."
show_sort="true"
form_classes="bg-gray-50 dark:bg-gray-700 p-6 rounded-lg border"
>
<c-slot:filters>
<div>
<label for="type" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Type</label>
<select name="type" id="type" class="block w-full px-3 py-2 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500">
<option value="">All Types</option>
<option value="park">Parks</option>
<option value="ride">Rides</option>
</select>
</div>
<div>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Status</label>
<div class="space-y-2">
<label class="flex items-center">
<input type="checkbox" name="status" value="operational" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300">Operational</span>
</label>
<label class="flex items-center">
<input type="checkbox" name="status" value="closed" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<span class="ml-2 text-sm text-gray-700 dark:text-gray-300">Closed</span>
</label>
</div>
</div>
</c-slot:filters>
<c-slot:sort-options>
<div class="flex items-center space-x-2">
<label for="ordering" class="text-sm font-medium text-gray-700 dark:text-gray-300">Sort by:</label>
<select name="ordering" id="ordering" class="block px-3 py-2 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500">
<option value="name">Name (A-Z)</option>
<option value="-name">Name (Z-A)</option>
<option value="created_at">Newest First</option>
<option value="-created_at">Oldest First</option>
</select>
</div>
</c-slot:sort-options>
</c-ui.search_form>
</div>
</section>
<!-- Component 7: Login Form Tests -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-sm border">
<h2 class="text-2xl font-semibold mb-6 text-gray-900 dark:text-white">
<i class="fas fa-sign-in-alt mr-3 text-teal-500"></i>
7. Login Form Component Tests
</h2>
<div class="max-w-md mx-auto">
<div class="bg-gray-50 dark:bg-gray-700 p-6 rounded-lg">
<h3 class="text-lg font-medium mb-4 text-center">Test Login Form</h3>
<c-auth.login_form
button_text="Test Sign In"
show_remember="true"
show_forgot_password="true"
hx_target="#login-test-result"
hx_swap="innerHTML"
/>
<div id="login-test-result" class="mt-4 p-3 bg-white dark:bg-gray-800 rounded border text-center text-sm text-gray-600 dark:text-gray-400">
HTMX login form result will appear here
</div>
</div>
</div>
</section>
<!-- Component 8 & 9: Turnstile Widget Tests -->
<section class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-sm border">
<h2 class="text-2xl font-semibold mb-6 text-gray-900 dark:text-white">
<i class="fas fa-shield-alt mr-3 text-orange-500"></i>
8 & 9. Turnstile Widget Component Tests
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-4">
<h3 class="text-lg font-medium">Normal Turnstile Widget</h3>
<div class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
<c-auth.turnstile_widget site_key="test-site-key" />
</div>
</div>
<div class="space-y-4">
<h3 class="text-lg font-medium">Empty Turnstile Widget (DEBUG Mode)</h3>
<div class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
<c-auth.turnstile_empty
show_debug_message="true"
debug_message="Turnstile disabled for component testing"
/>
</div>
</div>
</div>
</section>
<!-- Test Results Summary -->
<section class="bg-green-50 dark:bg-green-900/20 rounded-lg p-8 border border-green-200 dark:border-green-700">
<h2 class="text-2xl font-semibold mb-6 text-green-800 dark:text-green-200">
<i class="fas fa-check-circle mr-3"></i>
Test Results Summary
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="text-center">
<div class="text-3xl font-bold text-green-600 dark:text-green-400 mb-2">9</div>
<p class="text-green-700 dark:text-green-300">Components Tested</p>
</div>
<div class="text-center" id="js-test-status">
<div class="text-3xl font-bold text-blue-600 dark:text-blue-400 mb-2" id="js-status">?</div>
<p class="text-blue-700 dark:text-blue-300">JavaScript Status</p>
</div>
<div class="text-center" id="responsive-test">
<div class="text-3xl font-bold text-purple-600 dark:text-purple-400 mb-2"></div>
<p class="text-purple-700 dark:text-purple-300">Responsive Design</p>
</div>
</div>
<div class="mt-6 p-4 bg-white dark:bg-gray-800 rounded border">
<h3 class="font-medium mb-3">JavaScript Test Results:</h3>
<div id="test-results" class="text-sm space-y-1">
<div class="text-gray-600 dark:text-gray-400">Running JavaScript tests...</div>
</div>
</div>
</section>
</div>
<!-- JavaScript for testing -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const testResults = document.getElementById('test-results');
const jsStatus = document.getElementById('js-status');
// Test Alpine.js availability
let tests = [];
if (typeof Alpine !== 'undefined') {
tests.push('✓ Alpine.js loaded successfully');
jsStatus.textContent = '✓';
jsStatus.className = 'text-3xl font-bold text-green-600 dark:text-green-400 mb-2';
} else {
tests.push('✗ Alpine.js not loaded');
jsStatus.textContent = '✗';
jsStatus.className = 'text-3xl font-bold text-red-600 dark:text-red-400 mb-2';
}
// Test HTMX availability
if (typeof htmx !== 'undefined') {
tests.push('✓ HTMX loaded successfully');
} else {
tests.push('✗ HTMX not loaded');
}
// Test for console errors
let hasErrors = false;
const originalError = console.error;
const originalWarn = console.warn;
console.error = function(...args) {
hasErrors = true;
originalError.apply(console, args);
};
console.warn = function(...args) {
if (args[0] && args[0].includes && args[0].includes('Alpine Expression Error')) {
hasErrors = true;
}
originalWarn.apply(console, args);
};
setTimeout(() => {
if (!hasErrors) {
tests.push('✓ No console errors detected');
} else {
tests.push('✗ Console errors detected');
}
testResults.innerHTML = tests.map(test =>
`<div class="${test.startsWith('✓') ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}">${test}</div>`
).join('');
console.error = originalError;
console.warn = originalWarn;
}, 1000);
});
</script>
{% endblock %}

View File

@@ -71,6 +71,21 @@ urlpatterns = [
TemplateView.as_view(template_name="pages/privacy.html"),
name="privacy",
),
path(
"cotton-test/",
TemplateView.as_view(template_name="pages/cotton_test.html"),
name="cotton_test",
),
path(
"cotton-simple/",
TemplateView.as_view(template_name="pages/cotton_simple_test.html"),
name="cotton_simple_test",
),
path(
"cotton-minimal/",
TemplateView.as_view(template_name="pages/cotton_minimal_test.html"),
name="cotton_minimal_test",
),
# Custom authentication URLs first (to override allauth defaults)
path("accounts/", include("apps.accounts.urls")),
# Default allauth URLs (for social auth and other features)