diff --git a/client/src/app/site/motions/modules/motion-detail/components/amendment-create-wizard/amendment-create-wizard.component.html b/client/src/app/site/motions/modules/motion-detail/components/amendment-create-wizard/amendment-create-wizard.component.html index b444876fb..3044e8108 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/amendment-create-wizard/amendment-create-wizard.component.html +++ b/client/src/app/site/motions/modules/motion-detail/components/amendment-create-wizard/amendment-create-wizard.component.html @@ -46,32 +46,18 @@ {{ 'Change paragraph' | translate }} -

Amendment text *

+

Amendment text

-

+

- {{ 'Line' | translate }} {{ paragraph.lineFrom }} * + {{ 'Line' | translate }} {{ paragraph.lineFrom }}: {{ 'Line' | translate }} {{ paragraph.lineFrom }} - - {{ paragraph.lineTo - 1 }} * + - {{ paragraph.lineTo - 1 }}:

- -
- This field is required. -
+
diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html index b5d7f8c51..3087ea11b 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html @@ -645,15 +645,14 @@
-

+

- {{ 'Line' | translate }} {{ paragraph.lineFrom }} + {{ 'Line' | translate }} {{ paragraph.lineFrom }} + - {{ 'Line' | translate }} {{ paragraph.lineFrom }} - {{ paragraph.lineTo - 1 }}  - * -

+ {{ 'Line' | translate }} {{ paragraph.lineFrom }} - {{ paragraph.lineTo - 1 }} + +
- Line {{ paragraph.diffLineFrom }}: + {{ 'Line' | translate }} {{ paragraph.diffLineFrom }}:

- Line {{ paragraph.diffLineFrom }} - {{ paragraph.diffLineTo - 1 }}: + {{ 'Line' | translate }} {{ paragraph.diffLineFrom }} - {{ paragraph.diffLineTo - 1 }}:

diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.scss b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.scss index d90e267b3..8e05e26bb 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.scss +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.scss @@ -77,6 +77,10 @@ span { } } +.amendment-line-header { + font-style: italic; +} + .motion-content { h4 { margin: 10px 10px 15px 0; diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts index 31834e366..88ca0ef9f 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts @@ -656,7 +656,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, paragraphsToChoose.forEach( (paragraph: ParagraphToChoose, paragraphNo: number): void => { - if (formMotion.amendment_paragraphs[paragraphNo]) { + if (formMotion.amendment_paragraphs[paragraphNo] !== null) { this.contentForm.addControl( 'text_' + paragraphNo, new FormControl('', Validators.required) diff --git a/openslides/motions/serializers.py b/openslides/motions/serializers.py index dec7f268e..f885083c8 100644 --- a/openslides/motions/serializers.py +++ b/openslides/motions/serializers.py @@ -401,7 +401,8 @@ class MotionSerializer(ModelSerializer): modified_final_version = CharField(allow_blank=True, required=False) reason = CharField(allow_blank=True, required=False) state_restriction = SerializerMethodField() - text = CharField(allow_blank=True) + text = CharField(allow_blank=True, required=False) # This will be checked + # during validation title = CharField(max_length=255) amendment_paragraphs = AmendmentParagraphsJSONSerializerField(required=False) workflow_id = IntegerField( @@ -472,6 +473,7 @@ class MotionSerializer(ModelSerializer): if "reason" in data: data["reason"] = validate_html(data["reason"]) + # The motion text is only needed, if it is not a paragraph based amendment. if "amendment_paragraphs" in data: data["amendment_paragraphs"] = list( map( @@ -483,7 +485,9 @@ class MotionSerializer(ModelSerializer): ) data["text"] = "" else: - if "text" in data and not data["text"]: + if (self.partial and "text" in data and not data["text"]) or ( + not self.partial and not data.get("text") + ): raise ValidationError({"detail": "The text field may not be blank."}) if config["motions_reason_required"]: if (self.partial and "reason" in data and not data["reason"]) or ( diff --git a/tests/integration/motions/test_viewset.py b/tests/integration/motions/test_viewset.py index 01d691908..6231c7586 100644 --- a/tests/integration/motions/test_viewset.py +++ b/tests/integration/motions/test_viewset.py @@ -266,9 +266,15 @@ class CreateMotion(TestCase): def test_without_data(self): response = self.client.post(reverse("motion-list"), {}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertTrue("title" in response.data) + + def test_without_text(self): + response = self.client.post( + reverse("motion-list"), {"title": "test_title_dlofp23m9O(ZD2d1lwHG"} + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( - response.data, - {"title": ["This field is required."], "text": ["This field is required."]}, + str(response.data["detail"][0]), "The text field may not be blank." ) def test_with_category(self): @@ -569,6 +575,14 @@ class UpdateMotion(TestCase): self.assertEqual(motion.title, "test_title_aeng7ahChie3waiR8xoh") self.assertEqual(motion.identifier, "test_identifier_jieseghohj7OoSah1Ko9") + def test_patch_empty_text(self): + response = self.client.patch( + reverse("motion-detail", args=[self.motion.pk]), {"text": ""}, format="json" + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + motion = Motion.objects.get() + self.assertEqual(motion.text, "test_text_xeigheeha7thopubeu4U") + def test_patch_workflow(self): """ Tests to only update the workflow of a motion.