add sign up process for backlogger
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.contrib.auth.models import User
|
||||
from .models import Item
|
||||
|
||||
|
||||
@@ -7,3 +9,14 @@ class ItemAdmin(admin.ModelAdmin):
|
||||
list_display = ['name', 'category', 'progress_percent', 'favorite', 'created_at']
|
||||
list_filter = ['category', 'favorite']
|
||||
search_fields = ['name']
|
||||
|
||||
|
||||
admin.site.unregister(User)
|
||||
|
||||
|
||||
@admin.register(User)
|
||||
class CustomUserAdmin(UserAdmin):
|
||||
list_display = ['username', 'email', 'is_active', 'date_joined']
|
||||
list_editable = ['is_active']
|
||||
list_filter = ['is_active']
|
||||
ordering = ['date_joined']
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
from django import forms
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from django.contrib.auth.models import User
|
||||
from .models import Item
|
||||
|
||||
|
||||
class SignupForm(UserCreationForm):
|
||||
email = forms.EmailField(required=True)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['username', 'email', 'password1', 'password2']
|
||||
|
||||
|
||||
class ItemForm(forms.ModelForm):
|
||||
progress_percent = forms.FloatField(
|
||||
min_value=0,
|
||||
|
||||
@@ -89,7 +89,13 @@
|
||||
<p class="subtitle">Backlogger</p>
|
||||
|
||||
{% if form.non_field_errors %}
|
||||
<div class="error-banner">Invalid username or password.</div>
|
||||
{% for error in form.non_field_errors %}
|
||||
{% if 'inactive' in error|lower or 'active' in error|lower %}
|
||||
<div class="error-banner">Your account is pending approval. You'll be able to log in once it's activated.</div>
|
||||
{% else %}
|
||||
<div class="error-banner">Invalid username or password.</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post">
|
||||
@@ -109,6 +115,9 @@
|
||||
|
||||
<button type="submit" class="btn">Log in</button>
|
||||
</form>
|
||||
<p style="text-align:center; margin-top:1.25rem; font-size:0.83rem; color:#64748b;">
|
||||
No account? <a href="/accounts/signup/" style="color:#38bdf8; text-decoration:none;">Sign up</a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
117
backlogger/templates/backlogger/signup.html
Normal file
117
backlogger/templates/backlogger/signup.html
Normal file
@@ -0,0 +1,117 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Sign up — Backlogger</title>
|
||||
<style>
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
background: #0f172a;
|
||||
color: #e2e8f0;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.card {
|
||||
background: #0a0f1e;
|
||||
border: 1px solid #1e293b;
|
||||
border-radius: 12px;
|
||||
padding: 2.5rem 2rem;
|
||||
width: 100%;
|
||||
max-width: 360px;
|
||||
}
|
||||
.brand {
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: #38bdf8;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 0.4rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
.subtitle {
|
||||
text-align: center;
|
||||
color: #64748b;
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.field { margin-bottom: 1.1rem; }
|
||||
.field label {
|
||||
display: block;
|
||||
font-size: 0.78rem;
|
||||
color: #94a3b8;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.07em;
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
.field input {
|
||||
width: 100%;
|
||||
background: #1e293b;
|
||||
border: 1px solid #334155;
|
||||
border-radius: 6px;
|
||||
color: #e2e8f0;
|
||||
padding: 0.6rem 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.field input:focus { outline: none; border-color: #38bdf8; }
|
||||
.btn {
|
||||
width: 100%;
|
||||
background: #38bdf8;
|
||||
color: #0f172a;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 0.6rem;
|
||||
font-size: 0.9rem;
|
||||
cursor: pointer;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.btn:hover { opacity: 0.88; }
|
||||
.errorlist { list-style: none; color: #f87171; font-size: 0.8rem; margin-top: 0.3rem; }
|
||||
.help { font-size: 0.75rem; color: #475569; margin-top: 0.3rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<a class="brand" href="/">killmybacklog.com</a>
|
||||
<p class="subtitle">Create an account</p>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="field">
|
||||
<label for="{{ form.username.id_for_label }}">Username</label>
|
||||
{{ form.username }}
|
||||
{{ form.username.errors }}
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="{{ form.email.id_for_label }}">Email</label>
|
||||
{{ form.email }}
|
||||
{{ form.email.errors }}
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="{{ form.password1.id_for_label }}">Password</label>
|
||||
{{ form.password1 }}
|
||||
{{ form.password1.errors }}
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="{{ form.password2.id_for_label }}">Confirm password</label>
|
||||
{{ form.password2 }}
|
||||
{{ form.password2.errors }}
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn">Request account</button>
|
||||
</form>
|
||||
<p style="text-align:center; margin-top:1.25rem; font-size:0.83rem; color:#64748b;">
|
||||
Already have an account? <a href="/accounts/login/" style="color:#38bdf8; text-decoration:none;">Log in</a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
51
backlogger/templates/backlogger/signup_pending.html
Normal file
51
backlogger/templates/backlogger/signup_pending.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Account requested — Backlogger</title>
|
||||
<style>
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
background: #0f172a;
|
||||
color: #e2e8f0;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.card {
|
||||
background: #0a0f1e;
|
||||
border: 1px solid #1e293b;
|
||||
border-radius: 12px;
|
||||
padding: 2.5rem 2rem;
|
||||
width: 100%;
|
||||
max-width: 360px;
|
||||
text-align: center;
|
||||
}
|
||||
.brand {
|
||||
display: block;
|
||||
color: #38bdf8;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 0.4rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
.icon { font-size: 2rem; margin: 1.25rem 0 0.75rem; }
|
||||
h2 { font-size: 1rem; font-weight: 600; margin-bottom: 0.6rem; }
|
||||
p { font-size: 0.85rem; color: #64748b; line-height: 1.5; }
|
||||
a { color: #38bdf8; text-decoration: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<a class="brand" href="/">killmybacklog.com</a>
|
||||
<div class="icon">✓</div>
|
||||
<h2>Account requested</h2>
|
||||
<p>Your account is pending approval.<br>You'll receive access once it's activated.</p>
|
||||
<p style="margin-top:1.5rem;"><a href="/accounts/login/">Back to log in</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,7 +1,20 @@
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from .models import Item
|
||||
from .forms import ItemForm
|
||||
from .forms import ItemForm, SignupForm
|
||||
|
||||
|
||||
def signup(request):
|
||||
if request.method == 'POST':
|
||||
form = SignupForm(request.POST)
|
||||
if form.is_valid():
|
||||
user = form.save(commit=False)
|
||||
user.is_active = False
|
||||
user.save()
|
||||
return render(request, 'backlogger/signup_pending.html')
|
||||
else:
|
||||
form = SignupForm()
|
||||
return render(request, 'backlogger/signup.html', {'form': form})
|
||||
|
||||
|
||||
SORT_MAP = {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.urls import path, include
|
||||
from backlogger.views import signup
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('accounts/login/', auth_views.LoginView.as_view(template_name='backlogger/login.html'), name='login'),
|
||||
path('accounts/logout/', auth_views.LogoutView.as_view(), name='logout'),
|
||||
path('accounts/signup/', signup, name='signup'),
|
||||
path('backlogger/', include('backlogger.urls')),
|
||||
path('daily-stone/', include('dailystone.urls')),
|
||||
path('', include('core.urls')),
|
||||
|
||||
Reference in New Issue
Block a user