Coverage for src/django_resume/plugins/projects.py: 47%

1 import json

2

3 from typing import Type, Any

4

5 from django import forms

6

7 from .base import ListPlugin, ListItemFormMixin, ListTemplates, ListInline

8

9

10 class ProjectItemForm(ListItemFormMixin, forms.Form):

11 title = forms.CharField(widget=forms.TextInput())

12 url = forms.URLField(widget=forms.URLInput(), required=False, assume_scheme="https")

13 description = forms.CharField(widget=forms.Textarea())

14 initial_badges = ["Some Badge", "Another Badge"]

15 badges = forms.JSONField(

16 widget=forms.TextInput(), required=False, initial=initial_badges

17 )

18 position = forms.IntegerField(widget=forms.NumberInput(), required=False)

19

20 def __init__(self, *args, **kwargs):

21 super().__init__(*args, **kwargs)

22 self.set_initial_position()

23

24 def badges_as_json(self):

25 """

26 Return the initial badges which should already be a normal list of strings

27 or the initial_badged list for the first render of the form encoded as json.

28 """

29 existing_badges = self.initial.get("badges")

30 if existing_badges is not None:

31 return json.dumps(existing_badges)

32 return json.dumps(self.initial_badges)

33

34 @staticmethod

35 def get_initial() -> dict[str, Any]:

36 """Just some default values."""

37 return {

38 "title": "Project Title",

39 "url": "https://example.com/project/",

40 "description": "description",

41 "badges": ProjectItemForm.initial_badges,

42 }

43

44 def set_context(self, item: dict, context: dict[str, Any]) -> dict[str, Any]:

45 context["project"] = {

46 "id": item["id"],

47 "url": item["url"],

48 "title": item["title"],

49 "description": item["description"],

50 "badges": item["badges"],

51 "edit_url": context["edit_url"],

52 "delete_url": context["delete_url"],

53 }

54 return context

55

56 def set_initial_badges(self):

57 """Transform the list of badges into a comma-separated string."""

58 if "badges" in self.initial and isinstance(self.initial["badges"], list):

59 self.initial["badges"] = ",".join(self.initial["badges"])

60

61 @staticmethod

62 def get_max_position(items):

63 """Return the maximum position value from the existing items."""

64 positions = [item.get("position", 0) for item in items]

65 return max(positions) if positions else -1

66

67 def set_initial_position(self):

68 """Set the position to the next available position."""

69 if "position" not in self.initial:

70 self.initial["position"] = self.get_max_position(self.existing_items) + 1

71

72 def clean_title(self):

73 title = self.cleaned_data["title"]

74 if title == "Senor Developer":

75 print("No Senor! Validation Error!")

76 raise forms.ValidationError("No Senor!")

77 return title

78

79 def clean_position(self):

80 position = self.cleaned_data.get("position", 0)

81 if position < 0:

82 raise forms.ValidationError("Position must be a positive integer.")

83 for item in self.existing_items:

84 if item["id"] == self.cleaned_data["id"]:

85 # updating the existing item, so we can skip checking its position

86 continue

87 if item.get("position") == position:

88 max_position = self.get_max_position(self.existing_items)

89 raise forms.ValidationError(

90 f"Position must be unique - take {max_position + 1} instead."

91 )

92 return position

93

94

95 class ProjectFlatForm(forms.Form):

96 title = forms.CharField(

97 widget=forms.TextInput(), required=False, max_length=50, initial="Projects"

98 )

99

100 @staticmethod

101 def set_context(item: dict, context: dict[str, Any]) -> dict[str, Any]:

102 context["projects"] = {"title": item.get("title", "")}

103 context["projects"]["edit_flat_url"] = context["edit_flat_url"]

104 return context

105

106

107 class ProjectsPlugin(ListPlugin):

108 name: str = "projects"

109 verbose_name: str = "Projects"

110 inline: ListInline

111 templates = ListTemplates(

112 main="django_resume/plain/projects.html",

113 flat="django_resume/plain/projects_flat.html",

114 flat_form="django_resume/plain/projects_flat_form.html",

115 item="django_resume/plain/projects_item.html",

116 item_form="django_resume/plain/projects_item_form.html",

117 )

118 flat_form_class = ProjectFlatForm

119

120 @staticmethod

121 def get_form_classes() -> dict[str, Type[forms.Form]]:

122 return {"item": ProjectItemForm, "flat": ProjectFlatForm}