Coverage for apps/comments_views/core/forms.py: 62%

51 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-05-19 19:20 +0000

1from typing import Any 

2 

3from ckeditor.fields import RichTextFormField 

4 

5from django import forms 

6from django.core.exceptions import ValidationError 

7from django.utils.translation import gettext_lazy as _ 

8 

9from comments_api.constants import COMMENT_STATUS_CHOICES 

10 

11 

12class CommentForm(forms.Form): 

13 """ 

14 Form for user comments. The only user input is the content of the comment. 

15 """ 

16 

17 content = RichTextFormField(required=True, label=False, config_name="comment") 

18 approval = forms.BooleanField(required=True) 

19 

20 # Hidden inputs 

21 doi = forms.CharField(required=True, widget=forms.HiddenInput()) 

22 id = forms.IntegerField(required=False, widget=forms.HiddenInput) 

23 parent = forms.IntegerField(required=False, widget=forms.HiddenInput()) 

24 parent_author_name = forms.CharField( 

25 max_length=128, required=False, widget=forms.HiddenInput() 

26 ) 

27 #### TODO: Is `date_submitted` really used ???? 

28 date_submitted = forms.CharField(required=False, widget=forms.HiddenInput()) 

29 status = forms.ChoiceField( 

30 choices=COMMENT_STATUS_CHOICES, 

31 required=False, 

32 widget=forms.HiddenInput(), 

33 ) 

34 

35 def clean(self): 

36 cleaned_data = super().clean() 

37 parent = cleaned_data.get("parent") 

38 parent_author_name = cleaned_data.get("parent_author_name") 

39 null_values = [None, 0, "", ":~:init:~:"] 

40 

41 if (parent in null_values and parent_author_name not in null_values) or ( 

42 parent not in null_values and parent_author_name in null_values 

43 ): 

44 raise forms.ValidationError( 

45 _("Both Parent ID and Parent author name must be null or non-null."), 

46 code="invalid", 

47 ) 

48 

49 if self.prefix == "reply" and (parent in null_values or parent_author_name in null_values): 49 ↛ 50line 49 didn't jump to line 50, because the condition on line 49 was never true

50 raise forms.ValidationError( 

51 _("Both Parent ID and Parent author name must be non-null for a reply comment."), 

52 code="invalid", 

53 ) 

54 

55 return cleaned_data 

56 

57 

58class CommentFormAutogrow(CommentForm): 

59 content = RichTextFormField(required=True, label=False, config_name="comment_autogrow") 

60 approval = None 

61 

62 

63class BaseCommentStatusForm(forms.Form): 

64 """ 

65 Base comment status form. Only contains the status field. 

66 

67 Used for quick actions 

68 """ 

69 

70 post_url = "comment_status_change_light" 

71 status = forms.ChoiceField( 

72 choices=COMMENT_STATUS_CHOICES, 

73 required=True, 

74 widget=forms.HiddenInput(), 

75 ) 

76 

77 

78class DetailedCommentStatusForm(BaseCommentStatusForm): 

79 """ 

80 Form to change a comment status with additional fields available to moderators. 

81 """ 

82 

83 post_url = "comment_status_change" 

84 article_author_comment = forms.BooleanField( 

85 label="Article's author", 

86 required=False, 

87 help_text="Check this box if the comment is from an author of the article.", 

88 ) 

89 editorial_team_comment = forms.BooleanField( 

90 label="Editorial team", 

91 required=False, 

92 help_text="Check this box if the comment is from someone of the editorial team.", 

93 ) 

94 hide_author_name = forms.BooleanField( 

95 label="Hide author name", 

96 required=False, 

97 help_text="Check this box to hide the name of the comment's author.", 

98 ) 

99 

100 def clean(self) -> dict[str, Any]: 

101 cleaned_data = super().clean() 

102 if ( 

103 cleaned_data["hide_author_name"] 

104 and not cleaned_data["article_author_comment"] 

105 and not cleaned_data["editorial_team_comment"] 

106 ): 

107 raise ValidationError( 

108 "'Article's author' or 'Editorial team' must be checked" 

109 " when 'Hide author name' is checked." 

110 ) 

111 if cleaned_data["article_author_comment"] and cleaned_data["editorial_team_comment"]: 

112 raise ValidationError( 

113 "'Article's author' and 'Editorial team' can't be checked together." 

114 ) 

115 return cleaned_data 

116 

117 

118def format_form_errors(form: forms.Form): 

119 """ 

120 Return the formatted list of all the form error messages, if any. 

121 

122 Field error messages are prefixed with the field name. 

123 """ 

124 errors = [] 

125 for field, error_list in form.errors.items(): 

126 if field == "__all__": 

127 errors.extend(error_list) 

128 continue 

129 errors.extend([f"{field} - {err}" for err in error_list]) 

130 

131 return errors