Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create user defined forms app #882

Merged
merged 39 commits into from Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
19a093d
Preliminary work on replacing prefilter logic with filtersets
rabstejnek Aug 10, 2023
98f69fc
Data pivots largely done
rabstejnek Aug 21, 2023
cdede6f
Visuals largely done
rabstejnek Aug 21, 2023
7cee82b
Cleanup, linting
rabstejnek Aug 22, 2023
89d2f58
Improvements
rabstejnek Aug 23, 2023
228d876
Fix tests
rabstejnek Aug 23, 2023
ca90cf1
create initial form library classes
munnsmunns Aug 24, 2023
c2175de
migrate needed files and add new app
munnsmunns Aug 28, 2023
14a4d64
add to apps
munnsmunns Aug 28, 2023
ab0e7eb
add validation to form
munnsmunns Aug 28, 2023
66e0031
add migration and admin site
munnsmunns Aug 29, 2023
b4e1e37
add url and get form view running
munnsmunns Aug 29, 2023
249b751
improve form layout
munnsmunns Aug 29, 2023
7d74a7d
migrate tests from hero
munnsmunns Aug 29, 2023
aaf6159
ruff
munnsmunns Aug 29, 2023
0c8a9bc
enable feature flag for tests
munnsmunns Aug 29, 2023
7cb09df
fix settings file
munnsmunns Aug 29, 2023
3d1ae6d
skip failing test for now
munnsmunns Aug 29, 2023
34aab55
add more fields from review
munnsmunns Aug 31, 2023
b13a478
add fields to form
munnsmunns Aug 31, 2023
cc8829c
lint
munnsmunns Aug 31, 2023
b64f959
fix test
shapiromatron Sep 7, 2023
441f6b5
set the creator outside with data from request, not form fields
shapiromatron Sep 7, 2023
b3ee0a8
updates from review
munnsmunns Sep 12, 2023
9c8dfac
remove comment
munnsmunns Sep 12, 2023
300736c
fix urls
munnsmunns Sep 12, 2023
3729afa
vendor dynamic forms
shapiromatron Sep 16, 2023
848f016
Merge branch 'dynamic-forms' into form-library
shapiromatron Sep 16, 2023
aa4caba
fix merge conflicts
shapiromatron Sep 17, 2023
9500b80
revert db fixture
shapiromatron Sep 17, 2023
99660b4
use regex
shapiromatron Sep 17, 2023
3c3e384
remove ID
shapiromatron Sep 17, 2023
59ae0d4
rename to udf
shapiromatron Sep 17, 2023
2978b32
lint; add test UDF to db schema
shapiromatron Sep 17, 2023
f853b49
dont hard-code model related models
shapiromatron Sep 17, 2023
f7ea9c4
validate field name via regex
shapiromatron Sep 17, 2023
deb5d97
Merge branch 'dynamic-forms' into form-library
shapiromatron Sep 17, 2023
efd1e4f
Merge branch 'main' into form-library
shapiromatron Sep 18, 2023
ffcda36
Merge branch 'main' into form-library
shapiromatron Sep 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Empty file added hawc/apps/udf/__init__.py
Empty file.
11 changes: 11 additions & 0 deletions hawc/apps/udf/admin.py
@@ -0,0 +1,11 @@
from django.contrib import admin

from . import models


class CustomDataExtractionInline(admin.TabularInline):
model = models.UserDefinedForm
extra = 0


admin.site.register(models.UserDefinedForm)
7 changes: 7 additions & 0 deletions hawc/apps/udf/apps.py
@@ -0,0 +1,7 @@
from django.apps import AppConfig


class FormLibraryConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "hawc.apps.udf"
verbose_name = "User Defined Forms"
41 changes: 41 additions & 0 deletions hawc/apps/udf/forms.py
@@ -0,0 +1,41 @@
from django import forms
from django.urls import reverse

from hawc.apps.common.autocomplete.forms import AutocompleteSelectMultipleWidget
from hawc.apps.common.dynamic_forms.schemas import Schema
from hawc.apps.common.forms import BaseFormHelper, PydanticValidator
from hawc.apps.myuser.autocomplete import UserAutocomplete

from .models import UserDefinedForm


class UDFForm(forms.ModelForm):
schema = forms.JSONField(
initial=Schema(fields=[]).dict(),
validators=[PydanticValidator(Schema)],
)

def __init__(self, *args, **kwargs):
user = kwargs.pop("user")
super().__init__(*args, **kwargs)
if self.instance.id is None:
self.instance.creator = user

class Meta:
model = UserDefinedForm
exclude = ("parent_form", "creator", "created", "last_updated")
widgets = {
"editors": AutocompleteSelectMultipleWidget(UserAutocomplete),
}

@property
def helper(self):
self.fields["description"].widget.attrs["rows"] = 3
cancel_url = reverse("portal") # TODO: replace temp cancel url
helper = BaseFormHelper(
self,
legend_text="Create a custom data extraction form",
cancel_url=cancel_url,
submit_text="Create Form",
)
return helper
59 changes: 59 additions & 0 deletions hawc/apps/udf/migrations/0001_initial.py
@@ -0,0 +1,59 @@
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="UserDefinedForm",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.CharField(max_length=128)),
("description", models.TextField()),
("schema", models.JSONField()),
("deprecated", models.BooleanField(default=False)),
("created", models.DateTimeField(auto_now_add=True)),
("last_updated", models.DateTimeField(auto_now=True)),
(
"creator",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="udf_forms_creator",
to=settings.AUTH_USER_MODEL,
),
),
(
"editors",
models.ManyToManyField(
blank=True, related_name="udf_forms", to=settings.AUTH_USER_MODEL
),
),
(
"parent",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="children",
to="udf.userdefinedform",
),
),
],
options={
"ordering": ("-last_updated",),
"unique_together": {("creator", "name")},
},
),
]
Empty file.
30 changes: 30 additions & 0 deletions hawc/apps/udf/models.py
@@ -0,0 +1,30 @@
import reversion
from django.conf import settings
from django.db import models


class UserDefinedForm(models.Model):
name = models.CharField(max_length=128)
description = models.TextField()
schema = models.JSONField()
creator = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.PROTECT, related_name="udf_forms_creator"
)
editors = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name="udf_forms")
parent = models.ForeignKey(
"self",
blank=True,
null=True,
on_delete=models.SET_NULL,
related_name="children",
)
deprecated = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)

class Meta:
unique_together = (("creator", "name"),)
ordering = ("-last_updated",)


reversion.register(UserDefinedForm)
7 changes: 7 additions & 0 deletions hawc/apps/udf/templates/udf/udf_form.html
@@ -0,0 +1,7 @@
{% extends "crumbless.html" %}

{% load crispy_forms_tags %}

{% block content %}
{% crispy form %}
{% endblock %}
13 changes: 13 additions & 0 deletions hawc/apps/udf/urls.py
@@ -0,0 +1,13 @@
from django.conf import settings
from django.urls import path

from . import views

app_name = "udf"
urlpatterns = (
[
path("create/", views.CreateUDFView.as_view(), name="udf_create"),
]
if settings.HAWC_FEATURES.ENABLE_UDF
else []
)
20 changes: 20 additions & 0 deletions hawc/apps/udf/views.py
@@ -0,0 +1,20 @@
from django.urls import reverse
from django.views.generic.edit import CreateView

from hawc.apps.common.views import LoginRequiredMixin, MessageMixin

from .forms import UDFForm


class CreateUDFView(LoginRequiredMixin, MessageMixin, CreateView):
template_name = "udf/udf_form.html"
form_class = UDFForm
success_message = "Form created."

def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update(user=self.request.user)
return kwargs

def get_success_url(self) -> str:
return reverse("portal")
1 change: 1 addition & 0 deletions hawc/constants.py
Expand Up @@ -17,6 +17,7 @@ class FeatureFlags(BaseModel):
ANONYMOUS_ACCOUNT_CREATION: bool = True
ENABLE_BMDS_33 = False
ENABLE_PLOTLY_VISUAL: bool = False
ENABLE_UDF: bool = False

@classmethod
def from_env(cls, variable) -> "FeatureFlags":
Expand Down
1 change: 1 addition & 0 deletions hawc/main/settings/base.py
Expand Up @@ -125,6 +125,7 @@
"hawc.apps.hawc_admin",
"hawc.apps.materialized",
"hawc.apps.epiv2",
"hawc.apps.udf",
)
# DB settings
DATABASES = {
Expand Down
1 change: 1 addition & 0 deletions hawc/main/settings/unittest.py
Expand Up @@ -10,6 +10,7 @@

# enable feature flags for tests
HAWC_FEATURES.ENABLE_BMDS_33 = True
HAWC_FEATURES.ENABLE_UDF = True

# remove toolbar for integration tests
INSTALLED_APPS = [app for app in INSTALLED_APPS if app != "debug_toolbar"]
Expand Down
2 changes: 2 additions & 0 deletions hawc/main/urls.py
Expand Up @@ -17,6 +17,7 @@
import hawc.apps.riskofbias.urls
import hawc.apps.study.urls
import hawc.apps.summary.urls
import hawc.apps.udf.urls
import hawc.apps.vocab.urls
from hawc.apps.assessment import views
from hawc.apps.common.autocomplete import get_autocomplete
Expand All @@ -43,6 +44,7 @@
path("epidemiology/", include("hawc.apps.epiv2.urls")),
path("epi-meta/", include("hawc.apps.epimeta.urls")),
path("in-vitro/", include("hawc.apps.invitro.urls")),
path("udf/", include("hawc.apps.udf.urls")),
path("bmd/", include("hawc.apps.bmd.urls")),
path("lit/", include("hawc.apps.lit.urls")),
path("summary/", include("hawc.apps.summary.urls")),
Expand Down
19 changes: 19 additions & 0 deletions tests/data/fixtures/db.yaml
Expand Up @@ -10247,6 +10247,25 @@
due_date: null
started: null
completed: null
- model: udf.UserDefinedForm
pk: 1
fields:
name: demo form
description: a demo form
schema: {
fields: [
{name: "field1", type: "char"},
{name: "field2", type: "integer"},
]
}
creator:
- pm@hawcproject.org
editors:
- - team@hawcproject.org
parent: null
deprecated: false
created: 2023-09-17 04:10:29.880052+00:00
last_updated: 2023-09-17 04:15:33.309627+00:00
- model: reversion.revision
pk: 1
fields:
Expand Down