Commit cffa623877cdc6db005c531108e33b585a63e890
1 parent
67a50452
Exists in
dev
fixing who can submit proposal, Add user invitation when editing an SP_Period, r…
…emoved SPForm modification when editing SP_Period
Showing
4 changed files
with
87 additions
and
28 deletions
Show diff stats
src/core/pyros_django/misc/templates/base.html
@@ -588,7 +588,7 @@ footer{ | @@ -588,7 +588,7 @@ footer{ | ||
588 | <footer class="sticky-footer"> | 588 | <footer class="sticky-footer"> |
589 | <div> | 589 | <div> |
590 | <div class="text-right my-auto"> | 590 | <div class="text-right my-auto"> |
591 | - <span>VERSION 0.2.4.0_2.0_3.6_2021-10-07</span> | 591 | + <span>VERSION 0.2.5.0_2.0_3.6_2021-10-08</span> |
592 | </div> | 592 | </div> |
593 | </div> | 593 | </div> |
594 | </footer> | 594 | </footer> |
src/core/pyros_django/scientific_program/templates/scientific_program/scientific_program_detail_edit.html
@@ -3,20 +3,18 @@ | @@ -3,20 +3,18 @@ | ||
3 | {% block content %} | 3 | {% block content %} |
4 | <form id="editSPForm" action="" method="post"> | 4 | <form id="editSPForm" action="" method="post"> |
5 | {% csrf_token %} | 5 | {% csrf_token %} |
6 | - {% if sp_period.status == "Draft" %} | ||
7 | - {{ SPForm.as_p }} | ||
8 | - {% else %} | 6 | + |
9 | {% for field in SPForm %} | 7 | {% for field in SPForm %} |
10 | <div class="fieldWrapper"> | 8 | <div class="fieldWrapper"> |
11 | {{ field.label_tag }} {{ field.value }} | 9 | {{ field.label_tag }} {{ field.value }} |
10 | + {{ field.as_hidden }} | ||
12 | </div> | 11 | </div> |
13 | {% endfor %} | 12 | {% endfor %} |
14 | - {% endif %} | ||
15 | {% if sp_period.status == "Draft" %} | 13 | {% if sp_period.status == "Draft" %} |
16 | <p style="color:red;"><strong>This proposal will be automatically submitted for evaluation on {{ sp_period.period.submission_end_date }}</strong> </p> | 14 | <p style="color:red;"><strong>This proposal will be automatically submitted for evaluation on {{ sp_period.period.submission_end_date }}</strong> </p> |
17 | {% endif %} | 15 | {% endif %} |
18 | - {% if USER_LEVEL|ifinlist:"Unit-PI,Admin,TAC"%} | ||
19 | - {% if sp_period.referee1 != None %} | 16 | + {% if USER_LEVEL|ifinlist:"Unit-PI,Admin,Unit-board"%} |
17 | + {% if sp_period.referee1 != None and sp_period.referee1 == request.user %} | ||
20 | <p><strong>vote referee 1: </strong>{{ sp_period.vote_referee1 }} {{ sp_period.reason_referee1 }} by {{ sp_period.referee1.first_name }} {{ sp_period.referee1.last_name}} </p> | 18 | <p><strong>vote referee 1: </strong>{{ sp_period.vote_referee1 }} {{ sp_period.reason_referee1 }} by {{ sp_period.referee1.first_name }} {{ sp_period.referee1.last_name}} </p> |
21 | {% endif %} | 19 | {% endif %} |
22 | {% if sp_period.referee2 != None %} | 20 | {% if sp_period.referee2 != None %} |
src/core/pyros_django/scientific_program/templates/scientific_program/scientific_program_period_detail.html
@@ -56,7 +56,7 @@ | @@ -56,7 +56,7 @@ | ||
56 | {% if CAN_OBSERVER_EDIT or CAN_TAC_EVALUATE or CAN_UNIT_PI_VALIDATE %} | 56 | {% if CAN_OBSERVER_EDIT or CAN_TAC_EVALUATE or CAN_UNIT_PI_VALIDATE %} |
57 | <a href="{% url "edit_scientific_program_period" id_sp=scientific_program.id id_period=sp_period.period.pk %}" class="btn btn-info" role="button">Edit</a> | 57 | <a href="{% url "edit_scientific_program_period" id_sp=scientific_program.id id_period=sp_period.period.pk %}" class="btn btn-info" role="button">Edit</a> |
58 | {% endif %} | 58 | {% endif %} |
59 | - {% if sp_period.status == "Draft" %} | 59 | + {% if CAN_SUBMIT_PROPOSAL %} |
60 | <a href="{% url "submit_proposal" sp_period.id %}" class="btn btn-info" role="button">Submit proposal</a> | 60 | <a href="{% url "submit_proposal" sp_period.id %}" class="btn btn-info" role="button">Submit proposal</a> |
61 | {% endif %} | 61 | {% endif %} |
62 | {% if CAN_OBSERVER_DELETE %} | 62 | {% if CAN_OBSERVER_DELETE %} |
src/core/pyros_django/scientific_program/views.py
@@ -338,6 +338,10 @@ def list_evaluated_scientific_program(request): | @@ -338,6 +338,10 @@ def list_evaluated_scientific_program(request): | ||
338 | 338 | ||
339 | @login_required | 339 | @login_required |
340 | def accept_sp_invitation(request, id_SP, id_period): | 340 | def accept_sp_invitation(request, id_SP, id_period): |
341 | + """ | ||
342 | + An invitation to join an SP is valid until the end of Exploitation period | ||
343 | + | ||
344 | + """ | ||
341 | sp_period = SP_Period.objects.get(scientific_program=id_SP, period=id_period) | 345 | sp_period = SP_Period.objects.get(scientific_program=id_SP, period=id_period) |
342 | current_user = PyrosUser.objects.get(username=request.user) | 346 | current_user = PyrosUser.objects.get(username=request.user) |
343 | is_user_guest_of_sp = SP_Period_Guest.objects.filter( | 347 | is_user_guest_of_sp = SP_Period_Guest.objects.filter( |
@@ -365,6 +369,7 @@ def edit_scientific_program_period(request, id_sp, id_period): | @@ -365,6 +369,7 @@ def edit_scientific_program_period(request, id_sp, id_period): | ||
365 | today = timezone.now().date() | 369 | today = timezone.now().date() |
366 | sp_period = SP_Period.objects.get( | 370 | sp_period = SP_Period.objects.get( |
367 | scientific_program=scientific_program, period=Period.objects.get(id=id_period)) | 371 | scientific_program=scientific_program, period=Period.objects.get(id=id_period)) |
372 | + period=Period.objects.get(id=id_period) | ||
368 | SP_Period_form = SP_PeriodForm(request.POST or None, instance=sp_period) | 373 | SP_Period_form = SP_PeriodForm(request.POST or None, instance=sp_period) |
369 | sp_pi = scientific_program.sp_pi | 374 | sp_pi = scientific_program.sp_pi |
370 | if request.session.get("role") == "Observer" and request.user.id != sp_pi.id: | 375 | if request.session.get("role") == "Observer" and request.user.id != sp_pi.id: |
@@ -376,25 +381,78 @@ def edit_scientific_program_period(request, id_sp, id_period): | @@ -376,25 +381,78 @@ def edit_scientific_program_period(request, id_sp, id_period): | ||
376 | users_informations = PyrosUser.objects.filter( | 381 | users_informations = PyrosUser.objects.filter( |
377 | id__in=user_of_sp.values_list("user", flat=True)) | 382 | id__in=user_of_sp.values_list("user", flat=True)) |
378 | guests = ",".join(guests) | 383 | guests = ",".join(guests) |
384 | + error = False | ||
385 | + error_message = "" | ||
386 | + list_of_emails = None | ||
387 | + recipient_list = [] | ||
379 | if request.POST: | 388 | if request.POST: |
380 | - | ||
381 | - if SPForm.is_valid() and SP_Period_form.is_valid() and sp_period.status == SP_Period.STATUSES_DRAFT: | ||
382 | - SP = SPForm.save() | ||
383 | - SP_period = SP_Period_form.save() | ||
384 | - if request.POST.getlist("user"): | ||
385 | - for sp_period_user in users_informations: | ||
386 | - if sp_period_user.id not in map(int, request.POST.getlist("user")): | ||
387 | - sp_period_user.delete() | ||
388 | - | ||
389 | - for user in request.POST.getlist("user"): | ||
390 | - user_instance = PyrosUser.objects.get(id=int(user)) | ||
391 | - if user_instance not in users_informations: | ||
392 | - SP_Period_User.objects.create( | ||
393 | - SP_Period=sp_period, user=user_instance) | ||
394 | - else: | ||
395 | - SP_Period_User.objects.filter( | ||
396 | - SP_Period=sp_period).delete() | ||
397 | - return redirect('detail_scientific_program_period', id_sp=scientific_program.id, id_period=id_period) | 389 | + if SP_Period_form.is_valid(): |
390 | + # can send invitation until the end of exploitation | ||
391 | + if request.POST.get("users") and today < period.end_date: | ||
392 | + # Invite user to join the SP | ||
393 | + regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' | ||
394 | + list_of_emails = request.POST.get("users").strip() | ||
395 | + | ||
396 | + for email in list_of_emails.split(","): | ||
397 | + if re.fullmatch(regex, email): | ||
398 | + recipient_list.append(email) | ||
399 | + else: | ||
400 | + error = True | ||
401 | + error_message = f"Invalid mail for {email}" | ||
402 | + if not error: | ||
403 | + domain = settings.DEFAULT_DOMAIN | ||
404 | + url = f"{domain}{reverse('sp_register',args=(scientific_program.pk,sp_period.period.pk))}" | ||
405 | + mail_subject = '[PyROS CC] New registration to an observing proposal' | ||
406 | + mail_message = (f"Hi,\n\nYou were invited to join an observing proposal that as been submitted using PyROS.\n" | ||
407 | + f"The name of the proposal is {scientific_program.name} and his PI is {sp_pi.first_name} {sp_pi.last_name}.\n" | ||
408 | + f"To accept this invitation, click on the following link : {url}\n" | ||
409 | + "You might be asked to login first and will be redirected to the proposal page.\n" | ||
410 | + "If the redirection doesn't work, click again on the link after you've logged in.\n" | ||
411 | + "If you don't own an PyROS account, go on the website in order to create an account with the same mail adress that you are using to read this mail." | ||
412 | + "\n\nCordially,\n\nPyROS Control Center") | ||
413 | + if len(recipient_list) > 0: | ||
414 | + try: | ||
415 | + # Delete previous guests (resetting list of guests) | ||
416 | + SP_Period_Guest.objects.filter(SP_Period=sp_period).delete() | ||
417 | + finally: | ||
418 | + for recipient in recipient_list: | ||
419 | + guest = SP_Period_Guest.objects.create( | ||
420 | + SP_Period=sp_period, email=recipient) | ||
421 | + send_mail( | ||
422 | + mail_subject, | ||
423 | + mail_message, | ||
424 | + from_email=None, | ||
425 | + recipient_list=[recipient], | ||
426 | + fail_silently=False, | ||
427 | + ) | ||
428 | + else: | ||
429 | + return render(request, 'scientific_program/scientific_program_detail_edit.html', { | ||
430 | + 'id_sp': id_sp, | ||
431 | + "id_period": id_period, | ||
432 | + "SPForm": SPForm, | ||
433 | + "period": sp_period.period, | ||
434 | + "guests": guests, | ||
435 | + "users_of_sp_period": users_informations, | ||
436 | + "SP_PeriodForm": SP_Period_form, | ||
437 | + "sp_period": sp_period, | ||
438 | + "error_message":error_message | ||
439 | + }) | ||
440 | + SP_period = SP_Period_form.save() | ||
441 | + # save changes on user list | ||
442 | + if request.POST.getlist("user"): | ||
443 | + for sp_period_user in users_informations: | ||
444 | + if sp_period_user.id not in map(int, request.POST.getlist("user")): | ||
445 | + sp_period_user.delete() | ||
446 | + | ||
447 | + for user in request.POST.getlist("user"): | ||
448 | + user_instance = PyrosUser.objects.get(id=int(user)) | ||
449 | + if user_instance not in users_informations: | ||
450 | + SP_Period_User.objects.create( | ||
451 | + SP_Period=sp_period, user=user_instance) | ||
452 | + else: | ||
453 | + SP_Period_User.objects.filter( | ||
454 | + SP_Period=sp_period).delete() | ||
455 | + return redirect('detail_scientific_program_period', id_sp=scientific_program.id, id_period=id_period) | ||
398 | if SP_Period_form.is_valid() and request.session.get("role") == "TAC" and sp_period.status != SP_Period.STATUSES_DRAFT: | 456 | if SP_Period_form.is_valid() and request.session.get("role") == "TAC" and sp_period.status != SP_Period.STATUSES_DRAFT: |
399 | # vote TAC | 457 | # vote TAC |
400 | if sp_period.referee1 == None or sp_period.referee1 == request.user and request.POST.get("vote_referee1") and request.POST.get("reason_referee1"): | 458 | if sp_period.referee1 == None or sp_period.referee1 == request.user and request.POST.get("vote_referee1") and request.POST.get("reason_referee1"): |
@@ -438,7 +496,8 @@ def edit_scientific_program_period(request, id_sp, id_period): | @@ -438,7 +496,8 @@ def edit_scientific_program_period(request, id_sp, id_period): | ||
438 | "guests": guests, | 496 | "guests": guests, |
439 | "users_of_sp_period": users_informations, | 497 | "users_of_sp_period": users_informations, |
440 | "SP_PeriodForm": SP_Period_form, | 498 | "SP_PeriodForm": SP_Period_form, |
441 | - "sp_period": sp_period | 499 | + "sp_period": sp_period, |
500 | + "error_message":error_message | ||
442 | }) | 501 | }) |
443 | 502 | ||
444 | 503 | ||
@@ -493,6 +552,7 @@ def detail_scientific_program_period(request, id_sp, id_period): | @@ -493,6 +552,7 @@ def detail_scientific_program_period(request, id_sp, id_period): | ||
493 | CAN_UNIT_PI_VALIDATE = request.session.get("role") in ("Unit-PI","Unit-board") and sp_period.status == SP_Period.STATUSES_EVALUATED | 552 | CAN_UNIT_PI_VALIDATE = request.session.get("role") in ("Unit-PI","Unit-board") and sp_period.status == SP_Period.STATUSES_EVALUATED |
494 | CAN_OBSERVER_DELETE = request.session.get("role") in ("Admin","Observer") and sp_period.status == SP_Period.STATUSES_DRAFT | 553 | CAN_OBSERVER_DELETE = request.session.get("role") in ("Admin","Observer") and sp_period.status == SP_Period.STATUSES_DRAFT |
495 | CAN_VIEW_TAC_VOTES = request.session.get("role") in ("Admin","Unit-PI","Unit-board") | 554 | CAN_VIEW_TAC_VOTES = request.session.get("role") in ("Admin","Unit-PI","Unit-board") |
555 | + CAN_SUBMIT_PROPOSAL = request.user == sp_pi and request.session.get("role") == "Observer" and sp_period.status == SP_Period.STATUSES_DRAFT | ||
496 | return render(request, 'scientific_program/scientific_program_period_detail.html', { | 556 | return render(request, 'scientific_program/scientific_program_period_detail.html', { |
497 | 'scientific_program': scientific_program, | 557 | 'scientific_program': scientific_program, |
498 | "users": users_informations, | 558 | "users": users_informations, |
@@ -505,7 +565,8 @@ def detail_scientific_program_period(request, id_sp, id_period): | @@ -505,7 +565,8 @@ def detail_scientific_program_period(request, id_sp, id_period): | ||
505 | "CAN_UNIT_PI_VALIDATE": CAN_UNIT_PI_VALIDATE, | 565 | "CAN_UNIT_PI_VALIDATE": CAN_UNIT_PI_VALIDATE, |
506 | "CAN_OBSERVER_DELETE": CAN_OBSERVER_DELETE, | 566 | "CAN_OBSERVER_DELETE": CAN_OBSERVER_DELETE, |
507 | "is_proposal": True, | 567 | "is_proposal": True, |
508 | - "CAN_VIEW_TAC_VOTES": CAN_VIEW_TAC_VOTES | 568 | + "CAN_VIEW_TAC_VOTES": CAN_VIEW_TAC_VOTES, |
569 | + "CAN_SUBMIT_PROPOSAL": CAN_SUBMIT_PROPOSAL | ||
509 | }) | 570 | }) |
510 | 571 | ||
511 | 572 |