Coverage for src/mesh/admin.py: 90%

103 statements  

« prev     ^ index     » next       coverage.py v7.7.0, created at 2025-04-28 07:45 +0000

1from django.contrib import admin 

2from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin 

3from django.forms import BaseForm 

4from django.http import HttpRequest 

5from django.utils.translation import gettext_lazy as _ 

6 

7from .models.base_models import BaseChangeTrackingModel 

8from .models.editorial_models import ( 

9 EditorialDecision, 

10 EditorialDecisionFile, 

11 EditorSectionRight, 

12 EditorSubmissionRight, 

13) 

14from .models.file_models import BaseFileWrapperModel 

15from .models.journal_models import JournalSection 

16from .models.review_models import Review, ReviewAdditionalFile 

17from .models.submission_models import ( 

18 Submission, 

19 SubmissionAdditionalFile, 

20 SubmissionAuthor, 

21 SubmissionLog, 

22 SubmissionMainFile, 

23 SubmissionVersion, 

24) 

25from .models.user_models import SuggestedReviewer, Suggestion, User, UserToken 

26 

27 

28def get_file_wrapper_inline( 

29 model_class: type[BaseFileWrapperModel], 

30 name_plural: str = "Files", 

31 extra_fields: list[str] = [], 

32 read_only_fields: list[str] = [], 

33) -> type[admin.TabularInline]: 

34 """ 

35 Returns a `TalubarInline` to display related `BaseFileWrapperModel` instances. 

36 """ 

37 

38 class FileWrapperInlineAdmin(admin.TabularInline): 

39 model = model_class 

40 extra = 0 

41 verbose_name_plural = name_plural 

42 fields = ["file", "name", *extra_fields] 

43 readonly_fields = read_only_fields 

44 

45 return FileWrapperInlineAdmin 

46 

47 

48class BaseUserChangeTrackingAdmin(admin.ModelAdmin): 

49 """ 

50 Base admin model for models inheriting from BaseChangeTrackingModel. 

51 Attach the request to the object to be saved. 

52 """ 

53 

54 readonly_fields: list[str] = [ 

55 "date_created", 

56 "created_by", 

57 "date_last_modified", 

58 "last_modified_by", 

59 ] 

60 

61 def save_model( 

62 self, 

63 request: HttpRequest, 

64 obj: BaseChangeTrackingModel, 

65 form: BaseForm, 

66 change: bool, 

67 ) -> None: 

68 obj._user = request.user # type:ignore 

69 # change = whether the object is being created or updated 

70 if change and not form.has_changed(): 

71 obj.do_not_update = True 

72 

73 super().save_model(request, obj, form, change) 

74 

75 

76class UserTokenInline(admin.StackedInline): 

77 model = UserToken 

78 fk_name = "user" 

79 can_delete = False 

80 fields = ["key", "date_refreshed", "date_created"] 

81 readonly_fields = ["date_created"] 

82 

83 

84@admin.register(User) 

85class UserAdmin(DjangoUserAdmin): 

86 """Define admin model for our custom User model having no email field.""" 

87 

88 inlines = (UserTokenInline,) 

89 fieldsets = ( 

90 (None, {"fields": ("email", "password")}), 

91 (_("Personal info"), {"fields": ("first_name", "last_name")}), 

92 (_("For staff"), {"fields": ["current_role", "journal_manager"]}), 

93 ( 

94 _("Permissions"), 

95 { 

96 "fields": ( 

97 "is_active", 

98 "is_staff", 

99 "is_superuser", 

100 "groups", 

101 "user_permissions", 

102 ) 

103 }, 

104 ), 

105 (_("Important dates"), {"fields": ("last_login", "date_joined")}), 

106 ) 

107 add_fieldsets = ( 

108 ( 

109 None, 

110 { 

111 "classes": ("wide",), 

112 "fields": ( 

113 "email", 

114 "password1", 

115 "password2", 

116 "first_name", 

117 "last_name", 

118 ), 

119 }, 

120 ), 

121 ) 

122 list_display = ( 

123 "email", 

124 "first_name", 

125 "last_name", 

126 "current_role", 

127 "is_staff", 

128 "is_superuser", 

129 "journal_manager", 

130 ) 

131 search_fields = ("email", "first_name", "last_name") 

132 ordering = ("email",) 

133 readonly_fields = ["current_role", "last_login", "date_joined"] 

134 

135 

136@admin.register(SubmissionLog) 

137class ModelLogAdmin(BaseUserChangeTrackingAdmin): 

138 list_display = [field.name for field in SubmissionLog._meta.get_fields()] 

139 

140 

141@admin.register(JournalSection) 

142class JournalSectionAdmin(BaseUserChangeTrackingAdmin): 

143 fieldsets = ( 

144 (None, {"fields": ["name", "parent"]}), 

145 (_("Object metadata"), {"fields": ["date_created", "created_by"]}), 

146 ) 

147 list_display = ["name", "parent", "date_created", "created_by"] 

148 

149 

150class EditorSubmissionRightInline(admin.TabularInline): 

151 extra = 0 

152 verbose_name_plural = _("Assigned Editors") 

153 model = EditorSubmissionRight 

154 

155 

156@admin.register(Submission) 

157class SubmissionAdmin(BaseUserChangeTrackingAdmin): 

158 inlines = (EditorSubmissionRightInline,) 

159 fieldsets = ( 

160 ( 

161 _("Metadata"), 

162 {"fields": ["created_by", "journal_section", "state", "date_created"]}, 

163 ), 

164 (_("Submission data"), {"fields": ["name", "abstract"]}), 

165 ) 

166 readonly_fields = ["name", "abstract"] 

167 list_display = ["created_by", "date_created", "journal_section", "name", "state"] 

168 

169 def get_readonly_fields(self, request: HttpRequest, obj) -> set[str]: 

170 return set(list(BaseUserChangeTrackingAdmin.readonly_fields) + list(self.readonly_fields)) 

171 

172 

173@admin.register(SubmissionVersion) 

174class SubmissionVersionAdmin(BaseUserChangeTrackingAdmin): 

175 inlines = ( 

176 get_file_wrapper_inline(SubmissionMainFile), 

177 get_file_wrapper_inline(SubmissionAdditionalFile), 

178 ) 

179 fieldsets = [ 

180 ( 

181 _("Submission version"), 

182 {"fields": ["submission", "number", "submitted", "date_submitted"]}, 

183 ) 

184 ] 

185 readonly_fields = ["submission", "number", "submitted", "date_submitted"] 

186 list_display = [ 

187 "submission", 

188 "number", 

189 "date_created", 

190 "submitted", 

191 "date_submitted", 

192 ] 

193 

194 def get_readonly_fields(self, request: HttpRequest, obj) -> set[str]: 

195 return set(list(BaseUserChangeTrackingAdmin.readonly_fields) + list(self.readonly_fields)) 

196 

197 

198@admin.register(SubmissionAuthor) 

199class SubmissionAuthorAdmin(BaseUserChangeTrackingAdmin): 

200 fieldsets = [ 

201 ( 

202 None, 

203 { 

204 "fields": [ 

205 "first_name", 

206 "last_name", 

207 "email", 

208 "corresponding", 

209 "date_created", 

210 "created_by", 

211 ] 

212 }, 

213 ) 

214 ] 

215 list_display = [ 

216 "first_name", 

217 "last_name", 

218 "email", 

219 "corresponding", 

220 "date_created", 

221 "created_by", 

222 ] 

223 

224 

225@admin.register(EditorSectionRight) 

226class EditorSectionRightAdmin(BaseUserChangeTrackingAdmin): 

227 fieldsets = [(None, {"fields": ["user", "journal_section", "date_created", "created_by"]})] 

228 list_display = ["user", "journal_section", "date_created", "created_by"] 

229 

230 

231@admin.register(EditorSubmissionRight) 

232class EditorSubmissionRightAdmin(BaseUserChangeTrackingAdmin): 

233 fieldsets = [(None, {"fields": ["user", "submission", "date_created", "created_by"]})] 

234 list_display = ["user", "submission", "date_created", "created_by"] 

235 

236 

237@admin.register(Review) 

238class ReviewAdmin(BaseUserChangeTrackingAdmin): 

239 inlines = (get_file_wrapper_inline(ReviewAdditionalFile, extra_fields=["author_access"]),) 

240 fieldsets = [ 

241 ( 

242 None, 

243 { 

244 "fields": [ 

245 "version", 

246 "reviewer", 

247 "state", 

248 "date_response_due", 

249 "date_review_due", 

250 "request_email", 

251 "accepted", 

252 "date_accepted", 

253 "accept_comment", 

254 "recommendation", 

255 "comment", 

256 "date_created", 

257 "created_by", 

258 ] 

259 }, 

260 ) 

261 ] 

262 list_display = [ 

263 "reviewer", 

264 "date_response_due", 

265 "accepted", 

266 "date_review_due", 

267 "recommendation", 

268 "date_created", 

269 "created_by", 

270 ] 

271 

272 readonly_fields = ["version", "accepted", "date_accepted"] 

273 

274 def get_readonly_fields(self, request: HttpRequest, obj) -> set[str]: 

275 return set(list(BaseUserChangeTrackingAdmin.readonly_fields) + list(self.readonly_fields)) 

276 

277 

278@admin.register(EditorialDecision) 

279class EditorialDecisionAdmin(BaseUserChangeTrackingAdmin): 

280 inlines = (get_file_wrapper_inline(EditorialDecisionFile),) 

281 fieldsets = [ 

282 ( 

283 None, 

284 { 

285 "fields": [ 

286 "version", 

287 "value", 

288 "date_created", 

289 "created_by", 

290 "comment", 

291 "last_modified_by", 

292 "date_last_modified", 

293 ] 

294 }, 

295 ) 

296 ] 

297 

298 list_display = ["version", "value", "date_created", "created_by", "comment"] 

299 readonly_fields = ["version"] 

300 

301 def get_readonly_fields(self, request: HttpRequest, obj) -> set[str]: 

302 return set(list(BaseUserChangeTrackingAdmin.readonly_fields) + list(self.readonly_fields)) 

303 

304 

305@admin.register(SuggestedReviewer) 

306class SuggestedReviewerAdmin(admin.ModelAdmin): 

307 list_display = ["first_name", "last_name", "email"] 

308 

309 

310@admin.register(Suggestion) 

311class SuggestionAdmin(admin.ModelAdmin): 

312 list_display = ["submission", "suggested_reviewer", "suggested_user", "suggest_to_avoid"]