diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4603487b..437d5284 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: # ahead of planned upgrades we can add versions as # needed python-version: [3.8] - mariadb-version: ["10.3"] + mariadb-version: ["10.3", "10.4"] services: mysql: diff --git a/gregor_django/gregor_anvil/forms.py b/gregor_django/gregor_anvil/forms.py index 7cd723a7..6bbe6652 100644 --- a/gregor_django/gregor_anvil/forms.py +++ b/gregor_django/gregor_anvil/forms.py @@ -1,10 +1,7 @@ """Forms classes for the gregor_anvil app.""" from anvil_consortium_manager.forms import Bootstrap5MediaFormMixin -from dal import autocomplete from django import forms -from django.core.exceptions import ValidationError -from django.urls import reverse from . import models @@ -63,72 +60,22 @@ class Meta: class CombinedConsortiumDataWorkspaceForm(Bootstrap5MediaFormMixin, forms.ModelForm): """Form for a CombinedConsortiumDataWorkspace object.""" - ERROR_UPLOAD_CYCLE_DOES_NOT_MATCH = ( - "upload_cycle must match upload_cycle for upload_workspaces." - ) - class Meta: model = models.CombinedConsortiumDataWorkspace - fields = ("workspace", "upload_cycle", "upload_workspaces") - help_texts = { - "upload_workspaces": """Upload workspaces contributing to the combined workspace. - All upload workspaces must have the same version.""" - } - widgets = { - "upload_workspaces": autocomplete.ModelSelect2Multiple( - url=reverse( - "anvil_consortium_manager:workspaces:autocomplete_by_type", - args=["upload"], - ), - attrs={"data-theme": "bootstrap-5"}, - forward=["upload_cycle"], - ), - } - - def clean(self): - cleaned_data = super().clean() - if "upload_cycle" in cleaned_data and "upload_workspaces" in cleaned_data: - upload_cycle = cleaned_data["upload_cycle"] - upload_workspace_cycles = set( - [x.upload_cycle for x in cleaned_data["upload_workspaces"]] - ) - if len(upload_workspace_cycles) > 1: - raise ValidationError(self.ERROR_UPLOAD_CYCLE_DOES_NOT_MATCH) - x = upload_workspace_cycles.pop() - if x != upload_cycle: - raise ValidationError(self.ERROR_UPLOAD_CYCLE_DOES_NOT_MATCH) - - # def clean_upload_workspaces(self): - # """Validate that all UploadWorkspaces have the same version.""" - # data = self.cleaned_data["upload_workspaces"] - # versions = set([x.version for x in data]) - # if len(versions) > 1: - # self.add_error( - # "upload_workspaces", - # ValidationError(self.ERROR_UPLOAD_VERSION_DOES_NOT_MATCH), - # ) - # return data + fields = ( + "workspace", + "upload_cycle", + ) class ReleaseWorkspaceForm(Bootstrap5MediaFormMixin, forms.ModelForm): """Form for a ReleaseWorkspace object.""" - ERROR_CONSENT_DOES_NOT_MATCH = ( - "Consent group must match consent group of upload workspaces." - ) - ERROR_UPLOAD_WORKSPACE_CONSENT = ( - "Consent group for upload workspaces must be the same." - ) - ERROR_UPLOAD_CYCLE = ( - "upload_cycle must match upload_cycle of all upload_workspaces." - ) - class Meta: model = models.ReleaseWorkspace fields = ( "upload_cycle", "consent_group", - "upload_workspaces", "full_data_use_limitations", "dbgap_version", "dbgap_participant_set", @@ -136,66 +83,13 @@ class Meta: "workspace", ) help_texts = { - "upload_workspaces": """Upload workspaces contributing to this Release Workspace. - All upload workspaces must have the same consent group.""", "date_released": """Do not select a date for this field unless the workspace has been released to the scientific community.""", } widgets = { - # We considered checkboxes for workspaces with default all checked. - # Unfortunately we need to select only those with a given consent, not all workspaces. - # So go back to the ModelSelect2Multiple widget. - "upload_workspaces": autocomplete.ModelSelect2Multiple( - url=reverse( - "anvil_consortium_manager:workspaces:autocomplete_by_type", - args=["upload"], - ), - attrs={"data-theme": "bootstrap-5"}, - forward=["consent_group", "upload_cycle"], - ), - # "date_released": forms.SelectDateInput(), - # "date_released": forms.DateInput(), - # "date_released": AdminDateWidget(), "date_released": CustomDateInput(), } - def clean_upload_workspaces(self): - """Validate that all UploadWorkspaces have the same consent group.""" - data = self.cleaned_data["upload_workspaces"] - versions = set([x.consent_group for x in data]) - upload_cycles = set([x.upload_cycle for x in data]) - if len(versions) > 1: - self.add_error( - "upload_workspaces", - ValidationError(self.ERROR_UPLOAD_WORKSPACE_CONSENT), - ) - if len(upload_cycles) > 1: - self.add_error( - "upload_workspaces", - ValidationError(self.ERROR_UPLOAD_CYCLE), - ) - return data - - def clean(self): - """Validate that consent_group matches the consent group for upload_workspaces.""" - cleaned_data = super().clean() - # Make sure that the consent group specified matches the consent group for the upload_workspaces. - consent_group = cleaned_data.get("consent_group") - upload_workspaces = cleaned_data.get("upload_workspaces") - upload_cycle = cleaned_data.get("upload_cycle") - if consent_group and upload_workspaces: - # We only need to check the first workspace since the clean_upload_workspaces method checks - # that all upload_workspaces have the same consent. - if consent_group != upload_workspaces[0].consent_group: - raise ValidationError(self.ERROR_CONSENT_DOES_NOT_MATCH) - if upload_cycle and upload_workspaces: - # We only need to check the first workspace since the clean_upload_workspaces method checks - # that all upload_workspaces have the same upload_cycle. - if upload_cycle != upload_workspaces[0].upload_cycle: - raise ValidationError(self.ERROR_UPLOAD_CYCLE) - - return cleaned_data - class DCCProcessingWorkspaceForm(Bootstrap5MediaFormMixin, forms.ModelForm): """Form for a DCCProcessingWorkspace object.""" diff --git a/gregor_django/gregor_anvil/migrations/0016_remove_combinedconsortiumdataworkspace_upload_workspaces.py b/gregor_django/gregor_anvil/migrations/0016_remove_combinedconsortiumdataworkspace_upload_workspaces.py new file mode 100644 index 00000000..1925c52f --- /dev/null +++ b/gregor_django/gregor_anvil/migrations/0016_remove_combinedconsortiumdataworkspace_upload_workspaces.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.19 on 2023-08-04 22:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('gregor_anvil', '0015_dccworkspaces'), + ] + + operations = [ + migrations.RemoveField( + model_name='combinedconsortiumdataworkspace', + name='upload_workspaces', + ), + ] diff --git a/gregor_django/gregor_anvil/migrations/0017_remove_releaseworkspace_upload_workspaces.py b/gregor_django/gregor_anvil/migrations/0017_remove_releaseworkspace_upload_workspaces.py new file mode 100644 index 00000000..013b5292 --- /dev/null +++ b/gregor_django/gregor_anvil/migrations/0017_remove_releaseworkspace_upload_workspaces.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.19 on 2023-08-07 16:01 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('gregor_anvil', '0016_remove_combinedconsortiumdataworkspace_upload_workspaces'), + ] + + operations = [ + migrations.RemoveField( + model_name='releaseworkspace', + name='upload_workspaces', + ), + ] diff --git a/gregor_django/gregor_anvil/models.py b/gregor_django/gregor_anvil/models.py index 4d0d6a70..e502df65 100644 --- a/gregor_django/gregor_anvil/models.py +++ b/gregor_django/gregor_anvil/models.py @@ -151,9 +151,6 @@ class CombinedConsortiumDataWorkspace(TimeStampedModel, BaseWorkspaceData): """A model to track a workspace that has data combined from multiple upload workspaces.""" upload_cycle = models.ForeignKey(UploadCycle, on_delete=models.PROTECT) - upload_workspaces = models.ManyToManyField( - UploadWorkspace, help_text="Upload workspaces" - ) class ReleaseWorkspace(TimeStampedModel, BaseWorkspaceData): @@ -168,10 +165,6 @@ class ReleaseWorkspace(TimeStampedModel, BaseWorkspaceData): on_delete=models.PROTECT, ) upload_cycle = models.ForeignKey(UploadCycle, on_delete=models.PROTECT) - upload_workspaces = models.ManyToManyField( - UploadWorkspace, - help_text="Upload workspaces contributing data to this workspace.", - ) full_data_use_limitations = models.TextField( help_text="The full data use limitations for this workspace." ) diff --git a/gregor_django/gregor_anvil/tables.py b/gregor_django/gregor_anvil/tables.py index eea7c181..5461e75f 100644 --- a/gregor_django/gregor_anvil/tables.py +++ b/gregor_django/gregor_anvil/tables.py @@ -1,6 +1,6 @@ import django_tables2 as tables from anvil_consortium_manager.adapters.workspace import workspace_adapter_registry -from anvil_consortium_manager.models import Account, Workspace +from anvil_consortium_manager.models import Account, ManagedGroup, Workspace from django.utils.html import format_html from . import models @@ -80,20 +80,26 @@ def render_cycle(self, record): return str(record) -class WorkspaceSharedWithConsortiumTable(tables.Table): +class WorkspaceConsortiumAccessTable(tables.Table): """Table including a column to indicate if a workspace is shared with PRIMED_ALL.""" - is_shared = tables.columns.Column( + consortium_access = tables.columns.Column( accessor="pk", - verbose_name="Shared with GREGoR?", + verbose_name="Consortium access?", orderable=False, ) - def render_is_shared(self, record): - is_shared = record.workspacegroupsharing_set.filter( - group__name="GREGOR_ALL" - ).exists() - if is_shared: + def render_consortium_access(self, record): + try: + group = ManagedGroup.objects.get(name="GREGOR_ALL") + except ManagedGroup.DoesNotExist: + has_consortium_access = False + else: + has_consortium_access = record.is_in_authorization_domain( + group + ) and record.is_shared(group) + + if has_consortium_access: icon = "check-circle-fill" color = "green" value = format_html( @@ -104,7 +110,7 @@ def render_is_shared(self, record): return value -class DefaultWorkspaceTable(WorkspaceSharedWithConsortiumTable, tables.Table): +class DefaultWorkspaceTable(WorkspaceConsortiumAccessTable, tables.Table): """Class to use for default workspace tables in GREGoR.""" name = tables.Column(linkify=True, verbose_name="Workspace") @@ -122,12 +128,12 @@ class Meta: "name", "billing_project", "number_groups", - "is_shared", + "consortium_access", ) order_by = ("name",) -class UploadWorkspaceTable(WorkspaceSharedWithConsortiumTable, tables.Table): +class UploadWorkspaceTable(WorkspaceConsortiumAccessTable, tables.Table): """A table for Workspaces that includes fields from UploadWorkspace.""" name = tables.columns.Column(linkify=True) @@ -140,11 +146,11 @@ class Meta: "uploadworkspace__upload_cycle", "uploadworkspace__research_center", "uploadworkspace__consent_group", - "is_shared", + "consortium_access", ) -class TemplateWorkspaceTable(WorkspaceSharedWithConsortiumTable, tables.Table): +class TemplateWorkspaceTable(WorkspaceConsortiumAccessTable, tables.Table): """A table for Workspaces that includes fields from TemplateWorkspace.""" name = tables.columns.Column(linkify=True) @@ -154,7 +160,7 @@ class Meta: fields = ( "name", "templateworkspace__intended_use", - "is_shared", + "consortium_access", ) @@ -177,40 +183,26 @@ def render_workspace_type(self, value): class CombinedConsortiumDataWorkspaceTable( - WorkspaceSharedWithConsortiumTable, tables.Table + WorkspaceConsortiumAccessTable, tables.Table ): """A table for Workspaces that includes fields from CombinedConsortiumDataWorkspace.""" name = tables.columns.Column(linkify=True) combinedconsortiumdataworkspace__upload_cycle = tables.columns.Column(linkify=True) - number_workspaces = tables.columns.Column( - accessor="pk", - verbose_name="Number of workspaces", - orderable=False, - ) class Meta: model = Workspace fields = ( "name", "combinedconsortiumdataworkspace__upload_cycle", - "number_workspaces", ) - def render_number_workspaces(self, record): - return record.combinedconsortiumdataworkspace.upload_workspaces.count() - class ReleaseWorkspaceTable(tables.Table): """A table for Workspaces that includes fields from ReleaseWorkspace.""" name = tables.columns.Column(linkify=True) releaseworkspace__upload_cycle = tables.columns.Column(linkify=True) - number_workspaces = tables.columns.Column( - accessor="pk", - verbose_name="Number of workspaces", - orderable=False, - ) class Meta: model = Workspace @@ -220,13 +212,9 @@ class Meta: "releaseworkspace__consent_group", "releaseworkspace__dbgap_version", "releaseworkspace__dbgap_participant_set", - "number_workspaces", "releaseworkspace__date_released", ) - def render_number_workspaces(self, record): - return record.releaseworkspace.upload_workspaces.count() - class DCCProcessingWorkspaceTable(tables.Table): """A table for Workspaces that includes fields from DCCProcessingWorkspace.""" @@ -242,7 +230,7 @@ class Meta: ) -class DCCProcessedDataWorkspaceTable(WorkspaceSharedWithConsortiumTable, tables.Table): +class DCCProcessedDataWorkspaceTable(WorkspaceConsortiumAccessTable, tables.Table): """A table for Workspaces that includes fields from DCCProcessedDataWorkspace.""" name = tables.columns.Column(linkify=True) @@ -254,5 +242,5 @@ class Meta: "name", "dccprocesseddataworkspace__upload_cycle", "dccprocesseddataworkspace__consent_group", - "is_shared", + "consortium_access", ) diff --git a/gregor_django/gregor_anvil/tests/test_forms.py b/gregor_django/gregor_anvil/tests/test_forms.py index adc6909b..eef888c5 100644 --- a/gregor_django/gregor_anvil/tests/test_forms.py +++ b/gregor_django/gregor_anvil/tests/test_forms.py @@ -3,7 +3,6 @@ from datetime import date, timedelta from anvil_consortium_manager.tests.factories import WorkspaceFactory -from django.core.exceptions import NON_FIELD_ERRORS from django.test import TestCase from .. import forms @@ -261,37 +260,6 @@ def setUp(self): """Create a workspace for use in the form.""" self.workspace = WorkspaceFactory.create() - def test_valid_one_upload_workspace(self): - """Form is valid with necessary input.""" - upload_cycle = factories.UploadCycleFactory.create() - upload_workspace = factories.UploadWorkspaceFactory.create( - upload_cycle=upload_cycle - ) - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_cycle, - "upload_workspaces": [upload_workspace], - } - form = self.form_class(data=form_data) - self.assertTrue(form.is_valid()) - - def test_valid_two_upload_workspaces(self): - """Form is valid with necessary input.""" - upload_cycle = factories.UploadCycleFactory.create() - upload_workspace_1 = factories.UploadWorkspaceFactory.create( - upload_cycle=upload_cycle - ) - upload_workspace_2 = factories.UploadWorkspaceFactory.create( - upload_cycle=upload_cycle - ) - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_cycle, - "upload_workspaces": [upload_workspace_1, upload_workspace_2], - } - form = self.form_class(data=form_data) - self.assertTrue(form.is_valid()) - def test_invalid_missing_workspace(self): """Form is invalid when missing workspace.""" upload_cycle = factories.UploadCycleFactory.create() @@ -309,41 +277,10 @@ def test_invalid_missing_workspace(self): self.assertEqual(len(form.errors["workspace"]), 1) self.assertIn("required", form.errors["workspace"][0]) - def test_invalid_missing_upload_workspace(self): - """Form is invalid when missing upload_workspace.""" - upload_cycle = factories.UploadCycleFactory.create() - form_data = { - "upload_cycle": upload_cycle, - "workspace": self.workspace, - } - form = self.form_class(data=form_data) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertIn("upload_workspaces", form.errors) - self.assertEqual(len(form.errors["upload_workspaces"]), 1) - self.assertIn("required", form.errors["upload_workspaces"][0]) - - def test_invalid_blank_upload_workspace(self): - """Form is invalid when missing upload_workspace.""" - upload_cycle = factories.UploadCycleFactory.create() - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_cycle, - "upload_workspaces": [], - } - form = self.form_class(data=form_data) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertIn("upload_workspaces", form.errors) - self.assertEqual(len(form.errors["upload_workspaces"]), 1) - self.assertIn("required", form.errors["upload_workspaces"][0]) - def test_invalid_blank_upload_cycle(self): """Form is invalid when missing upload_workspace.""" - upload_workspace = factories.UploadWorkspaceFactory.create() form_data = { "workspace": self.workspace, - "upload_workspaces": [upload_workspace], } form = self.form_class(data=form_data) self.assertFalse(form.is_valid()) @@ -352,48 +289,6 @@ def test_invalid_blank_upload_cycle(self): self.assertEqual(len(form.errors["upload_cycle"]), 1) self.assertIn("required", form.errors["upload_cycle"][0]) - def test_clean_upload_workspace_from_previous_cycle(self): - """Form is invalid with a workspace from a previous upload cycle.""" - upload_workspace = factories.UploadWorkspaceFactory.create( - upload_cycle__cycle=1 - ) - upload_cycle = factories.UploadCycleFactory.create(cycle=2) - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_cycle, - "upload_workspaces": [upload_workspace], - } - form = self.form_class(data=form_data) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertIn(NON_FIELD_ERRORS, form.errors) - self.assertEqual(len(form.errors[NON_FIELD_ERRORS]), 1) - self.assertIn( - form.ERROR_UPLOAD_CYCLE_DOES_NOT_MATCH, - form.errors[NON_FIELD_ERRORS][0], - ) - - def test_clean_upload_cycle(self): - """Form is invalid when a workspace from a later cycle is selected.""" - upload_cycle = factories.UploadCycleFactory.create(cycle=1) - upload_workspace = factories.UploadWorkspaceFactory.create( - upload_cycle__cycle=2 - ) - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_cycle, - "upload_workspaces": [upload_workspace], - } - form = self.form_class(data=form_data) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertIn(NON_FIELD_ERRORS, form.errors) - self.assertEqual(len(form.errors[NON_FIELD_ERRORS]), 1) - self.assertIn( - form.ERROR_UPLOAD_CYCLE_DOES_NOT_MATCH, - form.errors[NON_FIELD_ERRORS][0], - ) - class ReleaseWorkspaceFormTest(TestCase): """Tests for the ReleaseWorkspace class.""" @@ -403,16 +298,16 @@ class ReleaseWorkspaceFormTest(TestCase): def setUp(self): """Create a workspace for use in the form.""" self.workspace = WorkspaceFactory() + self.upload_cycle = factories.UploadCycleFactory.create() + self.consent_group = factories.ConsentGroupFactory.create() def test_valid(self): """Form is valid with necessary input.""" - upload_workspace = factories.UploadWorkspaceFactory.create() form_data = { "workspace": self.workspace, - "upload_cycle": upload_workspace.upload_cycle, - "upload_workspaces": [upload_workspace], + "upload_cycle": self.upload_cycle, "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace.consent_group, + "consent_group": self.consent_group, "dbgap_version": 1, "dbgap_participant_set": 1, } @@ -421,13 +316,11 @@ def test_valid(self): def test_invalid_missing_workspace(self): """Form is invalid when missing research_center.""" - upload_workspace = factories.UploadWorkspaceFactory.create() form_data = { # "workspace": self.workspace, - "upload_cycle": upload_workspace.upload_cycle, - "upload_workspaces": [upload_workspace], + "upload_cycle": self.upload_cycle, "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace.consent_group, + "consent_group": self.consent_group, "dbgap_version": 1, "dbgap_participant_set": 1, } @@ -440,13 +333,11 @@ def test_invalid_missing_workspace(self): def test_invalid_missing_upload_cycle(self): """Form is invalid when missing consent_group.""" - upload_workspace = factories.UploadWorkspaceFactory.create() form_data = { "workspace": self.workspace, - # "upload_cycle": upload_workspace.upload_cycle, - "upload_workspaces": [upload_workspace], + # "upload_cycle": self.upload_cycle, "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace.consent_group, + "consent_group": self.consent_group, "dbgap_version": 1, "dbgap_participant_set": 1, } @@ -458,35 +349,13 @@ def test_invalid_missing_upload_cycle(self): self.assertEqual(len(form.errors["upload_cycle"]), 1) self.assertIn("required", form.errors["upload_cycle"][0]) - def test_invalid_missing_upload_workspaces(self): - """Form is invalid when missing research_center.""" - upload_workspace = factories.UploadWorkspaceFactory.create() - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_workspace.upload_cycle, - # "upload_workspaces": [upload_workspace], - "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace.consent_group, - "dbgap_version": 1, - "dbgap_participant_set": 1, - } - form = self.form_class(data=form_data) - form = self.form_class(data=form_data) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertIn("upload_workspaces", form.errors) - self.assertEqual(len(form.errors["upload_workspaces"]), 1) - self.assertIn("required", form.errors["upload_workspaces"][0]) - def test_invalid_missing_consent_group(self): """Form is invalid when missing consent_group.""" - upload_workspace = factories.UploadWorkspaceFactory.create() form_data = { "workspace": self.workspace, - "upload_cycle": upload_workspace.upload_cycle, - "upload_workspaces": [upload_workspace], + "upload_cycle": self.upload_cycle, "full_data_use_limitations": "foo bar", - # "consent_group": upload_workspace.consent_group, + # "consent_group": self.consent_group, "dbgap_version": 1, "dbgap_participant_set": 1, } @@ -500,13 +369,11 @@ def test_invalid_missing_consent_group(self): def test_invalid_missing_version(self): """Form is invalid when missing research_center.""" - upload_workspace = factories.UploadWorkspaceFactory.create() form_data = { "workspace": self.workspace, - "upload_cycle": upload_workspace.upload_cycle, - "upload_workspaces": [upload_workspace], + "upload_cycle": self.upload_cycle, "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace.consent_group, + "consent_group": self.consent_group, # "dbgap_version": 1, "dbgap_participant_set": 1, } @@ -519,13 +386,11 @@ def test_invalid_missing_version(self): def test_invalid_missing_dbgap_participant_set(self): """Form is invalid when missing research_center.""" - upload_workspace = factories.UploadWorkspaceFactory.create() form_data = { "workspace": self.workspace, - "upload_cycle": upload_workspace.upload_cycle, - "upload_workspaces": [upload_workspace], + "upload_cycle": self.upload_cycle, "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace.consent_group, + "consent_group": self.consent_group, "dbgap_version": 1, # "dbgap_participant_set": 1, } @@ -539,14 +404,9 @@ def test_invalid_missing_dbgap_participant_set(self): def test_invalid_duplicate_object(self): """Form is invalid with a duplicated object.""" release_workspace = factories.ReleaseWorkspaceFactory.create() - upload_workspace = factories.UploadWorkspaceFactory.create( - consent_group=release_workspace.consent_group, - upload_cycle=release_workspace.upload_cycle, - ) form_data = { "workspace": self.workspace, "upload_cycle": release_workspace.upload_cycle, - "upload_workspaces": [upload_workspace], "full_data_use_limitations": "foo bar", "consent_group": release_workspace.consent_group, "dbgap_version": 1, @@ -559,114 +419,6 @@ def test_invalid_duplicate_object(self): self.assertEqual(len(non_field_errors), 1) self.assertIn("already exists", non_field_errors[0]) - def test_valid_two_upload_workspaces(self): - upload_workspace_1 = factories.UploadWorkspaceFactory.create() - upload_workspace_2 = factories.UploadWorkspaceFactory.create( - consent_group=upload_workspace_1.consent_group, - upload_cycle=upload_workspace_1.upload_cycle, - ) - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_workspace_1.upload_cycle, - "upload_workspaces": [upload_workspace_1, upload_workspace_2], - "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace_1.consent_group, - "dbgap_version": 1, - "dbgap_participant_set": 1, - } - form = self.form_class(data=form_data) - self.assertTrue(form.is_valid()) - - def test_invalid_upload_workspaces_have_different_consent_group(self): - upload_workspace_1 = factories.UploadWorkspaceFactory.create() - upload_workspace_2 = factories.UploadWorkspaceFactory.create( - upload_cycle=upload_workspace_1.upload_cycle - ) - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_workspace_1.upload_cycle, - "upload_workspaces": [upload_workspace_1, upload_workspace_2], - "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace_1.consent_group, - "dbgap_version": 1, - "dbgap_participant_set": 1, - } - form = self.form_class(data=form_data) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertIn("upload_workspaces", form.errors) - self.assertEqual(len(form.errors["upload_workspaces"]), 1) - self.assertIn( - self.form_class.ERROR_UPLOAD_WORKSPACE_CONSENT, - form.errors["upload_workspaces"][0], - ) - - def test_invalid_upload_workspaces_have_different_upload_cycles(self): - upload_workspace_1 = factories.UploadWorkspaceFactory.create() - upload_workspace_2 = factories.UploadWorkspaceFactory.create( - consent_group=upload_workspace_1.consent_group - ) - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_workspace_1.upload_cycle, - "upload_workspaces": [upload_workspace_1, upload_workspace_2], - "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace_1.consent_group, - "dbgap_version": 1, - "dbgap_participant_set": 1, - } - form = self.form_class(data=form_data) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertIn("upload_workspaces", form.errors) - self.assertEqual(len(form.errors["upload_workspaces"]), 1) - self.assertIn( - self.form_class.ERROR_UPLOAD_CYCLE, - form.errors["upload_workspaces"][0], - ) - - def test_invalid_upload_workspace_consent_does_not_match_consent_group(self): - consent_group = factories.ConsentGroupFactory() - upload_workspace = factories.UploadWorkspaceFactory.create() - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_workspace.upload_cycle, - "upload_workspaces": [upload_workspace], - "full_data_use_limitations": "foo bar", - "consent_group": consent_group, - "dbgap_version": 1, - "dbgap_participant_set": 1, - } - form = self.form_class(data=form_data) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - non_field_errors = form.non_field_errors() - self.assertEqual(len(non_field_errors), 1) - self.assertIn(self.form_class.ERROR_CONSENT_DOES_NOT_MATCH, non_field_errors[0]) - - def test_clean(self): - """Form is invalid when upload_workspace upload cycle does not match upload_cycle.""" - upload_workspace = factories.UploadWorkspaceFactory.create() - upload_cycle = factories.UploadCycleFactory.create() - form_data = { - "workspace": self.workspace, - "upload_cycle": upload_cycle, - "upload_workspaces": [upload_workspace], - "full_data_use_limitations": "foo bar", - "consent_group": upload_workspace.consent_group, - "dbgap_version": 1, - "dbgap_participant_set": 1, - } - form = self.form_class(data=form_data) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertIn(NON_FIELD_ERRORS, form.errors) - self.assertEqual(len(form.errors[NON_FIELD_ERRORS]), 1) - self.assertIn( - self.form_class.ERROR_UPLOAD_CYCLE, - form.errors[NON_FIELD_ERRORS][0], - ) - class DCCProcessingWorkspaceFormTest(TestCase): """Tests for the DCCProcessingWorkspace class.""" diff --git a/gregor_django/gregor_anvil/tests/test_models.py b/gregor_django/gregor_anvil/tests/test_models.py index 787935a1..1453787e 100644 --- a/gregor_django/gregor_anvil/tests/test_models.py +++ b/gregor_django/gregor_anvil/tests/test_models.py @@ -373,32 +373,6 @@ def test_str_method(self): self.assertIsInstance(instance.__str__(), str) self.assertEqual(instance.__str__(), instance.workspace.__str__()) - def test_one_upload_workspace(self): - """Can link one upload workspace.""" - instance = factories.CombinedConsortiumDataWorkspaceFactory.create() - upload_workspace = factories.UploadWorkspaceFactory.create( - upload_cycle=instance.upload_cycle - ) - instance.save() - instance.upload_workspaces.add(upload_workspace) - self.assertEqual(instance.upload_workspaces.count(), 1) - self.assertIn(upload_workspace, instance.upload_workspaces.all()) - - def test_two_upload_workspaces(self): - """Can link two upload workspaces.""" - instance = factories.CombinedConsortiumDataWorkspaceFactory.create() - upload_workspace_1 = factories.UploadWorkspaceFactory.create( - upload_cycle=instance.upload_cycle - ) - upload_workspace_2 = factories.UploadWorkspaceFactory.create( - upload_cycle=instance.upload_cycle - ) - instance.save() - instance.upload_workspaces.add(upload_workspace_1, upload_workspace_2) - self.assertEqual(instance.upload_workspaces.count(), 2) - self.assertIn(upload_workspace_1, instance.upload_workspaces.all()) - self.assertIn(upload_workspace_2, instance.upload_workspaces.all()) - class ReleaseWorkspaceTest(TestCase): """Tests for the ReleaseWorkspace model.""" @@ -426,32 +400,6 @@ def test_str_method(self): self.assertIsInstance(instance.__str__(), str) self.assertEqual(instance.__str__(), instance.workspace.__str__()) - def test_one_upload_workspace(self): - """Can link one upload workspace.""" - instance = factories.ReleaseWorkspaceFactory.create() - instance.save() - upload_workspace = factories.UploadWorkspaceFactory.create( - consent_group=instance.consent_group, upload_cycle=instance.upload_cycle - ) - instance.upload_workspaces.add(upload_workspace) - self.assertEqual(instance.upload_workspaces.count(), 1) - self.assertIn(upload_workspace, instance.upload_workspaces.all()) - - def test_two_upload_workspaces(self): - """Can link two upload workspaces.""" - instance = factories.ReleaseWorkspaceFactory.create() - instance.save() - upload_workspace_1 = factories.UploadWorkspaceFactory.create( - consent_group=instance.consent_group, upload_cycle=instance.upload_cycle - ) - upload_workspace_2 = factories.UploadWorkspaceFactory.create( - consent_group=instance.consent_group, upload_cycle=instance.upload_cycle - ) - instance.upload_workspaces.add(upload_workspace_1, upload_workspace_2) - self.assertEqual(instance.upload_workspaces.count(), 2) - self.assertIn(upload_workspace_1, instance.upload_workspaces.all()) - self.assertIn(upload_workspace_2, instance.upload_workspaces.all()) - def test_unique_constraint(self): """Cannot save two instances with the same ConsentGroup and upload_cycle.""" instance_1 = factories.ReleaseWorkspaceFactory.create() diff --git a/gregor_django/gregor_anvil/tests/test_tables.py b/gregor_django/gregor_anvil/tests/test_tables.py index c364f64b..64b38ccb 100644 --- a/gregor_django/gregor_anvil/tests/test_tables.py +++ b/gregor_django/gregor_anvil/tests/test_tables.py @@ -2,6 +2,11 @@ from anvil_consortium_manager.tests.factories import ( AccountFactory, GroupAccountMembershipFactory, + GroupGroupMembershipFactory, + ManagedGroupFactory, + WorkspaceAuthorizationDomainFactory, + WorkspaceFactory, + WorkspaceGroupSharingFactory, ) from django.db.models import Count, Q from django.test import TestCase @@ -112,6 +117,114 @@ def test_row_count_with_two_objects(self): self.assertEqual(len(table.rows), 2) +class WorkspaceConsortiumAccessTableTest(TestCase): + """Tests for the is_shared column.""" + + def setUp(self): + self.gregor_all = ManagedGroupFactory.create(name="GREGOR_ALL") + + def test_is_shared_no_auth_domain_not_shared(self): + """Workspace has no auth domain and is not shared with GREGOR_ALL.""" + workspace = WorkspaceFactory.create() + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertNotIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_no_auth_domain_shared(self): + """Workspace has no auth domain and is shared with GREGOR_ALL.""" + workspace = WorkspaceFactory.create() + WorkspaceGroupSharingFactory.create(workspace=workspace, group=self.gregor_all) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_no_auth_domain_shared_other_group(self): + """Workspace has no auth domain and is shared with a different group.""" + workspace = WorkspaceFactory.create() + WorkspaceGroupSharingFactory.create(workspace=workspace) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertNotIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_one_auth_domain_not_shared_not_in_auth_domain(self): + """GREGOR_ALL is not in auth domain and workspace is not shared.""" + workspace = WorkspaceFactory.create() + WorkspaceAuthorizationDomainFactory.create(workspace=workspace) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertNotIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_one_auth_domain_not_shared_in_auth_domain(self): + """GREGOR_ALL is in auth domain and workspace is not shared.""" + workspace = WorkspaceFactory.create() + auth_domain = WorkspaceAuthorizationDomainFactory.create(workspace=workspace) + GroupGroupMembershipFactory.create( + parent_group=auth_domain.group, child_group=self.gregor_all + ) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertNotIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_one_auth_domain_shared_different_group_in_auth_domain(self): + """GREGOR_ALL is in auth domain and workspace is shared with a different group.""" + workspace = WorkspaceFactory.create() + auth_domain = WorkspaceAuthorizationDomainFactory.create(workspace=workspace) + GroupGroupMembershipFactory.create( + parent_group=auth_domain.group, child_group=self.gregor_all + ) + WorkspaceGroupSharingFactory.create(workspace=workspace) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertNotIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_one_auth_domain_shared_with_gregor_all_not_in_auth_domain(self): + """GREGOR_ALL is not in auth domain and workspace is shared with GREGOR_ALL.""" + workspace = WorkspaceFactory.create() + WorkspaceAuthorizationDomainFactory.create(workspace=workspace) + WorkspaceGroupSharingFactory.create(workspace=workspace, group=self.gregor_all) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertNotIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_one_auth_domain_shared_with_auth_domain_not_in_auth_domain(self): + """GREGOR_ALL is not in auth domain and workspace is shared with its auth domain.""" + workspace = WorkspaceFactory.create() + auth_domain = WorkspaceAuthorizationDomainFactory.create(workspace=workspace) + WorkspaceGroupSharingFactory.create( + workspace=workspace, group=auth_domain.group + ) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertNotIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_one_auth_domain_shared_with_gregor_all_in_auth_domain(self): + """GREGOR_ALL is in auth domain and workspace is shared with GREGOR_ALL.""" + workspace = WorkspaceFactory.create() + auth_domain = WorkspaceAuthorizationDomainFactory.create(workspace=workspace) + GroupGroupMembershipFactory.create( + parent_group=auth_domain.group, child_group=self.gregor_all + ) + WorkspaceGroupSharingFactory.create(workspace=workspace, group=self.gregor_all) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_one_auth_domain_shared_with_auth_domain_in_auth_domain(self): + """GREGOR_ALL is in auth domain and workspace is shared with its auth domain.""" + workspace = WorkspaceFactory.create() + auth_domain = WorkspaceAuthorizationDomainFactory.create(workspace=workspace) + GroupGroupMembershipFactory.create( + parent_group=auth_domain.group, child_group=self.gregor_all + ) + WorkspaceGroupSharingFactory.create( + workspace=workspace, group=auth_domain.group + ) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertIn("check-circle-fill", table.render_consortium_access(workspace)) + + def test_is_shared_one_auth_domain_shared_with_different_group_in_auth_domain(self): + """GREGOR_ALL is in auth domain and workspace is shared with a different group.""" + workspace = WorkspaceFactory.create() + auth_domain = WorkspaceAuthorizationDomainFactory.create(workspace=workspace) + GroupGroupMembershipFactory.create( + parent_group=auth_domain.group, child_group=self.gregor_all + ) + WorkspaceGroupSharingFactory.create(workspace=workspace) + table = tables.WorkspaceConsortiumAccessTable(Workspace.objects.all()) + self.assertNotIn("check-circle-fill", table.render_consortium_access(workspace)) + + class UploadWorkspaceTableTest(TestCase): model = Workspace model_factory = factories.UploadWorkspaceFactory @@ -175,20 +288,6 @@ def test_row_count_with_two_objects(self): table = self.table_class(self.model.objects.all()) self.assertEqual(len(table.rows), 2) - def test_number_workspaces(self): - self.model_factory.create() - workspace_1 = self.model_factory.create() - workspace_1.upload_workspaces.add(factories.UploadWorkspaceFactory.create()) - workspace_2 = self.model_factory.create() - workspace_2.upload_workspaces.add(factories.UploadWorkspaceFactory.create()) - workspace_2.upload_workspaces.add(factories.UploadWorkspaceFactory.create()) - table = self.table_class( - self.model.objects.filter(workspace_type="combined_consortium") - ) - self.assertEqual(table.rows[0].get_cell("number_workspaces"), 0) - self.assertEqual(table.rows[1].get_cell("number_workspaces"), 1) - self.assertEqual(table.rows[2].get_cell("number_workspaces"), 2) - class ReleaseWorkspaceTableTest(TestCase): """Tests for the AccountTable in this app.""" @@ -211,24 +310,6 @@ def test_row_count_with_two_objects(self): table = self.table_class(self.model.objects.all()) self.assertEqual(len(table.rows), 2) - def test_number_workspaces(self): - self.model_factory.create() - release_workspace_1 = self.model_factory.create() - release_workspace_1.upload_workspaces.add( - factories.UploadWorkspaceFactory.create() - ) - release_workspace_2 = self.model_factory.create() - release_workspace_2.upload_workspaces.add( - factories.UploadWorkspaceFactory.create() - ) - release_workspace_2.upload_workspaces.add( - factories.UploadWorkspaceFactory.create() - ) - table = self.table_class(self.model.objects.filter(workspace_type="release")) - self.assertEqual(table.rows[0].get_cell("number_workspaces"), 0) - self.assertEqual(table.rows[1].get_cell("number_workspaces"), 1) - self.assertEqual(table.rows[2].get_cell("number_workspaces"), 2) - class WorkspaceReportTableTest(TestCase): model = Workspace diff --git a/gregor_django/gregor_anvil/tests/test_views.py b/gregor_django/gregor_anvil/tests/test_views.py index 47224bd9..0e7311da 100644 --- a/gregor_django/gregor_anvil/tests/test_views.py +++ b/gregor_django/gregor_anvil/tests/test_views.py @@ -1,5 +1,6 @@ import json from datetime import date, timedelta +from unittest import skip import responses from anvil_consortium_manager import models as acm_models @@ -960,6 +961,11 @@ def setUp(self): codename=acm_models.AnVILProjectManagerAccess.VIEW_PERMISSION_CODENAME ) ) + self.user.user_permissions.add( + Permission.objects.get( + codename=acm_models.AnVILProjectManagerAccess.EDIT_PERMISSION_CODENAME + ) + ) self.object = factories.UploadWorkspaceFactory.create() def get_url(self, *args): @@ -976,6 +982,26 @@ def test_status_code(self): ) self.assertEqual(response.status_code, 200) + def test_contains_share_with_auth_domain_button(self): + acm_factories.WorkspaceAuthorizationDomainFactory.create( + workspace=self.object.workspace, group__name="test_auth" + ) + self.client.force_login(self.user) + response = self.client.get( + self.get_url( + self.object.workspace.billing_project.name, self.object.workspace.name + ) + ) + url = reverse( + "anvil_consortium_manager:workspaces:sharing:new_by_group", + args=[ + self.object.workspace.billing_project.name, + self.object.workspace.name, + "test_auth", + ], + ) + self.assertContains(response, url) + class UploadWorkspaceListTest(TestCase): """Tests of the anvil_consortium_manager WorkspaceList view using this app's adapter.""" @@ -1471,6 +1497,11 @@ def setUp(self): codename=acm_models.AnVILProjectManagerAccess.VIEW_PERMISSION_CODENAME ) ) + self.user.user_permissions.add( + Permission.objects.get( + codename=acm_models.AnVILProjectManagerAccess.EDIT_PERMISSION_CODENAME + ) + ) self.object = factories.CombinedConsortiumDataWorkspaceFactory.create() def get_url(self, *args): @@ -1479,8 +1510,6 @@ def get_url(self, *args): def test_status_code(self): """Response has a status code of 200.""" - upload_workspace = factories.UploadWorkspaceFactory.create() - self.object.upload_workspaces.add(upload_workspace) self.client.force_login(self.user) response = self.client.get( self.get_url( @@ -1489,6 +1518,78 @@ def test_status_code(self): ) self.assertEqual(response.status_code, 200) + @skip("Need to allow extra context in ACM.") + def test_contains_upload_workspaces(self): + """Response contains the upload workspaces.""" + upload_workspace_1 = factories.UploadWorkspaceFactory.create( + upload_cycle=self.object.upload_cycle + ) + upload_workspace_2 = factories.UploadWorkspaceFactory.create( + upload_cycle=self.object.upload_cycle + ) + self.client.force_login(self.user) + response = self.client.get( + self.get_url( + self.object.workspace.billing_project.name, self.object.workspace.name + ) + ) + self.assertIn("upload_workspace_table", response.context_data) + self.assertIn( + upload_workspace_1, response.context_data["upload_workspace_table"].data + ) + self.assertIn( + upload_workspace_2, response.context_data["upload_workspace_table"].data + ) + + @skip("Need to allow extra context in ACM.") + def test_contains_upload_workspaces_from_previous_cycles(self): + """Response contains the upload workspaces.""" + upload_cycle_1 = factories.UploadCycleFactory.create(upload_cycle=1) + upload_cycle_2 = factories.UploadCycleFactory.create(upload_cycle=2) + combined_workspace = factories.CombinedConsortiumDataWorkspaceFactory.create( + upload_cycle=upload_cycle_2 + ) + upload_workspace_1 = factories.UploadWorkspaceFactory.create( + upload_cycle=upload_cycle_1 + ) + upload_workspace_2 = factories.UploadWorkspaceFactory.create( + upload_cycle=upload_cycle_2 + ) + self.client.force_login(self.user) + response = self.client.get( + self.get_url( + combined_workspace.workspace.billing_project.name, + combined_workspace.workspace.name, + ) + ) + self.assertIn("upload_workspace_table", response.context_data) + self.assertIn( + upload_workspace_1, response.context_data["upload_workspace_table"].data + ) + self.assertIn( + upload_workspace_2, response.context_data["upload_workspace_table"].data + ) + + def test_contains_share_with_auth_domain_button(self): + acm_factories.WorkspaceAuthorizationDomainFactory.create( + workspace=self.object.workspace, group__name="test_auth" + ) + self.client.force_login(self.user) + response = self.client.get( + self.get_url( + self.object.workspace.billing_project.name, self.object.workspace.name + ) + ) + url = reverse( + "anvil_consortium_manager:workspaces:sharing:new_by_group", + args=[ + self.object.workspace.billing_project.name, + self.object.workspace.name, + "test_auth", + ], + ) + self.assertContains(response, url) + class ReleaseWorkspaceDetailTest(TestCase): """Tests of the anvil_consortium_manager WorkspaceDetail view using the ReleaseWorkspaceAdapter.""" @@ -1511,8 +1612,6 @@ def get_url(self, *args): def test_status_code(self): """Response has a status code of 200.""" - upload_workspace = factories.UploadWorkspaceFactory.create() - self.object.upload_workspaces.add(upload_workspace) self.client.force_login(self.user) response = self.client.get( self.get_url( @@ -1521,6 +1620,62 @@ def test_status_code(self): ) self.assertEqual(response.status_code, 200) + @skip("Need to allow extra context in ACM.") + def test_contains_upload_workspaces(self): + """Response contains the upload workspaces.""" + upload_workspace_1 = factories.UploadWorkspaceFactory.create( + upload_cycle=self.object.upload_cycle + ) + upload_workspace_2 = factories.UploadWorkspaceFactory.create( + upload_cycle=self.object.upload_cycle + ) + self.client.force_login(self.user) + response = self.client.get( + self.get_url( + self.object.workspace.billing_project.name, self.object.workspace.name + ) + ) + self.assertIn("included_workspace_table", response.context_data) + self.assertIn( + upload_workspace_1.workspace, + response.context_data["included_workspace_table"].data, + ) + self.assertIn( + upload_workspace_2.workspace, + response.context_data["included_workspace_table"].data, + ) + + @skip("Need to allow extra context in ACM.") + def test_contains_upload_workspaces_from_previous_cycles(self): + """Response contains the upload workspaces.""" + upload_cycle_1 = factories.UploadCycleFactory.create(upload_cycle=1) + upload_cycle_2 = factories.UploadCycleFactory.create(upload_cycle=2) + combined_workspace = factories.CombinedConsortiumDataWorkspaceFactory.create( + upload_cycle=upload_cycle_2 + ) + upload_workspace_1 = factories.UploadWorkspaceFactory.create( + upload_cycle=upload_cycle_1 + ) + upload_workspace_2 = factories.UploadWorkspaceFactory.create( + upload_cycle=upload_cycle_2 + ) + self.client.force_login(self.user) + response = self.client.get( + self.get_url( + combined_workspace.workspace.billing_project.name, + combined_workspace.workspace.name, + ) + ) + self.assertIn("included_workspace_table", response.context_data) + self.assertIn( + upload_workspace_1.workspace, + response.context_data["included_workspace_table"].data, + ) + self.assertIn( + upload_workspace_2.workspace, + response.context_data["included_workspace_table"].data, + ) + class WorkspaceReportTest(TestCase): def setUp(self): diff --git a/gregor_django/templates/gregor_anvil/combinedconsortiumdataworkspace_detail.html b/gregor_django/templates/gregor_anvil/combinedconsortiumdataworkspace_detail.html index 4204abec..bf43f32d 100644 --- a/gregor_django/templates/gregor_anvil/combinedconsortiumdataworkspace_detail.html +++ b/gregor_django/templates/gregor_anvil/combinedconsortiumdataworkspace_detail.html @@ -4,10 +4,21 @@
Upload cycle
{{ object.combinedconsortiumdataworkspace.upload_cycle }}
-
Upload workspaces
- {% for upload_workspace in object.combinedconsortiumdataworkspace.upload_workspaces.all %} - {{ upload_workspace }}
- {% endfor %} -
{% endblock workspace_data %} + + +{% block action_buttons %} + +{% if show_edit_links %} + {% if object.authorization_domains.first %} +

+ Share with auth domain +

+ {% else %} +

no auth domain

+ {% endif %} +{% endif %} + +{{ block.super }} +{% endblock action_buttons %} diff --git a/gregor_django/templates/gregor_anvil/releaseworkspace_detail.html b/gregor_django/templates/gregor_anvil/releaseworkspace_detail.html index 68058480..c35dad75 100644 --- a/gregor_django/templates/gregor_anvil/releaseworkspace_detail.html +++ b/gregor_django/templates/gregor_anvil/releaseworkspace_detail.html @@ -6,11 +6,6 @@
Consent group
{{ object.releaseworkspace.consent_group }}
dbGaP accession
{{ object.releaseworkspace.get_dbgap_accession }}
Upload cycle
{{ object.releaseworkspace.upload_cycle }}
-
Upload workspaces
- {% for upload_workspace in object.releaseworkspace.upload_workspaces.all %} - {{ upload_workspace }}
- {% endfor %} -
{% endblock workspace_data %} diff --git a/gregor_django/templates/gregor_anvil/uploadworkspace_detail.html b/gregor_django/templates/gregor_anvil/uploadworkspace_detail.html index 6fb1d913..e556e626 100644 --- a/gregor_django/templates/gregor_anvil/uploadworkspace_detail.html +++ b/gregor_django/templates/gregor_anvil/uploadworkspace_detail.html @@ -31,3 +31,17 @@

{{ block.super }} {% endblock after_panel %} + +{% block action_buttons %} +{% if show_edit_links %} + {% if object.authorization_domains.first %} +

+ Share with auth domain +

+ {% else %} +

no auth domain

+ {% endif %} +{% endif %} + +{{ block.super }} +{% endblock action_buttons %}