Skip to content

Commit

Permalink
Interface refinements
Browse files Browse the repository at this point in the history
Items remaining countdown, "add item" form, etc.
  • Loading branch information
sheepman4267 committed Apr 27, 2023
1 parent 7360b00 commit 684aeb8
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 18 deletions.
13 changes: 7 additions & 6 deletions agenda_hat/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
# SECRET_KEY = 'django-insecure-4=nvn+3!^^#3489hot0brrx-!m+efx_^+x@^mwq^)c-$#u^^_m'
SECRET_KEY = os.environ['HAT_SECRET_KEY']
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = {'False': False, 'True': True}[os.environ['HAT_DEBUG']]

ALLOWED_HOSTS = os.environ['HAT_ALLOWED_HOSTS'].split(',')
CSRF_TRUSTED_ORIGINS = ['https://'+host for host in ALLOWED_HOSTS]
if DEBUG:
SECRET_KEY = 'django-insecure-4=nvn+3!^^#3489hot0brrx-!m+efx_^+x@^mwq^)c-$#u^^_m'

STATIC_ROOT = Path(os.environ['HAT_STATIC_ROOT'])
else:
SECRET_KEY = os.environ['HAT_SECRET_KEY']
ALLOWED_HOSTS = os.environ['HAT_ALLOWED_HOSTS'].split(',')
CSRF_TRUSTED_ORIGINS = ['https://'+host for host in ALLOWED_HOSTS]
STATIC_ROOT = Path(os.environ['HAT_STATIC_ROOT'])

# Application definition

Expand Down
2 changes: 1 addition & 1 deletion agenda_hat/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@

urlpatterns = [
path('admin/', admin.site.urls),
path('', include("hat.urls"))
path('', include("hat.urls")),
]
7 changes: 6 additions & 1 deletion hat/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@
# Create your models here.
class Item(models.Model):
text = models.TextField()
pulled = models.BooleanField(default=False, editable=False)
pulled = models.BooleanField(default=False, editable=False)
pulled_at = models.DateTimeField(null=True, blank=True)


# todo: shame meeting for taking forever. We already have a query of all items pulled today,
# todo: and we're storing times... timedelta, then add red highlight or something to long items
91 changes: 89 additions & 2 deletions hat/static/hat/hat.css
Original file line number Diff line number Diff line change
@@ -1,17 +1,53 @@
body {
text-align: center;
display: grid;
grid-template-columns: 1fr 5fr 1fr;
height: 100dvh;
overflow: clip;
}

ul {
list-style: none;
padding: 0;
}

.h1 {
height: 80px;
}

.sidebar {
display: flex;
gap: 0.5rem;
flex-direction: column;
}

.sidebar button {
width: 100%;
}

.message.new > form {
display: flex;
flex-direction: column;
margin: 1rem;
height: 7rem;
gap: 0.5rem;
}

.message.new > form > button {
width: 50%;
align-self: center;
}

/*Begin animation mess*/

.hat-pull.new + .hat,
.hat {
width: 500px;
height: auto;
rotate: 180deg;
margin-top: auto;
justify-self: end;
animation: none;
}

.hat.finished {
Expand All @@ -33,12 +69,27 @@ body {
align-self: center;
}

.hat-pull.htmx-swapping .message.new {
opacity: 0;
transition: opacity 1s;
animation: 0.5s new-item-throw ease-in;
}

.hat-pull.htmx-settling .message.new {
animation: none;
}

.hat-pull.new {
animation: none;
}

.hat-pull img {
width: 300px;
height: auto;
}

.hat-pull p {
.hat-pull .message {
margin-top: 3rem;
text-align: center;
width: 500px;
height: fit-content;
Expand All @@ -49,7 +100,14 @@ body {
margin-left: -132%;
}

.hat-pull.finished p {
.hat-pull .message.new {
animation: none;
opacity: 100%;
transition: opacity 0.5s;
}

.hat-pull.finished .message,
.hat-pull.index .message {
opacity: 0;
animation: none;
}
Expand All @@ -58,6 +116,12 @@ body {
animation: 1s hand-wave infinite;
}

.hat-pull.index {
animation: 1s hello-wave infinite;
}



@keyframes hand-pull {
from {
}
Expand Down Expand Up @@ -124,4 +188,27 @@ body {
to {
rotate: -45deg;
}
}

@keyframes hello-wave {
from {
rotate: -5deg;
}
50% {
rotate: 5deg;
}
to {
rotate: -5deg;
}
}

@keyframes new-item-throw {
from {
opacity: 1;
}

to {
transform: translate(0, 100dvh) scale(1%);
opacity: 0;
}
}
16 changes: 16 additions & 0 deletions hat/templates/hat/counter-snippet.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div id="counter" hx-swap-oob="true">
<h2>Are we there yet?</h2>
{% if remaining_items == 0 %}
<span class="announcement">
Yes!
</span>
{% elif remaining_items < 3 %}
<span class="announcement">
Almost! There are only {{ remaining_items }} agenda items left!
</span>
{% else %}
<span class="announcement">
NO. There are {{ remaining_items }} agenda items left.
</span>
{% endif %}
</div>
26 changes: 21 additions & 5 deletions hat/templates/hat/hat.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,34 @@
<head>
<meta charset="UTF-8">
<title>Agenda Hat</title>
<link rel="stylesheet" href="{% static 'hat/hat.css' %}"
<link rel="stylesheet" href="{% static 'hat/hat.css' %}">
<script src="https://unpkg.com/[email protected]"></script>
<script src="https://unpkg.com/[email protected]"></script>
</head>
<body>
<h1>Agenda Hat</h1>
<div class="sidebar left">
<h1>Agenda Hat</h1>
<button hx-get="{% url 'new-item' %}" hx-target="#hat-pull" hx-swap="outerHTML">Add Something...</button>
<a href="{% url 'pull-item' %}"><button>Next Item</button></a>
</div>
<div class="hat-container">
<div class="hat-pull {{ hat_class }}">
<div class="hat-pull {{ hat_class }}" id="hat-pull">
<img src="{% static 'hat/hand.png' %}">
<p>
<div class="message">
{{ item.text }}
</p>
</div>
</div>
<img class="hat {{ hat_class }}" src="{% static 'hat/tophat.png' %}" alt="hat!">
</div>
<div class="sidebar right">
{% include 'hat/counter-snippet.html' %}
<ul>
{% for item in past_items %}
<li>
<del>{{ item.text }}</del>
</li>
{% endfor %}
</ul>
</div>
</body>
</html>
21 changes: 21 additions & 0 deletions hat/templates/hat/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Agenda Hat</title>
<link rel="stylesheet" href="{% static 'hat/hat.css' %}"
</head>
<body>
<h1>Agenda Hat</h1>
<div class="hat-container">
<div class="hat-pull {{ hat_class }}">
<img src="{% static 'hat/hand.png' %}">
<p>
{{ item.text }}
</p>
</div>
<img class="hat {{ hat_class }}" src="{% static 'hat/tophat.png' %}" alt="hat!">
</div>
</body>
</html>
17 changes: 17 additions & 0 deletions hat/templates/hat/new_item.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% load static %}

<div id="hat-pull" class="hat-pull {{ hat_class }} new">
<img src="{% static 'hat/hand.png' %}">
<div class="message new">
<form>
{% csrf_token %}
{{ form.text }}
<button hx-post="{% url 'new-item' %}" hx-target="#hat-pull" hx-swap="outerHTML settle:0.5s swap:0.5s"
_="on click add .lock to #hat-pull">
Submit
</button>
</form>
</div>
</div>

{% include 'hat/counter-snippet.html' with remaining_items=remaining_items %}
6 changes: 4 additions & 2 deletions hat/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.urls import path
from .views import pull_item
from .views import pull_item, index, CreateItemView


urlpatterns = [
path('', pull_item)
path("", index, name="index"),
path("next", pull_item, name="pull-item"),
path("add", CreateItemView.as_view(), name="new-item"),
]
34 changes: 33 additions & 1 deletion hat/views.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,53 @@
from django.shortcuts import render
from django.urls import reverse_lazy
from django.utils import timezone
from django.views.generic import CreateView

import random

from .models import Item


def get_remaining_items():
return Item.objects.filter(pulled=False).count()

def index(request):
return render(request, 'hat/hat.html', {
'hat_class': 'index', # todo: make timedelta in line 12 configurable
'past_items': Item.objects.filter(pulled=True, pulled_at__range=(timezone.now() - timezone.timedelta(hours=6), timezone.now())),
'remaining_items': Item.objects.filter(pulled=False).count(),
})


def pull_item(request):
item = ''
hat_class = ''
try:
item = random.choice(Item.objects.filter(pulled=False))
item.pulled = True
item.pulled_at = timezone.now()
item.save()
except IndexError:
hat_class = 'finished'

return render(request, 'hat/hat.html', {
'item': item,
'hat_class': hat_class,
})
'past_items': Item.objects.filter(pulled=True, pulled_at__range=(timezone.now() - timezone.timedelta(hours=6), timezone.now())),
'remaining_items': Item.objects.filter(pulled=False).count(),
})


class CreateItemView(CreateView):
model = Item
template_name = "hat/new_item.html"
fields = [
'text',
]
success_url = reverse_lazy('new-item')
print(Item.objects.filter(pulled=False))
extra_context = {
'remaining_items': get_remaining_items
}


0 comments on commit 684aeb8

Please sign in to comment.