Add first version of a wishlist app - create wishes in the admin for now. Fix a few unrelated things while here: update our date and time formats to be more internationally unambigous, and always show timezone. Also fix an old bug which meant that bornhack.dk/program redirect never worked. (#445)

This commit is contained in:
Thomas Steen Rasmussen 2020-02-13 22:07:28 +01:00 committed by GitHub
parent 575324f3cc
commit 95b41bdd44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 217 additions and 6 deletions

View file

@ -50,6 +50,7 @@ INSTALLED_APPS = [
"tokens",
"feedback",
"economy",
"wishlist",
"allauth",
"allauth.account",
"allauth_2fa",
@ -69,10 +70,10 @@ LANGUAGE_CODE = "en-us"
# USE_I18N = True
# USE_L10N = True
USE_TZ = True
SHORT_DATE_FORMAT = "d/m-Y"
DATE_FORMAT = "d/m-Y"
DATETIME_FORMAT = "d/m-Y H:i"
TIME_FORMAT = "H:i"
SHORT_DATE_FORMAT = "Ymd"
DATE_FORMAT = "l, M jS, Y"
DATETIME_FORMAT = "l, M jS, Y, H:i (e)"
TIME_FORMAT = "H:i (e)"
TEMPLATES = [
{

View file

@ -63,7 +63,7 @@ urlpatterns = [
path(
"program/",
CampRedirectView.as_view(),
kwargs={"page": "schedule_index"},
kwargs={"page": "program:schedule_index"},
name="schedule_index_redirect",
),
path(
@ -84,6 +84,12 @@ urlpatterns = [
kwargs={"page": "village_list"},
name="village_list_redirect",
),
path(
"wishlist/",
CampRedirectView.as_view(),
kwargs={"page": "wishlist:list"},
name="wish_list_redirect",
),
path("people/", PeopleView.as_view(), name="people"),
# camp specific urls below here
path(
@ -129,6 +135,7 @@ urlpatterns = [
path("backoffice/", include("backoffice.urls", namespace="backoffice")),
path("feedback/", FeedbackCreate.as_view(), name="feedback"),
path("economy/", include("economy.urls", namespace="economy")),
path("wishlist/", include("wishlist.urls", namespace="wishlist")),
]
),
),

View file

@ -18,7 +18,7 @@ News | {{ block.super }}
{% endif %}
{% for item in news_items %}
<div>
<h3><a href="{% url 'news:detail' slug=item.slug %}">{{ item.title }}</a> <small>{{ item.published_at|date:"Y-m-d" }}</small></h3>
<h3><a href="{% url 'news:detail' slug=item.slug %}">{{ item.title }}</a> <small>{{ item.published_at }}</small></h3>
</div>
{{ item.content|trustedcommonmark }}
{% if not forloop.last %}

View file

@ -75,6 +75,7 @@
</li>
<li><a href="{% url 'contact' %}">Contact</a></li>
<li><a href="{% url 'people' %}">People</a></li>
<li><a href="{% url 'wish_list_redirect' %}">Wishlist</a></li>
{% if request.user.is_staff %}
<li><a href="{% url 'admin:index' %}">Django Admin</a></li>
{% endif %}

0
src/wishlist/__init__.py Normal file
View file

8
src/wishlist/admin.py Normal file
View file

@ -0,0 +1,8 @@
from django.contrib import admin
from .models import Wish
@admin.register(Wish)
class WishAdmin(admin.ModelAdmin):
pass

5
src/wishlist/apps.py Normal file
View file

@ -0,0 +1,5 @@
from django.apps import AppConfig
class WishlistConfig(AppConfig):
name = 'wishlist'

View file

@ -0,0 +1,33 @@
# Generated by Django 3.0.3 on 2020-02-09 18:24
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('teams', '0051_auto_20190312_1129'),
]
operations = [
migrations.CreateModel(
name='Wish',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('name', models.CharField(help_text='Short description of the wish', max_length=100)),
('slug', models.SlugField(help_text='The url slug for this wish')),
('description', models.TextField(help_text='Description of the needed item. Markdown is supported!')),
('count', models.IntegerField(default=1, help_text='How many do we need?')),
('fulfilled', models.BooleanField(default=False, help_text='A Wish is marked as fulfilled when we no longer need the thing.')),
('team', models.ForeignKey(help_text='The team that needs this thing. When in doubt pick Orga :)', on_delete=django.db.models.deletion.PROTECT, related_name='wishes', to='teams.Team')),
],
options={
'abstract': False,
},
),
]

View file

66
src/wishlist/models.py Normal file
View file

@ -0,0 +1,66 @@
from django.db import models
from django.urls import reverse
from django.utils.text import slugify
from django.core.exceptions import ValidationError
from utils.models import CampRelatedModel
class Wish(CampRelatedModel):
"""
This model contains the stuff BornHack needs. This can be anything from kitchen equipment
to network cables, or anything really.
"""
name = models.CharField(
max_length=100,
help_text="Short description of the wish",
)
slug = models.SlugField(
blank=True,
help_text="The url slug for this wish. Leave blank to autogenerate one.",
)
description = models.TextField(
help_text="Description of the needed item. Markdown is supported!"
)
count = models.IntegerField(
default=1,
help_text="How many do we need?",
)
fulfilled = models.BooleanField(
default=False,
help_text="A Wish is marked as fulfilled when we no longer need the thing.",
)
team = models.ForeignKey(
"teams.Team",
help_text="The team that needs this thing. When in doubt pick Orga :)",
on_delete=models.PROTECT,
related_name="wishes",
)
@property
def camp(self):
return self.team.camp
camp_filter = "team__camp"
def __str__(self):
return self.name
def save(self, **kwargs):
print("inside save()")
if not self.slug:
self.slug = slugify(self.name)
if not self.slug:
raise ValidationError("Unable to slugify")
super().save(**kwargs)
def get_absolute_url(self):
return reverse("wishlist:detail", kwargs={
"camp_slug": self.camp.slug,
"wish_slug": self.slug,
})

View file

@ -0,0 +1,19 @@
{% extends 'base.html' %}
{% load static %}
{% load commonmark %}
{% block title %}
Wish List | {{ block.super }}
{% endblock %}
{% block content %}
<h2>BornHack Wish: {{ wish.name }}</h2>
<p class="lead">{{ wish.description }}</p>
<p class="lead">Number needed: {{ wish.count }}</p>
<p class="lead"><i>This wish was created by the <a href="{% url 'teams:general' camp_slug=wish.team.camp.slug team_slug=wish.team.slug %}">{{ wish.team.name }} Team</a> for {{ wish.team.camp.title }} on {{ wish.created }}. If you can help please visit their <a href="{% url 'teams:general' camp_slug=wish.camp.slug team_slug=wish.team.slug %}">team page</a> for contact info!</i></p>
<a class="btn btn-primary" href="{% url 'wish_list_redirect' %}"><i class="fas fa-undo"></i> Back to Wish List</a>
{% endblock %}

View file

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% load static %}
{% load commonmark %}
{% block title %}
Wish List | {{ block.super }}
{% endblock %}
{% block content %}
<h2>BornHack Wishlist</h2>
<p class="lead">
This is a list of things the different BornHack teams need. If you own
something on the list and you would like to donate it to BornHack then please
don't hesitate to contact the team in question. Partial donations are also welcome,
so if a team needs 10 of something and you have 5 then we still want to hear from you.
When we no longer need something it will be removed from this list.
</p>
<table class="table table-hover table-striped">
<tr>
<th>Wish</th>
<th>Team</th>
<th>Description</th>
<th>Number</th>
<th>Created</th>
</tr>
{% for wish in wish_list %}
<tr>
<td>
<a href="{% url 'wishlist:detail' camp_slug=camp.slug wish_slug=wish.slug %}">{{ wish.name }}</a>
</td>
<td>{{ wish.team.name }} Team</td>
<td>{{ wish.description|trustedcommonmark }}</td>
<td>{{ wish.count }}</td>
<td>{{ wish.created }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}

3
src/wishlist/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

9
src/wishlist/urls.py Normal file
View file

@ -0,0 +1,9 @@
from django.urls import path
from .views import WishListView, WishDetailView
app_name = "wishlist"
urlpatterns = [
path("", WishListView.as_view(), name="list"),
path("<slug:wish_slug>/", WishDetailView.as_view(), name="detail"),
]

16
src/wishlist/views.py Normal file
View file

@ -0,0 +1,16 @@
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from .models import Wish
class WishListView(ListView):
model = Wish
template_name = "wish_list.html"
class WishDetailView(DetailView):
model = Wish
template_name = "wish_detail.html"
slug_url_kwarg = "wish_slug"