This commit is contained in:
stupidcomputer 2024-06-21 03:02:03 -05:00
parent ca61adc1e6
commit 79d441d1f6
13 changed files with 214 additions and 13 deletions

10
docker-compose.yml Normal file
View File

@ -0,0 +1,10 @@
version: '3.8'
services:
web:
build: ./franklincce
command: gunicorn franklincce.wsgi:application --bind 0.0.0.0:8000
volumes:
- ./franklincce/:/usr/src/franklincce
ports:
- 8000:8000

20
franklincce/Dockerfile Normal file
View File

@ -0,0 +1,20 @@
FROM python:3.11.4-slim-buster
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
# copy project
COPY . .
RUN mkdir /var/www/static -p
RUN python3 manage.py collectstatic --noinput

View File

@ -5,6 +5,8 @@ from .lib.parsers import HSYIG, HSMUN
import io
import fitz
from collections import namedtuple
class LegislationBook(models.Model):
class ConferenceType(models.TextChoices):
MIDDLE = "M", _("Middle School")
@ -106,3 +108,7 @@ class LegislativeText(models.Model):
self.committee,
self.docket_order,
)
def get_lines(self):
cls = namedtuple('LegLine', ['linenumber', 'linetext'])
return [cls(i + 1, j) for i, j in enumerate(self.text.split('\n'))]

View File

@ -0,0 +1,15 @@
{% extends "explorer/base.html" %}
{% block content %}
<h1>All legislative texts</h1>
{% if legislative_texts %}
<ul>
{% for text in legislative_texts %}
<li><a href="{% url 'viewleg' text.id %}">{{ text.legislation_title }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No texts available</p>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
{% if page_title %}
<title>explorer - {{ title }}</title>
{% else %}
<title>explorer</title>
{% endif %}
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<nav id="navbar">
<div id="leftnav">
<a href="/explorer">explorer</a>
</div>
<div id="rightnav">
<a href="/explorer/all">all</a>
<a href="/explorer/topics">by topic</a>
<a href="/explorer/search">search</a>
<a href="/explorer/stats">stats</a>
</div>
</nav>
{% block content %}
{% endblock content %}
</body>
</html>

View File

@ -1,3 +1,12 @@
{% extends "explorer/base.html" %}
{% block content %}
<h1>Welcome to explorer</h1>
<p><i>an interactive database for YMCA CCE legislation</i></p>
<h2>Some randomly selected legislation</h2>
{% if legislative_texts %}
<ul>
{% for text in legislative_texts %}
@ -7,3 +16,4 @@
{% else %}
<p>No texts available</p>
{% endif %}
{% endblock content %}

View File

@ -1,9 +1,24 @@
<h1>{{ legislation.legislation_title }}</h1>
{% extends "explorer/base.html" %}
{% block content %}
<div id="legcontainer">
<div id="leginfo" class="boxed">
<h1 class="no-margin-top wrapword">{{ legislation.legislation_title }}</h1>
<i>{{ legislation.assembly }}/{{ legislation.committee }}/{{ legislation.docket_order }}</i>
<p>Sponsored by {{ legislation.sponsors }} of {{ legislation.school }}</p>
</div>
<blockquote>
{{ legislation.text }}
</blockquote>
<div id="legislation" class="boxed">
<table>
{% for line in lines %}
<tr>
<td class="legnumbers">{{ line.linenumber }}</td>
<td>{{ line.linetext }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock content %}

View File

@ -4,5 +4,6 @@ from . import views
urlpatterns = [
path("", views.index, name="index"),
path("all/", views.all, name="all"),
path("legislation/<int:legislation_id>/", views.view_legislation, name="viewleg"),
]

View File

@ -3,16 +3,27 @@ from django.http import HttpResponse
from .models import LegislativeText, LegislationBook
from random import sample
def index(request):
legislative_texts = LegislativeText.objects.all()
legislative_texts = list(LegislativeText.objects.all())
legislative_texts = sample(legislative_texts, 5)
context = {
"legislative_texts": legislative_texts,
}
return render(request, "explorer/index.html", context)
def all(request):
legislative_texts = list(LegislativeText.objects.all())
context = {
"legislative_texts": legislative_texts,
}
return render(request, "explorer/all.html", context)
def view_legislation(request, legislation_id):
legislation = get_object_or_404(LegislativeText, pk=legislation_id)
context = {
"legislation": legislation,
"lines": legislation.get_lines()
}
return render(request, "explorer/legislation.html", context)

View File

@ -15,7 +15,6 @@ from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
@ -25,8 +24,7 @@ SECRET_KEY = 'django-insecure-1%p#re)z*_xd9umo0!1foh(yiz&2=*5q#0b4(m42r0^m%kxli#
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "[::1]"]
# Application definition
@ -81,6 +79,9 @@ DATABASES = {
}
}
STATICFILES_DIRS = [
BASE_DIR / "static",
]
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
@ -100,7 +101,6 @@ AUTH_PASSWORD_VALIDATORS = [
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
@ -116,7 +116,7 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/'
STATIC_URL = '/static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

View File

@ -16,8 +16,10 @@ Including another URLconf
"""
from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('explorer/', include("explorer.urls")),
path('admin/', admin.site.urls),
]
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@ -0,0 +1,3 @@
django
pymupdf
gunicorn

View File

@ -0,0 +1,79 @@
body {
font-family: sans-serif;
}
nav#navbar {
border-bottom: 1px solid black; /* block for top bar */
padding-bottom: 10px;
display: flex; /* make it from left to right */
flex-direction: row;
}
#leftnav {
padding-right: 10px;
}
#rightnav {
padding-left: 10px;
/* make this part right justified */
margin-left: auto;
margin-right: 0;
}
#legcontainer {
display: flex;
flex-direction: row;
gap: 5px;
}
#leginfo {
width: 15em;
}
#legislation {
width: 100%;
}
@media only screen and (max-width: 280px) {
#rightnav {
display: none;
}
}
@media only screen and (max-width: 570px) {
#legcontainer {
flex-direction: column;
}
#leginfo {
width: 100%;
}
}
.no-margin-top {
margin-top: 0px;
}
.boxed {
margin-top: 10px;
padding: 5px;
padding-top: 0px;
border: solid 1px;
border-radius: 5px;
}
.wrapword {
white-space: -moz-pre-wrap !important;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
white-space: pre-wrap;
word-wrap: break-word;
white-space: -webkit-pre-wrap;
word-break: break-all;
white-space: normal;
}
.legnumbers {
text-align: right;
user-select: none;
}