Import and export timelines
parent
f3d1de684d
commit
ce3d9aaf48
|
@ -65,6 +65,14 @@ def store_user_stories(project, data):
|
|||
return results
|
||||
|
||||
|
||||
def store_timeline_entries(project, data):
|
||||
results = []
|
||||
for timeline in data.get('timeline', []):
|
||||
tl = service.store_timeline_entry(project, timeline)
|
||||
results.append(tl)
|
||||
return results
|
||||
|
||||
|
||||
def store_issues(project, data):
|
||||
issues = []
|
||||
for issue in data.get('issues', []):
|
||||
|
@ -167,4 +175,11 @@ def dict_to_project(data, owner=None):
|
|||
|
||||
store_tags_colors(proj, data)
|
||||
|
||||
if service.get_errors(clear=False):
|
||||
raise TaigaImportError('error importing colors')
|
||||
|
||||
store_timeline_entries(proj, data)
|
||||
if service.get_errors(clear=False):
|
||||
raise TaigaImportError('error importing timelines')
|
||||
|
||||
return proj
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import base64
|
||||
import copy
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
|
||||
|
@ -39,6 +40,8 @@ from taiga.projects.milestones import models as milestones_models
|
|||
from taiga.projects.wiki import models as wiki_models
|
||||
from taiga.projects.history import models as history_models
|
||||
from taiga.projects.attachments import models as attachments_models
|
||||
from taiga.timeline import models as timeline_models
|
||||
from taiga.timeline import service as timeline_service
|
||||
from taiga.users import models as users_models
|
||||
from taiga.projects.votes import services as votes_service
|
||||
from taiga.projects.history import services as history_service
|
||||
|
@ -548,6 +551,39 @@ class WikiLinkExportSerializer(serializers.ModelSerializer):
|
|||
exclude = ('id', 'project')
|
||||
|
||||
|
||||
|
||||
class TimelineDataField(serializers.WritableField):
|
||||
read_only = False
|
||||
|
||||
def to_native(self, data):
|
||||
new_data = copy.deepcopy(data)
|
||||
try:
|
||||
user = users_models.User.objects.get(pk=new_data["user"]["id"])
|
||||
new_data["user"]["email"] = user.email
|
||||
del new_data["user"]["id"]
|
||||
except users_models.User.DoesNotExist:
|
||||
pass
|
||||
return new_data
|
||||
|
||||
def from_native(self, data):
|
||||
new_data = copy.deepcopy(data)
|
||||
try:
|
||||
user = users_models.User.objects.get(email=new_data["user"]["email"])
|
||||
new_data["user"]["id"] = user.id
|
||||
del new_data["user"]["email"]
|
||||
except users_models.User.DoesNotExist:
|
||||
pass
|
||||
|
||||
return new_data
|
||||
|
||||
|
||||
class TimelineExportSerializer(serializers.ModelSerializer):
|
||||
data = TimelineDataField()
|
||||
class Meta:
|
||||
model = timeline_models.Timeline
|
||||
exclude = ('id', 'project', 'namespace', 'object_id')
|
||||
|
||||
|
||||
class ProjectExportSerializer(serializers.ModelSerializer):
|
||||
owner = UserRelatedField(required=False)
|
||||
default_points = serializers.SlugRelatedField(slug_field="name", required=False)
|
||||
|
@ -579,7 +615,12 @@ class ProjectExportSerializer(serializers.ModelSerializer):
|
|||
anon_permissions = PgArrayField(required=False)
|
||||
public_permissions = PgArrayField(required=False)
|
||||
modified_date = serializers.DateTimeField(required=False)
|
||||
timeline = serializers.SerializerMethodField("get_timeline")
|
||||
|
||||
class Meta:
|
||||
model = projects_models.Project
|
||||
exclude = ('id', 'creation_template', 'members')
|
||||
|
||||
def get_timeline(self, obj):
|
||||
timeline_qs = timeline_service.get_project_timeline(obj)
|
||||
return TimelineExportSerializer(timeline_qs, many=True).data
|
||||
|
|
|
@ -23,6 +23,7 @@ from django.contrib.contenttypes.models import ContentType
|
|||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from taiga.projects.history.services import make_key_from_model_object
|
||||
from taiga.timeline.service import build_project_namespace
|
||||
from taiga.projects.references import sequences as seq
|
||||
from taiga.projects.references import models as refs
|
||||
from taiga.projects.services import find_invited_user
|
||||
|
@ -275,6 +276,19 @@ def store_attachment(project, obj, attachment):
|
|||
return serialized
|
||||
|
||||
|
||||
def store_timeline_entry(project, timeline):
|
||||
serialized = serializers.TimelineExportSerializer(data=timeline, context={"project": project})
|
||||
if serialized.is_valid():
|
||||
serialized.object.project = project
|
||||
serialized.object.namespace = build_project_namespace(project)
|
||||
serialized.object.object_id = project.id
|
||||
serialized.object._importing = True
|
||||
serialized.save()
|
||||
return serialized
|
||||
add_errors("timeline", serialized.errors)
|
||||
return serialized
|
||||
|
||||
|
||||
def store_history(project, obj, history):
|
||||
serialized = serializers.HistoryExportSerializer(data=history, context={"project": project})
|
||||
if serialized.is_valid():
|
||||
|
|
|
@ -76,6 +76,8 @@ class HistoryEntry(models.Model):
|
|||
# snapshot. The rest are partial snapshot.
|
||||
is_snapshot = models.BooleanField(default=False)
|
||||
|
||||
_importing = None
|
||||
|
||||
@cached_property
|
||||
def is_change(self):
|
||||
return self.type == HistoryType.change
|
||||
|
|
|
@ -29,8 +29,8 @@ class Timeline(models.Model):
|
|||
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()
|
||||
namespace = models.CharField(max_length=250, default="default", db_index=True)
|
||||
event_type = models.CharField(max_length=250, db_index=True)
|
||||
project = models.ForeignKey(Project)
|
||||
data = JsonField()
|
||||
data_content_type = models.ForeignKey(ContentType, related_name="data_timelines")
|
||||
|
|
|
@ -71,6 +71,9 @@ def _push_to_timelines(project, user, obj, event_type, extra_data={}):
|
|||
|
||||
|
||||
def on_new_history_entry(sender, instance, created, **kwargs):
|
||||
if instance._importing:
|
||||
return
|
||||
|
||||
if instance.is_hidden:
|
||||
return None
|
||||
|
||||
|
|
Loading…
Reference in New Issue