Refactoring timeline
parent
872e274825
commit
982d79d8aa
|
@ -96,10 +96,13 @@ def _common_users_values(diff):
|
|||
|
||||
return values
|
||||
|
||||
def project_values(diff):
|
||||
values = _common_users_values(diff)
|
||||
return values
|
||||
|
||||
|
||||
def milestone_values(diff):
|
||||
values = _common_users_values(diff)
|
||||
|
||||
return values
|
||||
|
||||
|
||||
|
|
|
@ -367,12 +367,14 @@ register_freeze_implementation("issues.issue", issue_freezer)
|
|||
register_freeze_implementation("tasks.task", task_freezer)
|
||||
register_freeze_implementation("wiki.wikipage", wikipage_freezer)
|
||||
|
||||
from .freeze_impl import project_values
|
||||
from .freeze_impl import milestone_values
|
||||
from .freeze_impl import userstory_values
|
||||
from .freeze_impl import issue_values
|
||||
from .freeze_impl import task_values
|
||||
from .freeze_impl import wikipage_values
|
||||
|
||||
register_values_implementation("projects.project", project_values)
|
||||
register_values_implementation("milestones.milestone", milestone_values)
|
||||
register_values_implementation("userstories.userstory", userstory_values)
|
||||
register_values_implementation("issues.issue", issue_values)
|
||||
|
|
|
@ -281,6 +281,11 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
|
|||
user_stories = user_stories.prefetch_related('role_points', 'role_points__points')
|
||||
return self._get_user_stories_points(user_stories)
|
||||
|
||||
|
||||
@property
|
||||
def project(self):
|
||||
return self
|
||||
|
||||
@property
|
||||
def future_team_increment(self):
|
||||
team_increment = self._get_points_increment(False, True)
|
||||
|
|
|
@ -19,6 +19,7 @@ from django.apps import apps
|
|||
from django.db.models import signals
|
||||
|
||||
from . import signals as handlers
|
||||
from taiga.projects.history.models import HistoryEntry
|
||||
|
||||
|
||||
class TimelineAppConfig(AppConfig):
|
||||
|
@ -26,12 +27,7 @@ class TimelineAppConfig(AppConfig):
|
|||
verbose_name = "Timeline"
|
||||
|
||||
def ready(self):
|
||||
signals.post_save.connect(handlers.create_project_push_to_timeline,
|
||||
sender=apps.get_model("projects", "Project"))
|
||||
signals.post_save.connect(handlers.create_user_story_push_to_timeline,
|
||||
sender=apps.get_model("userstories", "UserStory"))
|
||||
signals.post_save.connect(handlers.create_issue_push_to_timeline,
|
||||
sender=apps.get_model("issues", "Issue"))
|
||||
signals.post_save.connect(handlers.on_new_history_entry, sender=HistoryEntry, dispatch_uid="timeline")
|
||||
signals.pre_save.connect(handlers.create_membership_push_to_timeline,
|
||||
sender=apps.get_model("projects", "Membership"))
|
||||
signals.post_delete.connect(handlers.delete_membership_push_to_timeline,
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models import Model
|
||||
|
||||
from taiga.projects.models import Project
|
||||
from taiga.projects.history import services as history_services
|
||||
from taiga.projects.history.choices import HistoryType
|
||||
from taiga.projects.history.models import HistoryEntry
|
||||
from taiga.timeline.models import Timeline
|
||||
from taiga.timeline.service import (_add_to_object_timeline, _get_impl_key_from_model,
|
||||
_timeline_impl_map)
|
||||
from taiga.timeline.signals import on_new_history_entry, _push_to_timelines
|
||||
from taiga.users.models import User
|
||||
|
||||
from unittest.mock import patch
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
import django_pgjson.fields
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
timelime_objects = []
|
||||
created = None
|
||||
|
||||
def custom_add_to_object_timeline(obj:object, instance:object, event_type:str, namespace:str="default", extra_data:dict={}):
|
||||
global created
|
||||
global timelime_objects
|
||||
assert isinstance(obj, Model), "obj must be a instance of Model"
|
||||
assert isinstance(instance, Model), "instance must be a instance of Model"
|
||||
event_type_key = _get_impl_key_from_model(instance.__class__, event_type)
|
||||
impl = _timeline_impl_map.get(event_type_key, None)
|
||||
|
||||
timelime_objects.append(Timeline(
|
||||
content_object=obj,
|
||||
namespace=namespace,
|
||||
event_type=event_type_key,
|
||||
project=instance.project,
|
||||
data=impl(instance, extra_data=extra_data),
|
||||
data_content_type = ContentType.objects.get_for_model(instance.__class__),
|
||||
created = created,
|
||||
))
|
||||
|
||||
|
||||
def generate_timeline(apps, schema_editor):
|
||||
global created
|
||||
global timelime_objects
|
||||
with patch('taiga.timeline.service._add_to_object_timeline', new=custom_add_to_object_timeline):
|
||||
# Projects api wasn't a HistoryResourceMixin so we can't interate on the HistoryEntries in this case
|
||||
for project in Project.objects.order_by("created_date").iterator():
|
||||
created = project.created_date
|
||||
print("Project:", created)
|
||||
extra_data = {
|
||||
"values_diff": {},
|
||||
"user": {
|
||||
"pk": project.owner.id,
|
||||
"user_name": project.owner.get_full_name(),
|
||||
},
|
||||
}
|
||||
_push_to_timelines(project, project.owner, project, "create", extra_data=extra_data)
|
||||
|
||||
Timeline.objects.bulk_create(timelime_objects, batch_size=10000)
|
||||
timelime_objects = []
|
||||
|
||||
for historyEntry in HistoryEntry.objects.order_by("created_at").iterator():
|
||||
print("History entry:", historyEntry.created_at)
|
||||
try:
|
||||
created = historyEntry.created_at
|
||||
on_new_history_entry(None, historyEntry, None)
|
||||
except ObjectDoesNotExist as e:
|
||||
print("Ignoring")
|
||||
|
||||
Timeline.objects.bulk_create(timelime_objects, batch_size=10000)
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('projects', '0019_auto_20150311_0821'),
|
||||
('contenttypes', '0001_initial'),
|
||||
('timeline', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='Timeline',
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Timeline',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
|
||||
('object_id', models.PositiveIntegerField()),
|
||||
('namespace', models.SlugField(default='default')),
|
||||
('event_type', models.SlugField()),
|
||||
('project', models.ForeignKey(to='projects.Project')),
|
||||
('data', django_pgjson.fields.JsonField()),
|
||||
('data_content_type', models.ForeignKey(to='contenttypes.ContentType', related_name='data_timelines')),
|
||||
('created', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('content_type', models.ForeignKey(to='contenttypes.ContentType', related_name='content_type_timelines')),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='timeline',
|
||||
index_together=set([('content_type', 'object_id', 'namespace')]),
|
||||
),
|
||||
migrations.RunPython(generate_timeline),
|
||||
]
|
|
@ -23,14 +23,17 @@ from django.core.exceptions import ValidationError
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.contenttypes.generic import GenericForeignKey
|
||||
|
||||
from taiga.projects.models import Project
|
||||
|
||||
class Timeline(models.Model):
|
||||
content_type = models.ForeignKey(ContentType)
|
||||
content_type = models.ForeignKey(ContentType, related_name="content_type_timelines")
|
||||
object_id = models.PositiveIntegerField()
|
||||
content_object = GenericForeignKey('content_type', 'object_id')
|
||||
namespace = models.SlugField(default="default")
|
||||
event_type = models.SlugField()
|
||||
project = models.ForeignKey(Project)
|
||||
data = JsonField()
|
||||
data_content_type = models.ForeignKey(ContentType, related_name="data_timelines")
|
||||
created = models.DateTimeField(default=timezone.now)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
|
|
@ -14,12 +14,16 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.db.models import Model
|
||||
from django.db.models.query import QuerySet
|
||||
from functools import partial, wraps
|
||||
from django.apps import apps
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import Model
|
||||
from django.db.models import Q
|
||||
from django.db.models.query import QuerySet
|
||||
|
||||
from functools import partial, wraps
|
||||
|
||||
from taiga.base.utils.db import get_typename_for_model_class
|
||||
from taiga.celery import app
|
||||
|
||||
_timeline_impl_map = {}
|
||||
|
||||
|
@ -37,22 +41,28 @@ def _get_impl_key_from_typename(typename:str, event_type:str):
|
|||
raise Exception("Not valid typename parameter")
|
||||
|
||||
|
||||
def _get_class_implementation(model:Model, event_type:str):
|
||||
key = _get_impl_key_from_model(model, event_type)
|
||||
return _timeline_impl_map.get(key, None)
|
||||
def build_user_namespace(user:object):
|
||||
return "{0}:{1}".format("user", user.id)
|
||||
|
||||
|
||||
def build_project_namespace(project:object):
|
||||
return "{0}:{1}".format("project", project.id)
|
||||
|
||||
|
||||
def _add_to_object_timeline(obj:object, instance:object, event_type:str, namespace:str="default", extra_data:dict={}):
|
||||
assert isinstance(obj, Model), "obj must be a instance of Model"
|
||||
assert isinstance(instance, Model), "instance must be a instance of Model"
|
||||
from .models import Timeline
|
||||
event_type_key = _get_impl_key_from_model(instance.__class__, event_type)
|
||||
impl = _timeline_impl_map.get(event_type_key, None)
|
||||
|
||||
impl = _get_class_implementation(instance.__class__, event_type)
|
||||
Timeline.objects.create(
|
||||
content_object=obj,
|
||||
namespace=namespace,
|
||||
event_type=event_type,
|
||||
data=impl(instance, extra_data=extra_data)
|
||||
event_type=event_type_key,
|
||||
project=instance.project,
|
||||
data=impl(instance, extra_data=extra_data),
|
||||
data_content_type = ContentType.objects.get_for_model(instance.__class__),
|
||||
)
|
||||
|
||||
|
||||
|
@ -61,6 +71,7 @@ def _add_to_objects_timeline(objects, instance:object, event_type:str, namespace
|
|||
_add_to_object_timeline(obj, instance, event_type, namespace, extra_data)
|
||||
|
||||
|
||||
@app.task
|
||||
def push_to_timeline(objects, instance:object, event_type:str, namespace:str="default", extra_data:dict={}):
|
||||
if isinstance(objects, Model):
|
||||
_add_to_object_timeline(objects, instance, event_type, namespace, extra_data)
|
||||
|
@ -70,12 +81,73 @@ def push_to_timeline(objects, instance:object, event_type:str, namespace:str="de
|
|||
raise Exception("Invalid objects parameter")
|
||||
|
||||
|
||||
def get_timeline(obj, namespace="default"):
|
||||
def get_timeline(obj, namespace=None):
|
||||
assert isinstance(obj, Model), "obj must be a instance of Model"
|
||||
from .models import Timeline
|
||||
|
||||
ct = ContentType.objects.get_for_model(obj.__class__)
|
||||
return Timeline.objects.filter(content_type=ct, object_id=obj.pk, namespace=namespace)
|
||||
timeline = Timeline.objects.filter(content_type=ct, object_id=obj.pk)
|
||||
if namespace is not None:
|
||||
timeline = timeline.filter(namespace=namespace)
|
||||
|
||||
timeline = timeline.order_by("-created")
|
||||
return timeline
|
||||
|
||||
|
||||
def filter_timeline_for_user(timeline, user):
|
||||
# Filtering public projects
|
||||
tl_filter = Q(project__is_private=False)
|
||||
|
||||
# Filtering private project with some public parts
|
||||
content_types = {
|
||||
"view_project": ContentType.objects.get(app_label="projects", model="project"),
|
||||
"view_milestones": ContentType.objects.get(app_label="milestones", model="milestone"),
|
||||
"view_us": ContentType.objects.get(app_label="userstories", model="userstory"),
|
||||
"view_tasks": ContentType.objects.get(app_label="tasks", model="task"),
|
||||
"view_issues": ContentType.objects.get(app_label="issues", model="issue"),
|
||||
"view_wiki_pages": ContentType.objects.get(app_label="wiki", model="wikipage"),
|
||||
"view_wiki_links": ContentType.objects.get(app_label="wiki", model="wikilink"),
|
||||
}
|
||||
|
||||
for content_type_key, content_type in content_types.items():
|
||||
tl_filter |= Q(project__is_private=True,
|
||||
project__anon_permissions__contains=[content_type_key],
|
||||
data_content_type=content_type)
|
||||
|
||||
# Filtering private projects where user is member
|
||||
if not user.is_anonymous():
|
||||
membership_model = apps.get_model('projects', 'Membership')
|
||||
memberships_qs = membership_model.objects.filter(user=user)
|
||||
for membership in memberships_qs:
|
||||
for content_type_key, content_type in content_types.items():
|
||||
if content_type_key in membership.role.permissions or membership.is_owner:
|
||||
tl_filter |= Q(project=membership.project, data_content_type=content_type)
|
||||
|
||||
timeline = timeline.filter(tl_filter)
|
||||
return timeline
|
||||
|
||||
|
||||
def get_profile_timeline(user, accessing_user=None):
|
||||
timeline = get_timeline(user)
|
||||
if accessing_user is not None:
|
||||
timeline = filter_timeline_for_user(timeline, accessing_user)
|
||||
return timeline
|
||||
|
||||
|
||||
def get_user_timeline(user, accessing_user=None):
|
||||
namespace = build_user_namespace(user)
|
||||
timeline = get_timeline(user, namespace)
|
||||
if accessing_user is not None:
|
||||
timeline = filter_timeline_for_user(timeline, accessing_user)
|
||||
return timeline
|
||||
|
||||
|
||||
def get_project_timeline(project, accessing_user=None):
|
||||
namespace = build_project_namespace(project)
|
||||
timeline = get_timeline(project, namespace)
|
||||
if accessing_user is not None:
|
||||
timeline = filter_timeline_for_user(timeline, accessing_user)
|
||||
return timeline
|
||||
|
||||
|
||||
def register_timeline_implementation(typename:str, event_type:str, fn=None):
|
||||
|
|
|
@ -14,43 +14,90 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from taiga.timeline.service import push_to_timeline
|
||||
from django.conf import settings
|
||||
|
||||
from taiga.projects.history import services as history_services
|
||||
from taiga.projects.models import Project
|
||||
from taiga.users.models import User
|
||||
from taiga.projects.history.choices import HistoryType
|
||||
from taiga.timeline.service import push_to_timeline, build_user_namespace, build_project_namespace
|
||||
|
||||
# TODO: Add events to followers timeline when followers are implemented.
|
||||
# TODO: Add events to project watchers timeline when project watchers are implemented.
|
||||
|
||||
|
||||
def create_project_push_to_timeline(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
push_to_timeline(instance, instance, "create")
|
||||
def _push_to_timeline(*args, **kwargs):
|
||||
if settings.CELERY_ENABLED:
|
||||
push_to_timeline.delay(*args, **kwargs)
|
||||
else:
|
||||
push_to_timeline(*args, **kwargs)
|
||||
|
||||
|
||||
def create_user_story_push_to_timeline(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
push_to_timeline(instance.project, instance, "create")
|
||||
def _push_to_timelines(project, user, obj, event_type, extra_data={}):
|
||||
# Project timeline
|
||||
_push_to_timeline(project, obj, event_type,
|
||||
namespace=build_project_namespace(project),
|
||||
extra_data=extra_data)
|
||||
|
||||
# User timeline
|
||||
_push_to_timeline(user, obj, event_type,
|
||||
namespace=build_user_namespace(user),
|
||||
extra_data=extra_data)
|
||||
|
||||
# Related people: watchers and assigned to
|
||||
if hasattr(obj, "assigned_to") and obj.assigned_to and user != obj.assigned_to:
|
||||
_push_to_timeline(obj.assigned_to, obj, event_type,
|
||||
namespace=build_user_namespace(user),
|
||||
extra_data=extra_data)
|
||||
|
||||
watchers = hasattr(obj, "watchers") and obj.watchers.exclude(id=user.id) or []
|
||||
if watchers:
|
||||
_push_to_timeline(watchers, obj, event_type,
|
||||
namespace=build_user_namespace(user),
|
||||
extra_data=extra_data)
|
||||
|
||||
|
||||
def create_issue_push_to_timeline(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
push_to_timeline(instance.project, instance, "create")
|
||||
def on_new_history_entry(sender, instance, created, **kwargs):
|
||||
if instance.is_hidden:
|
||||
return None
|
||||
|
||||
model = history_services.get_model_from_key(instance.key)
|
||||
pk = history_services.get_pk_from_key(instance.key)
|
||||
obj = model.objects.get(pk=pk)
|
||||
project = obj.project
|
||||
|
||||
if instance.type == HistoryType.create:
|
||||
event_type = "create"
|
||||
elif instance.type == HistoryType.change:
|
||||
event_type = "change"
|
||||
elif instance.type == HistoryType.delete:
|
||||
event_type = "delete"
|
||||
|
||||
extra_data = {
|
||||
"values_diff": instance.values_diff,
|
||||
"user": instance.user,
|
||||
"comment": instance.comment,
|
||||
}
|
||||
|
||||
user = User.objects.get(id=instance.user["pk"])
|
||||
_push_to_timelines(project, user, obj, event_type, extra_data=extra_data)
|
||||
|
||||
|
||||
def create_membership_push_to_timeline(sender, instance, **kwargs):
|
||||
# Creating new membership with associated user
|
||||
if not instance.pk and instance.user:
|
||||
push_to_timeline(instance.project, instance, "create")
|
||||
_push_to_timelines(instance.project, instance.user, instance, "create")
|
||||
|
||||
#Updating existing membership
|
||||
elif instance.pk:
|
||||
prev_instance = sender.objects.get(pk=instance.pk)
|
||||
if prev_instance.user != prev_instance.user:
|
||||
push_to_timeline(instance.project, instance, "create")
|
||||
elif prev_instance.role != prev_instance.role:
|
||||
extra_data = {
|
||||
"prev_role": {
|
||||
"id": prev_instance.role.pk,
|
||||
"name": prev_instance.role.name,
|
||||
}
|
||||
}
|
||||
push_to_timeline(instance.project, instance, "role-changed", extra_data=extra_data)
|
||||
if instance.user != prev_instance.user:
|
||||
# The new member
|
||||
_push_to_timelines(instance.project, instance.user, instance, "create")
|
||||
# If we are updating the old user is removed from project
|
||||
if prev_instance.user:
|
||||
_push_to_timelines(instance.project, prev_instance.user, prev_instance, "delete")
|
||||
|
||||
|
||||
def delete_membership_push_to_timeline(sender, instance, **kwargs):
|
||||
push_to_timeline(instance.project, instance, "delete")
|
||||
if instance.user:
|
||||
_push_to_timelines(instance.project, instance.user, instance, "delete")
|
||||
|
|
|
@ -18,23 +18,45 @@ from taiga.timeline.service import register_timeline_implementation
|
|||
|
||||
|
||||
@register_timeline_implementation("projects.project", "create")
|
||||
def project_create_timeline(instance, extra_data={}):
|
||||
return {
|
||||
@register_timeline_implementation("projects.project", "change")
|
||||
@register_timeline_implementation("projects.project", "delete")
|
||||
def project_timeline(instance, extra_data={}):
|
||||
result ={
|
||||
"project": {
|
||||
"id": instance.pk,
|
||||
"slug": instance.slug,
|
||||
"name": instance.name,
|
||||
},
|
||||
"creator": {
|
||||
"id": instance.owner.pk,
|
||||
"name": instance.owner.get_full_name(),
|
||||
}
|
||||
result.update(extra_data)
|
||||
return result
|
||||
|
||||
|
||||
@register_timeline_implementation("milestones.milestone", "create")
|
||||
@register_timeline_implementation("milestones.milestone", "change")
|
||||
@register_timeline_implementation("milestones.milestone", "delete")
|
||||
def project_timeline(instance, extra_data={}):
|
||||
result ={
|
||||
"milestone": {
|
||||
"id": instance.pk,
|
||||
"slug": instance.slug,
|
||||
"name": instance.name,
|
||||
},
|
||||
"project": {
|
||||
"id": instance.project.pk,
|
||||
"slug": instance.project.slug,
|
||||
"name": instance.project.name,
|
||||
}
|
||||
}
|
||||
result.update(extra_data)
|
||||
return result
|
||||
|
||||
|
||||
@register_timeline_implementation("userstories.userstory", "create")
|
||||
def userstory_create_timeline(instance, extra_data={}):
|
||||
return {
|
||||
@register_timeline_implementation("userstories.userstory", "change")
|
||||
@register_timeline_implementation("userstories.userstory", "delete")
|
||||
def userstory_timeline(instance, extra_data={}):
|
||||
result ={
|
||||
"userstory": {
|
||||
"id": instance.pk,
|
||||
"subject": instance.subject,
|
||||
|
@ -43,17 +65,17 @@ def userstory_create_timeline(instance, extra_data={}):
|
|||
"id": instance.project.pk,
|
||||
"slug": instance.project.slug,
|
||||
"name": instance.project.name,
|
||||
},
|
||||
"creator": {
|
||||
"id": instance.owner.pk,
|
||||
"name": instance.owner.get_full_name(),
|
||||
}
|
||||
}
|
||||
result.update(extra_data)
|
||||
return result
|
||||
|
||||
|
||||
@register_timeline_implementation("issues.issue", "create")
|
||||
def issue_create_timeline(instance, extra_data={}):
|
||||
return {
|
||||
@register_timeline_implementation("issues.issue", "change")
|
||||
@register_timeline_implementation("issues.issue", "delete")
|
||||
def issue_timeline(instance, extra_data={}):
|
||||
result ={
|
||||
"issue": {
|
||||
"id": instance.pk,
|
||||
"subject": instance.subject,
|
||||
|
@ -62,62 +84,53 @@ def issue_create_timeline(instance, extra_data={}):
|
|||
"id": instance.project.pk,
|
||||
"slug": instance.project.slug,
|
||||
"name": instance.project.name,
|
||||
}
|
||||
}
|
||||
result.update(extra_data)
|
||||
return result
|
||||
|
||||
|
||||
@register_timeline_implementation("tasks.task", "create")
|
||||
@register_timeline_implementation("tasks.task", "change")
|
||||
@register_timeline_implementation("tasks.task", "delete")
|
||||
def task_timeline(instance, extra_data={}):
|
||||
result ={
|
||||
"task": {
|
||||
"id": instance.pk,
|
||||
"subject": instance.subject,
|
||||
},
|
||||
"creator": {
|
||||
"id": instance.owner.pk,
|
||||
"name": instance.owner.get_full_name(),
|
||||
"project": {
|
||||
"id": instance.project.pk,
|
||||
"slug": instance.project.slug,
|
||||
"name": instance.project.name,
|
||||
}
|
||||
}
|
||||
result.update(extra_data)
|
||||
return result
|
||||
|
||||
|
||||
@register_timeline_implementation("wiki.wikipage", "create")
|
||||
@register_timeline_implementation("wiki.wikipage", "change")
|
||||
@register_timeline_implementation("wiki.wikipage", "delete")
|
||||
def wiki_page_timeline(instance, extra_data={}):
|
||||
result ={
|
||||
"wiki_page": {
|
||||
"id": instance.pk,
|
||||
"slug": instance.slug,
|
||||
},
|
||||
"project": {
|
||||
"id": instance.project.pk,
|
||||
"slug": instance.project.slug,
|
||||
"name": instance.project.name,
|
||||
}
|
||||
}
|
||||
result.update(extra_data)
|
||||
return result
|
||||
|
||||
|
||||
@register_timeline_implementation("projects.membership", "create")
|
||||
def membership_create_timeline(instance, extra_data={}):
|
||||
return {
|
||||
"user": {
|
||||
"id": instance.user.pk,
|
||||
"name": instance.user.get_full_name(),
|
||||
},
|
||||
"project": {
|
||||
"id": instance.project.pk,
|
||||
"slug": instance.project.slug,
|
||||
"name": instance.project.name,
|
||||
},
|
||||
"role": {
|
||||
"id": instance.role.pk,
|
||||
"name": instance.role.name,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@register_timeline_implementation("projects.membership", "delete")
|
||||
def membership_delete_timeline(instance, extra_data={}):
|
||||
if instance.user:
|
||||
return {
|
||||
"user": {
|
||||
"id": instance.user.pk,
|
||||
"name": instance.user.get_full_name(),
|
||||
},
|
||||
"project": {
|
||||
"id": instance.project.pk,
|
||||
"slug": instance.project.slug,
|
||||
"name": instance.project.name,
|
||||
},
|
||||
}
|
||||
return {
|
||||
"invitation": {
|
||||
"id": instance.pk,
|
||||
"email": instance.email,
|
||||
},
|
||||
"project": {
|
||||
"id": instance.project.pk,
|
||||
"slug": instance.project.slug,
|
||||
"name": instance.project.name,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@register_timeline_implementation("projects.membership", "role-changed")
|
||||
def membership_role_changed_timeline(instance, extra_data={}):
|
||||
def membership_create_timeline(instance, extra_data={}):
|
||||
result = {
|
||||
"user": {
|
||||
"id": instance.user.pk,
|
||||
|
@ -128,9 +141,6 @@ def membership_role_changed_timeline(instance, extra_data={}):
|
|||
"slug": instance.project.slug,
|
||||
"name": instance.project.name,
|
||||
},
|
||||
"role": {
|
||||
"id": instance.role.pk,
|
||||
"name": instance.role.name,
|
||||
}
|
||||
}
|
||||
return dict(result.items() + extra_data.items())
|
||||
result.update(extra_data)
|
||||
return result
|
||||
|
|
Loading…
Reference in New Issue