mirror of
https://github.com/boostorg/website-v2.git
synced 2026-01-19 16:52:16 +00:00
Added library graphic; sorting by library "great","good","standard" (#1624)
This commit is contained in:
11
core/custom_model_fields.py
Normal file
11
core/custom_model_fields.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from django.db import models
|
||||
from django.db.models.fields.files import FieldFile
|
||||
|
||||
|
||||
class NullableFileField(models.FileField):
|
||||
def get_db_prep_value(self, value, connection, prepared=False):
|
||||
if isinstance(value, FieldFile):
|
||||
if not value.name:
|
||||
return None
|
||||
value = value.name
|
||||
return super().get_db_prep_value(value, connection, prepared)
|
||||
@@ -1,7 +1,7 @@
|
||||
import io
|
||||
import base64
|
||||
from functools import cached_property
|
||||
from itertools import groupby
|
||||
from itertools import groupby, chain
|
||||
from operator import attrgetter
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import date, timedelta
|
||||
@@ -271,14 +271,18 @@ class CreateReportForm(CreateReportFullForm):
|
||||
)
|
||||
|
||||
def _get_top_libraries_for_version(self):
|
||||
return (
|
||||
self.library_queryset.filter(
|
||||
library_version=LibraryVersion.objects.filter(
|
||||
library=OuterRef("id"), version=self.cleaned_data["version"]
|
||||
)[:1],
|
||||
base_queryset = self.library_queryset.filter(
|
||||
library_version=LibraryVersion.objects.filter(
|
||||
library=OuterRef("id"), version=self.cleaned_data["version"]
|
||||
)[:1],
|
||||
).order_by("name")
|
||||
# returns "great", "good", and "standard" libraries in that order
|
||||
return list(
|
||||
chain(
|
||||
base_queryset.filter(graphic__isnull=False),
|
||||
base_queryset.filter(graphic__isnull=True, is_good=True),
|
||||
base_queryset.filter(graphic__isnull=True, is_good=False),
|
||||
)
|
||||
.annotate(commit_count=Count("library_version__commit"))
|
||||
.order_by("-commit_count")
|
||||
)
|
||||
|
||||
def _get_library_version_counts(self, libraries, library_order):
|
||||
@@ -703,15 +707,11 @@ class CreateReportForm(CreateReportFullForm):
|
||||
top_libraries_for_version = self._get_top_libraries_for_version()
|
||||
library_order = self._get_library_order(top_libraries_for_version)
|
||||
libraries = Library.objects.filter(id__in=library_order)
|
||||
library_names = (
|
||||
LibraryVersion.objects.filter(
|
||||
version=version,
|
||||
library__in=self.library_queryset,
|
||||
)
|
||||
.annotate(name=F("library__name"))
|
||||
.order_by("name")
|
||||
.values_list("name", flat=True)
|
||||
)
|
||||
all_libraries = Library.objects.filter(
|
||||
library_version__version=version,
|
||||
library_version__library__in=self.library_queryset,
|
||||
).order_by("name")
|
||||
|
||||
library_data = [
|
||||
{
|
||||
"library": item[0],
|
||||
@@ -810,7 +810,7 @@ class CreateReportForm(CreateReportFullForm):
|
||||
"top_libraries_for_version": top_libraries_for_version,
|
||||
"library_count": library_count,
|
||||
"library_count_prior": library_count_prior,
|
||||
"library_names": library_names,
|
||||
"all_libraries": all_libraries,
|
||||
"added_library_count": added_library_count,
|
||||
"removed_library_count": removed_library_count,
|
||||
"downloads": downloads,
|
||||
|
||||
41
libraries/migrations/0028_library_graphic_library_is_good.py
Normal file
41
libraries/migrations/0028_library_graphic_library_is_good.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# Generated by Django 4.2.16 on 2025-02-05 21:58
|
||||
|
||||
import core.custom_model_fields
|
||||
import core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("libraries", "0027_libraryversion_dependencies"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="library",
|
||||
name="graphic",
|
||||
field=core.custom_model_fields.NullableFileField(
|
||||
blank=True,
|
||||
default=None,
|
||||
null=True,
|
||||
upload_to="library_graphics",
|
||||
validators=[
|
||||
core.validators.FileTypeValidator(
|
||||
extensions=[".jpg", ".jpeg", ".png"]
|
||||
),
|
||||
core.validators.MaxFileSizeValidator(max_size=1048576),
|
||||
],
|
||||
verbose_name="Library Graphic",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="library",
|
||||
name="is_good",
|
||||
field=models.BooleanField(
|
||||
default=False,
|
||||
help_text="Is this library considered 'good' by the Boost community?",
|
||||
verbose_name="Good Library",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -8,10 +8,11 @@ from django.db.models import Sum
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.text import slugify
|
||||
from django.db.models.functions import Upper
|
||||
|
||||
from core.custom_model_fields import NullableFileField
|
||||
from core.markdown import process_md
|
||||
from core.models import RenderedContent
|
||||
from core.asciidoc import convert_adoc_to_html
|
||||
from core.validators import image_validator, max_file_size_validator
|
||||
from libraries.managers import IssueManager
|
||||
from mailing_list.models import EmailData
|
||||
from .constants import LIBRARY_GITHUB_URL_OVERRIDES
|
||||
@@ -151,6 +152,19 @@ class Library(models.Model):
|
||||
description = models.TextField(
|
||||
blank=True, null=True, help_text="The description of the library."
|
||||
) # holds the most recent version's description
|
||||
graphic = NullableFileField(
|
||||
upload_to="library_graphics",
|
||||
blank=True,
|
||||
null=True,
|
||||
default=None,
|
||||
validators=[image_validator, max_file_size_validator],
|
||||
verbose_name="Library Graphic",
|
||||
)
|
||||
is_good = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name="Good Library",
|
||||
help_text="Is this library considered 'good' by the Boost community?",
|
||||
)
|
||||
github_url = models.URLField(
|
||||
max_length=500,
|
||||
blank=True,
|
||||
@@ -216,6 +230,15 @@ class Library(models.Model):
|
||||
|
||||
return "".join(processed_segments)
|
||||
|
||||
@cached_property
|
||||
def group(self):
|
||||
if self.graphic:
|
||||
return "great"
|
||||
elif self.is_good:
|
||||
return "good"
|
||||
else:
|
||||
return "standard"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
@@ -315,9 +315,14 @@ body {
|
||||
<div class="flex flex-col h-full mx-auto w-full">
|
||||
<h2 class="mx-auto">Library Index</h2>
|
||||
<div class="flex flex-col flex-wrap gap-x-4 gap-y-1 text-xs h-5/6">
|
||||
{% for name in library_names %}
|
||||
{% for library in all_libraries %}
|
||||
<div class="max-w-[10rem]">
|
||||
{{ name }}
|
||||
{{ library.name }}
|
||||
{% if library.group == "great" %}
|
||||
<i class="text-orange fa-solid fa-star"></i>
|
||||
{% elif library.group == "good" %}
|
||||
<i class="text-orange fa-regular fa-star"></i>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@@ -325,29 +330,13 @@ body {
|
||||
{% include "admin/_release_report_page_footer.html" %}
|
||||
</div>
|
||||
{% for item in library_data %}
|
||||
<div class="pdf-page flex flex-col items-center justify-center {{ bg_color }}">
|
||||
<div class="pdf-page flex flex-col {{ bg_color }}">
|
||||
<div class="grid grid-cols-3 gap-x-8 w-full p-4">
|
||||
<div class="px-4">
|
||||
<div class="mx-auto mb-6">Top Contributors</div>
|
||||
<div class="m-auto grid grid-cols-1 gap-2">
|
||||
{% for author in item.top_contributors_release %}
|
||||
<div class="flex flex-row gap-y-2 w-40 items-center">
|
||||
{% avatar commitauthor=author %}
|
||||
<div class="w-full flex flex-col ml-2">
|
||||
<div class="text-[0.8rem] font-semibold overflow-ellipsis overflow-hidden whitespace-nowrap w-full">
|
||||
{{ author.name }}
|
||||
</div>
|
||||
<div class="text-[0.7rem]"><span class="font-bold">{{ author.commit_count }}</span> commit{{ author.commit_count|pluralize }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-2 flex flex-col gap-y-4">
|
||||
<div>
|
||||
<h2 class="text-orange mb-1 mt-0">{{ item.library.name }}</h2>
|
||||
<div class="flex flex-col gap-y-4">
|
||||
<h2 class="text-orange mb-1 mt-0">{{ item.library.display_name }}</h2>
|
||||
<div>{{ item.library.description }}</div>
|
||||
{% if item.library.graphic %}<div><img src="{{ item.library.graphic.url }}" alt="" /></div>{% endif %}
|
||||
</div>
|
||||
<div class="flex flex-col gap-y-1">
|
||||
<div>
|
||||
@@ -382,6 +371,22 @@ body {
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4">
|
||||
<div class="mx-auto mb-6">Top Contributors</div>
|
||||
<div class="m-auto grid grid-cols-1 gap-2">
|
||||
{% for author in item.top_contributors_release %}
|
||||
<div class="flex flex-row gap-y-2 w-40 items-center">
|
||||
{% avatar commitauthor=author %}
|
||||
<div class="w-full flex flex-col ml-2">
|
||||
<div class="text-[0.8rem] font-semibold overflow-ellipsis overflow-hidden whitespace-nowrap w-full">
|
||||
{{ author.name }}
|
||||
</div>
|
||||
<div class="text-[0.7rem]"><span class="font-bold">{{ author.commit_count }}</span> commit{{ author.commit_count|pluralize }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "admin/_release_report_page_footer.html" %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user