Skip to content

Commit

Permalink
Instructor training workflow
Browse files Browse the repository at this point in the history
Later on, I'll split this commit into 7 smaller commits:

1. Instructor Training: Schema changes

- introduce new models: TrainingProgress and TrainingRequirement

- add `TrainingRequest.state` and `TrainingRequest.person` fields

- add `TrainingRequirement` to django-admin site

- put everything in one migration

2. Instructor Training: Modify trainee dashboard

- display progress of becoming SWC/DC Instructor

- let the trainee send SWC or DC homework using SendHomeworkForm

3. Instructor Training: Modify training requests list view

- add bulk operations:

    - discard selected requests (BulkChangeTrainingRequestForm)

    - unmatch selected people from trainings
      (BulkChangeTrainingRequestForm again)

    - match selected people to chosen training
      (BulkMatchTrainingRequestForm)

- added filtering sidebar (TrainingRequestFilter)

- "mail selected people" feature (piece of JS in `bulk_email.js`)

4. Instructor Training: Modify Training request detailed view

- display new fields (state and matched person)

- add form to match request with selected person or with a new one
  (AcceptTrainingRequestForm); this form suggest matching Person

5. Instructor Training: Add training request edit view

- introduce TrainingRequestUpdateForm

6. Instructor Training: Add trainees list view

- add filtering sidebar (TraineeFilter, TTTEventLookup)

- add bulk operations:

    - add training progress (BulkAddTrainingProgressForm)

    - discard training progress (BulkDiscardProgressesForm)

7. Instructor Training: add CRUD views for TrainingProgress

- introduce TrainingProgressForm
  • Loading branch information
chrismedrela committed Jul 12, 2016
1 parent 3015ea2 commit 62d5551
Show file tree
Hide file tree
Showing 16 changed files with 1,448 additions and 80 deletions.
3 changes: 2 additions & 1 deletion workshops/admin.py
Expand Up @@ -9,7 +9,7 @@
Lesson,
KnowledgeDomain,
Badge,
)
TrainingRequirement)


class RoleAdmin(admin.ModelAdmin):
Expand All @@ -24,3 +24,4 @@ class RoleAdmin(admin.ModelAdmin):
admin.site.register(Lesson)
admin.site.register(KnowledgeDomain)
admin.site.register(Badge)
admin.site.register(TrainingRequirement)
139 changes: 138 additions & 1 deletion workshops/filters.py
@@ -1,3 +1,7 @@
from django.db.models import Q

from django.forms import widgets

import django.forms.widgets

import django_filters
Expand All @@ -15,7 +19,7 @@
InvoiceRequest,
EventSubmission,
DCSelfOrganizedEventRequest,
)
TrainingRequest)

EMPTY_SELECTION = (None, '---------')

Expand Down Expand Up @@ -207,6 +211,139 @@ def get_order_by(self, order_value):
return super().get_order_by(order_value)


def filter_all_persons(queryset, all_persons):
if all_persons:
return queryset
else:
return queryset.filter(
task__role__name='learner',
task__event__tags__name='TTT').distinct()


def filter_trainee_name(queryset, name):
return queryset.filter(Q(personal__icontains=name) |
Q(family__icontains=name) |
Q(email__icontains=name) |
Q(github__icontains=name))


def filter_unevaluated_homework(queryset, flag):
if flag is None:
return queryset
elif flag: # return only trainees with an unevaluated homework
return queryset.filter(trainingprogress__state='n') \
.distinct()
else: # return only trainees without unevaluated homework
return queryset.exclude(trainingprogress__state='n') \
.distinct()


def filter_training(queryset, training):
if training is None:
return queryset
else:
print(training)
return queryset.filter(task__role__name='learner',
task__event=training).distinct()


class TraineeFilter(FilterSetWithoutHelpText):
search = django_filters.CharFilter(
action=filter_trainee_name,
label='Name or GitHub or email')

all_persons = django_filters.BooleanFilter(
label='Include all people, not only trainees',
action=filter_all_persons,
widget=widgets.CheckboxInput)

is_swc_instructor = django_filters.BooleanFilter(
label='Is SWC Instructor?',
name='is_swc_instructor',
)

is_dc_instructor = django_filters.BooleanFilter(
label='Is DC Instructor?',
name='is_dc_instructor',
)

non_evaluated_homework = django_filters.BooleanFilter(
label='Unevaluated homework?',
action=filter_unevaluated_homework,
)

training = django_filters.ModelChoiceFilter(
queryset=Event.objects.ttt(),
action=filter_training,
)

class Meta:
model = Person
fields = [
'search',
'all_persons',
'is_swc_instructor',
'is_dc_instructor',
'training',
]
order_by = ["-last_login", "lastname", "-lastname", "firstname", "-firstname",
"email", "-email"]

def get_order_by(self, order_value):
if order_value == 'firstname':
return ['personal', 'middle', 'family']
elif order_value == '-firstname':
return ['-personal', '-middle', '-family']
elif order_value == 'lastname':
return ['family', 'middle', 'personal']
elif order_value == '-lastname':
return ['-family', '-middle', '-personal']
else:
return super().get_order_by(order_value)


def filter_matched(queryset, choice):
if choice == '':
return queryset
elif choice == 'u': # unmatched
return queryset.filter(person=None)
elif choice == 'p': # matched person, unmatched training
return queryset.filter(person__isnull=False)\
.exclude(person__task__role__name='learner',
person__task__event__tags__name='TTT')\
.distinct()
else:
assert choice == 't' # matched person and training
return queryset.filter(person__task__role__name='learner',
person__task__event__tags__name='TTT')\
.distinct()


class TrainingRequestFilter(FilterSetWithoutHelpText):
state = django_filters.ChoiceFilter(
choices=(('', 'All'),) + TrainingRequest.STATES,
)

matched = django_filters.ChoiceFilter(
label='Matched?',
choices=(
('', 'Unknown'),
('u', 'Unmatched'),
('p', 'Matched person, unmatched training'),
('t', 'Matched person and training'),
),
action=filter_matched,
)

class Meta:
model = TrainingRequest
fields = [
'state',
'matched',
]
order_by = ['created_at', '-created_at']


class TaskFilter(FilterSetWithoutHelpText):
class Meta:
model = Task
Expand Down

0 comments on commit 62d5551

Please sign in to comment.