Skip to content

Commit

Permalink
Merge pull request #285 from UW-GAC/deploy/stage
Browse files Browse the repository at this point in the history
Deploy to prod
  • Loading branch information
amstilp authored Aug 7, 2023
2 parents 0e97c61 + 3e6460d commit 5e94c41
Show file tree
Hide file tree
Showing 13 changed files with 379 additions and 514 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
114 changes: 4 additions & 110 deletions gregor_django/gregor_anvil/forms.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -63,139 +60,36 @@ 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",
"date_released",
"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."""
Expand Down
Original file line number Diff line number Diff line change
@@ -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',
),
]
Original file line number Diff line number Diff line change
@@ -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',
),
]
7 changes: 0 additions & 7 deletions gregor_django/gregor_anvil/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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."
)
Expand Down
60 changes: 24 additions & 36 deletions gregor_django/gregor_anvil/tables.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -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")
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -154,7 +160,7 @@ class Meta:
fields = (
"name",
"templateworkspace__intended_use",
"is_shared",
"consortium_access",
)


Expand All @@ -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
Expand All @@ -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."""
Expand All @@ -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)
Expand All @@ -254,5 +242,5 @@ class Meta:
"name",
"dccprocesseddataworkspace__upload_cycle",
"dccprocesseddataworkspace__consent_group",
"is_shared",
"consortium_access",
)
Loading

0 comments on commit 5e94c41

Please sign in to comment.