From de2789bd9960a29eae89aa04d95b49b19512a78a Mon Sep 17 00:00:00 2001 From: mohamad Date: Sun, 31 May 2026 12:45:05 +0330 Subject: [PATCH] fix button words --- apps/pages/admin.py | 4 +- .../migrations/0012_aboutsectionitem_icon.py | 20 +++++ apps/pages/models.py | 12 ++- apps/products/admin.py | 29 ++++++- .../0013_package_release_button_labels.py | 33 ++++++++ apps/products/models.py | 20 +++++ apps/products/release_context.py | 18 ++++- apps/products/views.py | 11 ++- static/css/main.css | 43 +++++++++++ templates/partials/_page_sections.html | 76 ++++++++++++++----- .../_section_featured_screenshots.html | 9 +++ templates/partials/_standard_item_card.html | 20 +++++ templates/products/_releases_section.html | 8 +- .../products/_versions_archive_body.html | 4 +- 14 files changed, 271 insertions(+), 36 deletions(-) create mode 100644 apps/pages/migrations/0012_aboutsectionitem_icon.py create mode 100644 apps/products/migrations/0013_package_release_button_labels.py create mode 100644 templates/partials/_section_featured_screenshots.html create mode 100644 templates/partials/_standard_item_card.html diff --git a/apps/pages/admin.py b/apps/pages/admin.py index 41b636a..8a4f22c 100644 --- a/apps/pages/admin.py +++ b/apps/pages/admin.py @@ -63,10 +63,10 @@ class HomepageSectionAdmin(admin.ModelAdmin): ) -class AboutSectionItemInline(admin.StackedInline): +class AboutSectionItemInline(admin.TabularInline): model = AboutSectionItem extra = 1 - fields = ("badge", "title", "content", "url", "image", "image_alt", "is_featured", "order") + fields = ("icon", "title", "content", "url", "image", "image_alt", "badge", "is_featured", "order") ordering = ("order",) diff --git a/apps/pages/migrations/0012_aboutsectionitem_icon.py b/apps/pages/migrations/0012_aboutsectionitem_icon.py new file mode 100644 index 0000000..a80749f --- /dev/null +++ b/apps/pages/migrations/0012_aboutsectionitem_icon.py @@ -0,0 +1,20 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("pages", "0011_custompagesectionitem_page_aboutsectionitem_url"), + ] + + operations = [ + migrations.AddField( + model_name="aboutsectionitem", + name="icon", + field=models.CharField( + blank=True, + help_text="Emoji or short symbol (e.g. ⚗️).", + max_length=20, + ), + ), + ] diff --git a/apps/pages/models.py b/apps/pages/models.py index 37ba61c..0420b56 100644 --- a/apps/pages/models.py +++ b/apps/pages/models.py @@ -98,6 +98,7 @@ class AboutSection(models.Model): TYPE_GRID = "grid" TYPE_HISTORY = "history" TYPE_CUSTOM = "custom" + TYPE_SUPPORTERS = "supporters" TYPE_CHOICES = [ (TYPE_HERO, "Hero"), @@ -105,6 +106,7 @@ class AboutSection(models.Model): (TYPE_GRID, "Grid Cards"), (TYPE_HISTORY, "History Block"), (TYPE_CUSTOM, "Custom Content"), + (TYPE_SUPPORTERS, "Supporters"), ] section_type = models.CharField(max_length=30, choices=TYPE_CHOICES, default=TYPE_CUSTOM) @@ -134,11 +136,17 @@ class AboutSection(models.Model): class AboutSectionItem(models.Model): section = models.ForeignKey(AboutSection, on_delete=models.CASCADE, related_name="items") + icon = models.CharField(max_length=20, blank=True, help_text="Emoji or short symbol (e.g. ⚗️).") badge = models.CharField(max_length=100, blank=True) title = models.CharField(max_length=300, blank=True) content = models.TextField(blank=True, help_text="Description text or link label for History links.") url = models.CharField(max_length=300, blank=True, help_text="Optional link; makes this item clickable.") - image = models.ImageField(upload_to="about/", blank=True, null=True) + image = models.ImageField( + upload_to="about/items/", + blank=True, + null=True, + help_text="Logo or image (used for Supporters cards).", + ) image_alt = models.CharField(max_length=200, blank=True) is_featured = models.BooleanField(default=False, help_text="Mark as featured item (e.g. large screenshot).") order = models.PositiveIntegerField(default=0) @@ -149,7 +157,7 @@ class AboutSectionItem(models.Model): verbose_name_plural = "About Section Items" def __str__(self): - return f"{self.section} › {self.title or self.badge or '(item)'}" + return f"{self.section} › {self.title or self.icon or self.badge or '(item)'}" class ContactSubmission(models.Model): diff --git a/apps/products/admin.py b/apps/products/admin.py index 38f720c..103d98f 100644 --- a/apps/products/admin.py +++ b/apps/products/admin.py @@ -83,7 +83,19 @@ class MainProductAdmin(admin.ModelAdmin): list_editable = ("order", "is_active", "show_on_homepage", "homepage_order") inlines = [MainProductArticleInline, MainProductVersionInline, SubProductInline] fieldsets = ( - (None, {"fields": ("name", "slug", "short_description", "distribution")}), + ( + None, + { + "fields": ( + "name", + "slug", + "short_description", + "distribution", + "package_resource_button_text", + "package_source_button_text", + ) + }, + ), ("Description", {"fields": ("description_format", "description")}), ("Media", {"fields": ("image",)}), ("Homepage", {"fields": ("show_on_homepage", "homepage_order")}), @@ -110,7 +122,20 @@ class SubProductAdmin(admin.ModelAdmin): raw_id_fields = ("main_product",) inlines = [SubProductArticleInline, SubProductVersionInline] fieldsets = ( - (None, {"fields": ("main_product", "name", "slug", "distribution", "short_description")}), + ( + None, + { + "fields": ( + "main_product", + "name", + "slug", + "distribution", + "short_description", + "package_resource_button_text", + "package_source_button_text", + ) + }, + ), ("Description", {"fields": ("description_format", "description")}), ("Media", {"fields": ("image", "logo")}), ("Homepage", {"fields": ("show_on_homepage", "homepage_order")}), diff --git a/apps/products/migrations/0013_package_release_button_labels.py b/apps/products/migrations/0013_package_release_button_labels.py new file mode 100644 index 0000000..b242665 --- /dev/null +++ b/apps/products/migrations/0013_package_release_button_labels.py @@ -0,0 +1,33 @@ +# Generated by Django 5.0.2 on 2026-05-31 09:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('products', '0012_migrate_homepage_visibility_to_mainproduct'), + ] + + operations = [ + migrations.AddField( + model_name='mainproduct', + name='package_resource_button_text', + field=models.CharField(default='PyPI', help_text='Label for the package resource button on package releases.', max_length=100), + ), + migrations.AddField( + model_name='mainproduct', + name='package_source_button_text', + field=models.CharField(default='Source', help_text='Label for the source code button on package releases.', max_length=100), + ), + migrations.AddField( + model_name='subproduct', + name='package_resource_button_text', + field=models.CharField(default='PyPI', help_text='Label for the package resource button on package releases.', max_length=100), + ), + migrations.AddField( + model_name='subproduct', + name='package_source_button_text', + field=models.CharField(default='Source', help_text='Label for the source code button on package releases.', max_length=100), + ), + ] diff --git a/apps/products/models.py b/apps/products/models.py index 220f6f2..1924b7a 100644 --- a/apps/products/models.py +++ b/apps/products/models.py @@ -36,6 +36,16 @@ class MainProduct(models.Model): default=DISTRIBUTION_INSTALLABLE, help_text="Only affects how releases appear on the public site.", ) + package_resource_button_text = models.CharField( + max_length=100, + default="PyPI", + help_text="Label for the package resource button on package releases.", + ) + package_source_button_text = models.CharField( + max_length=100, + default="Source", + help_text="Label for the source code button on package releases.", + ) order = models.PositiveIntegerField(default=0) is_active = models.BooleanField(default=True) show_on_homepage = models.BooleanField(default=False, help_text="Display this product in the homepage Products section.") @@ -99,6 +109,16 @@ class SubProduct(models.Model): default=DISTRIBUTION_INSTALLABLE, help_text="Only affects how releases appear on the public site.", ) + package_resource_button_text = models.CharField( + max_length=100, + default="PyPI", + help_text="Label for the package resource button on package releases.", + ) + package_source_button_text = models.CharField( + max_length=100, + default="Source", + help_text="Label for the source code button on package releases.", + ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) diff --git a/apps/products/release_context.py b/apps/products/release_context.py index 2a5438a..ffada6e 100644 --- a/apps/products/release_context.py +++ b/apps/products/release_context.py @@ -1,5 +1,17 @@ from .models import DISTRIBUTION_INSTALLABLE, DISTRIBUTION_PACKAGE, INSTALLABLE_PLATFORM_SPECS +DEFAULT_PACKAGE_RESOURCE_BUTTON_TEXT = "PyPI" +DEFAULT_PACKAGE_SOURCE_BUTTON_TEXT = "Source" + + +def package_button_labels(product): + resource = (getattr(product, "package_resource_button_text", "") or "").strip() + source = (getattr(product, "package_source_button_text", "") or "").strip() + return { + "package_resource_button_text": resource or DEFAULT_PACKAGE_RESOURCE_BUTTON_TEXT, + "package_source_button_text": source or DEFAULT_PACKAGE_SOURCE_BUTTON_TEXT, + } + def featured_version(qs): ordered = qs.order_by("order", "pk") @@ -16,7 +28,7 @@ def install_specs_from_versions(version_list): return tuple(s for s in INSTALLABLE_PLATFORM_SPECS if s[0] in present) -def build_release_context(distribution, active_versions): +def build_release_context(distribution, active_versions, product): context = { "distribution_installable": distribution == DISTRIBUTION_INSTALLABLE, "distribution_package": distribution == DISTRIBUTION_PACKAGE, @@ -25,6 +37,7 @@ def build_release_context(distribution, active_versions): "featured_install_cells": [], "show_older_versions_link": False, "package_versions": [], + **package_button_labels(product), } if distribution == DISTRIBUTION_INSTALLABLE: @@ -62,7 +75,7 @@ def build_release_context(distribution, active_versions): return context -def build_archive_context(distribution, active_versions): +def build_archive_context(distribution, active_versions, product): featured = featured_version(active_versions) archive = list( active_versions.exclude(pk=featured.pk).order_by("order", "pk") @@ -72,6 +85,7 @@ def build_archive_context(distribution, active_versions): context = { "featured_version": featured, "archive_versions": archive, + **package_button_labels(product), } if distribution == DISTRIBUTION_INSTALLABLE: diff --git a/apps/products/views.py b/apps/products/views.py index 0cea905..752ca7a 100644 --- a/apps/products/views.py +++ b/apps/products/views.py @@ -31,6 +31,7 @@ class MainProductDetailView(DetailView): release_context = build_release_context( self.object.distribution, self.object.versions.filter(is_active=True), + self.object, ) release_context["versions_archive_url"] = self.object.get_versions_archive_url() context.update(release_context) @@ -52,7 +53,9 @@ class MainProductOlderVersionsView(TemplateView): context["sub_product"] = None context["product_detail_url"] = main_product.get_absolute_url() context.update( - build_archive_context(main_product.distribution, active_versions) + build_archive_context( + main_product.distribution, active_versions, main_product + ) ) return context @@ -85,7 +88,7 @@ class SubProductDetailView(TemplateView): ) active_versions = sub_product.versions.filter(is_active=True) release_context = build_release_context( - sub_product.distribution, active_versions + sub_product.distribution, active_versions, sub_product ) release_context["versions_archive_url"] = sub_product.get_versions_archive_url() context.update(release_context) @@ -113,6 +116,8 @@ class SubProductOlderVersionsView(TemplateView): context["sub_product"] = sub_product context["product_detail_url"] = sub_product.get_absolute_url() context.update( - build_archive_context(sub_product.distribution, active_versions) + build_archive_context( + sub_product.distribution, active_versions, sub_product + ) ) return context diff --git a/static/css/main.css b/static/css/main.css index 036c20e..6805f6c 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -839,6 +839,12 @@ h1, h2, h3, h4, h5, h6 { font-size: 2rem; margin-bottom: 1rem; display: block; + line-height: 1; +} + +.feature-icon--inline { + font-size: 1.25rem; + margin-bottom: 0.35rem; } .feature-title { @@ -1727,6 +1733,43 @@ a.citation-count-badge:hover { padding: 1.75rem; } +.history-link-icon { + margin-right: 0.35rem; +} + +.history-visual-image { + position: relative; + z-index: 2; + max-width: 100%; + max-height: 160px; + object-fit: contain; + border-radius: var(--radius-sm); +} + +.about-hero-gallery { + margin-top: 2.5rem; +} + +.about-section-screenshots { + margin-top: 1.5rem; +} + +.about-hero-gallery:not(:has(.screenshot-item)) { + display: none; +} + +.about-section-screenshots:not(:has(.screenshot-item)) { + display: none; +} + +.standards-grid:not(:has(.standard-card)) { + display: none; +} + +.history-visual:has(.history-visual-image) .history-year { + display: none; +} + .standard-badge { display: inline-block; font-size: 0.7rem; diff --git a/templates/partials/_page_sections.html b/templates/partials/_page_sections.html index d52c3d1..08571c9 100644 --- a/templates/partials/_page_sections.html +++ b/templates/partials/_page_sections.html @@ -17,6 +17,23 @@ {% if section.subtitle %}

{{ section.subtitle }}

{% endif %} {% if section.content %}
{{ section.rendered_content }}
{% endif %} + {% with items=section.items.all %} + {% if items %} + + {% endif %} + {% endwith %} @@ -31,6 +48,19 @@ {% endif %} + {% with items=section.items.all %} + {% if items %} +
+ {% for item in items %} + {% if item.is_featured and item.image %} + {% else %} + {% include "partials/_standard_item_card.html" with item=item %} + {% endif %} + {% endfor %} +
+ {% include "partials/_section_featured_screenshots.html" with items=items %} + {% endif %} + {% endwith %} @@ -48,13 +78,13 @@ {% if items %}
{% for item in items %} - {% include "partials/_linked_card_open.html" with url=item.url card_class="standard-card" %} - {% if item.badge %}
{{ item.badge }}
{% endif %} - {% if item.title %}

{{ item.title }}

{% endif %} - {% if item.content %}

{{ item.content }}

{% endif %} - {% include "partials/_linked_card_close.html" with url=item.url %} + {% if item.is_featured and item.image %} + {% else %} + {% include "partials/_standard_item_card.html" with item=item %} + {% endif %} {% endfor %}
+ {% include "partials/_section_featured_screenshots.html" with items=items %} {% endif %} {% endwith %} @@ -64,27 +94,35 @@
+ {% with links=section.items.all %}
{% if section.badge %}
{{ section.badge }}
{% endif %} {% if section.title %}

{{ section.title }}

{% endif %} {% if section.content %}
{{ section.rendered_content }}
{% endif %} - {% with links=section.items.all %} {% if links %} {% endif %} - {% endwith %}
+ {% endwith %}
@@ -107,13 +145,13 @@ {% if items %}
{% for item in items %} - {% include "partials/_linked_card_open.html" with url=item.url card_class="standard-card" %} - {% if item.badge %}
{{ item.badge }}
{% endif %} - {% if item.title %}

{{ item.title }}

{% endif %} - {% if item.content %}

{{ item.content }}

{% endif %} - {% include "partials/_linked_card_close.html" with url=item.url %} + {% if item.is_featured and item.image %} + {% else %} + {% include "partials/_standard_item_card.html" with item=item %} + {% endif %} {% endfor %}
+ {% include "partials/_section_featured_screenshots.html" with items=items %} {% endif %} {% endwith %} @@ -125,7 +163,7 @@
{% if section.badge %}
{{ section.badge }}
{% endif %} {% if section.title %}

{{ section.title }}

{% endif %} - {% if section.description %}

{{ section.description }}

{% endif %} + {% if section.description %}

{{ section.description }}

{% elif section.content %}
{{ section.rendered_content }}
{% endif %}
{% for item in section.items.all %} @@ -145,7 +183,7 @@
{% if section.badge %}
{{ section.badge }}
{% endif %} {% if section.title %}

{{ section.title }}

{% endif %} - {% if section.description %}

{{ section.description }}

{% endif %} + {% if section.description %}

{{ section.description }}

{% elif section.content %}
{{ section.rendered_content }}
{% endif %}
{% for item in section.items.all %} @@ -179,7 +217,7 @@
{% if section.badge %}
{{ section.badge }}
{% endif %} {% if section.title %}

{{ section.title }}

{% endif %} - {% if section.description %}

{{ section.description }}

{% endif %} + {% if section.description %}

{{ section.description }}

{% elif section.content %}
{{ section.rendered_content }}
{% endif %}
{% for product in homepage_products %} @@ -213,7 +251,7 @@
{% if section.badge %}
{{ section.badge }}
{% endif %} {% if section.title %}

{{ section.title }}

{% endif %} - {% if section.description %}

{{ section.description }}

{% endif %} + {% if section.description %}

{{ section.description }}

{% elif section.content %}
{{ section.rendered_content }}
{% endif %}
{% for product in homepage_products_catalog %} @@ -259,7 +297,7 @@
{% if section.badge %}
{{ section.badge }}
{% endif %} {% if section.title %}

{{ section.title }}

{% endif %} - {% if section.description %}

{{ section.description }}

{% endif %} + {% if section.description %}

{{ section.description }}

{% elif section.content %}
{{ section.rendered_content }}
{% endif %}
{% for item in section.items.all %} @@ -279,7 +317,7 @@
{% if section.badge %}
{{ section.badge }}
{% endif %} {% if section.title %}

{{ section.title }}

{% endif %} - {% if section.description %}

{{ section.description }}

{% endif %} + {% if section.description %}

{{ section.description }}

{% elif section.content %}
{{ section.rendered_content }}
{% endif %}
{% for item in section.items.all %} diff --git a/templates/partials/_section_featured_screenshots.html b/templates/partials/_section_featured_screenshots.html new file mode 100644 index 0000000..174bbe7 --- /dev/null +++ b/templates/partials/_section_featured_screenshots.html @@ -0,0 +1,9 @@ +
+ {% for item in items %} + {% if item.is_featured and item.image %} + {% include "partials/_linked_card_open.html" with url=item.url card_class="screenshot-item fade-in screenshot-item--featured" %} + {{ item.image_alt|default:item.title }} + {% include "partials/_linked_card_close.html" with url=item.url %} + {% endif %} + {% endfor %} +
diff --git a/templates/partials/_standard_item_card.html b/templates/partials/_standard_item_card.html new file mode 100644 index 0000000..34765c8 --- /dev/null +++ b/templates/partials/_standard_item_card.html @@ -0,0 +1,20 @@ +{% if item.image %} +{% include "partials/_linked_card_open.html" with url=item.url card_class="supporter-card" %} + +
+ {% if item.icon %}{% endif %} + {% if item.badge %}
{{ item.badge }}
{% endif %} + {% if item.title %}

{{ item.title }}

{% endif %} + {% if item.content %}

{{ item.content }}

{% endif %} +
+{% include "partials/_linked_card_close.html" with url=item.url %} +{% else %} +{% include "partials/_linked_card_open.html" with url=item.url card_class="feature-card" %} + {% if item.icon %}{% endif %} + {% if item.badge %}
{{ item.badge }}
{% endif %} + {% if item.title %}

{{ item.title }}

{% endif %} + {% if item.content %}

{{ item.content }}

{% endif %} +{% include "partials/_linked_card_close.html" with url=item.url %} +{% endif %} diff --git a/templates/products/_releases_section.html b/templates/products/_releases_section.html index a649ceb..9b1e701 100644 --- a/templates/products/_releases_section.html +++ b/templates/products/_releases_section.html @@ -34,7 +34,7 @@ {% endif %}
{{ cell.label }} - v{{ featured_version.version }} + {{ featured_version.version }} {% if cell.label == "Source code" %}Source{% else %}Download{% endif %}
{% endfor %} @@ -72,7 +72,7 @@ {% for ver in package_versions %}
  • - v{{ ver.version }} + {{ ver.version }} {% if ver.is_featured_stable %}
    {% if ver.package_resource_url %} - Open + {{ package_resource_button_text }} {% endif %} {% if ver.source_code_url %} - Source + {{ package_source_button_text }} {% endif %}
    {% if ver.release_notes %} diff --git a/templates/products/_versions_archive_body.html b/templates/products/_versions_archive_body.html index ea1881f..f530a5f 100644 --- a/templates/products/_versions_archive_body.html +++ b/templates/products/_versions_archive_body.html @@ -50,9 +50,9 @@ {% for ver in archive_versions %}
  • - v{{ ver.version }} + {{ ver.version }} {% if ver.package_resource_url %} - Open + {{ package_resource_button_text }} {% endif %}
    {% if ver.release_notes %}