diff --git a/testapp/forms/page.py b/testapp/forms/issue.py similarity index 70% rename from testapp/forms/page.py rename to testapp/forms/issue.py index 67df94fd..3c8a4023 100644 --- a/testapp/forms/page.py +++ b/testapp/forms/issue.py @@ -1,4 +1,4 @@ -from django.forms.fields import CharField, SlugField +from django.forms.fields import CharField, IntegerField from django.forms.models import ModelChoiceField, ModelForm, construct_instance from django.forms.widgets import HiddenInput @@ -6,9 +6,9 @@ from formset.dialog import DialogModelForm from formset.fields import Activator from formset.renderers import ButtonVariant -from formset.widgets import Button, Selectize, SlugInput +from formset.widgets import Button, Selectize -from testapp.models import Reporter, PageModel +from testapp.models import Reporter, IssueModel class ChangeReporterDialogForm(DialogModelForm): @@ -29,14 +29,14 @@ def is_valid(self): class EditReporterDialogForm(ChangeReporterDialogForm): title = "Edit Reporter" - induce_open = 'page.edit_reporter:active' + induce_open = 'issue.edit_reporter:active' induce_close = '.change:active || .cancel:active' - id = CharField(widget=HiddenInput) + id = IntegerField(widget=HiddenInput) change = Activator( label="Change Reporter", widget=Button( - action='submitPartial -> setFieldValue(page.reporter, ^reporter_id) -> activate("clear")', + action='submitPartial -> setFieldValue(issue.reporter, ^reporter_id) -> activate("clear")', button_variant=ButtonVariant.PRIMARY, ), ) @@ -48,13 +48,13 @@ class Meta: class CreateReporterDialogForm(ChangeReporterDialogForm): title = "Create Reporter" - induce_open = 'page.add_reporter:active' + induce_open = 'issue.add_reporter:active' induce_close = '.create:active || .cancel:active' create = Activator( label="Create Reporter", widget=Button( - action='submitPartial -> setFieldValue(page.reporter, ^reporter_id) -> activate("clear")', + action='submitPartial -> setFieldValue(issue.reporter, ^reporter_id) -> activate("clear")', button_variant=ButtonVariant.PRIMARY, ), ) @@ -64,16 +64,11 @@ class Meta: fields = ['full_name'] -class PageForm(ModelForm): +class IssueForm(ModelForm): title = CharField( label="Title", max_length=100, ) - slug = SlugField( - label="Slug", - required=False, - widget=SlugInput(populate_from='title'), - ) reporter = ModelChoiceField( queryset=Reporter.objects.all(), label="Reporter", @@ -85,8 +80,8 @@ class PageForm(ModelForm): edit_reporter = Activator( label="Edit Reporter", widget=Button( - action='activate("prefill", page.reporter)', - attrs={'df-disable': '!page.reporter'}, + action='activate("prefill", issue.reporter)', + attrs={'df-disable': '!issue.reporter'}, button_variant=ButtonVariant.SUCCESS, ), ) @@ -99,17 +94,17 @@ class PageForm(ModelForm): ) class Meta: - model = PageModel - fields = ['title', 'slug', 'reporter'] + model = IssueModel + fields = ['title', 'reporter'] -class EditPageCollection(FormCollection): +class EditIssueCollection(FormCollection): create_reporter = CreateReporterDialogForm() edit_reporter = EditReporterDialogForm() - page = PageForm() + issue = IssueForm() def construct_instance(self, main_object): assert not self.partial - instance = construct_instance(self.valid_holders['page'], main_object) + instance = construct_instance(self.valid_holders['issue'], main_object) instance.save() return instance diff --git a/testapp/migrations/0001_initial.py b/testapp/migrations/0001_initial.py index 1b61dd99..fb914ea2 100644 --- a/testapp/migrations/0001_initial.py +++ b/testapp/migrations/0001_initial.py @@ -270,6 +270,15 @@ class Migration(migrations.Migration): 'unique_together': {('name', 'department')}, }, ), + migrations.CreateModel( + name='IssueModel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=100, verbose_name='Issue Title')), + ('created_by', models.CharField(db_index=True, editable=False, max_length=40)), + ('reporter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='issues', to='testapp.reporter', verbose_name='Reporter')), + ], + ), migrations.RunPython(initialize_opinions, reverse_code=migrations.RunPython.noop), migrations.RunPython(initialize_counties, reverse_code=migrations.RunPython.noop), migrations.RunPython(initialize_reporters, reverse_code=migrations.RunPython.noop), diff --git a/testapp/models/__init__.py b/testapp/models/__init__.py index 5a524f2f..a1310596 100644 --- a/testapp/models/__init__.py +++ b/testapp/models/__init__.py @@ -3,6 +3,7 @@ from .company import Company, Department, Team from .county import County, CountyUnnormalized, State from .blog import BlogModel +from .issue import IssueModel from .page import PageModel from .person import PersonModel, UserContact from .poll import OpinionModel, PollModel, WeightedOpinion diff --git a/testapp/models/issue.py b/testapp/models/issue.py new file mode 100644 index 00000000..ce67593d --- /dev/null +++ b/testapp/models/issue.py @@ -0,0 +1,28 @@ +from django.db import models +from django.urls import reverse + +from testapp.models.reporter import Reporter + + +class IssueModel(models.Model): + title = models.CharField( + verbose_name="Issue Title", + max_length=100, + ) + reporter = models.ForeignKey( + Reporter, + on_delete=models.CASCADE, + verbose_name="Reporter", + related_name='issues', + ) + created_by = models.CharField( + editable=False, + max_length=40, + db_index=True, + ) + + def __str__(self): + return self.title + + def get_absolute_url(self): + return f"/pages/{self.id}/" diff --git a/testapp/tests/test_e2e_dialogmodel.py b/testapp/tests/test_e2e_dialogmodel.py index 101effde..79c9e0db 100644 --- a/testapp/tests/test_e2e_dialogmodel.py +++ b/testapp/tests/test_e2e_dialogmodel.py @@ -3,7 +3,7 @@ from playwright.sync_api import expect from django.urls import path -from django.forms.fields import CharField, SlugField +from django.forms.fields import CharField, IntegerField from django.forms.models import ModelChoiceField, ModelForm, construct_instance from django.forms.widgets import HiddenInput from django.http import JsonResponse, HttpResponseBadRequest @@ -12,19 +12,19 @@ from formset.dialog import DialogModelForm from formset.fields import Activator from formset.views import EditCollectionView -from formset.widgets import Button, Selectize, SlugInput +from formset.widgets import Button, Selectize from .utils import get_javascript_catalog -from testapp.models import Reporter, PageModel +from testapp.models import Reporter, IssueModel class ChangeReporterDialogForm(DialogModelForm): title = "Edit Reporter" - induce_open = 'page.edit_reporter:active || page.add_reporter:active' + induce_open = 'issue.edit_reporter:active || issue.add_reporter:active' induce_close = '.change:active || .cancel:active' - id = CharField( + id = IntegerField( widget=HiddenInput, required=False, help_text="Primary key of Reporter object. Leave empty to create a new object.", @@ -34,7 +34,7 @@ class ChangeReporterDialogForm(DialogModelForm): ) change = Activator( widget=Button( - action='submitPartial -> setFieldValue(page.reporter, ^reporter_id) -> activate("clear")', + action='submitPartial -> setFieldValue(issue.reporter, ^reporter_id) -> activate("clear")', ), ) @@ -49,28 +49,18 @@ def is_valid(self): return True -class PageForm(ModelForm): - title = CharField( - label="Title", - max_length=100, - ) - slug = SlugField( - label="Slug", - required=False, - widget=SlugInput(populate_from='title'), - ) +class IssueForm(ModelForm): + title = CharField() reporter = ModelChoiceField( queryset=Reporter.objects.all(), - label="Reporter", widget=Selectize( search_lookup='full_name__icontains', ), - required=False, ) edit_reporter = Activator( widget=Button( - action='activate("prefill", page.reporter)', - attrs={'df-disable': '!page.reporter'}, + action='activate("prefill", issue.reporter)', + attrs={'df-disable': '!issue.reporter'}, ), ) add_reporter = Activator( @@ -80,30 +70,30 @@ class PageForm(ModelForm): ) delete_reporter = Activator( widget=Button( - action='deletePartial(change_reporter, page.reporter) -> setFieldValue(page.reporter, "")', - attrs={'df-disable': '!page.reporter'}, + action='deletePartial(change_reporter, issue.reporter) -> setFieldValue(issue.reporter, "")', + attrs={'df-disable': '!issue.reporter'}, ), ) class Meta: - model = PageModel - fields = ['title', 'slug', 'reporter'] + model = IssueModel + fields = ['title', 'reporter'] -class EditPageCollection(FormCollection): +class EditIssueCollection(FormCollection): change_reporter = ChangeReporterDialogForm() - page = PageForm() + issue = IssueForm() def construct_instance(self, main_object): assert not self.partial - instance = construct_instance(self.valid_holders['page'], main_object) + instance = construct_instance(self.valid_holders['issue'], main_object) instance.save() return instance -class PageCollectionView(EditCollectionView): - model = PageModel - collection_class = EditPageCollection +class IssueCollectionView(EditCollectionView): + model = IssueModel + collection_class = EditIssueCollection template_name = 'testapp/form-collection.html' def get_object(self, queryset=None): @@ -126,17 +116,17 @@ def form_collection_valid(self, form_collection): urlpatterns = [ - path('page', PageCollectionView.as_view( - collection_class=EditPageCollection, + path('issue', IssueCollectionView.as_view( + collection_class=EditIssueCollection, template_name='testapp/form-collection.html', extra_context={'click_actions': 'submit -> proceed', 'force_submission': True}, - ), name='page'), + ), name='issue'), get_javascript_catalog(), ] @pytest.mark.urls(__name__) -@pytest.mark.parametrize('viewname', ['page']) +@pytest.mark.parametrize('viewname', ['issue']) def test_add_reporter(page, mocker, viewname): form_collection = page.locator('django-formset > django-form-collection') dialog = form_collection.nth(0).locator('> dialog') @@ -155,7 +145,7 @@ def test_add_reporter(page, mocker, viewname): full_name_input.fill("Sarah Hemingway") expect(full_name_input.locator('+ [role="alert"]')).to_be_empty() full_name_input.blur() - spy = mocker.spy(PageCollectionView, 'post') + spy = mocker.spy(IssueCollectionView, 'post') dialog.locator('button[name="change"]').click() expect(dialog).not_to_be_visible() @@ -169,7 +159,7 @@ def test_add_reporter(page, mocker, viewname): @pytest.mark.urls(__name__) -@pytest.mark.parametrize('viewname', ['page']) +@pytest.mark.parametrize('viewname', ['issue']) def test_edit_reporter(page, mocker, viewname): form_collection = page.locator('django-formset > django-form-collection') dialog = form_collection.nth(0).locator('> dialog') @@ -190,7 +180,7 @@ def test_edit_reporter(page, mocker, viewname): expect(dialog.locator('> div.dialog-header > h3')).to_have_text("Edit Reporter") full_name_input.fill("Sarah Johnson") full_name_input.blur() - spy = mocker.spy(PageCollectionView, 'post') + spy = mocker.spy(IssueCollectionView, 'post') dialog.locator('button[name="change"]').click() expect(dialog).not_to_be_visible() @@ -203,7 +193,7 @@ def test_edit_reporter(page, mocker, viewname): @pytest.mark.urls(__name__) -@pytest.mark.parametrize('viewname', ['page']) +@pytest.mark.parametrize('viewname', ['issue']) def test_delete_reporter(page, mocker, viewname): form_collection = page.locator('django-formset > django-form-collection') dialog = form_collection.nth(0).locator('> dialog') @@ -217,7 +207,7 @@ def test_delete_reporter(page, mocker, viewname): expect(pseudo_input).to_have_text("Sarah Hemingway") # delete the current reporter remotely - spy = mocker.spy(PageCollectionView, 'delete') + spy = mocker.spy(IssueCollectionView, 'delete') form_collection.nth(1).locator('button[name="delete_reporter"]').click() # check if the reporter was deleted from the database and from the selectize widget diff --git a/testapp/views.py b/testapp/views.py index 9fd51937..7f8b52ed 100644 --- a/testapp/views.py +++ b/testapp/views.py @@ -45,10 +45,10 @@ from testapp.forms.county import CountyForm from testapp.forms.customer import CustomerCollection from testapp.forms.gallerycollection import GalleryCollection +from testapp.forms.issue import EditIssueCollection from testapp.forms.moment import MomentBoxForm, MomentCalendarForm, MomentInputForm, MomentPickerForm from testapp.forms.moon import MoonForm, MoonCalendarRenderer from testapp.forms.opinion import OpinionForm -from testapp.forms.page import EditPageCollection from testapp.forms.person import ButtonActionsForm, sample_person_data, ModelPersonForm from testapp.forms.phone import PhoneForm from testapp.forms.poll import ModelPollForm, PollCollection @@ -59,7 +59,7 @@ from testapp.forms.terms_of_use import AcceptTermsCollection from testapp.forms.user import UserCollection, UserListCollection from testapp.forms.upload import UploadForm -from testapp.models import BlogModel, Company, PageModel, PersonModel, PollModel, Reporter +from testapp.models import BlogModel, Company, IssueModel, PersonModel, PollModel, Reporter from testapp.models.gallery import Gallery @@ -315,9 +315,9 @@ class GalleryCollectionView(DemoFormCollectionViewMixin, SessionFormCollectionVi } -class PageCollectionView(DemoFormCollectionViewMixin, SessionFormCollectionViewMixin, EditCollectionView): - model = PageModel - collection_class = EditPageCollection +class IssueCollectionView(DemoFormCollectionViewMixin, SessionFormCollectionViewMixin, EditCollectionView): + model = IssueModel + collection_class = EditIssueCollection template_name = 'testapp/form-collection.html' def form_collection_valid(self, form_collection): @@ -569,9 +569,7 @@ class CompleteForm(FormMixin, forms.Form): collection_class=AcceptTermsCollection, template_name='testapp/form-collection-no-buttons.html', ), name='simplecontact'), - path('page', PageCollectionView.as_view( - collection_class=EditPageCollection, - ), name='page'), + path('issue', IssueCollectionView.as_view(), name='issue'), path('customer', DemoFormCollectionView.as_view( collection_class=CustomerCollection, ), name='customer'),