Coverage for src/mesh/views/views_submission_edit.py: 29%

306 statements  

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

1from functools import cached_property 

2from typing import Any 

3 

4from django.contrib import messages 

5from django.db.models import QuerySet 

6from django.http import HttpRequest, HttpResponse, HttpResponseRedirect 

7from django.shortcuts import get_object_or_404 

8from django.urls import reverse_lazy 

9from django.utils.translation import gettext_lazy as _ 

10from django.views.generic import FormView, TemplateView, View 

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

12 

13from mesh.model.file_helpers import post_delete_model_file 

14from mesh.model.roles.author import Author 

15from mesh.views.forms.base_forms import FormAction, HiddenModelChoiceForm 

16from mesh.views.forms.submission_forms import ( 

17 SubmissionAuthorForm, 

18 SubmissionConfirmForm, 

19 SubmissionCreateForm, 

20 SubmissionUpdateForm, 

21 SubmissionVersionForm, 

22) 

23from mesh.views.mixins import RoleMixin 

24 

25from ..models.review_models import ReviewState 

26from ..models.submission_models import ( 

27 Submission, 

28 SubmissionAuthor, 

29 SubmissionLog, 

30 SubmissionVersion, 

31) 

32from ..models.user_models import Suggestion 

33from ..views.views_base import SUBMIT_QUERY_PARAMETER, SubmittableModelFormMixin 

34from ..views.views_reviewer import add_suggestion 

35 

36# from .components.breadcrumb import get_base_breadcrumb 

37# from .components.breadcrumb import get_submission_breadcrumb 

38from .components.button import Button 

39from .components.stepper import get_submission_stepper 

40from .model_proxy import SubmissionProxy 

41 

42# def submission_stepper_form_buttons() -> list[Button]: 

43# return [ 

44# Button( 

45# id="form_save", 

46# title=_("Save as draft"), 

47# icon_class="fa-floppy-disk", 

48# attrs={"type": ["submit"], "class": ["save-button", "light"]}, 

49# ), 

50# Button( 

51# id="form_next", 

52# title=_("Next"), 

53# icon_class="fa-right-long", 

54# attrs={"type": ["submit"], "class": ["save-button"], "name": [FormAction.NEXT.value]}, 

55# ), 

56# ] 

57 

58 

59class SubmissionCreateView(RoleMixin, CreateView): 

60 """ 

61 View for submitting a new submission. 

62 """ 

63 

64 model = Submission 

65 form_class = SubmissionCreateForm 

66 template_name = "mesh/forms/form_full_page.html" 

67 restricted_roles = [Author] 

68 

69 def restrict_dispatch(self, request: HttpRequest, *args, **kwargs): 

70 return not self.role_handler.check_rights("can_create_submission") 

71 

72 def get_success_url(self) -> str: 

73 """ 

74 Redirects to the SubmissionAuthor view to add authors to the 

75 newly created submission. 

76 """ 

77 if FormAction.NEXT.value in self.request.POST: 

78 return reverse_lazy( 

79 "mesh:submission_authors", 

80 kwargs={"pk": self.object.pk}, # type:ignore 

81 ) 

82 return reverse_lazy( 

83 "mesh:submission_details", 

84 kwargs={"pk": self.object.pk}, # type:ignore 

85 ) 

86 

87 def form_valid(self, form: SubmissionCreateForm) -> HttpResponse: 

88 """ 

89 Injects the current user in the form instance. 

90 Adds a message to the submission log. 

91 """ 

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

93 

94 response = super().form_valid(form) 

95 

96 SubmissionLog.add_message( 

97 self.object, # type:ignore 

98 content=_("Creation of the submission"), 

99 content_en="Creation of the submission", 

100 user=self.request.user, 

101 significant=True, 

102 ) 

103 

104 messages.success(self.request, _("New submission successfully created.")) 

105 return response 

106 

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

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

109 context["page_title"] = _("New submission") 

110 

111 # Stepper 

112 step_id = "metadata" 

113 stepper = get_submission_stepper(None) 

114 stepper.set_active_step(step_id) 

115 context["stepper"] = stepper 

116 

117 # Form buttons 

118 # No Save/Next button in the form, they are put in the stepper 

119 context["form"].buttons = [] # = submission_stepper_form_buttons() 

120 

121 descriptions = [ 

122 "You are about to start the submit process.", 

123 'Please read our guidelines <a href="">here</a>', 

124 ] 

125 context["form_description"] = descriptions 

126 

127 # # Generate breadcrumb data 

128 # breadcrumb = get_base_breadcrumb() 

129 # breadcrumb.add_item(title=_("New submission"), url=reverse_lazy("mesh:submission_create")) 

130 # context["breadcrumb"] = breadcrumb 

131 return context 

132 

133 

134class SubmissionUpdateView(RoleMixin, UpdateView): 

135 """ 

136 View for updating a submission (only the metadata). 

137 """ 

138 

139 model: type[Submission] = Submission 

140 form_class = SubmissionUpdateForm 

141 template_name = "mesh/forms/form_full_page.html" 

142 submission: Submission 

143 restricted_roles = [Author] 

144 message_on_restrict = False 

145 

146 def restrict_dispatch(self, request: HttpRequest, *args, **kwargs): 

147 pk = kwargs["pk"] 

148 self.submission = get_object_or_404(self.model, pk=pk) 

149 

150 return not self.role_handler.check_rights("can_edit_submission", self.submission) 

151 

152 def get_fail_redirect_uri(self) -> str: 

153 """ 

154 Return to the submission details page if the user cannot update the submission. 

155 """ 

156 return self.get_success_url() 

157 

158 def get_object(self, *args, **kwargs) -> Submission: 

159 """ 

160 Override `get_object` built-in method to avoid an additional look-up when 

161 we already have the object loaded. 

162 """ 

163 return self.submission 

164 

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

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

167 context["page_title"] = _("Edit article metadata") 

168 

169 if self.submission.is_draft: 

170 step_id = "metadata" 

171 stepper = get_submission_stepper(self.submission) 

172 stepper.set_active_step(step_id) 

173 context["stepper"] = stepper 

174 

175 # No Save/Next button in the form, they are put in the stepper 

176 context["form"].buttons = [] # = submission_stepper_form_buttons() 

177 

178 # Generate breadcrumb data 

179 # breadcrumb = get_submission_breadcrumb(self.submission) 

180 # breadcrumb.add_item( 

181 # title=_("Edit metadata"), 

182 # url=reverse_lazy("mesh:submission_update", kwargs={"pk": self.submission.pk}), 

183 # ) 

184 # context["breadcrumb"] = breadcrumb 

185 

186 return context 

187 

188 def get_success_url(self) -> str: 

189 if FormAction.NEXT.value in self.request.POST: 

190 return reverse_lazy("mesh:submission_authors", kwargs={"pk": self.submission.pk}) 

191 return reverse_lazy("mesh:submission_details", kwargs={"pk": self.submission.pk}) 

192 

193 def form_valid(self, form: SubmissionUpdateForm) -> HttpResponse: 

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

195 if not form.changed_data: 

196 form.instance.do_not_update = True 

197 

198 response = super().form_valid(form) 

199 

200 if form.has_changed(): 

201 SubmissionLog.add_message( 

202 self.submission, 

203 content=_("Modification of the submission's metadata"), 

204 content_en="Modification of the submission's metadata", 

205 user=self.request.user, 

206 ) 

207 return response 

208 

209 

210class SubmissionVersionCreateView(RoleMixin, SubmittableModelFormMixin, CreateView): 

211 """ 

212 View for creating a new submission version. 

213 """ 

214 

215 model = SubmissionVersion 

216 form_class = SubmissionVersionForm 

217 template_name = "mesh/forms/form_full_page.html" 

218 submission: Submission 

219 restricted_roles = [Author] 

220 save_submission = False 

221 add_confirm_message = False 

222 

223 def restrict_dispatch(self, request: HttpRequest, *args, **kwargs): 

224 submission_pk = kwargs["submission_pk"] 

225 self.submission = get_object_or_404(Submission, pk=submission_pk) 

226 

227 return not self.role_handler.check_rights("can_create_version", self.submission) 

228 

229 def get_success_url(self) -> str: 

230 if FormAction.NEXT.value in self.request.POST: 

231 return self.submit_url() 

232 return reverse_lazy("mesh:submission_details", kwargs={"pk": self.submission.pk}) 

233 

234 def submit_url(self) -> str: 

235 return reverse_lazy("mesh:submission_confirm", kwargs={"pk": self.submission.pk}) 

236 

237 def form_pre_save(self, form: SubmissionVersionForm): 

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

239 form.instance.submission = self.submission 

240 

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

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

243 current_version = self.submission.current_version 

244 version = current_version.number + 1 if current_version else 1 

245 context["page_title"] = _("Submission files") 

246 if not self.submission.is_draft: 

247 context["page_title"] += f" - Version {version}" 

248 

249 submission_url = reverse_lazy("mesh:submission_details", kwargs={"pk": self.submission.pk}) 

250 description = "Please fill the form below to submit your files for the submission " 

251 description += f"<a href='{submission_url}'><i>{self.submission.name}</i></a>.<br>" 

252 context["form_description"] = [description] 

253 

254 if self.submission.is_draft: 

255 stepper = get_submission_stepper(self.submission) 

256 stepper.set_active_step("version") 

257 context["stepper"] = stepper 

258 context["form"].buttons = [] 

259 

260 # # Generate breadcrumb data 

261 # breadcrumb = get_submission_breadcrumb(self.submission) 

262 # breadcrumb.add_item( 

263 # title=_("New version"), 

264 # url=reverse_lazy( 

265 # "mesh:submission_version_create", kwargs={"submission_pk": self.submission.pk} 

266 # ), 

267 # ) 

268 # context["breadcrumb"] = breadcrumb 

269 return context 

270 

271 def form_valid(self, form): 

272 result = super().form_valid(form) 

273 return result 

274 

275 

276class SubmissionVersionUpdateView(RoleMixin, SubmittableModelFormMixin, UpdateView): 

277 """ 

278 View for updating a submission version. 

279 

280 Submitting a version = submitting the whole submission. 

281 This requires extra care about checking that all previous steps have been 

282 taken when this is the first version. 

283 """ 

284 

285 model: type[SubmissionVersion] = SubmissionVersion 

286 form_class = SubmissionVersionForm 

287 template_name = "mesh/forms/form_full_page.html" 

288 version: SubmissionVersion 

289 restricted_roles = [Author] 

290 message_on_restrict = False 

291 save_submission = False 

292 add_confirm_message = False 

293 

294 def restrict_dispatch(self, request: HttpRequest, *args, **kwargs): 

295 pk = kwargs["pk"] 

296 self.version = get_object_or_404(self.model, pk=pk) 

297 return not self.role_handler.check_rights("can_edit_version", self.version) 

298 

299 def get_fail_redirect_uri(self) -> str: 

300 """ 

301 Redirects to the submission details page if the user cannot update the version. 

302 """ 

303 return self.get_success_url() 

304 

305 def get_object(self, *args, **kwargs) -> SubmissionVersion: 

306 """ 

307 Returns the already fetched version. 

308 """ 

309 return self.version 

310 

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

312 kwargs = super().get_form_kwargs() 

313 if self.request.GET.get(SUBMIT_QUERY_PARAMETER, None) == "true": 

314 kwargs[SUBMIT_QUERY_PARAMETER] = True 

315 return kwargs 

316 

317 def get_success_url(self) -> str: 

318 if FormAction.NEXT.value in self.request.POST: 

319 return self.submit_url() 

320 return reverse_lazy("mesh:submission_details", kwargs={"pk": self.version.submission.pk}) 

321 

322 def submit_url(self) -> str: 

323 return reverse_lazy("mesh:submission_confirm", kwargs={"pk": self.version.submission.pk}) 

324 

325 def form_pre_save(self, form: SubmissionVersionForm) -> None: 

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

327 

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

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

330 context["page_title"] = _(f"Submission files - Version {self.version.number}") 

331 

332 submission_url = reverse_lazy( 

333 "mesh:submission_details", kwargs={"pk": self.version.submission.pk} 

334 ) 

335 description = "Please fill the form below to submit your files for the submission " 

336 description += f"<a href='{submission_url}'><i>{self.version.submission.name}</i></a>.<br>" 

337 context["form_description"] = [description] 

338 

339 if self.version.submission.is_draft: 

340 stepper = get_submission_stepper(self.version.submission) 

341 stepper.set_active_step("version") 

342 context["stepper"] = stepper 

343 context["form"].buttons = [] 

344 

345 # # Generate breadcrumb data 

346 # breadcrumb = get_submission_breadcrumb(self.version.submission) 

347 # breadcrumb.add_item( 

348 # title=_("Edit version") + f" #{self.version.number}", 

349 # url=reverse_lazy("mesh:submission_version_update", kwargs={"pk": self.version.pk}), 

350 # ) 

351 # context["breadcrumb"] = breadcrumb 

352 return context 

353 

354 def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: 

355 """ 

356 View for updating the submission or deleting one of the associated files. 

357 """ 

358 deletion_requested, _ = post_delete_model_file(self.version, request, self.role_handler) 

359 

360 if deletion_requested: 

361 # Update the submission object. 

362 self.version = get_object_or_404(self.model, pk=self.version.pk) 

363 return self.get(request, *args, **kwargs) 

364 

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

366 

367 

368class SubmissionResumeView(RoleMixin, View): 

369 """ 

370 View handling the first submit of a submission. It resumes the submission process 

371 at the correct edit view according to the missing data. 

372 

373 Handles the submission stepper. It redirects to the correct step according to 

374 the submission status. 

375 - STEP 1: Metadata 

376 - STEP 2: Authors 

377 - STEP 3: Files 

378 - STEP 4: Confirmation 

379 """ 

380 

381 submission: Submission 

382 restricted_roles = [Author] 

383 

384 def restrict_dispatch(self, request: HttpRequest, *args, **kwargs) -> bool: 

385 self.submission = get_object_or_404(Submission, pk=kwargs["pk"]) 

386 return not self.role_handler.check_rights("can_submit_submission", self.submission) 

387 

388 def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: 

389 stepper = get_submission_stepper(self.submission) 

390 

391 # Redirects to the last active step 

392 for i in range(len(stepper.steps)): 

393 step = stepper.steps[-(i + 1)] 

394 if step.href and step.can_navigate: 

395 return HttpResponseRedirect(step.href) 

396 

397 return HttpResponseRedirect(reverse_lazy("mesh:submission_create")) 

398 

399 

400class SubmissionAuthorView(RoleMixin, TemplateView): 

401 """ 

402 View to add/remove a submission author from a given submission. 

403 """ 

404 

405 submission: Submission 

406 template_name = "mesh/forms/submission_author.html" 

407 restricted_roles = [Author] 

408 init_form: SubmissionAuthorForm | None = None 

409 _FORM_ACTION_CORRESPONDING = "_action_toggle_corresponding" 

410 

411 def restrict_dispatch(self, request: HttpRequest, *args, **kwargs) -> bool: 

412 self.submission = get_object_or_404(Submission, pk=kwargs["pk"]) 

413 return not self.role_handler.check_rights("can_edit_submission", self.submission) 

414 

415 @cached_property 

416 def authors(self) -> QuerySet[SubmissionAuthor]: 

417 return SubmissionAuthor.objects.filter(submission=self.submission) 

418 

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

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

421 

422 context["submission"] = self.submission 

423 

424 authors = self.authors 

425 context["authors"] = [ 

426 { 

427 "author": author, 

428 "delete_form": HiddenModelChoiceForm( 

429 _queryset=authors, 

430 form_action=FormAction.DELETE.value, 

431 initial={"instance": author}, 

432 ), 

433 "corresponding_form": HiddenModelChoiceForm( 

434 _queryset=authors, 

435 form_action="_action_toggle_corresponding", 

436 initial={"instance": author}, 

437 ), 

438 "buttons": [ 

439 Button( 

440 id=f"author-corresponding-{author.pk}", 

441 title=_("Corresponding"), 

442 icon_class=("fa-toggle-on" if author.corresponding else "fa-toggle-off"), 

443 form=HiddenModelChoiceForm( 

444 _queryset=authors, initial={"instance": author} 

445 ), 

446 attrs={ 

447 "href": [ 

448 reverse_lazy( 

449 "mesh:submission_authors", 

450 kwargs={"pk": self.submission.pk}, 

451 ) 

452 ], 

453 "type": ["submit"], 

454 "class": ["primary" if author.corresponding else "inactive"], 

455 "name": [self._FORM_ACTION_CORRESPONDING], 

456 "data-tooltip": [ 

457 _("Click to toggle whether the author is a corresponding contact.") 

458 ], 

459 }, 

460 ), 

461 Button( 

462 id=f"author-delete-{author.pk}", 

463 title=_("Remove"), 

464 icon_class="fa-trash", 

465 form=HiddenModelChoiceForm( 

466 _queryset=authors, initial={"instance": author} 

467 ), 

468 attrs={ 

469 "href": [ 

470 reverse_lazy( 

471 "mesh:submission_authors", 

472 kwargs={"pk": self.submission.pk}, 

473 ) 

474 ], 

475 "type": ["submit"], 

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

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

478 }, 

479 ), 

480 ], 

481 } 

482 for author in authors 

483 ] 

484 

485 initial = {} 

486 if not authors: 

487 initial.update( 

488 { 

489 "first_name": self.request.user.first_name, # type:ignore 

490 "last_name": self.request.user.last_name, # type:ignore 

491 "email": self.request.user.email, # type:ignore 

492 "primary": True, 

493 } 

494 ) 

495 

496 form = self.init_form or SubmissionAuthorForm( 

497 submission=self.submission, initial=initial or None 

498 ) 

499 

500 form.buttons = [ 

501 Button( 

502 id="form_save", 

503 title=_("Add author"), 

504 icon_class="fa-plus", 

505 attrs={"type": ["submit"], "class": ["save-button"]}, 

506 ) 

507 ] 

508 

509 context["page_title"] = _("Authors") 

510 

511 if self.submission.is_draft: 

512 step_id = "authors" 

513 stepper = get_submission_stepper(self.submission) 

514 stepper.set_active_step(step_id) 

515 context["stepper"] = stepper 

516 # version_step = stepper.get_step("version") 

517 # if version_step and version_step.can_navigate and version_step.href: 

518 # button = Button( 

519 # id="next", 

520 # title=_("Next"), 

521 # icon_class="fa-right-long", 

522 # attrs={"href": [version_step.href], "class": ["as-button"]}, 

523 # ) 

524 # context["title_buttons"] = [button] 

525 # 

526 # form.buttons.append( 

527 # Button( 

528 # id="form_next", 

529 # title=_("Next"), 

530 # icon_class="fa-right-long", 

531 # attrs={ 

532 # "href": [version_step.href], 

533 # "type": ["submit"], 

534 # "class": ["as-button", "save-button"], 

535 # }, 

536 # ) 

537 # ) 

538 

539 context["form"] = form 

540 

541 # # Generate breadcrumb data 

542 # breadcrumb = get_submission_breadcrumb(self.submission) 

543 # breadcrumb.add_item( 

544 # title=_("Authors"), 

545 # url=reverse_lazy("mesh:submission_authors", kwargs={"pk": self.submission.pk}), 

546 # ) 

547 # context["breadcrumb"] = breadcrumb 

548 

549 return context 

550 

551 def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: 

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

553 return self.remove_author(request) 

554 elif self._FORM_ACTION_CORRESPONDING in request.POST: 

555 return self.toggle_primary_author(request) 

556 

557 return self.add_author(request, *args, **kwargs) 

558 

559 def add_author(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: 

560 """ 

561 Add an `SubmissionAuthor` to the submission. 

562 """ 

563 response = HttpResponseRedirect( 

564 reverse_lazy("mesh:submission_authors", kwargs={"pk": self.submission.pk}) 

565 ) 

566 form = SubmissionAuthorForm(request.POST, submission=self.submission) 

567 if not form.is_valid(): 

568 self.init_form = form 

569 return self.get(request, *args, **kwargs) 

570 

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

572 form.instance.submission = self.submission 

573 form.save() 

574 

575 SubmissionLog.add_message( 

576 self.submission, 

577 content=f"Author added: {form.instance.first_name} {form.instance.last_name} ({form.instance.email})", 

578 content_en=_("Author added") 

579 + f": {form.instance.first_name} {form.instance.last_name} ({form.instance.email})", 

580 user=request.user, 

581 significant=True, 

582 ) 

583 messages.success( 

584 request, 

585 _("Author added") 

586 + f": {form.instance.first_name} {form.instance.last_name} ({form.instance.email})", 

587 ) 

588 

589 return response 

590 

591 def remove_author(self, request: HttpRequest) -> HttpResponse: 

592 """ 

593 Remove a `SubmissionAuthor` from the submission. 

594 """ 

595 response = HttpResponseRedirect( 

596 reverse_lazy("mesh:submission_authors", kwargs={"pk": self.submission.pk}) 

597 ) 

598 form = HiddenModelChoiceForm(request.POST, _queryset=self.authors) 

599 if not form.is_valid(): 

600 messages.error(request, _("Something went wrong. Please try again.")) 

601 return response 

602 

603 if len(self.authors) < 2: 

604 messages.error( 

605 request, 

606 _("There must be at least 1 author attached to the submission."), 

607 ) 

608 return response 

609 

610 author: SubmissionAuthor = form.cleaned_data["instance"] 

611 author_string = str(author) 

612 author.delete() 

613 

614 SubmissionLog.add_message( 

615 self.submission, 

616 content=f"Author removed: {author_string}", 

617 content_en=_("Author added") + f": {author_string}", 

618 request=request.user, 

619 significant=True, 

620 ) 

621 messages.success(request, _("The author has been removed.")) 

622 return response 

623 

624 def toggle_primary_author(self, request: HttpRequest) -> HttpResponse: 

625 """ 

626 Toggle the `corresponding` boolean of a `SubmissionAuthor` from the submission. 

627 """ 

628 response = HttpResponseRedirect( 

629 reverse_lazy("mesh:submission_authors", kwargs={"pk": self.submission.pk}) 

630 ) 

631 form = HiddenModelChoiceForm(request.POST, _queryset=self.authors) 

632 if not form.is_valid(): 

633 messages.error(request, _("Something went wrong. Please try again.")) 

634 return response 

635 

636 author: SubmissionAuthor = form.cleaned_data["instance"] 

637 author.corresponding = not author.corresponding 

638 author.save() 

639 word = "marked" if author.corresponding else "unmarked" 

640 messages.success( 

641 request, 

642 _(f"Author {author} has been {word} as a corresponding contact."), 

643 ) 

644 

645 return response 

646 

647 

648class SubmissionConfirmView(RoleMixin, FormView): 

649 """ 

650 View to confirm the submission the current SubmissionVersion. 

651 

652 It's used both when submitting a Submission for the first time and when 

653 submitting a revised SubmissionVersion. 

654 """ 

655 

656 template_name = "mesh/submission/version_confirm.html" 

657 submission: Submission 

658 form_class = SubmissionConfirmForm 

659 

660 def restrict_dispatch(self, request: HttpRequest, *args, **kwargs) -> bool: 

661 self.submission = get_object_or_404(Submission, pk=kwargs["pk"]) 

662 

663 if not self.role_handler.check_rights("can_edit_submission", self.submission): 

664 return True 

665 

666 return not self.submission.is_submittable 

667 

668 def get_success_url(self): 

669 return reverse_lazy("mesh:submission_details", kwargs={"pk": self.submission.pk}) 

670 

671 def get_object(self, queryset=None) -> SubmissionVersion: 

672 return self.submission.current_version # type:ignore 

673 

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

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

676 

677 context["form"].buttons = [ 

678 Button( 

679 id="form_save", 

680 title=_("Submit"), 

681 icon_class="fa-check", 

682 attrs={ 

683 "type": ["submit"], 

684 "class": ["save-button", "button-highlight"], 

685 }, 

686 ) 

687 ] 

688 

689 if self.submission.is_draft: 

690 stepper = get_submission_stepper(self.submission) 

691 stepper.set_active_step("confirm") 

692 context["stepper"] = stepper 

693 

694 context["submission_proxy"] = SubmissionProxy(self.submission, self.role_handler) 

695 

696 files = [] 

697 files.append( 

698 { 

699 "file_wrapper": self.submission.current_version.main_file, # type:ignore 

700 "type": "Main", 

701 } 

702 ) 

703 

704 for file_wrapper in self.submission.current_version.additional_files.all(): # type:ignore 

705 files.append({"file_wrapper": file_wrapper, "type": "Additional"}) 

706 context["submission_files"] = files 

707 

708 # # Breadcrumb 

709 # breadcrumb = get_submission_breadcrumb(self.submission) 

710 # breadcrumb.add_item( 

711 # title=_("Authors"), 

712 # url=reverse_lazy("mesh:submission_confirm", kwargs={"pk": self.submission.pk}), 

713 # ) 

714 # context["breadcrumb"] = breadcrumb 

715 

716 return context 

717 

718 def form_valid(self, form: SubmissionConfirmForm) -> HttpResponse: 

719 """ 

720 Submit the submission's current version. 

721 """ 

722 self.submission.submit(self.request.user) 

723 

724 if self.submission.current_version.number == 1: # type:ignore 

725 messages.success( 

726 self.request, 

727 _("Your submission has been successfully saved and confirmed."), 

728 ) 

729 else: 

730 messages.success(self.request, _("Your revisions were successfully submitted.")) 

731 

732 previous_round_number = self.submission.current_version.number - 1 

733 previous_round = self.submission.versions.get(number=previous_round_number) 

734 previous_reviewers = [ 

735 review.reviewer 

736 for review in previous_round.reviews.filter(state=ReviewState.SUBMITTED.value) 

737 ] 

738 for previous_reviewer in previous_reviewers: 

739 qs = Suggestion.objects.filter( 

740 submission=self.submission, suggested_user=previous_reviewer 

741 ) 

742 if not qs.exists(): 

743 add_suggestion( 

744 submission=self.submission, 

745 suggested_user=previous_reviewer, 

746 suggested_reviewer=None, 

747 ) 

748 

749 return HttpResponseRedirect(self.get_success_url())