Coverage for src / mesh / views / views_journal_section.py: 43%

87 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-07-09 13:14 +0000

1from typing import Any 

2 

3from django.contrib import messages 

4from django.contrib.auth.mixins import LoginRequiredMixin 

5from django.core.exceptions import PermissionDenied 

6from django.http import HttpResponseRedirect 

7from django.shortcuts import get_object_or_404 

8from django.urls import reverse 

9from django.utils.translation import gettext_lazy as _ 

10from django.views.generic.edit import CreateView, UpdateView 

11 

12from mesh.models.orm.journal_models import JournalSection 

13from mesh.views.forms.base_forms import DEFAULT_FORM_BUTTONS, FormAction 

14from mesh.views.forms.submission_forms import JournalSectionForm 

15 

16from .components.breadcrumb import get_base_breadcrumb 

17from .components.button import Button 

18from .components.tree_node import build_tree_recursive 

19 

20 

21class JournalSectionListView(LoginRequiredMixin, CreateView): 

22 """ 

23 View to display all existing sections of the journal. 

24 """ 

25 

26 model = JournalSection 

27 form_class = JournalSectionForm 

28 template_name = "mesh/journal_section_list.html" 

29 

30 # Commenting : get_form should always return a form 

31 # def get_form(self, form_class=None): 

32 # if not self.role_handler.check_rights("can_edit_journal_sections"): 

33 # return None 

34 # return super().get_form(form_class) 

35 

36 def get_form_kwargs(self) -> dict[str, Any]: 

37 kwargs = super().get_form_kwargs() 

38 kwargs["_parents"] = JournalSection.objects.all_journal_sections() 

39 return kwargs 

40 

41 def setup(self, request, *args, **kwargs): 

42 super().setup(request, *args, **kwargs) 

43 if not self.request.current_role.can_access_journal_sections(): 

44 raise PermissionDenied 

45 

46 def post(self, request, *args, **kwargs): 

47 if not self.request.current_role.can_edit_journal_sections(): 

48 raise PermissionError 

49 return super().post(request, *args, **kwargs) 

50 

51 def get_success_url(self) -> str: 

52 return reverse("mesh:journal_section_list") 

53 

54 def get_context_data(self, *args, **kwargs): 

55 context = super().get_context_data(*args, **kwargs) 

56 

57 context["journal_sections_tree"] = build_tree_recursive(JournalSection.objects) 

58 context["page_title"] = _("Journal sections") 

59 

60 breadcrumb = get_base_breadcrumb() 

61 breadcrumb.add_item(title=_("Journal sections"), url=reverse("mesh:journal_section_list")) 

62 context["breadcrumb"] = breadcrumb 

63 

64 return context 

65 

66 def form_valid(self, form): 

67 form.instance._user = self.request.user 

68 return super().form_valid(form) 

69 

70 

71class JournalSectionEditView(LoginRequiredMixin, UpdateView): 

72 model = JournalSection 

73 form_class = JournalSectionForm 

74 journal_section: JournalSection 

75 template_name = "mesh/forms/submission_journal_section_update.html" 

76 

77 def setup(self, request, *args, **kwargs): 

78 super().setup(request, *args, **kwargs) 

79 if not self.request.current_role.can_edit_journal_sections(): 

80 raise PermissionError 

81 self.journal_section = get_object_or_404(JournalSection, pk=kwargs["pk"]) 

82 

83 def get_success_url(self) -> str: 

84 return reverse("mesh:journal_section_list") 

85 

86 def get_form(self, form_class=None): 

87 form: JournalSectionForm = super().get_form(form_class) 

88 form.buttons = [ 

89 *DEFAULT_FORM_BUTTONS, 

90 Button( 

91 id="form_delete", 

92 title=_("Delete"), 

93 icon_class="fa-trash", 

94 attrs={ 

95 "type": ["submit"], 

96 "class": ["button-error"], 

97 "name": [FormAction.DELETE.value], 

98 }, 

99 ), 

100 ] 

101 return form 

102 

103 def get_form_kwargs(self): 

104 kwargs = super().get_form_kwargs() 

105 kwargs["_parents"] = JournalSection.objects.all_journal_sections().exclude( 

106 pk__in=[ 

107 *[c.pk for c in self.journal_section.all_children()], 

108 self.journal_section.pk, 

109 ] 

110 ) 

111 return kwargs 

112 

113 def form_valid(self, form): 

114 form.instance._user = self.request.user 

115 return super().form_valid(form) 

116 

117 def get_context_data(self, *args, **kwargs): 

118 context = super().get_context_data(*args, **kwargs) 

119 

120 context["journal_section"] = self.journal_section 

121 context["journal_sections_tree"] = build_tree_recursive( 

122 JournalSection.objects, self.journal_section 

123 ) 

124 

125 parent = self.journal_section.parent 

126 if parent is None: 

127 title_button = Button( 

128 id="title-back-to", 

129 title=_("Back to index"), 

130 icon_class="fa-folder-tree", 

131 attrs={ 

132 "href": [reverse("mesh:journal_section_list")], 

133 "class": ["as-button"], 

134 }, 

135 ) 

136 else: 

137 title_button = Button( 

138 id="title-back-to", 

139 title=_("Back to") + f" {parent.name}", 

140 icon_class="fa-arrow-right-long", 

141 attrs={ 

142 "href": [ 

143 reverse( 

144 "mesh:submission_journal_section_update", 

145 kwargs={"pk": parent.pk}, 

146 ) 

147 ], 

148 "class": ["as-button"], 

149 }, 

150 ) 

151 context["title_buttons"] = [title_button] 

152 

153 # Generate breadcrumb 

154 breadcrumb = get_base_breadcrumb() 

155 breadcrumb.add_item(title=_("Journal sections"), url=reverse("mesh:journal_section_list")) 

156 breadcrumb.add_item( 

157 title=self.journal_section.name, 

158 url=reverse( 

159 "mesh:submission_journal_section_update", 

160 kwargs={"pk": self.journal_section.pk}, 

161 ), 

162 ) 

163 context["breadcrumb"] = breadcrumb 

164 return context 

165 

166 def post(self, request, *args, **kwargs): 

167 if FormAction.DELETE.value in request.POST: 

168 self.journal_section.delete() 

169 messages.success( 

170 request, 

171 _(f"The journal_section {self.journal_section.name} was successfully deleted."), 

172 ) 

173 return HttpResponseRedirect(self.get_success_url()) 

174 return super().post(request, *args, **kwargs)