Skip to content

Commit

Permalink
Merge pull request #33 from chnm/iiif-integration
Browse files Browse the repository at this point in the history
Integration of IIIF and layouts for toponyms and front-end
  • Loading branch information
hepplerj authored Jun 10, 2024
2 parents 5aa0b44 + d8e5fda commit 8d14508
Show file tree
Hide file tree
Showing 13 changed files with 296 additions and 64 deletions.
2 changes: 2 additions & 0 deletions config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@

USE_TZ = True

# User authentication
LOGIN_REDIRECT_URL = "/admin/"

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
Expand Down
14 changes: 13 additions & 1 deletion manuscript/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,25 @@ class CodexAdmin(admin.ModelAdmin):
@admin.register(Location)
class LocationAdmin(ImportExportModelAdmin):
inlines = [LocationAliasInline]
list_display = ("country", "description_html", "latitude", "longitude", "id")
list_display = (
"country",
"description_html",
"latitude",
"longitude",
"get_related_folios",
"id",
)

def description_html(self, obj):
return format_html(obj.description) if obj.description else ""

description_html.short_description = "Description"

def get_related_folios(self, obj):
return ", ".join([str(folio.folio_number) for folio in obj.folio_set.all()])

get_related_folios.short_description = "Related folio"

def save_related(self, request, form, formsets, change):
super().save_related(request, form, formsets, change)
instance = form.instance
Expand Down
16 changes: 16 additions & 0 deletions manuscript/migrations/0075_remove_location_related_folio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Generated by Django 5.0.2 on 2024-06-07 16:15

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("manuscript", "0074_alter_stanzavariant_stanza"),
]

operations = [
migrations.RemoveField(
model_name="location",
name="related_folio",
),
]
23 changes: 7 additions & 16 deletions manuscript/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ class Folio(models.Model):
def __str__(self) -> str:
if self.folio_number is not None:
return f"Folio {self.folio_number}, from manuscript {self.manuscript}"
return f"Folio has no folio number but is associated with manuscript {self.manuscript}"
return f"Folio has no folio number, but is associated with manuscript {self.manuscript}"

class Meta:
ordering = ["folio_number"]
Expand Down Expand Up @@ -517,9 +517,9 @@ class Location(models.Model):
line_code = models.CharField(
blank=True, null=True, help_text="Citation line code.", max_length=510
)
related_folio = models.ForeignKey(
Folio, on_delete=models.CASCADE, blank=True, null=True
)
# related_folio = models.ForeignKey(
# Folio, on_delete=models.CASCADE, blank=True, null=True
# )
country = models.CharField(
max_length=255, blank=True, null=True, verbose_name="Modern country"
)
Expand Down Expand Up @@ -548,18 +548,9 @@ class Meta:
unique_together = ["country"]

def __str__(self) -> str:
if (
self.pk is not None
): # Only try to access locationalias_set if the Location has been saved
return ", ".join(
[
alias.placename_from_mss
for alias in self.locationalias_set.all()
if alias.placename_from_mss is not None
]
)
else:
return super().__str__()
return (
self.country if self.country is not None else "Missing modern country name"
)

def geocode(self):
if self.latitude is None or self.longitude is None:
Expand Down
7 changes: 5 additions & 2 deletions manuscript/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

urlpatterns = [
path("", views.index, name="index"),
path("manuscripts", views.manuscripts, name="manuscripts"),
path("stanzas", views.stanzas, name="stanzas"),
path("manuscripts/", views.manuscripts, name="manuscripts"),
path("manuscripts/<str:siglum>/", views.manuscript, name="manuscript"),
path("toponyms/", views.toponyms, name="toponyms"),
path("toponyms/<int:pk>/", views.toponym, name="toponym"),
path("stanzas/", views.stanzas, name="stanzas"),
]
53 changes: 47 additions & 6 deletions manuscript/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from collections import defaultdict
from html import unescape

from django.http import HttpRequest
from django.shortcuts import render
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic

from manuscript.models import SingleManuscript, Stanza
from manuscript.models import Location, SingleManuscript, Stanza


def index(request: HttpRequest):
Expand All @@ -18,11 +19,51 @@ def about(request: HttpRequest):

def stanzas(request: HttpRequest):
stanzas = Stanza.objects.all().order_by("stanza_line_code_starts")

books = defaultdict(lambda: defaultdict(list))
for stanza in stanzas:
stanza.stanza_text = unescape(stanza.stanza_text)
return render(request, "stanzas.html", {"stanzas": stanzas})
book_number = int(stanza.stanza_line_code_starts.split(".")[0])
stanza_number = int(stanza.stanza_line_code_starts.split(".")[1])

stanza.unescaped_stanza_text = unescape(stanza.stanza_text)
books[book_number][stanza_number].append(stanza)

books = {k: dict(v) for k, v in books.items()}

return render(request, "stanzas.html", {"stanzas": stanzas, "books": books})


def manuscripts(request: HttpRequest):
manuscripts = SingleManuscript.objects.all()
return render(request, "manuscripts.html", {"manuscripts": manuscripts})
manuscript_objs = SingleManuscript.objects.all()
return render(request, "manuscripts.html", {"manuscripts": manuscript_objs})


def manuscript(request: HttpRequest, siglum: str):
get_manuscript = get_object_or_404(SingleManuscript, siglum=siglum)
folios = get_manuscript.folio_set.prefetch_related("locations_mentioned").all()
return render(
request,
"manuscript_single.html",
{
"manuscript": get_manuscript,
"folios": folios,
"iiif_manifest": get_manuscript.iiif_url,
},
)


def toponyms(request: HttpRequest):
toponym_objs = Location.objects.all()
return render(request, "toponyms.html", {"toponyms": toponym_objs})


def toponym(request: HttpRequest, toponym_param: str):
filtered_toponym = get_object_or_404(Location, toponym=toponym_param)
filtered_manuscript = get_object_or_404(
SingleManuscript, folio__locations_mentioned__toponym=toponym_param
)
return render(
request,
"toponym.html",
{"toponym": filtered_toponym, "manuscript": filtered_manuscript},
)
14 changes: 14 additions & 0 deletions static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,17 @@ document.addEventListener("DOMContentLoaded", function () {
}
});
});

/* Hamburger menu navigation */
document.addEventListener("DOMContentLoaded", function () {
const menuToggle = document.getElementById("menu-toggle");
const menu = document.getElementById("menu");

menuToggle.addEventListener("click", function () {
if (menu.classList.contains("menu-hidden")) {
menu.classList.remove("menu-hidden");
} else {
menu.classList.add("menu-hidden");
}
});
});
45 changes: 28 additions & 17 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</head>
<body class="font-serif">
{% if request.resolver_match.url_name == 'index' %}
<header class="relative h-96 bg-cover bg-center" style="background-image: url('{% static 'images/troy.jpg' %}');">
<header class="relative h-screen bg-cover bg-center" style="background-image: url('{% static 'images/troy.jpg' %}');">
<div class="absolute inset-0 bg-black bg-opacity-50">
<div class="container mx-auto p-4 flex justify-between items-center">
<div class="flex items-center space-x-4">
Expand Down Expand Up @@ -80,12 +80,27 @@ <h1 class="text-white text-2xl">The La Sfera Project</h1>
</ul>
</nav>
</div>
<div class="container mx-auto h-72 flex items-center">
<div class="container mx-auto h-80 flex items-center">
<div class="text-left max-w-md">
<h2 class="text-white text-4xl">La Sfera: The Globe</h2>
<h2 class="text-white text-4xl">La Sfera: <em>The Globe</em></h2>
<p class="text-white mt-4">The La Sfera Project encompasses a number of different scholarly efforts exploring the Florentine merchant Gregorio Dati's treatise La sfera (The Globe), written sometime around 1430. It began with the <code>#lasferachallenge</code>, the social-media brainchild of Laura Morreale and Ben Albritton, in 2020, but has since expanded in multiple scholarly directions.</p>
</div>
</div>

<div class="container mx-auto mt-72 flex justify-between text-white">
<div class="bg-black bg-opacity-50 p-4 mx-20">
<h3 class="text-2xl">The Manuscript.</h3>
<p class="text-sm">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor,.</p>
</div>
<div class="bg-black bg-opacity-50 p-4 mx-20">
<h3 class="text-2xl">Mapping La Sfera.</h3>
<p class="text-sm">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor,.</p>
</div>
<div class="bg-black bg-opacity-50 p-4 mx-20">
<h3 class="text-2xl">Tracking La Sfera.</h3>
<p class="text-sm">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor,.</p>
</div>
</div>
</div>
</header>
{% else %}
Expand Down Expand Up @@ -165,7 +180,7 @@ <h1 class="text-white text-2xl">The La Sfera Project</h1>
<h5 class="block mb-6 text-xl antialiased font-semibold leading-snug tracking-normal text-inherit">
The La Sfera Project
</h5>
<div class="grid justify-between grid-cols-3 gap-4">
<div class="grid justify-between grid-cols-1 gap-4 md:grid-cols-4">
<ul>
<p
class="block mb-3 text-base antialiased font-medium leading-normal text-blue-gray-900 opacity-40">
Expand Down Expand Up @@ -261,18 +276,14 @@ <h5 class="block mb-6 text-xl antialiased font-semibold leading-snug tracking-no
Links
</a>
</li>
</ul>
<ul>
<p
class="block mb-3 text-base antialiased font-medium leading-normal text-blue-gray-900 opacity-40">
Administration
</p>
{% if user.is_authenticated %}
<li><a href="{% url 'admin:index' %}" class="underline hover:no-underline block py-1.5 text-sm font-normal leading-relaxed text-gray-700 antialiased transition-colors hover:text-blue-gray-900">Admin</a></li>
<li><a href="{% url 'logout' %}" class="underline hover:no-underline block py-1.5 text-sm font-normal leading-relaxed text-gray-700 antialiased transition-colors hover:text-blue-gray-900">Logout</a></li>
{% else %}
<li><a href="{% url 'login' %}" class="underline hover:no-underline block py-1.5 text-sm font-normal leading-relaxed text-gray-700 antialiased transition-colors hover:text-blue-gray-900">Login</a></li>
{% endif %}
<li class="mt-8">
{% if user.is_authenticated %}
<li><a href="{% url 'admin:index' %}" class="underline hover:no-underline block py-1.5 text-sm font-normal leading-relaxed text-gray-700 antialiased transition-colors hover:text-blue-gray-900">Admin</a></li>
<li><a href="{% url 'logout' %}" class="underline hover:no-underline block py-1.5 text-sm font-normal leading-relaxed text-gray-700 antialiased transition-colors hover:text-blue-gray-900">Logout</a></li>
{% else %}
<li><a href="{% url 'login' %}" class="underline hover:no-underline block py-1.5 text-sm font-normal leading-relaxed text-gray-700 antialiased transition-colors hover:text-blue-gray-900">Login</a></li>
{% endif %}
</li>
</ul>
</div>
</div>
Expand All @@ -282,7 +293,7 @@ <h5 class="block mb-6 text-xl antialiased font-semibold leading-snug tracking-no
class="flex flex-col items-center justify-center w-full py-4 mt-12 border-t border-blue-gray-50 md:flex-row md:justify-between">
<p
class="block mb-4 text-sm antialiased font-normal leading-normal text-center text-blue-gray-900 md:mb-0">
A project developed by the <a href="https://rrchnm.org">Roy Rosenzweig Center for History and New Media</a> at <a class="underline hover:no-underline" href="https://gmu.edu">George Mason University</a>.
A project developed by the <a class="underline hover:no-underline" href="https://rrchnm.org">Roy Rosenzweig Center for History and New Media</a> at <a class="underline hover:no-underline" href="https://gmu.edu">George Mason University</a>.
</p>
<div class="flex gap-4 text-blue-gray-900 sm:justify-center">
<a href="#"
Expand Down
68 changes: 68 additions & 0 deletions templates/manuscript_single.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{% extends "base.html" %}
{% load static %}

{% block title %}Manuscript - La Sfera{% endblock title %}

{% block content %}

<div class="flex justify-center mx-auto container">
<section id="manuscript" class="flex flex-col md:flex-row w-full p-4 my-10">
<div class="w-full md:w-2/5 p-2">
<h3 class="text-2xl pb-8" id="text">
Manuscript Metadata
</h3>

<p><strong>Siglum:</strong> {{ manuscript.siglum }}</p>
<p><strong>Library:</strong> {{ manuscript.library }}</p>
<p><strong>Shelfmark:</strong> {{ manuscript.shelfmark }}</p>

<h4 class="text-xl pt-8">Related Toponyms</h4>
{% for folio in folios %}
<p class="pb-1">Folio {{ folio.folio_number }}: {% for location in folio.locations_mentioned.all %}<a href="#" class="underline hover:no-underline">{{ location.country }}</a>{% empty %}No related toponyms.{% endfor %}<br></p>
{% empty %}
<p>No related folios.</p>
{% endfor %}

</div>

<div class="w-full md:w-3/5 p-2">
{% if manuscript.iiif_url %}
<div id="iiif-viewer" style="width: 100%; height: 600px;"></div>
{% else %}
<h3 class="text-lg">No IIIF manifest provided.</h3>
{% endif %}
</div>
</section>

</div>

{% endblock content %}

{% block scripts %}
<script src="{% static 'js/stanza.js' %}"></script>
<script src="https://unpkg.com/mirador@latest/dist/mirador.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/openseadragon/4.1.1/openseadragon.min.js" integrity="sha512-LbaoUnRCul2C+I4cdS/EMnMbynmZMU58AApBnZkhMzp/r8rOS7htjTsox7g6rf5ZXkSx56F5dDYmhLwqV1Zt4A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
const iiifUrl = "{{ iiif_url }}";
const viewer = OpenSeadragon({
id: "iiif-viewer",
preserveViewport: true,
visibilityRatio: 1,
minZoomLevel: 1,
defaultZoomLevel: 1,
sequenceMode: true,
tileSources: [{
"@context": "http://iiif.io/api/image/2/context.json",
"@id": iiifUrl,
"height": 7200,
"width": 5233,
"profile": [ "http://iiif.io/api/image/2/level2.json" ],
"protocol": "http://iiif.io/api/image",
"tiles": [{
"scaleFactors": [ 1, 2, 4, 8, 16, 32 ],
"width": 1024
}]
}]
});
</script>
{% endblock scripts %}
6 changes: 3 additions & 3 deletions templates/manuscripts.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ <h3 class="text-2xl pb-8" id="table">Table of manuscripts</a></h3>
<td class="border px-4 py-2">{{ manuscript.siglum }}</td>
<td class="border px-4 py-2">{{ manuscript.shelfmark }}</td>
<td class="border px-4 py-2">{{ manuscript.library }}</td>
<!-- <td class="border px-4 py-2">
<a href="/manuscript/{{ manuscript.id }}">Details</a>
</td> -->
<td class="border px-4 py-2">
<a class="underline hover:no-underline" href="/manuscripts/{{ manuscript.siglum }}">Details</a>
</td>
</tr>
{% endfor %}
</tbody>
Expand Down
32 changes: 32 additions & 0 deletions templates/registration/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{% extends "base.html" %}

{% block content %}
<div class="flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
<div class="max-w-md w-full space-y-8">
<div>
<h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900">
Log in to La Sfera
</h2>

<p>Only verified users are allowed to log into the content management system. If you believe you should have access please contact the project directors.</p>

</div>
<form method="post">
{% csrf_token %}
<div class="space-y-4">
<div>
<label for="username" class="block text-sm font-medium text-gray-700">Username</label>
<input type="text" name="username" id="username" class="w-full px-3 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div>
<label for="password" class="block text-sm font-medium text-gray-700">Password</label>
<input type="password" name="password" id="password" class="w-full px-3 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div>
<button type="submit" class="w-full px-4 py-2 font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700 focus:outline-none focus:ring focus:ring-blue-300">Login</button>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
Loading

0 comments on commit 8d14508

Please sign in to comment.