diff --git a/partners/migrations/0004_auto_20180112_1919.py b/partners/migrations/0004_auto_20180112_1919.py new file mode 100644 index 0000000000000000000000000000000000000000..2bd79a5ac6b3cee62bb4eae8ad08f00bd7630b30 --- /dev/null +++ b/partners/migrations/0004_auto_20180112_1919.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-12 18:19 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('partners', '0003_institution_css_class'), + ] + + operations = [ + migrations.AlterField( + model_name='institution', + name='css_class', + field=models.CharField(blank=True, max_length=256, verbose_name='Additional logo CSS class'), + ), + ] diff --git a/production/managers.py b/production/managers.py index a88a6ed1cebaa7920f658f12685436416e558460..fb0788d60275ad02710acd2a94f315f89cfc8375 100644 --- a/production/managers.py +++ b/production/managers.py @@ -3,6 +3,11 @@ from django.db import models from . import constants +class ProductionUserQuerySet(models.QuerySet): + def active(self): + return self.filter(user__isnull=False) + + class ProductionStreamQuerySet(models.QuerySet): def completed(self): return self.filter(status=constants.PRODUCTION_STREAM_COMPLETED) diff --git a/production/migrations/0003_productionuser_name.py b/production/migrations/0003_productionuser_name.py new file mode 100644 index 0000000000000000000000000000000000000000..2084c70d5b0b9e3acfa7466fa460ee64495975c3 --- /dev/null +++ b/production/migrations/0003_productionuser_name.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-12 18:38 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('production', '0002_auto_20171229_1435'), + ] + + operations = [ + migrations.AddField( + model_name='productionuser', + name='name', + field=models.CharField(blank=True, max_length=128), + ), + ] diff --git a/production/migrations/0004_auto_20180112_1957.py b/production/migrations/0004_auto_20180112_1957.py new file mode 100644 index 0000000000000000000000000000000000000000..cc0d0d230519822b9df903fe36ae510877441d76 --- /dev/null +++ b/production/migrations/0004_auto_20180112_1957.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-12 18:57 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('production', '0003_productionuser_name'), + ] + + operations = [ + migrations.AlterField( + model_name='productionuser', + name='user', + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='production_user', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/production/models.py b/production/models.py index 12c461b7d0523b84404f1f3fef6b112779ec9eb8..54becc09e16102a0bb5115c3d14f5bfc672303e0 100644 --- a/production/models.py +++ b/production/models.py @@ -8,7 +8,8 @@ from django.utils.functional import cached_property from .constants import PRODUCTION_STREAM_STATUS, PRODUCTION_STREAM_INITIATED, PRODUCTION_EVENTS,\ EVENT_MESSAGE, EVENT_HOUR_REGISTRATION, PRODUCTION_STREAM_COMPLETED,\ PROOFS_STATUSES, PROOFS_UPLOADED -from .managers import ProductionStreamQuerySet, ProductionEventManager, ProofsQuerySet +from .managers import ProductionStreamQuerySet, ProductionEventManager, ProofsQuerySet,\ + ProductionUserQuerySet from .utils import proofs_id_to_slug from finances.models import WorkLog @@ -21,12 +22,15 @@ class ProductionUser(models.Model): to relate all production related actions to. """ user = models.OneToOneField(User, on_delete=models.PROTECT, unique=True, - related_name='production_user') + related_name='production_user', null=True) + name = models.CharField(max_length=128, blank=True) - # objects = ProductionUserQuerySet.as_manager() -- Not implemented yet + objects = ProductionUserQuerySet.as_manager() def __str__(self): - return '%s, %s' % (self.user.last_name, self.user.first_name) + if self.user: + return '%s, %s' % (self.user.last_name, self.user.first_name) + return '%s (deactivated)' % self.name class ProductionStream(models.Model): diff --git a/production/templates/production/production.html b/production/templates/production/production.html index caf432ea2b5c240ce0133606dbcd6ebb5713dd8f..8198157beb4b015e49f7dfe0da807d4fda991e46 100644 --- a/production/templates/production/production.html +++ b/production/templates/production/production.html @@ -83,7 +83,7 @@ </div> <div class="col-6"> - <div class="card center-loader" id="details"> + <div class="card center-loader bg-white" id="details"> {% if stream %} {% include 'production/partials/production_stream_card.html' %} {% else %} @@ -144,7 +144,12 @@ <h3>Current Production Team</h3> <ul> {% for officer in production_officers %} - <li>{{ officer }}</li> + <li>{{ officer }} + <form action="{% url 'production:delete_officer' officer.id %}" class="d-inline px-1" method="post"> + {% csrf_token %} + <input type="submit" class="btn btn-danger mb-1" value="Remove Officer"> + </form> + </li> {% endfor %} </ul> diff --git a/production/urls.py b/production/urls.py index e0ecebf5d00fe77d42d40e79c8533a40fdeea3d1..f1419f395e8ee04d6b8c5d307f67b715139ae25f 100644 --- a/production/urls.py +++ b/production/urls.py @@ -7,6 +7,8 @@ urlpatterns = [ url(r'^(?P<stream_id>[0-9]+)$', production_views.production, name='production'), url(r'^completed$', production_views.completed, name='completed'), url(r'^officers/new$', production_views.user_to_officer, name='user_to_officer'), + url(r'^officers/(?P<officer_id>[0-9]+)/delete$', production_views.delete_officer, + name='delete_officer'), url(r'^streams/(?P<stream_id>[0-9]+)$', production_views.stream, name='stream'), url(r'^streams/(?P<stream_id>[0-9]+)/status$', diff --git a/production/views.py b/production/views.py index f368999aa87719819176a8ef2b3a22073c402cc1..52dc38d1669f07c93c894e0c11f3de82527d05bb 100644 --- a/production/views.py +++ b/production/views.py @@ -68,10 +68,10 @@ def production(request, stream_id=None): pass if request.user.has_perm('scipost.can_view_timesheets'): - context['production_team'] = ProductionUser.objects.all() + context['production_team'] = ProductionUser.objects.active() if request.user.has_perm('scipost.can_promote_to_production_team'): - context['production_officers'] = ProductionUser.objects.all() + context['production_officers'] = ProductionUser.objects.active() context['new_officer_form'] = UserToOfficerForm() return render(request, 'production/production.html', context) @@ -146,6 +146,20 @@ def user_to_officer(request): return redirect(reverse('production:production')) +@is_production_user() +@permission_required('scipost.can_promote_user_to_production_officer') +def delete_officer(request, officer_id): + production_user = get_object_or_404(ProductionUser.objects.active(), id=officer_id) + production_user.name = '{first_name} {last_name}'.format( + first_name=production_user.user.first_name, + last_name=production_user.user.last_name) + production_user.user = None + production_user.save() + + messages.success(request, '{user} removed as Production Officer'.format(user=production_user)) + return redirect(reverse('production:production')) + + @is_production_user() @permission_required('scipost.can_take_decisions_related_to_proofs', raise_exception=True) def update_status(request, stream_id):