From 36283f1a8b311d73886ef1d3db80ab4528648d66 Mon Sep 17 00:00:00 2001 From: AsadAzam <asadazam93@gmail.com> Date: Thu, 2 Sep 2021 13:25:53 +0500 Subject: [PATCH] feat! Modify DiscussionsConfiguration to allow programs (#28541) * feat! Modify DiscussionsConfiguration to allow programs * feat: add model for program discussions configuration --- openedx/core/djangoapps/discussions/admin.py | 19 ++++++- ...uration_programdiscussionsconfiguration.py | 56 +++++++++++++++++++ openedx/core/djangoapps/discussions/models.py | 50 ++++++++++++++++- 3 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 openedx/core/djangoapps/discussions/migrations/0004_historicalprogramdiscussionsconfiguration_programdiscussionsconfiguration.py diff --git a/openedx/core/djangoapps/discussions/admin.py b/openedx/core/djangoapps/discussions/admin.py index 33866b3f164..870940a9394 100644 --- a/openedx/core/djangoapps/discussions/admin.py +++ b/openedx/core/djangoapps/discussions/admin.py @@ -7,7 +7,7 @@ from simple_history.admin import SimpleHistoryAdmin from openedx.core.djangoapps.config_model_utils.admin import StackedConfigModelAdmin -from .models import DiscussionsConfiguration +from .models import DiscussionsConfiguration, ProgramDiscussionsConfiguration from .models import ProviderFilter @@ -27,6 +27,22 @@ class DiscussionsConfigurationAdmin(SimpleHistoryAdmin): ) +class ProgramDiscussionsConfigurationAdmin(SimpleHistoryAdmin): + """ + Customize the admin interface for the program discussions configuration + """ + + search_fields = ( + 'program_uuid', + 'enabled', + 'provider_type', + ) + list_filter = ( + 'enabled', + 'provider_type', + ) + + class AllowListFilter(SimpleListFilter): """ Customize the admin interface for the AllowList @@ -88,4 +104,5 @@ class ProviderFilterAdmin(StackedConfigModelAdmin): admin.site.register(DiscussionsConfiguration, DiscussionsConfigurationAdmin) +admin.site.register(ProgramDiscussionsConfiguration, ProgramDiscussionsConfigurationAdmin) admin.site.register(ProviderFilter, ProviderFilterAdmin) diff --git a/openedx/core/djangoapps/discussions/migrations/0004_historicalprogramdiscussionsconfiguration_programdiscussionsconfiguration.py b/openedx/core/djangoapps/discussions/migrations/0004_historicalprogramdiscussionsconfiguration_programdiscussionsconfiguration.py new file mode 100644 index 00000000000..872d2887a7e --- /dev/null +++ b/openedx/core/djangoapps/discussions/migrations/0004_historicalprogramdiscussionsconfiguration_programdiscussionsconfiguration.py @@ -0,0 +1,56 @@ +# Generated by Django 2.2.24 on 2021-08-31 11:18 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import model_utils.fields +import simple_history.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lti_consumer', '0012_rename_courseeditltifieldsenabledflag_model'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('discussions', '0003_alter_provider_filter_list'), + ] + + operations = [ + migrations.CreateModel( + name='ProgramDiscussionsConfiguration', + fields=[ + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ('program_uuid', models.CharField(db_index=True, max_length=50, primary_key=True, serialize=False, verbose_name='Program UUID')), + ('enabled', models.BooleanField(default=True, help_text='If disabled, the discussions in the associated program will be disabled.')), + ('provider_type', models.CharField(help_text="The discussion provider's id", max_length=50, verbose_name='Discussion provider')), + ('lti_configuration', models.ForeignKey(blank=True, help_text='The LTI configuration data for this program/provider.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='lti_consumer.LtiConfiguration')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='HistoricalProgramDiscussionsConfiguration', + fields=[ + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ('program_uuid', models.CharField(db_index=True, max_length=50, verbose_name='Program UUID')), + ('enabled', models.BooleanField(default=True, help_text='If disabled, the discussions in the associated program will be disabled.')), + ('provider_type', models.CharField(help_text="The discussion provider's id", max_length=50, verbose_name='Discussion provider')), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_date', models.DateTimeField()), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('lti_configuration', models.ForeignKey(blank=True, db_constraint=False, help_text='The LTI configuration data for this program/provider.', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='lti_consumer.LtiConfiguration')), + ], + options={ + 'verbose_name': 'historical program discussions configuration', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + ] diff --git a/openedx/core/djangoapps/discussions/models.py b/openedx/core/djangoapps/discussions/models.py index 9164e478e89..f7d131af6c8 100644 --- a/openedx/core/djangoapps/discussions/models.py +++ b/openedx/core/djangoapps/discussions/models.py @@ -360,8 +360,7 @@ class DiscussionsConfiguration(TimeStampedModel): def clean(self): """ - Validate the model - + Validate the model. Currently, this only support courses, this can be extended whenever discussions are available in other contexts """ @@ -418,3 +417,50 @@ class DiscussionsConfiguration(TimeStampedModel): @classmethod def get_available_providers(cls, context_key: CourseKey) -> list[str]: return ProviderFilter.current(course_key=context_key).available_providers + + +class ProgramDiscussionsConfiguration(TimeStampedModel): + """ + Associates a program with a discussion provider and configuration + """ + + program_uuid = models.CharField( + primary_key=True, + db_index=True, + max_length=50, + verbose_name=_("Program UUID"), + ) + enabled = models.BooleanField( + default=True, + help_text=_("If disabled, the discussions in the associated program will be disabled.") + ) + lti_configuration = models.ForeignKey( + LtiConfiguration, + on_delete=models.SET_NULL, + blank=True, + null=True, + help_text=_("The LTI configuration data for this program/provider."), + ) + provider_type = models.CharField( + blank=False, + max_length=50, + verbose_name=_("Discussion provider"), + help_text=_("The discussion provider's id"), + ) + history = HistoricalRecords() + + def __str__(self): + return f"ProgramDiscussionConfiguration(uuid='{self.uuid}', provider='{self.provider}', enabled={self.enabled})" + + @classmethod + def is_enabled(cls, program_uuid) -> bool: + """ + Check if there is an active configuration for a given program uuid + + Default to False, if no configuration exists + """ + try: + configuration = cls.objects.get(program_uuid=program_uuid) + return configuration.enabled + except cls.DoesNotExist: + return False -- GitLab