Skip to content
This repository has been archived by the owner on Aug 20, 2018. It is now read-only.

Commit

Permalink
Bug 1039628 - Add ability to edit Task Ownership
Browse files Browse the repository at this point in the history
  • Loading branch information
bobsilverberg committed Oct 16, 2014
1 parent df3eceb commit e550ef0
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 40 deletions.
4 changes: 2 additions & 2 deletions oneanddone/tasks/filters.py
Expand Up @@ -14,7 +14,7 @@

class ActivityFilterSet(django_filters.FilterSet):

task__creator = django_filters.ModelChoiceFilter(
task__owner = django_filters.ModelChoiceFilter(
label=_lazy(u'Task Owner'),
queryset=User.objects.filter(task__isnull=False).distinct())

Expand All @@ -33,7 +33,7 @@ class ActivityFilterSet(django_filters.FilterSet):

class Meta:
model = TaskAttempt
fields = ('task__creator', 'task__team', 'user', 'modified')
fields = ('task__owner', 'task__team', 'user', 'modified')


class TasksFilterSet(django_filters.FilterSet):
Expand Down
4 changes: 3 additions & 1 deletion oneanddone/tasks/forms.py
Expand Up @@ -13,6 +13,7 @@
from oneanddone.tasks.models import (BugzillaBug, Feedback, Task,
TaskImportBatch,
TaskInvalidationCriterion)
from oneanddone.users.models import User


class BaseTaskInvalidCriteriaFormSet(forms.formsets.BaseFormSet):
Expand Down Expand Up @@ -49,6 +50,7 @@ class TaskForm(forms.ModelForm):
help_text=_('Please use commas to separate your keywords.'),
required=False,
widget=forms.TextInput(attrs={'class': 'medium-field'})))
owner = forms.ModelChoiceField(queryset=User.objects.filter(is_staff=True))

def __init__(self, *args, **kwargs):
if kwargs['instance']:
Expand Down Expand Up @@ -88,7 +90,7 @@ class Meta:
fields = ('name', 'short_description', 'execution_time', 'difficulty',
'priority', 'repeatable', 'team', 'project', 'type', 'start_date',
'end_date', 'why_this_matters', 'prerequisites', 'instructions',
'is_draft', 'is_invalid')
'is_draft', 'is_invalid', 'owner')
widgets = {
'name': forms.TextInput(attrs={'size': 100, 'class': 'fill-width'}),
'short_description': forms.TextInput(attrs={'size': 100, 'class': 'fill-width'}),
Expand Down
185 changes: 185 additions & 0 deletions oneanddone/tasks/migrations/0019_auto__add_field_task_owner.py
@@ -0,0 +1,185 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding field 'Task.owner'
db.add_column('tasks_task', 'owner',
self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name='owner', to=orm['auth.User']),
keep_default=False)

# update existing tasks
if not db.dry_run:
for task in orm.Task.objects.all():
# set the initial owner to the creator
task.owner = task.creator
task.save()

def backwards(self, orm):
# Deleting field 'Task.owner'
db.delete_column('tasks_task', 'owner_id')

models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'tasks.bugzillabug': {
'Meta': {'object_name': 'BugzillaBug'},
'bugzilla_id': ('django.db.models.fields.IntegerField', [], {'unique': 'True', 'max_length': '20'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'summary': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'tasks.feedback': {
'Meta': {'object_name': 'Feedback'},
'attempt': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['tasks.TaskAttempt']", 'unique': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'text': ('django.db.models.fields.TextField', [], {})
},
'tasks.task': {
'Meta': {'ordering': "['priority', 'difficulty']", 'object_name': 'Task'},
'batch': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['tasks.TaskImportBatch']", 'null': 'True', 'blank': 'True'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'difficulty': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
'end_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'execution_time': ('django.db.models.fields.IntegerField', [], {'default': '30'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'instructions': ('django.db.models.fields.TextField', [], {}),
'is_draft': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_invalid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'object_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'owner'", 'to': "orm['auth.User']"}),
'prerequisites': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'priority': ('django.db.models.fields.IntegerField', [], {'default': '3'}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['tasks.TaskProject']", 'null': 'True', 'blank': 'True'}),
'repeatable': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'short_description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'start_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'team': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['tasks.TaskTeam']"}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['tasks.TaskType']", 'null': 'True', 'blank': 'True'}),
'why_this_matters': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'tasks.taskattempt': {
'Meta': {'ordering': "['-modified']", 'object_name': 'TaskAttempt'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'requires_notification': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taskattempt_set'", 'to': "orm['tasks.Task']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.SET_NULL'})
},
'tasks.taskimportbatch': {
'Meta': {'object_name': 'TaskImportBatch'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'query': ('django.db.models.fields.TextField', [], {}),
'source': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'tasks.taskinvalidationcriterion': {
'Meta': {'object_name': 'TaskInvalidationCriterion'},
'batches': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['tasks.TaskImportBatch']", 'symmetrical': 'False'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'field_name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'field_value': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'relation': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'tasks.taskkeyword': {
'Meta': {'object_name': 'TaskKeyword'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'keyword_set'", 'to': "orm['tasks.Task']"})
},
'tasks.taskmetrics': {
'Meta': {'ordering': "['-completed_users']", 'object_name': 'TaskMetrics'},
'abandoned_users': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'closed_users': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'completed_users': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'incomplete_users': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'task': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['tasks.Task']", 'unique': 'True'}),
'user_completes_then_completes_another_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'user_completes_then_takes_another_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'user_takes_then_quits_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
},
'tasks.taskproject': {
'Meta': {'object_name': 'TaskProject'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'tasks.taskteam': {
'Meta': {'object_name': 'TaskTeam'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'tasks.tasktype': {
'Meta': {'object_name': 'TaskType'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
}
}

complete_apps = ['tasks']
1 change: 1 addition & 0 deletions oneanddone/tasks/models.py
Expand Up @@ -291,6 +291,7 @@ class Task(CachedModel, CreatedModifiedModel, CreatedByModel):
content_type = models.ForeignKey(ContentType, null=True, blank=True)
object_id = models.PositiveIntegerField(null=True, blank=True)
imported_item = generic.GenericForeignKey('content_type', 'object_id')
owner = models.ForeignKey(User, related_name='owner')
project = models.ForeignKey(TaskProject, blank=True, null=True)
team = models.ForeignKey(TaskTeam)
type = models.ForeignKey(TaskType, blank=True, null=True)
Expand Down
3 changes: 2 additions & 1 deletion oneanddone/tasks/serializers.py
Expand Up @@ -29,10 +29,11 @@ class TaskSerializer(serializers.ModelSerializer):
project = serializers.SlugRelatedField(many=False, slug_field='name')
team = serializers.SlugRelatedField(many=False, slug_field='name')
type = serializers.SlugRelatedField(many=False, slug_field='name')
owner = serializers.SlugRelatedField(many=False, slug_field='email')

class Meta:
model = Task
fields = ('id', 'name', 'short_description', 'instructions',
fields = ('id', 'name', 'short_description', 'instructions', 'owner',
'prerequisites', 'execution_time', 'start_date', 'end_date',
'is_draft', 'is_invalid', 'project', 'team', 'type', 'repeatable',
'difficulty', 'why_this_matters', 'keyword_set', 'taskattempt_set')
2 changes: 1 addition & 1 deletion oneanddone/tasks/templates/tasks/activity_listing.html
Expand Up @@ -20,7 +20,7 @@
<tr class="activty-detail">
<td></td>
<td colspan="4" class="task-info">
<div>{{ _("Owner: {owner}")|fe(owner=attempt.task.creator) }}</div>
<div>{{ _("Owner: {owner}")|fe(owner=attempt.task.owner) }}</div>
<div>{{ _("Team: {team}")|fe(team=attempt.task.team.name) }}</div>
<div class="feedback{% if not attempt.has_feedback %} no-feedback{% endif %}">
{{ attempt.feedback_display }}
Expand Down
2 changes: 1 addition & 1 deletion oneanddone/tasks/templates/tasks/detail.html
Expand Up @@ -20,7 +20,7 @@ <h1>{{ task.name|buglinkify }}</h1>
<div>{{ task.short_description }}</div>
</div>
{% if user.is_staff %}
<div class="row"><div>{{ _('Owner') }}: {{ task.creator }}</div>
<div class="row"><div>{{ _('Owner') }}: {{ task.owner }}</div>
{% endif %}
<div class="row">
<div class="three-fields">
Expand Down
7 changes: 1 addition & 6 deletions oneanddone/tasks/templates/tasks/form.html
Expand Up @@ -40,12 +40,6 @@ <h4>{{ title }}</h4>

<form method="post" class="task-form">
{{ csrf() }}
{% if task_form.instance.pk %}
<div class="field">
<label for="id_owner">{{ _('Owner') }}</label>
<p id="id_owner">{{ task_form.instance.creator }}</p>
</div>
{% endif %}
{% if action == 'Import' %}
{{ stage_form__preview }}
{{ form_field(batch_form['description'], help_text=True) }}
Expand All @@ -64,6 +58,7 @@ <h5>{{ _('Base Task Description') }}</h5>
{% endif %}
{{ form_field(task_form['short_description']) }}
{{ form_field(task_form['keywords'], help_text=True) }}
{{ form_field(task_form['owner']) }}
<fieldset class="task-category first">
{{ form_field(task_form['team']) }}
{{ form_field(task_form['project']) }}
Expand Down
1 change: 1 addition & 0 deletions oneanddone/tasks/tests/__init__.py
Expand Up @@ -60,6 +60,7 @@ class TaskFactory(DjangoModelFactory):
is_draft = False
is_invalid = False
creator = SubFactory(UserFactory)
owner = creator
project = SubFactory(TaskProjectFactory)
team = SubFactory(TaskTeamFactory)
type = SubFactory(TaskTypeFactory)
Expand Down

0 comments on commit e550ef0

Please sign in to comment.