diff --git a/designsafe/apps/workspace/admin.py b/designsafe/apps/workspace/admin.py index 125fdbbed3..01b3cda683 100644 --- a/designsafe/apps/workspace/admin.py +++ b/designsafe/apps/workspace/admin.py @@ -9,7 +9,7 @@ AppListingEntry, AppVariant, AppTrayCategory, - AppTag + AppTag, ) admin.site.register(AppDescription) @@ -43,6 +43,7 @@ def get_fieldsets(self, request, obj=None): "label", "description", "enabled", + "priority", ) }, ), diff --git a/designsafe/apps/workspace/cms_plugins.py b/designsafe/apps/workspace/cms_plugins.py index 9d344e56fd..232dfd3f23 100644 --- a/designsafe/apps/workspace/cms_plugins.py +++ b/designsafe/apps/workspace/cms_plugins.py @@ -62,7 +62,9 @@ class RelatedApps(CMSPluginBase): def render(self, context, instance: AppListingEntry, placeholder): context = super().render(context, instance, placeholder) - listing_entries = instance.app.related_apps.filter(enabled=True) + listing_entries = instance.app.related_apps.filter(enabled=True).order_by( + "label" + ) serialized_listing = [ { "label": entry.label, diff --git a/designsafe/apps/workspace/migrations/0010_alter_applistingentry_options_and_more.py b/designsafe/apps/workspace/migrations/0010_alter_applistingentry_options_and_more.py new file mode 100644 index 0000000000..fa86a6582c --- /dev/null +++ b/designsafe/apps/workspace/migrations/0010_alter_applistingentry_options_and_more.py @@ -0,0 +1,37 @@ +# Generated by Django 4.2.11 on 2024-04-26 19:18 + +from django.db import migrations, models +import django.db.models.functions.comparison + + +class Migration(migrations.Migration): + dependencies = [ + ("workspace", "0009_alter_applistingentry_icon"), + ] + + operations = [ + migrations.AlterModelOptions( + name="applistingentry", + options={ + "ordering": ["is_popular", "label"], + "verbose_name_plural": "App Listing Entries", + }, + ), + migrations.AlterModelOptions( + name="appvariant", + options={ + "ordering": [ + "priority", + django.db.models.functions.comparison.Coalesce("label", "app_id"), + ] + }, + ), + migrations.AddField( + model_name="appvariant", + name="priority", + field=models.IntegerField( + default=0, + help_text="App variant priority, rendered in ascending order.", + ), + ), + ] diff --git a/designsafe/apps/workspace/models/app_entries.py b/designsafe/apps/workspace/models/app_entries.py index a756d3fded..337db3eed5 100644 --- a/designsafe/apps/workspace/models/app_entries.py +++ b/designsafe/apps/workspace/models/app_entries.py @@ -2,6 +2,7 @@ """ from django.db import models +from django.db.models.functions import Coalesce APP_ICONS = [ ("Generic-App", "Generic: Application"), @@ -146,6 +147,8 @@ class Meta: ) ] + ordering = ["is_popular", "label"] + class AppVariant(models.Model): """Model to represent a variant of an app, e.g. a software version or execution environment""" @@ -181,6 +184,11 @@ class AppVariant(models.Model): null=True, ) + priority = models.IntegerField( + help_text="App variant priority, rendered in ascending order.", + default=0, + ) + # HTML Apps html = models.TextField( help_text="HTML definition to display when app is loaded.", @@ -223,3 +231,5 @@ class Meta: name="unique_apps_per_bundle", ) ] + + ordering = ["priority", Coalesce("label", "app_id")] diff --git a/designsafe/apps/workspace/templates/designsafe/apps/workspace/related_apps_plugin.html b/designsafe/apps/workspace/templates/designsafe/apps/workspace/related_apps_plugin.html index 8e1c778649..ef3cdd48cf 100644 --- a/designsafe/apps/workspace/templates/designsafe/apps/workspace/related_apps_plugin.html +++ b/designsafe/apps/workspace/templates/designsafe/apps/workspace/related_apps_plugin.html @@ -1,6 +1,10 @@ +{% if listing|length > 0 %}