diff --git a/scipost_django/organizations/admin.py b/scipost_django/organizations/admin.py index 0f8da52cfc363b0c09cc419d75a8fea1d92d9d8c..6847805e893c5d11d2bef701f2bcb3a91655bd1f 100644 --- a/scipost_django/organizations/admin.py +++ b/scipost_django/organizations/admin.py @@ -6,8 +6,19 @@ from django.contrib import admin from guardian.admin import GuardedModelAdmin -from .models import Organization, OrganizationEvent, ContactPerson, Contact, ContactRole - +from .models import ( + Organization, + OrganizationLogo, + OrganizationEvent, + ContactPerson, + Contact, + ContactRole, +) + + +class OrganizationLogoInline(admin.TabularInline): + model = OrganizationLogo + extra = 0 class OrganizationEventInline(admin.TabularInline): model = OrganizationEvent @@ -21,6 +32,7 @@ class ContactPersonInline(admin.TabularInline): class OrganizationAdmin(GuardedModelAdmin): inlines = [ + OrganizationLogoInline, OrganizationEventInline, ContactPersonInline, ] diff --git a/scipost_django/organizations/migrations/0014_auto_20220220_0946.py b/scipost_django/organizations/migrations/0014_auto_20220220_0946.py new file mode 100644 index 0000000000000000000000000000000000000000..8babd78198009fff81d581c96f8eeaf9d6be8db4 --- /dev/null +++ b/scipost_django/organizations/migrations/0014_auto_20220220_0946.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.12 on 2022-02-20 08:46 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('organizations', '0013_auto_20210716_0926'), + ] + + operations = [ + migrations.CreateModel( + name='OrganizationLogo', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image', models.ImageField(blank=True, upload_to='organizations/logos/')), + ('mimetype', models.CharField(choices=[('gif', 'gif'), ('jpg', 'jpg'), ('png', 'png'), ('tif', 'tif'), ('webp', 'webp')], max_length=8)), + ('width', models.PositiveSmallIntegerField()), + ('height', models.PositiveSmallIntegerField()), + ('order', models.PositiveSmallIntegerField()), + ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='logos', to='organizations.organization')), + ], + options={ + 'ordering': ('organization', 'order'), + }, + ), + migrations.AddConstraint( + model_name='organizationlogo', + constraint=models.UniqueConstraint(fields=('organization', 'order'), name='unique_together_organization_order'), + ), + ] diff --git a/scipost_django/organizations/models.py b/scipost_django/organizations/models.py index ff3b1dbc60b809406c5f50b50f871d32873f258e..6e39ddac12de17277f79a25b8881d3f0a146c460 100644 --- a/scipost_django/organizations/models.py +++ b/scipost_django/organizations/models.py @@ -35,6 +35,53 @@ from journals.models import Journal, Publication, OrgPubFraction from profiles.models import Profile +class OrganizationLogo(models.Model): + """ + Logo of an Organization, with rendering info, for a `source` HTML tag. + """ + + MIMETYPE_GIF = 'gif' + MIMETYPE_JPG = 'jpg' + MIMETYPE_PNG = 'png' + MIMETYPE_TIF = 'tif' + MITETYPE_WEBP = 'webp' + MIMETYPE_CHOICES = ( + (MIMETYPE_GIF, 'gif'), + (MIMETYPE_JPG, 'jpg'), + (MIMETYPE_PNG, 'png'), + (MIMETYPE_TIF, 'tif'), + (MITETYPE_WEBP, 'webp'), + ) + organization = models.ForeignKey( + "organizations.Organization", + related_name="logos", + on_delete=models.CASCADE, + ) + image = models.ImageField(upload_to="organizations/logos/", blank=True) + mimetype = models.CharField(max_length=8, choices=MIMETYPE_CHOICES) + width = models.PositiveSmallIntegerField() + height = models.PositiveSmallIntegerField() + order = models.PositiveSmallIntegerField() + + class Meta: + constraints = [ + models.UniqueConstraint( + fields=["organization", "order"], + name="unique_together_organization_order", + ), + ] + ordering = ("organization", "order",) + + def __str__(self): + return (f"Logo ({self.mimetype}, w={self.width}, h={self.height}) " + f"for {self.organization.name}") + + def save(self, *args, **kwargs): + if not self.order: + self.order = self.organization.logos.count() + 1 + return super().save(*args, **kwargs) + + class Organization(models.Model): """ An Organization instance is any type of administrative unit which SciPost diff --git a/scipost_django/organizations/templates/organizations/_organization_detail_contents.html b/scipost_django/organizations/templates/organizations/_organization_detail_contents.html index 3c69914205706421e08c806af6e38a372f61b8fb..fea574327b9a82ca599e9148efdee758b86dff29 100644 --- a/scipost_django/organizations/templates/organizations/_organization_detail_contents.html +++ b/scipost_django/organizations/templates/organizations/_organization_detail_contents.html @@ -43,7 +43,16 @@ </table> </div> <div class="col-6"> - {% if org.logo %} + {% if org.logos %} + <li class="p-2"> + <picture> + {% for source in org.logos.all %} + <source type="{{ source.mimetype }}" srcset="{{ source.image.url }} {{ source.width }}w"> + {% endfor %} + <img class="rounded" style="max-height: 8rem; max-width: 16rem;" + src="{{ org.logo.url }}" alt="{{ org.name }} logo"> + </li> + {% elif org.logo %} <img class="d-flex me-3 {{ org.css_class }}" src="{{ org.logo.url }}" alt="image"/> {% endif %} </div> diff --git a/scipost_django/scipost/templates/scipost/_hx_sponsors.html b/scipost_django/scipost/templates/scipost/_hx_sponsors.html index ac34c8fe2a940cce18396d5bd8d7e86fc3910b1f..dba026e7e31812cd177b7a4e28a91473c522bdee 100644 --- a/scipost_django/scipost/templates/scipost/_hx_sponsors.html +++ b/scipost_django/scipost/templates/scipost/_hx_sponsors.html @@ -9,7 +9,16 @@ > <ul class="list list-unstyled"> {% for sponsor in current_sponsors %} - {% if sponsor.logo %} + {% if sponsor.logos %} + <li class="p-2"> + <picture> + {% for source in sponsor.logos.all %} + <source type="{{ source.mimetype }}" srcset="{{ source.image.url }} {{ source.width }}w"> + {% endfor %} + <img class="rounded" style="max-height: 8rem; max-width: 16rem;" + src="{{ sponsor.logo.url }}" alt="{{ sponsor.name }} logo"> + </li> + {% elif sponsor.logo %} <li class="p-2"> <img class="rounded" style="max-height: 8rem; max-width: 16rem;" src="{{ sponsor.logo.url }}" alt="{{ sponsor.name }} logo">