UI: Improve multi OS display #205
@ -100,13 +100,120 @@
|
|||||||
const btnInstallAction = document.querySelector('.js-btn-install-action');
|
const btnInstallAction = document.querySelector('.js-btn-install-action');
|
||||||
const btnInstallGroup = document.querySelector('.js-btn-install-group');
|
const btnInstallGroup = document.querySelector('.js-btn-install-group');
|
||||||
|
|
||||||
|
const dropdownAllVersionsItemDot = document.querySelectorAll('.js-dropdown-all-versions-item-dot');
|
||||||
|
const dropdownAllVersionsItemIcon = document.querySelectorAll('.js-dropdown-all-versions-item-icon');
|
||||||
|
const dropdownAllVersionsWrapper = document.querySelector('.js-dropdown-all-versions-wrapper');
|
||||||
|
|
||||||
// Create variables multiple
|
// Create variables multiple
|
||||||
const btnInstallActionItem = document.querySelectorAll('.js-btn-install-action-item');
|
const btnInstallActionItem = document.querySelectorAll('.js-btn-install-action-item');
|
||||||
|
|
||||||
|
// Create function isArchARM
|
||||||
|
function isArchARM() {
|
||||||
|
// Check if userAgentData and getHighEntropyValues are supported
|
||||||
|
if (navigator.userAgentData && navigator.userAgentData.getHighEntropyValues) {
|
||||||
|
navigator.userAgentData
|
||||||
|
.getHighEntropyValues(["architecture"])
|
||||||
|
.then((values) => {
|
||||||
|
// Extract the architecture value
|
||||||
|
const arch = values.architecture;
|
||||||
|
// Check if the architecture is ARM
|
||||||
|
if (arch.toLowerCase().includes('arm')) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Fallback for browsers that do not support userAgentData or getHighEntropyValues
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (btnInstall == null) {
|
if (btnInstall == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hide dropdownAllVersionsWrapper by default
|
||||||
|
dropdownAllVersionsWrapper.classList.add('d-none');
|
||||||
|
|
||||||
|
// Show multi OS install buttons based on active platform
|
||||||
|
if (btnInstallActionItem.length > 1) {
|
||||||
|
// Show dropdownAllVersionsWrapper
|
||||||
|
dropdownAllVersionsWrapper.classList.remove('d-none');
|
||||||
|
|
||||||
|
// Get active platform
|
||||||
|
|
||||||
|
/*
|
||||||
|
The navigator objects' 'platform' proporties are arbitrary, and specific to the browser.
|
||||||
|
|
||||||
|
For a light match, we can use the first 3 characters of the platform string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const activePlatform = navigator.platform.toLowerCase();
|
||||||
|
const activePlatformPrefix = activePlatform.substring(0, 3);
|
||||||
|
|
||||||
|
btnInstallActionItem.forEach(function(item) {
|
||||||
|
// Hide all items by default
|
||||||
|
item.classList.add('d-none');
|
||||||
|
|
||||||
|
// Hide dropdownAllVersionsItemDot by default
|
||||||
|
dropdownAllVersionsItemDot.forEach(function(item) {
|
||||||
|
item.classList.add('d-none');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Style dropdownAllVersionsItemIcon by default
|
||||||
|
dropdownAllVersionsItemIcon.forEach(function(item) {
|
||||||
|
item.classList.add('text-muted');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get item platform
|
||||||
|
const itemPlatform = item.getAttribute('data-platform');
|
||||||
|
const itemPlatformBase = itemPlatform.split('-')[0];
|
||||||
|
const itemPlatformBasePrefix = itemPlatformBase.substring(0, 3);
|
||||||
|
|
||||||
|
// Show button if item platform matches active platform
|
||||||
|
if (itemPlatformBasePrefix.startsWith(activePlatformPrefix)) {
|
||||||
|
item.classList.add('btn-install-action-item-active');
|
||||||
|
item.classList.remove('d-none');
|
||||||
|
|
||||||
|
// TODO: WIP show only relevant item for active macOS architecture, if architecture detection reliably works
|
||||||
|
if (activePlatformPrefix.startsWith('mac')) {
|
||||||
|
if (isArchARM()) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: refactor and DRY code
|
||||||
|
dropdownAllVersionsItemDot.forEach(function(item) {
|
||||||
|
// TODO: create named function to not repeat this (optional)
|
||||||
|
// Get item platform
|
||||||
|
const itemPlatform = item.getAttribute('data-platform');
|
||||||
|
const itemPlatformBase = itemPlatform.split('-')[0];
|
||||||
|
const itemPlatformBasePrefix = itemPlatformBase.substring(0, 3);
|
||||||
|
|
||||||
|
// Show dropdownAllVersionsItemDot if item platform matches active platform
|
||||||
|
if (itemPlatformBasePrefix.startsWith(activePlatformPrefix)) {
|
||||||
|
item.classList.remove('d-none');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dropdownAllVersionsItemIcon.forEach(function(item) {
|
||||||
|
// Get item platform
|
||||||
|
const itemPlatform = item.getAttribute('data-platform');
|
||||||
|
const itemPlatformBase = itemPlatform.split('-')[0];
|
||||||
|
const itemPlatformBasePrefix = itemPlatformBase.substring(0, 3);
|
||||||
|
|
||||||
|
// Show dropdownAllVersionsItemIcon if item platform matches active platform
|
||||||
|
if (itemPlatformBasePrefix.startsWith(activePlatformPrefix)) {
|
||||||
|
item.classList.remove('text-muted');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Show btnInstallAction
|
// Show btnInstallAction
|
||||||
btnInstall.addEventListener('click', function() {
|
btnInstall.addEventListener('click', function() {
|
||||||
// Hide btnInstallGroup
|
// Hide btnInstallGroup
|
||||||
|
@ -167,8 +167,9 @@
|
|||||||
.btn-install-action-item
|
.btn-install-action-item
|
||||||
+margin(3, bottom)
|
+margin(3, bottom)
|
||||||
|
|
||||||
&:last-child
|
.btn-install-action-item-active ~ .btn-install-action-item-active
|
||||||
+margin(0, bottom)
|
border-top: thin solid var(--border-color)
|
||||||
|
+padding(3, top)
|
||||||
|
|
||||||
.btn-install-drag,
|
.btn-install-drag,
|
||||||
.btn-install-drag:active
|
.btn-install-drag:active
|
||||||
@ -474,3 +475,11 @@ a
|
|||||||
|
|
||||||
.featured-image-preview
|
.featured-image-preview
|
||||||
width: 16rem
|
width: 16rem
|
||||||
|
|
||||||
|
.dropdown-all-versions-item-dot
|
||||||
|
background-color: var(--color-accent)
|
||||||
|
border-radius: 50%
|
||||||
|
height: var(--spacer-1)
|
||||||
|
position: absolute
|
||||||
|
transform: translateX(-1.2rem)
|
||||||
|
width: var(--spacer-1)
|
||||||
|
@ -35,6 +35,9 @@
|
|||||||
.mw-#{$i}
|
.mw-#{$i}
|
||||||
min-width: var(--spacer-#{$i})
|
min-width: var(--spacer-#{$i})
|
||||||
|
|
||||||
|
.list-style-none
|
||||||
|
list-style: none
|
||||||
|
|
||||||
.opacity-50
|
.opacity-50
|
||||||
opacity: 0.5
|
opacity: 0.5
|
||||||
|
|
||||||
|
28
extensions/migrations/0042_platform_name.py
Normal file
28
extensions/migrations/0042_platform_name.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 4.2.11 on 2024-05-14 11:06
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def update_platforms(apps, schema_editor):
|
||||||
|
lookup = {
|
||||||
|
"windows-x64": "Windows",
|
||||||
|
"windows-arm64": "Windows Arm",
|
||||||
|
"macos-x64": "macOS Intel",
|
||||||
|
"macos-arm64": "macOS Apple Silicon",
|
||||||
|
"linux-x64": "Linux",
|
||||||
|
}
|
||||||
|
Platform = apps.get_model('extensions', 'Platform')
|
||||||
|
for ob in Platform.objects.all():
|
||||||
|
ob.name = lookup.get(ob.slug, ob.name)
|
||||||
|
ob.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('extensions', '0041_remove_version_file'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(update_platforms),
|
||||||
|
]
|
@ -64,6 +64,20 @@ class Platform(CreatedModifiedMixin, models.Model):
|
|||||||
def get_by_slug(cls, slug: str):
|
def get_by_slug(cls, slug: str):
|
||||||
return cls.objects.filter(slug=slug).first()
|
return cls.objects.filter(slug=slug).first()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name_first_word(self):
|
||||||
|
"""Used for presentation in download_list."""
|
||||||
|
return self.name.split(None, 1)[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name_rest(self):
|
||||||
|
"""Used for presentation in download_list."""
|
||||||
|
parts = self.name.split(None, 1)
|
||||||
|
if len(parts) > 1:
|
||||||
|
return parts[1]
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class ExtensionManager(models.Manager):
|
class ExtensionManager(models.Manager):
|
||||||
@property
|
@property
|
||||||
@ -706,6 +720,18 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
|
|||||||
return file
|
return file
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_supported_platforms(self):
|
||||||
|
supported_platforms = {}
|
||||||
|
for platform in self.platforms.all():
|
||||||
|
architectures = supported_platforms.get(platform.name_first_word, [])
|
||||||
|
architectures.append(platform.name_rest)
|
||||||
|
supported_platforms[platform.name_first_word] = architectures
|
||||||
|
result = []
|
||||||
|
for platform, architectures in sorted(supported_platforms.items()):
|
||||||
|
item = {'name': platform, 'architectures': sorted(architectures)}
|
||||||
|
result.append(item)
|
||||||
|
return result
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_listed(self):
|
def is_listed(self):
|
||||||
# To be public, at least one version file must have a public status.
|
# To be public, at least one version file must have a public status.
|
||||||
@ -785,7 +811,7 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
|
|||||||
'url': self.get_download_url(file),
|
'url': self.get_download_url(file),
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
platform2file = {}
|
platform_slug2file = {}
|
||||||
for file in files:
|
for file in files:
|
||||||
platforms = file.get_platforms()
|
platforms = file.get_platforms()
|
||||||
if not platforms:
|
if not platforms:
|
||||||
@ -793,16 +819,17 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
|
|||||||
f'data error: Version pk={self.pk} has multiple files, but File pk={file.pk} '
|
f'data error: Version pk={self.pk} has multiple files, but File pk={file.pk} '
|
||||||
f'is not platform-specific'
|
f'is not platform-specific'
|
||||||
)
|
)
|
||||||
for platform in platforms:
|
for platform_slug in platforms:
|
||||||
platform2file[platform] = file
|
platform_slug2file[platform_slug] = file
|
||||||
|
all_platforms_by_slug = {p.slug: p for p in Platform.objects.all()}
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
'name': self.get_download_name(file),
|
'name': self.get_download_name(file),
|
||||||
'platform': p,
|
'platform': all_platforms_by_slug.get(platform_slug),
|
||||||
'size': file.size_bytes,
|
'size': file.size_bytes,
|
||||||
'url': self.get_download_url(file),
|
'url': self.get_download_url(file),
|
||||||
}
|
}
|
||||||
for p, file in platform2file.items()
|
for platform_slug, file in sorted(platform_slug2file.items(), reverse=True)
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_build_list(self) -> List[dict]:
|
def get_build_list(self) -> List[dict]:
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
{% has_maintainer extension as is_maintainer %}
|
{% has_maintainer extension as is_maintainer %}
|
||||||
{% with latest=extension.latest_version %}
|
{% with latest=extension.latest_version %}
|
||||||
|
|
||||||
<div class="hero extension-detail">
|
<div class="hero extension-detail position-relative z-2">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="hero-content">
|
<div class="hero-content">
|
||||||
{% block hero_breadcrumbs %}
|
{% block hero_breadcrumbs %}
|
||||||
|
@ -67,16 +67,13 @@
|
|||||||
</a>
|
</a>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if version.has_single_file %}
|
||||||
<div class="dl-col">
|
<div class="dl-col">
|
||||||
<dt>{% trans 'Size' %}</dt>
|
<dt>{% trans 'Size' %}</dt>
|
||||||
{% if version.has_single_file %}
|
|
||||||
<dd>{{ version.files.first.size_bytes|filesizeformat }}</dd>
|
<dd>{{ version.files.first.size_bytes|filesizeformat }}</dd>
|
||||||
{% else %}
|
|
||||||
{% for file in version.files.all %}
|
|
||||||
<dd>{{ file.size_bytes|filesizeformat }} ({{ file.get_platforms|join:", " }})</dd>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dl-row">
|
<div class="dl-row">
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% if version.platforms.all %}
|
{% with supported_platforms=version.get_supported_platforms %}
|
||||||
|
{% if supported_platforms %}
|
||||||
<div class="dl-row">
|
<div class="dl-row">
|
||||||
<div class="dl-col">
|
<div class="dl-col">
|
||||||
<dt>{% trans "Supported Platforms" %}</dt>
|
<dt>{% trans "Supported Platforms" %}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<ul class="mb-0 ps-3">
|
<ul class="list-style-none mb-0 ps-0">
|
||||||
{% for p in version.platforms.all %}
|
{% for item in supported_platforms|dictsortreversed:"name" %}
|
||||||
<li>{{p.name}}</li>
|
<li><i class="i-{{ item.name|lower }}"></i> {{ item.name }} <span class="text-muted">{{ item.architectures|join:', ' }}</span></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
@ -110,7 +110,7 @@
|
|||||||
|
|
||||||
{# Sidebar #}
|
{# Sidebar #}
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<aside class="is-sticky pt-2">
|
<aside class="is-sticky pt-2 z-1">
|
||||||
|
|
||||||
{# Info Summary #}
|
{# Info Summary #}
|
||||||
{% block extension_summary_sidebar %}
|
{% block extension_summary_sidebar %}
|
||||||
@ -185,23 +185,13 @@
|
|||||||
<dt>{% trans 'Downloads' %}</dt>
|
<dt>{% trans 'Downloads' %}</dt>
|
||||||
<dd>{{ extension.download_count }}</dd>
|
<dd>{{ extension.download_count }}</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if latest.has_single_file %}
|
||||||
<div class="dl-col">
|
<div class="dl-col">
|
||||||
<dt>{% trans 'Size' %}</dt>
|
<dt>{% trans 'Size' %}</dt>
|
||||||
{% if latest.has_single_file %}
|
|
||||||
<dd>{{ latest.files.first.size_bytes|filesizeformat }}</dd>
|
<dd>{{ latest.files.first.size_bytes|filesizeformat }}</dd>
|
||||||
{% else %}
|
|
||||||
<dd>
|
|
||||||
<ul class="ps-3">
|
|
||||||
{% for file in latest.files.all %}
|
|
||||||
<li class="lh-sm">
|
|
||||||
{{ file.size_bytes|filesizeformat }}<br>
|
|
||||||
<span class="fs-sm text-muted">({{ file.get_platforms|join:", " }})</span>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</dd>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dl-row">
|
<div class="dl-row">
|
||||||
@ -272,12 +262,27 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="fade js-btn-install-action">
|
<div class="fade js-btn-install-action">
|
||||||
{% for download_item in download_list %}
|
{% for download_item in download_list %}
|
||||||
<div class="btn-install-action-item js-btn-install-action-item" data-install-url="{{ request.scheme }}://{{ request.get_host }}{{ download_item.url }}" download="{{ download_item.name }}">
|
<div class="btn-install-action-item js-btn-install-action-item" data-install-url="{{ request.scheme }}://{{ request.get_host }}{{ download_item.url }}" data-platform="{{ download_item.platform.slug }}" download="{{ download_item.name }}">
|
||||||
<div class="btn-install-drag-group js-btn-install-drag-group mb-2 rounded">
|
<div class="btn-install-drag-group js-btn-install-drag-group mb-2 rounded">
|
||||||
<button class="btn btn-flex btn-primary btn-install-drag cursor-move js-btn-install-drag w-100" draggable="true">
|
<button class="btn btn-flex btn-primary btn-install-drag cursor-move js-btn-install-drag mb-2 w-100" draggable="true">
|
||||||
<i class="i-move"></i>
|
<i class="i-move"></i>
|
||||||
<span>{% trans 'Drag and Drop into Blender' %} <span class="fs-sm">{{ download_item.platform }}</span></span>
|
<span>{% trans 'Drag and Drop into Blender' %}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
<div class="text-center">
|
||||||
|
{% if download_list|length > 1 %}
|
||||||
|
<strong>
|
||||||
|
{% with platform=download_item.platform %}
|
||||||
|
{{ platform.name_first_word }}
|
||||||
|
|
||||||
|
{% if platform.name_rest %}
|
||||||
|
<span class="fw-normal"> - {{ platform.name_rest }}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
</strong>
|
||||||
|
– {{ download_item.size|filesizeformat }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<small class="d-block text-center w-100">
|
<small class="d-block text-center w-100">
|
||||||
{# TODO @front-end: Replace URL of the manual /dev/ with /latest/. #}
|
{# TODO @front-end: Replace URL of the manual /dev/ with /latest/. #}
|
||||||
@ -286,6 +291,27 @@
|
|||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
<div class="dropdown js-dropdown-all-versions-wrapper">
|
||||||
|
<button class="btn btn-link dropdown-toggle js-dropdown-toggle w-100" data-toggle-menu-id="js-dropdown-all-versions">
|
||||||
|
</i> {% trans 'Other versions' %}<i class="i-chevron-down"></i>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu js-dropdown-menu w-100" id="js-dropdown-all-versions">
|
||||||
|
{% for download_item in download_list %}
|
||||||
|
<li>
|
||||||
|
<a class="align-items-center d-flex dropdown-item justify-content-between" download="{{ download_item.name }}" href="{{ request.scheme }}://{{ request.get_host }}{{ download_item.url }}">
|
||||||
|
{% with platform=download_item.platform %}
|
||||||
|
<span class="dropdown-all-versions-item-dot js-dropdown-all-versions-item-dot" data-platform="{{ platform.name_first_word|lower|slice:"3" }}"></span>
|
||||||
|
<span>
|
||||||
|
<i class="i-{{ platform.name_first_word|lower }} js-dropdown-all-versions-item-icon me-0" data-platform="{{ platform.name_first_word|lower|slice:"3" }}"></i> {{ platform.name_first_word }} <span class="text-muted">{{ platform.name_rest}}</span>
|
||||||
|
</span>
|
||||||
|
{% endwith %}
|
||||||
|
<span class="text-muted">{{ download_item.size|filesizeformat }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# If JavaScript is disabled. #}
|
{# If JavaScript is disabled. #}
|
||||||
@ -294,7 +320,7 @@
|
|||||||
<div class="btn-col text-center">
|
<div class="btn-col text-center">
|
||||||
{% for download_item in download_list %}
|
{% for download_item in download_list %}
|
||||||
<a class="btn btn-flex btn-accent" href="{{ request.scheme }}://{{ request.get_host }}{{ download_item.url }}" download="{{ download_item.name }}">
|
<a class="btn btn-flex btn-accent" href="{{ request.scheme }}://{{ request.get_host }}{{ download_item.url }}" download="{{ download_item.name }}">
|
||||||
<i class="i-download"></i><span>{% trans 'Download' %} {{ extension.get_type_display }} {{ download_item.platform }}</span>
|
<i class="i-download"></i><span>{% trans 'Download' %} {{ extension.get_type_display }} {{ download_item.platform.slug }}</span>
|
||||||
</a>
|
</a>
|
||||||
<small class="mt-3">...and <a class="text-underline text-primary text-center" href="https://docs.blender.org/manual/en/dev/editors/preferences/extensions.html#install" target="_blank">Install from Disk</a></small>
|
<small class="mt-3">...and <a class="text-underline text-primary text-center" href="https://docs.blender.org/manual/en/dev/editors/preferences/extensions.html#install" target="_blank">Install from Disk</a></small>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -75,16 +75,12 @@
|
|||||||
<dt>Downloads</dt>
|
<dt>Downloads</dt>
|
||||||
<dd>{{ version.download_count }}</dd>
|
<dd>{{ version.download_count }}</dd>
|
||||||
</div>
|
</div>
|
||||||
|
{% if version.has_single_file %}
|
||||||
<div class="dl-col">
|
<div class="dl-col">
|
||||||
<dt>Size</dt>
|
<dt>Size</dt>
|
||||||
{% if version.has_single_file %}
|
|
||||||
<dd>{{ version.files.first.size_bytes|filesizeformat }}</dd>
|
<dd>{{ version.files.first.size_bytes|filesizeformat }}</dd>
|
||||||
{% else %}
|
|
||||||
{% for file in version.files.all %}
|
|
||||||
<dd>{{ file.size_bytes|filesizeformat }} ({{ file.get_platforms|join:", " }})</dd>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="dl-row">
|
<div class="dl-row">
|
||||||
<div class="dl-col">
|
<div class="dl-col">
|
||||||
@ -115,9 +111,14 @@
|
|||||||
<div class="btn-col">
|
<div class="btn-col">
|
||||||
{% with download_list=version.get_download_list %}
|
{% with download_list=version.get_download_list %}
|
||||||
{% for download_item in download_list %}
|
{% for download_item in download_list %}
|
||||||
<a href="{{ download_item.url }}" download="{{ download_item.name }}" class="btn btn-primary btn-block">
|
<a href="{{ download_item.url }}" download="{{ download_item.name }}" class="btn btn-primary btn-block d-flex justify-content-between text-start">
|
||||||
<i class="i-download"></i>
|
<span>
|
||||||
<span>{% trans 'Download' %} v{{ version.version }} {{ download_item.platform }}</span>
|
{% with platform=download_item.platform %}
|
||||||
|
<i class="i-{{ platform.name_first_word|lower }} me-1"></i> {{ platform.name }}
|
||||||
|
{% endwith %}
|
||||||
|
v{{ version.version }}
|
||||||
|
</span>
|
||||||
|
<span>{{ download_item.size|filesizeformat }}</span>
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
Loading…
Reference in New Issue
Block a user