def issue_freezer(issue) -> dict: promoted_to = list( issue.generated_user_stories.values_list("id", flat=True)) snapshot = { "ref": issue.ref, "owner": issue.owner_id, "status": issue.status.id if issue.status else None, "priority": issue.priority_id, "severity": issue.severity_id, "type": issue.type_id, "milestone": issue.milestone_id, "subject": issue.subject, "description": issue.description, "description_html": mdrender(issue.project, issue.description), "assigned_to": issue.assigned_to_id, "attachments": extract_attachments(issue), "tags": issue.tags, "is_blocked": issue.is_blocked, "blocked_note": issue.blocked_note, "blocked_note_html": mdrender(issue.project, issue.blocked_note), "custom_attributes": extract_issue_custom_attributes(issue), "due_date": str(issue.due_date) if issue.due_date else None, "promoted_to": promoted_to, } return snapshot
def task_freezer(task) -> dict: promoted_to = list(task.generated_user_stories.values_list("id", flat=True)) snapshot = { "ref": task.ref, "owner": task.owner_id, "status": task.status.id if task.status else None, "milestone": task.milestone_id, "subject": task.subject, "description": task.description, "description_html": mdrender(task.project, task.description), "assigned_to": task.assigned_to_id, "attachments": extract_attachments(task), "taskboard_order": task.taskboard_order, "us_order": task.us_order, "tags": task.tags, "user_story": task.user_story_id, "is_iocaine": task.is_iocaine, "is_blocked": task.is_blocked, "blocked_note": task.blocked_note, "blocked_note_html": mdrender(task.project, task.blocked_note), "custom_attributes": extract_task_custom_attributes(task), "due_date": str(task.due_date) if task.due_date else None, "promoted_to": promoted_to, } return snapshot
def userstory_freezer(us) -> dict: rp_cls = apps.get_model("userstories", "RolePoints") rpqsd = rp_cls.objects.filter(user_story=us) points = {} for rp in rpqsd: points[str(rp.role_id)] = rp.points_id snapshot = { "ref": us.ref, "owner": us.owner_id, "status": us.status_id, "is_closed": us.is_closed, "finish_date": str(us.finish_date), "backlog_order": us.backlog_order, "sprint_order": us.sprint_order, "kanban_order": us.kanban_order, "subject": us.subject, "description": us.description, "description_html": mdrender(us.project, us.description), "assigned_to": us.assigned_to_id, "milestone": us.milestone_id, "client_requirement": us.client_requirement, "team_requirement": us.team_requirement, "attachments": extract_attachments(us), "tags": us.tags, "points": points, "from_issue": us.generated_from_issue_id, "is_blocked": us.is_blocked, "blocked_note": us.blocked_note, "blocked_note_html": mdrender(us.project, us.blocked_note), "custom_attributes": extract_user_story_custom_attributes(us), } return snapshot
def _process_edited(self, item, comment, comment_github_url): histories = HistoryEntry.objects.filter(key="issues.issue:" + str(item.id), comment__contains=comment_github_url) for history in list(histories): history.comment = comment history.comment_html = mdrender(item.project, comment) history.save()
def productincrement_freezer(productincrement) -> dict: snapshot = { "ref": productincrement.ref, "owner": productincrement.owner_id, # "status": productincrement.status_id, # "priority": productincrement.priority_id, # "severity": productincrement.severity_id, # "type": productincrement.type_id, # "milestone": productincrement.milestone_id, # "subject": productincrement.subject, # "description": productincrement.description, "description_html": mdrender(productincrement.project, productincrement.description), # "assigned_to": productincrement.assigned_to_id, "attachments": extract_attachments(productincrement), # "tags": productincrement.tags, # "is_blocked": productincrement.is_blocked, # "blocked_note": productincrement.blocked_note, # "blocked_note_html": mdrender(productincrement.project, productincrement.blocked_note), # "custom_attributes": extract_issue_custom_attributes(productincrement), } return snapshot
def _import_activity(self, obj, activity, options): activity_data = self._transform_activity_data(obj, activity, options) if activity_data is None: return change_old = activity_data["change_old"] change_new = activity_data["change_new"] hist_type = activity_data["hist_type"] comment = activity_data["comment"] user = activity_data["user"] key = make_key_from_model_object(activity_data["obj"]) typename = get_typename_for_model_class(type(activity_data["obj"])) diff = make_diff_from_dicts(change_old, change_new) fdiff = FrozenDiff(key, diff, {}) entry = HistoryEntry.objects.create( user=user, project_id=obj.project.id, key=key, type=hist_type, snapshot=None, diff=fdiff.diff, values=make_diff_values(typename, fdiff), comment=comment, comment_html=mdrender(obj.project, comment), is_hidden=False, is_snapshot=False, ) HistoryEntry.objects.filter(id=entry.id).update( created_at=activity["occurred_at"]) return HistoryEntry.objects.get(id=entry.id)
def edit_comment(self, request, pk): obj = self.get_object() history_entry_id = request.QUERY_PARAMS.get('id', None) history_entry = services.get_history_queryset_by_model_instance(obj).filter(id=history_entry_id).first() obj = services.get_instance_from_key(history_entry.key) comment = request.DATA.get("comment", None) self.check_permissions(request, 'edit_comment', history_entry) if history_entry is None: return response.NotFound() if comment is None: return response.BadRequest({"error": _("comment is required")}) if history_entry.delete_comment_date or history_entry.delete_comment_user: return response.BadRequest({"error": _("deleted comments can't be edited")}) # comment_versions can be None if there are no historic versions of the comment comment_versions = history_entry.comment_versions or [] comment_versions.append({ "date": history_entry.created_at, "comment": history_entry.comment, "comment_html": history_entry.comment_html, "user": { "id": request.user.pk, } }) history_entry.edit_comment_date = timezone.now() history_entry.comment = comment history_entry.comment_html = mdrender(obj.project, comment) history_entry.comment_versions = comment_versions history_entry.save() return response.Ok()
def userstory_freezer(us) -> dict: rp_cls = get_model("userstories", "RolePoints") rpqsd = rp_cls.objects.filter(user_story=us) points = {} for rp in rpqsd: points[str(rp.role_id)] = rp.points_id snapshot = { "ref": us.ref, "owner": us.owner_id, "status": us.status_id, "is_closed": us.is_closed, "finish_date": us.finish_date, "order": us.order, "subject": us.subject, "description": us.description, "description_html": mdrender(us.project, us.description), "assigned_to": us.assigned_to_id, "milestone": us.milestone_id, "client_requirement": us.client_requirement, "team_requirement": us.team_requirement, "watchers": [x.id for x in us.watchers.all()], "attachments": extract_attachments(us), "tags": us.tags, "points": points, "from_issue": us.generated_from_issue_id, } return snapshot
def take_snapshot(obj:object, *, comment:str="", user=None, delete:bool=False): """ Given any model instance with registred content type, create new history entry of "change" type. This raises exception in case of object wasn't previously freezed. """ key = make_key_from_model_object(obj) typename = get_typename_for_model_class(obj.__class__) new_fobj = freeze_model_instance(obj) old_fobj, need_real_snapshot = get_last_snapshot_for_key(key) entry_model = apps.get_model("history", "HistoryEntry") user_id = None if user is None else user.id user_name = "" if user is None else user.get_full_name() # Determine history type if delete: entry_type = HistoryType.delete elif new_fobj and not old_fobj: entry_type = HistoryType.create elif new_fobj and old_fobj: entry_type = HistoryType.change else: raise RuntimeError("Unexpected condition") fdiff = make_diff(old_fobj, new_fobj) # If diff and comment are empty, do # not create empty history entry if (not fdiff.diff and not comment and old_fobj is not None and entry_type != HistoryType.delete): return None fvals = make_diff_values(typename, fdiff) if len(comment) > 0: is_hidden = False else: is_hidden = is_hidden_snapshot(fdiff) kwargs = { "user": {"pk": user_id, "name": user_name}, "key": key, "type": entry_type, "snapshot": fdiff.snapshot if need_real_snapshot else None, "diff": fdiff.diff, "values": fvals, "comment": comment, "comment_html": mdrender(obj.project, comment), "is_hidden": is_hidden, "is_snapshot": need_real_snapshot, } return entry_model.objects.create(**kwargs)
def _import_action(self, us, action, statuses, options): key = make_key_from_model_object(us) typename = get_typename_for_model_class(UserStory) action_data = self._transform_action_data(us, action, statuses, options) if action_data is None: return change_old = action_data['change_old'] change_new = action_data['change_new'] hist_type = action_data['hist_type'] comment = action_data['comment'] user = action_data['user'] diff = make_diff_from_dicts(change_old, change_new) fdiff = FrozenDiff(key, diff, {}) entry = HistoryEntry.objects.create( user=user, project_id=us.project.id, key=key, type=hist_type, snapshot=None, diff=fdiff.diff, values=make_diff_values(typename, fdiff), comment=comment, comment_html=mdrender(us.project, comment), is_hidden=False, is_snapshot=False, ) HistoryEntry.objects.filter(id=entry.id).update(created_at=action['date']) return HistoryEntry.objects.get(id=entry.id)
def _import_history(self, project, obj, history, options): key = make_key_from_model_object(obj) typename = get_typename_for_model_class(obj.__class__) history_data = self._transform_history_data(project, obj, history, options) if history_data is None: return change_old = history_data['change_old'] change_new = history_data['change_new'] hist_type = history_data['hist_type'] comment = history_data['comment'] user = history_data['user'] diff = make_diff_from_dicts(change_old, change_new) fdiff = FrozenDiff(key, diff, {}) values = make_diff_values(typename, fdiff) values.update(history_data['update_values']) entry = HistoryEntry.objects.create( user=user, project_id=obj.project.id, key=key, type=hist_type, snapshot=None, diff=fdiff.diff, values=values, comment=comment, comment_html=mdrender(obj.project, comment), is_hidden=False, is_snapshot=False, ) HistoryEntry.objects.filter(id=entry.id).update(created_at=history['created']) return HistoryEntry.objects.get(id=entry.id)
def _import_action(self, us, action, statuses, options): key = make_key_from_model_object(us) typename = get_typename_for_model_class(UserStory) action_data = self._transform_action_data(us, action, statuses, options) if action_data is None: return change_old = action_data['change_old'] change_new = action_data['change_new'] hist_type = action_data['hist_type'] comment = action_data['comment'] user = action_data['user'] diff = make_diff_from_dicts(change_old, change_new) fdiff = FrozenDiff(key, diff, {}) entry = HistoryEntry.objects.create( user=user, project_id=us.project.id, key=key, type=hist_type, snapshot=None, diff=fdiff.diff, values=make_diff_values(typename, fdiff), comment=comment, comment_html=mdrender(us.project, comment), is_hidden=False, is_snapshot=False, ) HistoryEntry.objects.filter(id=entry.id).update( created_at=action['date']) return HistoryEntry.objects.get(id=entry.id)
def userstory_freezer(us) -> dict: rp_cls = apps.get_model("userstories", "RolePoints") rpqsd = rp_cls.objects.filter(user_story=us) points = {} for rp in rpqsd: points[str(rp.role_id)] = rp.points_id assigned_users = [u.id for u in us.assigned_users.all()] # Due to multiple assignment migration, for new snapshots we add to # assigned users a list with the 'assigned to' value if us.assigned_to_id and not assigned_users: assigned_users = [us.assigned_to_id] snapshot = { "ref": us.ref, "owner": us.owner_id, "status": us.status.id if us.status else None, "swimlane": us.swimlane.id if us.swimlane else None, "is_closed": us.is_closed, "finish_date": str(us.finish_date), "backlog_order": us.backlog_order, "sprint_order": us.sprint_order, "kanban_order": us.kanban_order, "subject": us.subject, "description": us.description, "description_html": mdrender(us.project, us.description), "assigned_to": us.assigned_to_id, "assigned_users": assigned_users, "milestone": us.milestone_id, "client_requirement": us.client_requirement, "team_requirement": us.team_requirement, "attachments": extract_attachments(us), "tags": us.tags, "points": points, "from_issue": us.generated_from_issue_id, "from_task": us.generated_from_task_id, "is_blocked": us.is_blocked, "blocked_note": us.blocked_note, "blocked_note_html": mdrender(us.project, us.blocked_note), "custom_attributes": extract_user_story_custom_attributes(us), "tribe_gig": us.tribe_gig, "due_date": str(us.due_date) if us.due_date else None } return snapshot
def userstory_freezer(us) -> dict: rp_cls = apps.get_model("userstories", "RolePoints") rpqsd = rp_cls.objects.filter(user_story=us) points = {} for rp in rpqsd: points[str(rp.role_id)] = rp.points_id assigned_users = [u.id for u in us.assigned_users.all()] # Due to multiple assignment migration, for new snapshots we add to # assigned users a list with the 'assigned to' value if us.assigned_to_id and not assigned_users: assigned_users = [us.assigned_to_id] snapshot = { "ref": us.ref, "owner": us.owner_id, "status": us.status.id if us.status else None, "is_closed": us.is_closed, "finish_date": str(us.finish_date), "backlog_order": us.backlog_order, "sprint_order": us.sprint_order, "kanban_order": us.kanban_order, "subject": us.subject, "description": us.description, "description_html": mdrender(us.project, us.description), "assigned_to": us.assigned_to_id, "assigned_users": assigned_users, "milestone": us.milestone_id, "client_requirement": us.client_requirement, "team_requirement": us.team_requirement, "attachments": extract_attachments(us), "tags": us.tags, "points": points, "from_issue": us.generated_from_issue_id, "from_task": us.generated_from_task_id, "is_blocked": us.is_blocked, "blocked_note": us.blocked_note, "blocked_note_html": mdrender(us.project, us.blocked_note), "custom_attributes": extract_user_story_custom_attributes(us), "tribe_gig": us.tribe_gig, "due_date": str(us.due_date) if us.due_date else None } return snapshot
def wikipage_freezer(wiki) -> dict: snapshot = { "slug": wiki.slug, "owner": wiki.owner_id, "content": wiki.content, "content_html": mdrender(wiki.project, wiki.content), "attachments": extract_attachments(wiki), } return snapshot
def wiki_freezer(wiki) -> dict: snapshot = { "slug": wiki.slug, "owner": wiki.owner_id, "content": wiki.content, "content_home": mdrender(wiki.project, wiki.content), "watchers": [x.pk for x in wiki.watchers.all()], "attachments": extract_attachments(wiki), } return snapshot
def edit_comment(self, request, pk): obj = self.get_object() history_entry_id = request.QUERY_PARAMS.get("id", None) history_entry = ( services.get_history_queryset_by_model_instance(obj).filter( id=history_entry_id).first()) if history_entry is None: return response.NotFound() obj = services.get_instance_from_key(history_entry.key) comment = request.DATA.get("comment", None) self.check_permissions(request, "edit_comment", history_entry) if history_entry is None: return response.NotFound() if comment is None: return response.BadRequest({"error": _("comment is required")}) if history_entry.delete_comment_date or history_entry.delete_comment_user: return response.BadRequest( {"error": _("deleted comments can't be edited")}) # comment_versions can be None if there are no historic versions of the comment comment_versions = history_entry.comment_versions or [] comment_versions.append({ "date": history_entry.created_at, "comment": history_entry.comment, "comment_html": history_entry.comment_html, "user": { "id": request.user.pk, }, }) new_mentions = self._get_new_mentions(obj, history_entry.comment, comment) history_entry.edit_comment_date = timezone.now() history_entry.comment = comment history_entry.comment_html = mdrender(obj.project, comment) history_entry.comment_versions = comment_versions history_entry.save() if new_mentions: signal_mentions.send( sender=self.__class__, user=self.request.user, obj=obj, mentions=new_mentions, ) return response.Ok()
def epic_freezer(epic) -> dict: snapshot = { "ref": epic.ref, "color": epic.color, "owner": epic.owner_id, "status": epic.status.id if epic.status else None, "epics_order": epic.epics_order, "subject": epic.subject, "description": epic.description, "description_html": mdrender(epic.project, epic.description), "assigned_to": epic.assigned_to_id, "client_requirement": epic.client_requirement, "team_requirement": epic.team_requirement, "attachments": extract_attachments(epic), "tags": epic.tags, "is_blocked": epic.is_blocked, "blocked_note": epic.blocked_note, "blocked_note_html": mdrender(epic.project, epic.blocked_note), "custom_attributes": extract_epic_custom_attributes(epic) } return snapshot
def issue_freezer(issue) -> dict: snapshot = { "ref": issue.ref, "owner": issue.owner_id, "status": issue.status_id, "priority": issue.priority_id, "severity": issue.severity_id, "type": issue.type_id, "milestone": issue.milestone_id, "subject": issue.subject, "description": issue.description, "description_html": mdrender(issue.project, issue.description), "assigned_to": issue.assigned_to_id, "attachments": extract_attachments(issue), "tags": issue.tags, "is_blocked": issue.is_blocked, "blocked_note": issue.blocked_note, "blocked_note_html": mdrender(issue.project, issue.blocked_note), "custom_attributes": extract_issue_custom_attributes(issue), } return snapshot
def task_freezer(task) -> dict: snapshot = { "ref": task.ref, "owner": task.owner_id, "status": task.status_id, "milestone": task.milestone_id, "subject": task.subject, "description": task.description, "description_html": mdrender(task.project, task.description), "assigned_to": task.assigned_to_id, "attachments": extract_attachments(task), "taskboard_order": task.taskboard_order, "us_order": task.us_order, "tags": task.tags, "user_story": task.user_story_id, "is_iocaine": task.is_iocaine, "is_blocked": task.is_blocked, "blocked_note": task.blocked_note, "blocked_note_html": mdrender(task.project, task.blocked_note), "custom_attributes": extract_task_custom_attributes(task), } return snapshot
def render(self, request, **kwargs): content = request.DATA.get("content", None) project_id = request.DATA.get("project_id", None) if not content: raise exc.WrongArguments({"content": _("'content' parameter is mandatory")}) if not project_id: raise exc.WrongArguments({"project_id": _("'project_id' parameter is mandatory")}) project = get_object_or_404(Project, pk=project_id) self.check_permissions(request, "render", project) data = mdrender(project, content) return response.Ok({"data": data})
def take_snapshot(obj: object, *, comment: str = "", user=None): """ Given any model instance with registred content type, create new history entry of "change" type. This raises exception in case of object wasn't previously freezed. """ key = make_key_from_model_object(obj) typename = get_typename_for_model_class(obj.__class__) new_fobj = freeze_model_instance(obj) old_fobj, need_snapshot = get_last_snapshot_for_key(key) fdiff = make_diff(old_fobj, new_fobj) fvals = make_diff_values(typename, fdiff) # If diff and comment are empty, do # not create empty history entry if not fdiff.diff and not comment and old_fobj != None: return None entry_type = HistoryType.change if old_fobj else HistoryType.create entry_model = get_model("history", "HistoryEntry") user_id = None if user is None else user.id user_name = "" if user is None else user.get_full_name() kwargs = { "user": { "pk": user_id, "name": user_name }, "type": entry_type, "key": key, "diff": fdiff.diff, "snapshot": fdiff.snapshot if need_snapshot else None, "is_snapshot": need_snapshot, "comment": comment, "comment_html": mdrender(obj.project, comment), "values": fvals, } return entry_model.objects.create(**kwargs)
def task_freezer(task) -> dict: snapshot = { "ref": task.ref, "owner": task.owner_id, "status": task.status_id, "milestone": task.milestone_id, "subject": task.subject, "description": task.description, "description_html": mdrender(task.project, task.description), "assigned_to": task.assigned_to_id, "watchers": [x.pk for x in task.watchers.all()], "attachments": extract_attachments(task), "tags": task.tags, "user_story": task.user_story_id, "is_iocaine": task.is_iocaine, } return snapshot
def issue_freezer(issue) -> dict: snapshot = { "ref": issue.ref, "owner": issue.owner_id, "status": issue.status_id, "priority": issue.priority_id, "severity": issue.severity_id, "type": issue.type_id, "milestone": issue.milestone_id, "subject": issue.subject, "description": issue.description, "description_html": mdrender(issue.project, issue.description), "assigned_to": issue.assigned_to_id, "watchers": [x.pk for x in issue.watchers.all()], "attachments": extract_attachments(issue), "tags": issue.tags, } return snapshot
def render(self, request, **kwargs): content = request.DATA.get("content", None) project_id = request.DATA.get("project_id", None) if not content: return Response({"content": "No content parameter"}, status=status.HTTP_400_BAD_REQUEST) if not project_id: return Response({"project_id": "No project_id parameter"}, status=status.HTTP_400_BAD_REQUEST) try: project = Project.objects.get(pk=project_id) except Project.DoesNotExist: return Response({"project_id": "Not valid project id"}, status=status.HTTP_400_BAD_REQUEST) data = mdrender(project, content) return Response({"data": data})
def get_description_html(self, obj): return mdrender(obj.project, obj.description)
def _transform_activity_data(self, obj, activity, options): users_bindings = options.get('users_bindings', {}) due_date_field = obj.project.userstorycustomattributes.get(name="Due date") story_type_field = obj.project.userstorycustomattributes.get(name="Type") user = {"pk": None, "name": activity.get('performed_by', {}).get('name', None)} taiga_user = users_bindings.get(activity.get('performed_by', {}).get('id', None), None) if taiga_user: user = {"pk": taiga_user.id, "name": taiga_user.get_full_name()} result = { "change_old": {}, "change_new": {}, "hist_type": HistoryType.change, "comment": "", "user": user, "obj": obj } if activity['kind'] == "story_create_activity": UserStory.objects.filter(id=obj.id, created_date__gt=activity['occurred_at']).update( created_date=activity['occurred_at'], owner=users_bindings.get(activity["performed_by"]["id"], self._user) ) return None elif activity['kind'] == "epic_create_activity": Epic.objects.filter(id=obj.id, created_date__gt=activity['occurred_at']).update( created_date=activity['occurred_at'], owner=users_bindings.get(activity["performed_by"]["id"], self._user) ) return None elif activity['kind'] in ["story_update_activity", "epic_update_activity"]: for change in activity['changes']: if change['change_type'] != "update" or change['kind'] not in ["story", "epic"]: continue if 'description' in change['new_values']: result['change_old']["description"] = str(change['original_values']['description']) result['change_new']["description"] = str(change['new_values']['description']) result['change_old']["description_html"] = mdrender(obj.project, str(change['original_values']['description'])) result['change_new']["description_html"] = mdrender(obj.project, str(change['new_values']['description'])) if 'estimate' in change['new_values']: old_points = None if change['original_values']['estimate']: estimation = change['original_values']['estimate'] (old_points, _) = Points.objects.get_or_create( project=obj.project, value=estimation, defaults={ "name": str(estimation), "order": estimation, } ) old_points = old_points.id new_points = None if change['new_values']['estimate']: estimation = change['new_values']['estimate'] (new_points, _) = Points.objects.get_or_create( project=obj.project, value=estimation, defaults={ "name": str(estimation), "order": estimation, } ) new_points = new_points.id result['change_old']["points"] = {obj.project.roles.get(slug="main").id: old_points} result['change_new']["points"] = {obj.project.roles.get(slug="main").id: new_points} if 'name' in change['new_values']: result['change_old']["subject"] = change['original_values']['name'] result['change_new']["subject"] = change['new_values']['name'] if 'labels' in change['new_values']: result['change_old']["tags"] = [l.lower() for l in change['original_values']['labels']] result['change_new']["tags"] = [l.lower() for l in change['new_values']['labels']] if 'current_state' in change['new_values']: result['change_old']["status"] = obj.project.us_statuses.get(slug=change['original_values']['current_state']).id result['change_new']["status"] = obj.project.us_statuses.get(slug=change['new_values']['current_state']).id if 'story_type' in change['new_values']: if "custom_attributes" not in result['change_old']: result['change_old']["custom_attributes"] = [] if "custom_attributes" not in result['change_new']: result['change_new']["custom_attributes"] = [] result['change_old']["custom_attributes"].append({ "name": "Type", "value": change['original_values']['story_type'], "id": story_type_field.id }) result['change_new']["custom_attributes"].append({ "name": "Type", "value": change['new_values']['story_type'], "id": story_type_field.id }) if 'deadline' in change['new_values']: if "custom_attributes" not in result['change_old']: result['change_old']["custom_attributes"] = [] if "custom_attributes" not in result['change_new']: result['change_new']["custom_attributes"] = [] result['change_old']["custom_attributes"].append({ "name": "Due date", "value": change['original_values']['deadline'], "id": due_date_field.id }) result['change_new']["custom_attributes"].append({ "name": "Due date", "value": change['new_values']['deadline'], "id": due_date_field.id }) # TODO: Process owners_ids elif activity['kind'] == "task_create_activity": return None elif activity['kind'] == "task_update_activity": for change in activity['changes']: if change['change_type'] != "update" or change['kind'] != "task": continue try: task = Task.objects.get(project=obj.project, ref=change['id']) if 'description' in change['new_values']: result['change_old']["subject"] = change['original_values']['description'] result['change_new']["subject"] = change['new_values']['description'] result['obj'] = task if 'complete' in change['new_values']: result['change_old']["status"] = obj.project.task_statuses.get(slug="complete" if change['original_values']['complete'] else "incomplete").id result['change_new']["status"] = obj.project.task_statuses.get(slug="complete" if change['new_values']['complete'] else "incomplete").id result['obj'] = task except Task.DoesNotExist: return None elif activity['kind'] == "comment_create_activity": return None elif activity['kind'] == "comment_update_activity": return None elif activity['kind'] == "story_move_activity": return None return result
def get_blocked_note_html(self, obj): return mdrender(obj.project, obj.blocked_note)
def _transform_history_data(self, project, obj, history, options): users_bindings = options.get('users_bindings', {}) user = { "pk": None, "name": history.get('author', {}).get('displayName', None) } taiga_user = users_bindings.get( history.get('author', {}).get('key', None), None) if taiga_user: user = {"pk": taiga_user.id, "name": taiga_user.get_full_name()} result = { "change_old": {}, "change_new": {}, "update_values": {}, "hist_type": HistoryType.change, "comment": "", "user": user } custom_fields_by_names = { f["history_name"]: f for f in self.custom_fields } has_data = False for history_item in history['items']: if history_item['field'] == "Attachment": result['change_old']["attachments"] = [] for att in obj.cummulative_attachments: result['change_old']["attachments"].append({ "id": 0, "filename": att }) if history_item['from'] is not None: try: idx = obj.cummulative_attachments.index( history_item['fromString']) obj.cummulative_attachments.pop(idx) except ValueError: print( "ERROR: Removing attachment that doesn't exist in the history ({})" .format(history_item['fromString'])) if history_item['to'] is not None: obj.cummulative_attachments.append( history_item['toString']) result['change_new']["attachments"] = [] for att in obj.cummulative_attachments: result['change_new']["attachments"].append({ "id": 0, "filename": att }) has_data = True elif history_item['field'] == "description": result['change_old']["description"] = history_item[ 'fromString'] result['change_new']["description"] = history_item['toString'] result['change_old']["description_html"] = mdrender( obj.project, history_item['fromString'] or "") result['change_new']["description_html"] = mdrender( obj.project, history_item['toString'] or "") has_data = True elif history_item['field'] == "Epic Link": pass elif history_item['field'] == "Workflow": pass elif history_item['field'] == "Link": pass elif history_item['field'] == "labels": result['change_old']["tags"] = history_item[ 'fromString'].split() result['change_new']["tags"] = history_item['toString'].split() has_data = True elif history_item['field'] == "Rank": pass elif history_item['field'] == "RemoteIssueLink": pass elif history_item['field'] == "Sprint": old_milestone = None if history_item['fromString']: try: old_milestone = obj.project.milestones.get( name=history_item['fromString']).id except Milestone.DoesNotExist: old_milestone = -1 new_milestone = None if history_item['toString']: try: new_milestone = obj.project.milestones.get( name=history_item['toString']).id except Milestone.DoesNotExist: new_milestone = -2 result['change_old']["milestone"] = old_milestone result['change_new']["milestone"] = new_milestone if old_milestone == -1 or new_milestone == -2: result['update_values']["milestone"] = {} if old_milestone == -1: result['update_values']["milestone"]["-1"] = history_item[ 'fromString'] if new_milestone == -2: result['update_values']["milestone"]["-2"] = history_item[ 'toString'] has_data = True elif history_item['field'] == "status": if isinstance(obj, Task): try: old_status = obj.project.task_statuses.get( name=history_item['fromString']).id except Exception: old_status = -1 try: new_status = obj.project.task_statuses.get( name=history_item['toString']).id except Exception: new_status = -2 elif isinstance(obj, UserStory): try: old_status = obj.project.us_statuses.get( name=history_item['fromString']).id except Exception: old_status = -1 try: new_status = obj.project.us_statuses.get( name=history_item['toString']).id except Exception: new_status = -2 elif isinstance(obj, Issue): try: old_status = obj.project.issue_statuses.get( name=history_item['fromString']).id except Exception: old_status = -1 try: new_status = obj.project.us_statuses.get( name=history_item['toString']).id except Exception: new_status = -2 elif isinstance(obj, Epic): try: old_status = obj.project.epic_statuses.get( name=history_item['fromString']).id except Exception: old_status = -1 try: new_status = obj.project.epic_statuses.get( name=history_item['toString']).id except Exception: new_status = -2 if old_status == -1 or new_status == -2: result['update_values']["status"] = {} if old_status == -1: result['update_values']["status"]["-1"] = history_item[ 'fromString'] if new_status == -2: result['update_values']["status"]["-2"] = history_item[ 'toString'] result['change_old']["status"] = old_status result['change_new']["status"] = new_status has_data = True elif history_item['field'] == "Story Points": old_points = None if history_item['fromString']: estimation = float(history_item['fromString']) (old_points, _) = Points.objects.get_or_create(project=project, value=estimation, defaults={ "name": str(estimation), "order": estimation, }) old_points = old_points.id new_points = None if history_item['toString']: estimation = float(history_item['toString']) (new_points, _) = Points.objects.get_or_create(project=project, value=estimation, defaults={ "name": str(estimation), "order": estimation, }) new_points = new_points.id result['change_old']["points"] = { project.roles.get(slug="main").id: old_points } result['change_new']["points"] = { project.roles.get(slug="main").id: new_points } has_data = True elif history_item['field'] == "summary": result['change_old']["subject"] = history_item['fromString'] result['change_new']["subject"] = history_item['toString'] has_data = True elif history_item['field'] == "Epic Color": if isinstance(obj, Epic): result['change_old']["color"] = EPIC_COLORS.get( history_item['fromString'], None) result['change_new']["color"] = EPIC_COLORS.get( history_item['toString'], None) Epic.objects.filter( id=obj.id).update(color=EPIC_COLORS.get( history_item['toString'], "#999999")) has_data = True elif history_item['field'] == "assignee": old_assigned_to = None if history_item['from'] is not None: old_assigned_to = users_bindings.get( history_item['from'], -1) if old_assigned_to != -1: old_assigned_to = old_assigned_to.id new_assigned_to = None if history_item['to'] is not None: new_assigned_to = users_bindings.get( history_item['to'], -2) if new_assigned_to != -2: new_assigned_to = new_assigned_to.id result['change_old']["assigned_to"] = old_assigned_to result['change_new']["assigned_to"] = new_assigned_to if old_assigned_to == -1 or new_assigned_to == -2: result['update_values']["users"] = {} if old_assigned_to == -1: result['update_values']["users"]["-1"] = history_item[ 'fromString'] if new_assigned_to == -2: result['update_values']["users"]["-2"] = history_item[ 'toString'] has_data = True elif history_item['field'] in custom_fields_by_names: custom_field = custom_fields_by_names[history_item['field']] if isinstance(obj, Task): field_obj = obj.project.taskcustomattributes.get( name=custom_field['taiga_field_name']) elif isinstance(obj, UserStory): field_obj = obj.project.userstorycustomattributes.get( name=custom_field['taiga_field_name']) elif isinstance(obj, Issue): field_obj = obj.project.issuecustomattributes.get( name=custom_field['taiga_field_name']) elif isinstance(obj, Epic): field_obj = obj.project.epiccustomattributes.get( name=custom_field['taiga_field_name']) result['change_old']["custom_attributes"] = [{ "name": custom_field['taiga_field_name'], "value": history_item['fromString'], "id": field_obj.id }] result['change_new']["custom_attributes"] = [{ "name": custom_field['taiga_field_name'], "value": history_item['toString'], "id": field_obj.id }] has_data = True if not has_data: return None return result
def _transform_activity_data(self, obj, activity, options): users_bindings = options.get('users_bindings', {}) due_date_field = obj.project.userstorycustomattributes.get( name="Due date") story_type_field = obj.project.userstorycustomattributes.get( name="Type") user = { "pk": None, "name": activity.get('performed_by', {}).get('name', None) } taiga_user = users_bindings.get( activity.get('performed_by', {}).get('id', None), None) if taiga_user: user = {"pk": taiga_user.id, "name": taiga_user.get_full_name()} result = { "change_old": {}, "change_new": {}, "hist_type": HistoryType.change, "comment": "", "user": user, "obj": obj } if activity['kind'] == "story_create_activity": UserStory.objects.filter( id=obj.id, created_date__gt=activity['occurred_at']).update( created_date=activity['occurred_at'], owner=users_bindings.get(activity["performed_by"]["id"], self._user)) return None elif activity['kind'] == "epic_create_activity": Epic.objects.filter( id=obj.id, created_date__gt=activity['occurred_at']).update( created_date=activity['occurred_at'], owner=users_bindings.get(activity["performed_by"]["id"], self._user)) return None elif activity['kind'] in [ "story_update_activity", "epic_update_activity" ]: for change in activity['changes']: if change['change_type'] != "update" or change['kind'] not in [ "story", "epic" ]: continue if 'description' in change['new_values']: result['change_old']["description"] = str( change['original_values']['description']) result['change_new']["description"] = str( change['new_values']['description']) result['change_old']["description_html"] = mdrender( obj.project, str(change['original_values']['description'])) result['change_new']["description_html"] = mdrender( obj.project, str(change['new_values']['description'])) if 'estimate' in change['new_values']: old_points = None if change['original_values']['estimate']: estimation = change['original_values']['estimate'] (old_points, _) = Points.objects.get_or_create(project=obj.project, value=estimation, defaults={ "name": str(estimation), "order": estimation, }) old_points = old_points.id new_points = None if change['new_values']['estimate']: estimation = change['new_values']['estimate'] (new_points, _) = Points.objects.get_or_create(project=obj.project, value=estimation, defaults={ "name": str(estimation), "order": estimation, }) new_points = new_points.id result['change_old']["points"] = { obj.project.roles.get(slug="main").id: old_points } result['change_new']["points"] = { obj.project.roles.get(slug="main").id: new_points } if 'name' in change['new_values']: result['change_old']["subject"] = change[ 'original_values']['name'] result['change_new']["subject"] = change['new_values'][ 'name'] if 'labels' in change['new_values']: result['change_old']["tags"] = [ l.lower() for l in change['original_values']['labels'] ] result['change_new']["tags"] = [ l.lower() for l in change['new_values']['labels'] ] if 'current_state' in change['new_values']: result['change_old'][ "status"] = obj.project.us_statuses.get( slug=change['original_values']['current_state']).id result['change_new'][ "status"] = obj.project.us_statuses.get( slug=change['new_values']['current_state']).id if 'story_type' in change['new_values']: if "custom_attributes" not in result['change_old']: result['change_old']["custom_attributes"] = [] if "custom_attributes" not in result['change_new']: result['change_new']["custom_attributes"] = [] result['change_old']["custom_attributes"].append({ "name": "Type", "value": change['original_values']['story_type'], "id": story_type_field.id }) result['change_new']["custom_attributes"].append({ "name": "Type", "value": change['new_values']['story_type'], "id": story_type_field.id }) if 'deadline' in change['new_values']: if "custom_attributes" not in result['change_old']: result['change_old']["custom_attributes"] = [] if "custom_attributes" not in result['change_new']: result['change_new']["custom_attributes"] = [] result['change_old']["custom_attributes"].append({ "name": "Due date", "value": change['original_values']['deadline'], "id": due_date_field.id }) result['change_new']["custom_attributes"].append({ "name": "Due date", "value": change['new_values']['deadline'], "id": due_date_field.id }) # TODO: Process owners_ids elif activity['kind'] == "task_create_activity": return None elif activity['kind'] == "task_update_activity": for change in activity['changes']: if change['change_type'] != "update" or change[ 'kind'] != "task": continue try: task = Task.objects.get(project=obj.project, ref=change['id']) if 'description' in change['new_values']: result['change_old']["subject"] = change[ 'original_values']['description'] result['change_new']["subject"] = change['new_values'][ 'description'] result['obj'] = task if 'complete' in change['new_values']: result['change_old'][ "status"] = obj.project.task_statuses.get( slug="complete" if change['original_values'] ['complete'] else "incomplete").id result['change_new'][ "status"] = obj.project.task_statuses.get( slug="complete" if change['new_values'] ['complete'] else "incomplete").id result['obj'] = task except Task.DoesNotExist: return None elif activity['kind'] == "comment_create_activity": return None elif activity['kind'] == "comment_update_activity": return None elif activity['kind'] == "story_move_activity": return None return result
def field_from_native(self, data, files, field_name, into): super().field_from_native(data, files, field_name, into) into["comment_html"] = mdrender(self.context['project'], data.get("comment", ""))
def _transform_action_data(self, us, action, statuses, options): users_bindings = options.get('users_bindings', {}) due_date_field = us.project.userstorycustomattributes.first() ignored_actions = ["addAttachmentToCard", "addMemberToCard", "deleteAttachmentFromCard", "deleteCard", "removeMemberFromCard"] if action['type'] in ignored_actions: return None user = {"pk": None, "name": action.get('memberCreator', {}).get('fullName', None)} taiga_user = users_bindings.get(action.get('memberCreator', {}).get('id', None), None) if taiga_user: user = {"pk": taiga_user.id, "name": taiga_user.get_full_name()} result = { "change_old": {}, "change_new": {}, "hist_type": HistoryType.change, "comment": "", "user": user } if action['type'] == "commentCard": result['comment'] = str(action['data']['text']) elif action['type'] == "convertToCardFromCheckItem": UserStory.objects.filter(id=us.id, created_date__gt=action['date']).update( created_date=action['date'], owner=users_bindings.get(action["idMemberCreator"], self._user) ) result['hist_type'] = HistoryType.create elif action['type'] == "copyCommentCard": UserStory.objects.filter(id=us.id, created_date__gt=action['date']).update( created_date=action['date'], owner=users_bindings.get(action["idMemberCreator"], self._user) ) result['hist_type'] = HistoryType.create elif action['type'] == "createCard": UserStory.objects.filter(id=us.id, created_date__gt=action['date']).update( created_date=action['date'], owner=users_bindings.get(action["idMemberCreator"], self._user) ) result['hist_type'] = HistoryType.create elif action['type'] == "updateCard": if 'desc' in action['data']['old']: result['change_old']["description"] = str(action['data']['old'].get('desc', '')) result['change_new']["description"] = str(action['data']['card'].get('desc', '')) result['change_old']["description_html"] = mdrender(us.project, str(action['data']['old'].get('desc', ''))) result['change_new']["description_html"] = mdrender(us.project, str(action['data']['card'].get('desc', ''))) if 'idList' in action['data']['old']: old_status_name = statuses[action['data']['old']['idList']]['name'] result['change_old']["status"] = us.project.us_statuses.get(name=old_status_name).id new_status_name = statuses[action['data']['card']['idList']]['name'] result['change_new']["status"] = us.project.us_statuses.get(name=new_status_name).id if 'name' in action['data']['old']: result['change_old']["subject"] = action['data']['old']['name'] result['change_new']["subject"] = action['data']['card']['name'] if 'due' in action['data']['old']: result['change_old']["custom_attributes"] = [{ "name": "Due", "value": action['data']['old']['due'], "id": due_date_field.id }] result['change_new']["custom_attributes"] = [{ "name": "Due", "value": action['data']['card']['due'], "id": due_date_field.id }] if result['change_old'] == {}: return None return result
def _transform_action_data(self, us, action, statuses, options): users_bindings = options.get('users_bindings', {}) due_date_field = us.project.userstorycustomattributes.first() ignored_actions = [ "addAttachmentToCard", "addMemberToCard", "deleteAttachmentFromCard", "deleteCard", "removeMemberFromCard" ] if action['type'] in ignored_actions: return None user = { "pk": None, "name": action.get('memberCreator', {}).get('fullName', None) } taiga_user = users_bindings.get( action.get('memberCreator', {}).get('id', None), None) if taiga_user: user = {"pk": taiga_user.id, "name": taiga_user.get_full_name()} result = { "change_old": {}, "change_new": {}, "hist_type": HistoryType.change, "comment": "", "user": user } if action['type'] == "commentCard": result['comment'] = str(action['data']['text']) elif action['type'] == "convertToCardFromCheckItem": UserStory.objects.filter(id=us.id, created_date__gt=action['date']).update( created_date=action['date'], owner=users_bindings.get( action["idMemberCreator"], self._user)) result['hist_type'] = HistoryType.create elif action['type'] == "copyCommentCard": UserStory.objects.filter(id=us.id, created_date__gt=action['date']).update( created_date=action['date'], owner=users_bindings.get( action["idMemberCreator"], self._user)) result['hist_type'] = HistoryType.create elif action['type'] == "createCard": UserStory.objects.filter(id=us.id, created_date__gt=action['date']).update( created_date=action['date'], owner=users_bindings.get( action["idMemberCreator"], self._user)) result['hist_type'] = HistoryType.create elif action['type'] == "updateCard": if 'desc' in action['data']['old']: result['change_old']["description"] = str( action['data']['old'].get('desc', '')) result['change_new']["description"] = str( action['data']['card'].get('desc', '')) result['change_old']["description_html"] = mdrender( us.project, str(action['data']['old'].get('desc', ''))) result['change_new']["description_html"] = mdrender( us.project, str(action['data']['card'].get('desc', ''))) if 'idList' in action['data']['old']: old_status_name = statuses[action['data']['old'] ['idList']]['name'] result['change_old']["status"] = us.project.us_statuses.get( name=old_status_name).id new_status_name = statuses[action['data']['card'] ['idList']]['name'] result['change_new']["status"] = us.project.us_statuses.get( name=new_status_name).id if 'name' in action['data']['old']: result['change_old']["subject"] = action['data']['old']['name'] result['change_new']["subject"] = action['data']['card'][ 'name'] if 'due' in action['data']['old']: result['change_old']["custom_attributes"] = [{ "name": "Due", "value": action['data']['old']['due'], "id": due_date_field.id }] result['change_new']["custom_attributes"] = [{ "name": "Due", "value": action['data']['card']['due'], "id": due_date_field.id }] if result['change_old'] == {}: return None return result
def get_html(self, obj): return mdrender(obj.project, obj.content)
def _transform_action_data(self, us, action, statuses, options): users_bindings = options.get("users_bindings", {}) due_date_field = us.project.userstorycustomattributes.first() ignored_actions = [ "addAttachmentToCard", "addMemberToCard", "deleteAttachmentFromCard", "deleteCard", "removeMemberFromCard", ] if action["type"] in ignored_actions: return None user = { "pk": None, "name": action.get("memberCreator", {}).get("fullName", None), } taiga_user = users_bindings.get( action.get("memberCreator", {}).get("id", None), None) if taiga_user: user = {"pk": taiga_user.id, "name": taiga_user.get_full_name()} result = { "change_old": {}, "change_new": {}, "hist_type": HistoryType.change, "comment": "", "user": user, } if action["type"] == "commentCard": result["comment"] = str(action["data"]["text"]) elif action["type"] == "convertToCardFromCheckItem": UserStory.objects.filter(id=us.id, created_date__gt=action["date"]).update( created_date=action["date"], owner=users_bindings.get( action["idMemberCreator"], self._user), ) result["hist_type"] = HistoryType.create elif action["type"] == "copyCommentCard": UserStory.objects.filter(id=us.id, created_date__gt=action["date"]).update( created_date=action["date"], owner=users_bindings.get( action["idMemberCreator"], self._user), ) result["hist_type"] = HistoryType.create elif action["type"] == "createCard": UserStory.objects.filter(id=us.id, created_date__gt=action["date"]).update( created_date=action["date"], owner=users_bindings.get( action["idMemberCreator"], self._user), ) result["hist_type"] = HistoryType.create elif action["type"] == "updateCard": if "desc" in action["data"]["old"]: result["change_old"]["description"] = str( action["data"]["old"].get("desc", "")) result["change_new"]["description"] = str( action["data"]["card"].get("desc", "")) result["change_old"]["description_html"] = mdrender( us.project, str(action["data"]["old"].get("desc", ""))) result["change_new"]["description_html"] = mdrender( us.project, str(action["data"]["card"].get("desc", ""))) if "idList" in action["data"]["old"]: old_status_name = statuses[action["data"]["old"] ["idList"]]["name"] result["change_old"]["status"] = us.project.us_statuses.get( name=old_status_name).id new_status_name = statuses[action["data"]["card"] ["idList"]]["name"] result["change_new"]["status"] = us.project.us_statuses.get( name=new_status_name).id if "name" in action["data"]["old"]: result["change_old"]["subject"] = action["data"]["old"]["name"] result["change_new"]["subject"] = action["data"]["card"][ "name"] if "due" in action["data"]["old"]: result["change_old"]["custom_attributes"] = [{ "name": "Due", "value": action["data"]["old"]["due"], "id": due_date_field.id, }] result["change_new"]["custom_attributes"] = [{ "name": "Due", "value": action["data"]["card"]["due"], "id": due_date_field.id, }] if result["change_old"] == {}: return None return result