diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..3f0bbdf
--- /dev/null
+++ b/docker-compose.yml
@@ -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
diff --git a/franklincce/Dockerfile b/franklincce/Dockerfile
new file mode 100644
index 0000000..166c076
--- /dev/null
+++ b/franklincce/Dockerfile
@@ -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
diff --git a/franklincce/explorer/models.py b/franklincce/explorer/models.py
index 37a110a..dd06a43 100644
--- a/franklincce/explorer/models.py
+++ b/franklincce/explorer/models.py
@@ -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'))]
diff --git a/franklincce/explorer/templates/explorer/all.html b/franklincce/explorer/templates/explorer/all.html
new file mode 100644
index 0000000..53aa209
--- /dev/null
+++ b/franklincce/explorer/templates/explorer/all.html
@@ -0,0 +1,15 @@
+{% extends "explorer/base.html" %}
+
+{% block content %}
+
All legislative texts
+
+{% if legislative_texts %}
+
+{% else %}
+ No texts available
+{% endif %}
+{% endblock content %}
diff --git a/franklincce/explorer/templates/explorer/base.html b/franklincce/explorer/templates/explorer/base.html
new file mode 100644
index 0000000..7b60f1e
--- /dev/null
+++ b/franklincce/explorer/templates/explorer/base.html
@@ -0,0 +1,29 @@
+
+
+
+ {% if page_title %}
+ explorer - {{ title }}
+ {% else %}
+ explorer
+ {% endif %}
+
+
+
+
+
+
+
+ {% block content %}
+ {% endblock content %}
+
+
diff --git a/franklincce/explorer/templates/explorer/index.html b/franklincce/explorer/templates/explorer/index.html
index 8c8a495..113cc45 100644
--- a/franklincce/explorer/templates/explorer/index.html
+++ b/franklincce/explorer/templates/explorer/index.html
@@ -1,3 +1,12 @@
+{% extends "explorer/base.html" %}
+
+{% block content %}
+Welcome to explorer
+
+an interactive database for YMCA CCE legislation
+
+Some randomly selected legislation
+
{% if legislative_texts %}
{% for text in legislative_texts %}
@@ -7,3 +16,4 @@
{% else %}
No texts available
{% endif %}
+{% endblock content %}
diff --git a/franklincce/explorer/templates/explorer/legislation.html b/franklincce/explorer/templates/explorer/legislation.html
index a5bb810..e9f018e 100644
--- a/franklincce/explorer/templates/explorer/legislation.html
+++ b/franklincce/explorer/templates/explorer/legislation.html
@@ -1,9 +1,24 @@
-{{ legislation.legislation_title }}
+{% extends "explorer/base.html" %}
-{{ legislation.assembly }}/{{ legislation.committee }}/{{ legislation.docket_order }}
+{% block content %}
+
+
+
{{ legislation.legislation_title }}
-
Sponsored by {{ legislation.sponsors }} of {{ legislation.school }}
+
{{ legislation.assembly }}/{{ legislation.committee }}/{{ legislation.docket_order }}
-
- {{ legislation.text }}
-
+
Sponsored by {{ legislation.sponsors }} of {{ legislation.school }}
+
+
+
+
+ {% for line in lines %}
+
+ {{ line.linenumber }} |
+ {{ line.linetext }} |
+
+ {% endfor %}
+
+
+
+{% endblock content %}
diff --git a/franklincce/explorer/urls.py b/franklincce/explorer/urls.py
index 9f2b6b8..1a7d397 100644
--- a/franklincce/explorer/urls.py
+++ b/franklincce/explorer/urls.py
@@ -4,5 +4,6 @@ from . import views
urlpatterns = [
path("", views.index, name="index"),
+ path("all/", views.all, name="all"),
path("legislation//", views.view_legislation, name="viewleg"),
]
diff --git a/franklincce/explorer/views.py b/franklincce/explorer/views.py
index 04bd7f5..9af62f2 100644
--- a/franklincce/explorer/views.py
+++ b/franklincce/explorer/views.py
@@ -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)
diff --git a/franklincce/franklincce/settings.py b/franklincce/franklincce/settings.py
index 2e09de0..d3e6c57 100644
--- a/franklincce/franklincce/settings.py
+++ b/franklincce/franklincce/settings.py
@@ -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
diff --git a/franklincce/franklincce/urls.py b/franklincce/franklincce/urls.py
index 8b4072b..22d99a3 100644
--- a/franklincce/franklincce/urls.py
+++ b/franklincce/franklincce/urls.py
@@ -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)
diff --git a/franklincce/requirements.txt b/franklincce/requirements.txt
new file mode 100644
index 0000000..df751af
--- /dev/null
+++ b/franklincce/requirements.txt
@@ -0,0 +1,3 @@
+django
+pymupdf
+gunicorn
diff --git a/franklincce/static/style.css b/franklincce/static/style.css
new file mode 100644
index 0000000..b311bcc
--- /dev/null
+++ b/franklincce/static/style.css
@@ -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;
+}