Merge "Create timeline events for boards and worklists"
This commit is contained in:
commit
064fc81e9a
@ -13,12 +13,15 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from oslo_config import cfg
|
||||
from pecan import abort
|
||||
from pecan import request
|
||||
from pecan import response
|
||||
from pecan import rest
|
||||
from pecan.secure import secure
|
||||
import six
|
||||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
@ -27,6 +30,8 @@ from storyboard.api.v1 import wmodels
|
||||
from storyboard.common import decorators
|
||||
from storyboard.common import exception as exc
|
||||
from storyboard.db.api import boards as boards_api
|
||||
from storyboard.db.api import timeline_events as events_api
|
||||
from storyboard.db.api import users as users_api
|
||||
from storyboard.db.api import worklists as worklists_api
|
||||
from storyboard.openstack.common.gettextutils import _ # noqa
|
||||
|
||||
@ -34,6 +39,13 @@ from storyboard.openstack.common.gettextutils import _ # noqa
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def serialize_lane(lane):
|
||||
return {
|
||||
"worklist_id": lane.list_id,
|
||||
"position": lane.position
|
||||
}
|
||||
|
||||
|
||||
def get_lane(list_id, board):
|
||||
for lane in board['lanes']:
|
||||
if lane.list_id == list_id:
|
||||
@ -51,17 +63,66 @@ def update_lanes(board_dict, board_id):
|
||||
new_lane = get_lane(lane.list_id, board_dict)
|
||||
if lane.position != new_lane.position:
|
||||
del new_lane.worklist
|
||||
original = copy.deepcopy(lane)
|
||||
boards_api.update_lane(
|
||||
board, lane, new_lane.as_dict(omit_unset=True))
|
||||
updated = {
|
||||
"old": serialize_lane(original),
|
||||
"new": serialize_lane(new_lane)
|
||||
}
|
||||
|
||||
events_api.board_lanes_changed_event(board_id,
|
||||
request.current_user_id,
|
||||
updated=updated)
|
||||
|
||||
for lane in board_dict['lanes']:
|
||||
if lane.list_id not in existing_list_ids:
|
||||
lane.worklist = None
|
||||
boards_api.add_lane(board, lane.as_dict(omit_unset=True))
|
||||
events_api.board_lanes_changed_event(board_id,
|
||||
request.current_user_id,
|
||||
added=serialize_lane(lane))
|
||||
|
||||
board = boards_api.get(board_id)
|
||||
del board_dict['lanes']
|
||||
|
||||
|
||||
def post_timeline_events(original, updated):
|
||||
author_id = request.current_user_id
|
||||
|
||||
if original.title != updated.title:
|
||||
events_api.board_details_changed_event(
|
||||
original.id,
|
||||
author_id,
|
||||
'title',
|
||||
original.title,
|
||||
updated.title)
|
||||
|
||||
if original.description != updated.description:
|
||||
events_api.board_details_changed_event(
|
||||
original.id,
|
||||
author_id,
|
||||
'description',
|
||||
original.description,
|
||||
updated.description)
|
||||
|
||||
if original.private != updated.private:
|
||||
events_api.board_details_changed_event(
|
||||
original.id,
|
||||
author_id,
|
||||
'private',
|
||||
original.private,
|
||||
updated.private)
|
||||
|
||||
if original.archived != updated.archived:
|
||||
events_api.board_details_changed_event(
|
||||
original.id,
|
||||
author_id,
|
||||
'archived',
|
||||
original.archived,
|
||||
updated.archived)
|
||||
|
||||
|
||||
class PermissionsController(rest.RestController):
|
||||
"""Manages operations on board permissions."""
|
||||
|
||||
@ -91,9 +152,18 @@ class PermissionsController(rest.RestController):
|
||||
:param permission: The dict to use to create the permission.
|
||||
|
||||
"""
|
||||
if boards_api.editable(boards_api.get(board_id),
|
||||
request.current_user_id):
|
||||
return boards_api.create_permission(board_id)
|
||||
user_id = request.current_user_id
|
||||
if boards_api.editable(boards_api.get(board_id), user_id):
|
||||
created = boards_api.create_permission(board_id, permission)
|
||||
|
||||
users = [{user.id: user.full_name} for user in created.users]
|
||||
events_api.board_permission_created_event(board_id,
|
||||
user_id,
|
||||
created.id,
|
||||
created.codename,
|
||||
users)
|
||||
|
||||
return created
|
||||
else:
|
||||
raise exc.NotFound(_("Board %s not found") % board_id)
|
||||
|
||||
@ -108,9 +178,36 @@ class PermissionsController(rest.RestController):
|
||||
:param permission: The new contents of the permission.
|
||||
|
||||
"""
|
||||
if boards_api.editable(boards_api.get(board_id),
|
||||
request.current_user_id):
|
||||
return boards_api.update_permission(board_id, permission).codename
|
||||
user_id = request.current_user_id
|
||||
board = boards_api.get(board_id)
|
||||
|
||||
old = None
|
||||
for perm in board.permissions:
|
||||
if perm.codename == permission['codename']:
|
||||
old = perm
|
||||
|
||||
if old is None:
|
||||
raise exc.NotFound(_("Permission with codename %s not found")
|
||||
% permission['codename'])
|
||||
|
||||
old_users = {user.id: user.full_name for user in old.users}
|
||||
|
||||
if boards_api.editable(board, user_id):
|
||||
updated = boards_api.update_permission(board_id, permission)
|
||||
new_users = {user.id: user.full_name for user in updated.users}
|
||||
|
||||
added = [{id: name} for id, name in six.iteritems(new_users)
|
||||
if id not in old_users]
|
||||
removed = [{id: name} for id, name in six.iteritems(old_users)
|
||||
if id not in new_users]
|
||||
|
||||
if added or removed:
|
||||
events_api.board_permissions_changed_event(board.id,
|
||||
user_id,
|
||||
updated.id,
|
||||
updated.codename,
|
||||
added,
|
||||
removed)
|
||||
else:
|
||||
raise exc.NotFound(_("Board %s not found") % board_id)
|
||||
|
||||
@ -233,8 +330,15 @@ class BoardsController(rest.RestController):
|
||||
del board_dict['due_dates']
|
||||
|
||||
created_board = boards_api.create(board_dict)
|
||||
events_api.board_created_event(created_board.id,
|
||||
user_id,
|
||||
created_board.title,
|
||||
created_board.description)
|
||||
for lane in lanes:
|
||||
boards_api.add_lane(created_board, lane.as_dict())
|
||||
events_api.board_lanes_changed_event(created_board.id,
|
||||
user_id,
|
||||
added=serialize_lane(lane))
|
||||
|
||||
edit_permission = {
|
||||
'name': 'edit_board_%d' % created_board.id,
|
||||
@ -246,8 +350,22 @@ class BoardsController(rest.RestController):
|
||||
'codename': 'move_cards',
|
||||
'users': users
|
||||
}
|
||||
boards_api.create_permission(created_board.id, edit_permission)
|
||||
boards_api.create_permission(created_board.id, move_permission)
|
||||
edit = boards_api.create_permission(created_board.id, edit_permission)
|
||||
move = boards_api.create_permission(created_board.id, move_permission)
|
||||
event_owners = [{id: users_api.user_get(id).full_name}
|
||||
for id in owners]
|
||||
event_users = [{id: users_api.user_get(id).full_name}
|
||||
for id in users]
|
||||
events_api.board_permission_created_event(created_board.id,
|
||||
user_id,
|
||||
edit.id,
|
||||
edit.codename,
|
||||
event_owners)
|
||||
events_api.board_permission_created_event(created_board.id,
|
||||
user_id,
|
||||
move.id,
|
||||
move.codename,
|
||||
event_users)
|
||||
|
||||
return wmodels.Board.from_db_model(created_board)
|
||||
|
||||
@ -262,9 +380,15 @@ class BoardsController(rest.RestController):
|
||||
|
||||
"""
|
||||
user_id = request.current_user_id
|
||||
if not boards_api.editable(boards_api.get(id), user_id):
|
||||
original = boards_api.get(id)
|
||||
if not boards_api.editable(original, user_id):
|
||||
raise exc.NotFound(_("Board %s not found") % id)
|
||||
|
||||
# We use copy here because we only need to check changes
|
||||
# to the related objects, just the board's own attributes.
|
||||
# Also, deepcopy trips up on the lanes' backrefs.
|
||||
original = copy.copy(original)
|
||||
|
||||
board_dict = board.as_dict(omit_unset=True)
|
||||
update_lanes(board_dict, id)
|
||||
|
||||
@ -274,6 +398,8 @@ class BoardsController(rest.RestController):
|
||||
|
||||
updated_board = boards_api.update(id, board_dict)
|
||||
|
||||
post_timeline_events(original, updated_board)
|
||||
|
||||
if boards_api.visible(updated_board, user_id):
|
||||
board_model = wmodels.Board.from_db_model(updated_board)
|
||||
board_model.resolve_lanes(updated_board)
|
||||
@ -296,9 +422,21 @@ class BoardsController(rest.RestController):
|
||||
if not boards_api.editable(board, user_id):
|
||||
raise exc.NotFound(_("Board %s not found") % id)
|
||||
|
||||
boards_api.update(id, {"archived": True})
|
||||
# We use copy here because we only need to check changes
|
||||
# to the related objects, just the board's own attributes.
|
||||
# Also, deepcopy trips up on the lanes' backrefs.
|
||||
original = copy.copy(board)
|
||||
updated = boards_api.update(id, {"archived": True})
|
||||
|
||||
post_timeline_events(original, updated)
|
||||
|
||||
for lane in board.lanes:
|
||||
original = copy.deepcopy(worklists_api.get(lane.worklist.id))
|
||||
worklists_api.update(lane.worklist.id, {"archived": True})
|
||||
|
||||
if not original.archived:
|
||||
events_api.worklist_details_changed_event(
|
||||
lane.worklist.id, user_id, 'archived', original.archived,
|
||||
True)
|
||||
|
||||
permissions = PermissionsController()
|
||||
|
@ -13,12 +13,15 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from oslo_config import cfg
|
||||
from pecan import abort
|
||||
from pecan import request
|
||||
from pecan import response
|
||||
from pecan import rest
|
||||
from pecan.secure import secure
|
||||
import six
|
||||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
@ -28,6 +31,8 @@ from storyboard.common import decorators
|
||||
from storyboard.common import exception as exc
|
||||
from storyboard.db.api import stories as stories_api
|
||||
from storyboard.db.api import tasks as tasks_api
|
||||
from storyboard.db.api import timeline_events as events_api
|
||||
from storyboard.db.api import users as users_api
|
||||
from storyboard.db.api import worklists as worklists_api
|
||||
from storyboard.db import models
|
||||
from storyboard.openstack.common.gettextutils import _ # noqa
|
||||
@ -36,6 +41,58 @@ from storyboard.openstack.common.gettextutils import _ # noqa
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def serialize_filter(filter):
|
||||
serialized = {
|
||||
"id": filter.id,
|
||||
"type": filter.type,
|
||||
"criteria": []
|
||||
}
|
||||
for criterion in filter.criteria:
|
||||
serialized['criteria'].append({
|
||||
"title": criterion.title,
|
||||
"negative": criterion.negative,
|
||||
"value": criterion.value,
|
||||
"field": criterion.field
|
||||
})
|
||||
return serialized
|
||||
|
||||
|
||||
def post_timeline_events(original, updated):
|
||||
author_id = request.current_user_id
|
||||
|
||||
if original.title != updated.title:
|
||||
events_api.worklist_details_changed_event(
|
||||
original.id,
|
||||
author_id,
|
||||
'title',
|
||||
original.title,
|
||||
updated.title)
|
||||
|
||||
if original.private != updated.private:
|
||||
events_api.worklist_details_changed_event(
|
||||
original.id,
|
||||
author_id,
|
||||
'private',
|
||||
original.private,
|
||||
updated.private)
|
||||
|
||||
if original.automatic != updated.automatic:
|
||||
events_api.worklist_details_changed_event(
|
||||
original.id,
|
||||
author_id,
|
||||
'automatic',
|
||||
original.automatic,
|
||||
updated.automatic)
|
||||
|
||||
if original.archived != updated.archived:
|
||||
events_api.worklist_details_changed_event(
|
||||
original.id,
|
||||
author_id,
|
||||
'archived',
|
||||
original.archived,
|
||||
updated.archived)
|
||||
|
||||
|
||||
class PermissionsController(rest.RestController):
|
||||
"""Manages operations on worklist permissions."""
|
||||
|
||||
@ -75,9 +132,18 @@ class PermissionsController(rest.RestController):
|
||||
:param permission: The dict to use to create the permission.
|
||||
|
||||
"""
|
||||
if worklists_api.editable(worklists_api.get(worklist_id),
|
||||
request.current_user_id):
|
||||
return worklists_api.create_permission(worklist_id)
|
||||
user_id = request.current_user_id
|
||||
if worklists_api.editable(worklists_api.get(worklist_id), user_id):
|
||||
created = worklists_api.create_permission(worklist_id, permission)
|
||||
|
||||
users = [{user.id: user.full_name} for user in created.users]
|
||||
events_api.worklist_permission_created_event(worklist_id,
|
||||
user_id,
|
||||
created.id,
|
||||
created.codename,
|
||||
users)
|
||||
|
||||
return created.codename
|
||||
else:
|
||||
raise exc.NotFound(_("Worklist %s not found") % worklist_id)
|
||||
|
||||
@ -92,14 +158,58 @@ class PermissionsController(rest.RestController):
|
||||
|
||||
TODO
|
||||
|
||||
This takes a dict in the form::
|
||||
|
||||
{
|
||||
"codename": "my-permission",
|
||||
"users": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
}
|
||||
|
||||
The given codename must match an existing permission's
|
||||
codename.
|
||||
|
||||
:param worklist_id: The ID of the worklist.
|
||||
:param permission: The new contents of the permission.
|
||||
|
||||
"""
|
||||
if worklists_api.editable(worklists_api.get(worklist_id),
|
||||
request.current_user_id):
|
||||
return worklists_api.update_permission(
|
||||
worklist_id, permission).codename
|
||||
user_id = request.current_user_id
|
||||
worklist = worklists_api.get(worklist_id)
|
||||
|
||||
old = None
|
||||
for perm in worklist.permissions:
|
||||
if perm.codename == permission['codename']:
|
||||
old = perm
|
||||
|
||||
if old is None:
|
||||
raise exc.NotFound(_("Permission with codename %s not found")
|
||||
% permission['codename'])
|
||||
|
||||
old_users = {user.id: user.full_name for user in old.users}
|
||||
|
||||
if worklists_api.editable(worklist, user_id):
|
||||
updated = worklists_api.update_permission(
|
||||
worklist_id, permission)
|
||||
new_users = {user.id: user.full_name for user in updated.users}
|
||||
|
||||
added = [{id: name} for id, name in six.iteritems(new_users)
|
||||
if id not in old_users]
|
||||
removed = [{id: name} for id, name in six.iteritems(old_users)
|
||||
if id not in new_users]
|
||||
|
||||
if added or removed:
|
||||
events_api.worklist_permissions_changed_event(
|
||||
worklist_id,
|
||||
user_id,
|
||||
updated.id,
|
||||
updated.codename,
|
||||
added,
|
||||
removed)
|
||||
return updated.codename
|
||||
|
||||
else:
|
||||
raise exc.NotFound(_("Worklist %s not found") % worklist_id)
|
||||
|
||||
@ -179,6 +289,12 @@ class FilterSubcontroller(rest.RestController):
|
||||
raise exc.NotFound(_("Worklist %s not found") % worklist_id)
|
||||
|
||||
created = worklists_api.create_filter(worklist_id, filter.as_dict())
|
||||
|
||||
added = serialize_filter(created)
|
||||
events_api.worklist_filters_changed_event(worklist_id,
|
||||
user_id,
|
||||
added=added)
|
||||
|
||||
model = wmodels.WorklistFilter.from_db_model(created)
|
||||
model.resolve_criteria(created)
|
||||
return model
|
||||
@ -204,10 +320,23 @@ class FilterSubcontroller(rest.RestController):
|
||||
if not worklists_api.editable(worklist, user_id):
|
||||
raise exc.NotFound(_("Worklist %s not found") % worklist_id)
|
||||
|
||||
old = serialize_filter(worklists_api.get_filter(filter_id))
|
||||
|
||||
update_dict = filter.as_dict(omit_unset=True)
|
||||
updated = worklists_api.update_filter(filter_id, update_dict)
|
||||
|
||||
return wmodels.WorklistFilter.from_db_model(updated)
|
||||
changes = {
|
||||
"old": old,
|
||||
"new": serialize_filter(updated)
|
||||
}
|
||||
events_api.worklist_filters_changed_event(worklist_id,
|
||||
user_id,
|
||||
updated=changes)
|
||||
|
||||
updated_model = wmodels.WorklistFilter.from_db_model(updated)
|
||||
updated_model.resolve_criteria(updated)
|
||||
|
||||
return updated_model
|
||||
|
||||
@decorators.db_exceptions
|
||||
@secure(checks.authenticated)
|
||||
@ -228,6 +357,12 @@ class FilterSubcontroller(rest.RestController):
|
||||
if not worklists_api.editable(worklist, user_id):
|
||||
raise exc.NotFound(_("Worklist %s not found") % worklist_id)
|
||||
|
||||
filter = serialize_filter(worklists_api.get_filter(filter_id))
|
||||
|
||||
events_api.worklist_filters_changed_event(worklist_id,
|
||||
user_id,
|
||||
removed=filter)
|
||||
|
||||
worklists_api.delete_filter(filter_id)
|
||||
|
||||
|
||||
@ -303,6 +438,16 @@ class ItemsSubcontroller(rest.RestController):
|
||||
id, item_id, item_type, list_position,
|
||||
current_user=request.current_user_id)
|
||||
|
||||
added = {
|
||||
"worklist_id": id,
|
||||
"item_id": item_id,
|
||||
"item_title": item.title,
|
||||
"item_type": item_type,
|
||||
"position": list_position
|
||||
}
|
||||
|
||||
events_api.worklist_contents_changed_event(id, user_id, added=added)
|
||||
|
||||
return wmodels.WorklistItem.from_db_model(
|
||||
worklists_api.get_item_at_position(id, list_position))
|
||||
|
||||
@ -346,6 +491,26 @@ class ItemsSubcontroller(rest.RestController):
|
||||
raise exc.NotFound(_("Item %s refers to a non-existent task or "
|
||||
"story.") % item_id)
|
||||
|
||||
old = {
|
||||
"worklist_id": card.list_id,
|
||||
"item_id": card.item_id,
|
||||
"item_title": item.title,
|
||||
"item_type": card.item_type,
|
||||
"position": card.list_position,
|
||||
"due_date_id": card.display_due_date
|
||||
}
|
||||
|
||||
new = {
|
||||
"item_id": card.item_id,
|
||||
"item_title": item.title,
|
||||
"item_type": card.item_type
|
||||
}
|
||||
|
||||
if list_position != card.list_position and list_position is not None:
|
||||
new['position'] = list_position
|
||||
if list_id != card.list_id and list_id is not None:
|
||||
new['worklist_id'] = list_id
|
||||
|
||||
worklists_api.move_item(id, item_id, list_position, list_id)
|
||||
|
||||
if display_due_date is not None:
|
||||
@ -355,6 +520,15 @@ class ItemsSubcontroller(rest.RestController):
|
||||
'display_due_date': display_due_date
|
||||
}
|
||||
worklists_api.update_item(item_id, update_dict)
|
||||
new['due_date_id'] = display_due_date
|
||||
|
||||
updated = {
|
||||
"old": old,
|
||||
"new": new
|
||||
}
|
||||
events_api.worklist_contents_changed_event(id,
|
||||
user_id,
|
||||
updated=updated)
|
||||
|
||||
updated = worklists_api.get_item_by_id(item_id)
|
||||
result = wmodels.WorklistItem.from_db_model(updated)
|
||||
@ -379,13 +553,32 @@ class ItemsSubcontroller(rest.RestController):
|
||||
worklist = worklists_api.get(id)
|
||||
if not worklists_api.editable_contents(worklist, user_id):
|
||||
raise exc.NotFound(_("Worklist %s not found") % id)
|
||||
item = worklists_api.get_item_by_id(item_id)
|
||||
if item is None:
|
||||
card = worklists_api.get_item_by_id(item_id)
|
||||
if card is None:
|
||||
raise exc.NotFound(_("Item %s seems to have already been deleted,"
|
||||
" try refreshing your page.") % item_id)
|
||||
worklists_api.update_item(item_id, {'archived': True})
|
||||
worklists_api.normalize_positions(worklist)
|
||||
|
||||
item = None
|
||||
if card.item_type == 'story':
|
||||
item = stories_api.story_get(
|
||||
card.item_id, current_user=user_id)
|
||||
elif card.item_type == 'task':
|
||||
item = tasks_api.task_get(
|
||||
card.item_id, current_user=user_id)
|
||||
if item is None:
|
||||
item.title = ''
|
||||
|
||||
removed = {
|
||||
"worklist_id": id,
|
||||
"item_id": card.item_id,
|
||||
"item_title": item.title
|
||||
}
|
||||
events_api.worklist_contents_changed_event(id,
|
||||
user_id,
|
||||
removed=removed)
|
||||
|
||||
|
||||
class WorklistsController(rest.RestController):
|
||||
"""Manages operations on worklists."""
|
||||
@ -553,6 +746,9 @@ class WorklistsController(rest.RestController):
|
||||
users = []
|
||||
|
||||
created_worklist = worklists_api.create(worklist_dict)
|
||||
events_api.worklist_created_event(created_worklist.id,
|
||||
user_id,
|
||||
created_worklist.title)
|
||||
|
||||
edit_permission = {
|
||||
'name': 'edit_worklist_%d' % created_worklist.id,
|
||||
@ -564,13 +760,35 @@ class WorklistsController(rest.RestController):
|
||||
'codename': 'move_items',
|
||||
'users': users
|
||||
}
|
||||
worklists_api.create_permission(created_worklist.id, edit_permission)
|
||||
worklists_api.create_permission(created_worklist.id, move_permission)
|
||||
edit = worklists_api.create_permission(
|
||||
created_worklist.id, edit_permission)
|
||||
move = worklists_api.create_permission(
|
||||
created_worklist.id, move_permission)
|
||||
|
||||
event_owners = [{id: users_api.user_get(id).full_name}
|
||||
for id in owners]
|
||||
event_users = [{id: users_api.user_get(id).full_name}
|
||||
for id in users]
|
||||
|
||||
events_api.worklist_permission_created_event(created_worklist.id,
|
||||
user_id,
|
||||
edit.id,
|
||||
edit.codename,
|
||||
event_owners)
|
||||
events_api.worklist_permission_created_event(created_worklist.id,
|
||||
user_id,
|
||||
move.id,
|
||||
move.codename,
|
||||
event_users)
|
||||
|
||||
if worklist_dict['automatic']:
|
||||
for filter in filters:
|
||||
worklists_api.create_filter(created_worklist.id,
|
||||
filter.as_dict())
|
||||
created_filter = worklists_api.create_filter(
|
||||
created_worklist.id, filter.as_dict())
|
||||
added = serialize_filter(created_filter)
|
||||
events_api.worklist_filters_changed_event(created_worklist.id,
|
||||
user_id,
|
||||
added=added)
|
||||
|
||||
return wmodels.Worklist.from_db_model(created_worklist)
|
||||
|
||||
@ -602,8 +820,10 @@ class WorklistsController(rest.RestController):
|
||||
|
||||
worklist_dict = worklist.as_dict(omit_unset=True)
|
||||
|
||||
original = copy.deepcopy(worklists_api.get(id))
|
||||
updated_worklist = worklists_api.update(id, worklist_dict)
|
||||
|
||||
post_timeline_events(original, updated_worklist)
|
||||
if worklists_api.visible(updated_worklist, user_id):
|
||||
worklist_model = wmodels.Worklist.from_db_model(updated_worklist)
|
||||
worklist_model.resolve_items(updated_worklist)
|
||||
@ -630,11 +850,14 @@ class WorklistsController(rest.RestController):
|
||||
|
||||
"""
|
||||
worklist = worklists_api.get(worklist_id)
|
||||
original = copy.deepcopy(worklist)
|
||||
user_id = request.current_user_id
|
||||
if not worklists_api.editable(worklist, user_id):
|
||||
raise exc.NotFound(_("Worklist %s not found") % worklist_id)
|
||||
|
||||
worklists_api.update(worklist_id, {"archived": True})
|
||||
updated = worklists_api.update(worklist_id, {"archived": True})
|
||||
|
||||
post_timeline_events(original, updated)
|
||||
|
||||
items = ItemsSubcontroller()
|
||||
permissions = PermissionsController()
|
||||
|
@ -1,4 +1,5 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
# Copyright (c) 2016 Codethink Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -32,6 +33,27 @@ TASK_PRIORITY_CHANGED = "task_priority_changed"
|
||||
TASK_ASSIGNEE_CHANGED = "task_assignee_changed"
|
||||
TASK_DELETED = "task_deleted"
|
||||
|
||||
WORKLIST_CREATED = "worklist_created"
|
||||
# WORKLIST_DETAILS_CHANGED should occur when a value in any of the fields
|
||||
# in the `worklists` database table is changed. Changes in related tables
|
||||
# such as worklist_permissions, worklist_filters, and worklist_items have
|
||||
# their own event types.
|
||||
WORKLIST_DETAILS_CHANGED = "worklist_details_changed"
|
||||
WORKLIST_PERMISSION_CREATED = "worklist_permission_created"
|
||||
WORKLIST_PERMISSIONS_CHANGED = "worklist_permissions_changed"
|
||||
WORKLIST_FILTERS_CHANGED = "worklist_filters_changed"
|
||||
WORKLIST_CONTENTS_CHANGED = "worklist_contents_changed"
|
||||
|
||||
BOARD_CREATED = "board_created"
|
||||
# BOARD_DETAILS_CHANGED should occur when a value in any of the fields
|
||||
# in the `boards` database table is changed. Changes in related tables
|
||||
# such as board_permissions, and board_worklists have their own event
|
||||
# types.
|
||||
BOARD_DETAILS_CHANGED = "board_details_changed"
|
||||
BOARD_PERMISSION_CREATED = "board_permission_created"
|
||||
BOARD_PERMISSIONS_CHANGED = "board_permissions_changed"
|
||||
BOARD_LANES_CHANGED = "board_lanes_changed"
|
||||
|
||||
ALL = (
|
||||
STORY_CREATED,
|
||||
STORY_DETAILS_CHANGED,
|
||||
@ -43,5 +65,16 @@ ALL = (
|
||||
TASK_DETAILS_CHANGED,
|
||||
TASK_STATUS_CHANGED,
|
||||
TASK_PRIORITY_CHANGED,
|
||||
TASK_DELETED
|
||||
TASK_DELETED,
|
||||
WORKLIST_CREATED,
|
||||
WORKLIST_DETAILS_CHANGED,
|
||||
WORKLIST_PERMISSION_CREATED,
|
||||
WORKLIST_PERMISSIONS_CHANGED,
|
||||
WORKLIST_FILTERS_CHANGED,
|
||||
WORKLIST_CONTENTS_CHANGED,
|
||||
BOARD_CREATED,
|
||||
BOARD_DETAILS_CHANGED,
|
||||
BOARD_PERMISSION_CREATED,
|
||||
BOARD_PERMISSIONS_CHANGED,
|
||||
BOARD_LANES_CHANGED
|
||||
)
|
||||
|
@ -105,6 +105,8 @@ def subscription_get_all_subscriber_ids(resource, resource_id, session=None):
|
||||
resource_id,
|
||||
session=session)
|
||||
if event:
|
||||
if event.story_id is None:
|
||||
return set()
|
||||
resource = 'story'
|
||||
resource_id = event.story_id
|
||||
else:
|
||||
|
@ -1,4 +1,5 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
# Copyright (c) 2016 Codethink Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -222,3 +223,196 @@ def tags_deleted_event(story_id, author_id, story_title, tags):
|
||||
"event_type": event_types.TAGS_DELETED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def worklist_created_event(worklist_id, author_id, worklist_title):
|
||||
event_info = {
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"worklist_title": worklist_title
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.WORKLIST_CREATED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def worklist_details_changed_event(worklist_id, author_id, updated, old, new):
|
||||
event_info = {
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"field": updated,
|
||||
"old_value": old,
|
||||
"new_value": new
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.WORKLIST_DETAILS_CHANGED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def worklist_permission_created_event(worklist_id, author_id, permission_id,
|
||||
codename, users):
|
||||
event_info = {
|
||||
"worklist_id": worklist_id,
|
||||
"permission_id": permission_id,
|
||||
"author_id": author_id,
|
||||
"codename": codename,
|
||||
"users": users
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.WORKLIST_PERMISSION_CREATED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def worklist_permissions_changed_event(worklist_id, author_id, permission_id,
|
||||
codename, added=[], removed=[]):
|
||||
event_info = {
|
||||
"worklist_id": worklist_id,
|
||||
"permission_id": permission_id,
|
||||
"author_id": author_id,
|
||||
"codename": codename,
|
||||
"added": added,
|
||||
"removed": removed
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.WORKLIST_PERMISSIONS_CHANGED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def worklist_filters_changed_event(worklist_id, author_id, added=None,
|
||||
removed=None, updated=None):
|
||||
event_info = {
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"added": added,
|
||||
"removed": removed,
|
||||
"updated": updated
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.WORKLIST_FILTERS_CHANGED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def worklist_contents_changed_event(worklist_id, author_id, added=None,
|
||||
removed=None, updated=None):
|
||||
event_info = {
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"added": added,
|
||||
"removed": removed,
|
||||
"updated": updated
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"worklist_id": worklist_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.WORKLIST_CONTENTS_CHANGED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def board_created_event(board_id, author_id, board_title, board_description):
|
||||
event_info = {
|
||||
"board_id": board_id,
|
||||
"author_id": author_id,
|
||||
"board_title": board_title,
|
||||
"board_description": board_description
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"board_id": board_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.BOARD_CREATED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def board_details_changed_event(board_id, author_id, updated, old, new):
|
||||
event_info = {
|
||||
"board_id": board_id,
|
||||
"author_id": author_id,
|
||||
"field": updated,
|
||||
"old_value": old,
|
||||
"new_value": new
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"board_id": board_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.BOARD_DETAILS_CHANGED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def board_permission_created_event(board_id, author_id, permission_id,
|
||||
codename, users):
|
||||
event_info = {
|
||||
"board_id": board_id,
|
||||
"permission_id": permission_id,
|
||||
"author_id": author_id,
|
||||
"codename": codename,
|
||||
"users": users
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"board_id": board_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.BOARD_PERMISSION_CREATED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def board_permissions_changed_event(board_id, author_id, permission_id,
|
||||
codename, added=[], removed=[]):
|
||||
event_info = {
|
||||
"board_id": board_id,
|
||||
"permission_id": permission_id,
|
||||
"author_id": author_id,
|
||||
"codename": codename,
|
||||
"added": added,
|
||||
"removed": removed
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"board_id": board_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.BOARD_PERMISSIONS_CHANGED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
||||
|
||||
def board_lanes_changed_event(board_id, author_id, added=None, removed=None,
|
||||
updated=None):
|
||||
event_info = {
|
||||
"board_id": board_id,
|
||||
"author_id": author_id,
|
||||
"added": added,
|
||||
"removed": removed,
|
||||
"updated": updated
|
||||
}
|
||||
|
||||
return event_create({
|
||||
"board_id": board_id,
|
||||
"author_id": author_id,
|
||||
"event_type": event_types.BOARD_LANES_CHANGED,
|
||||
"event_info": json.dumps(event_info)
|
||||
})
|
||||
|
@ -553,6 +553,8 @@ def create_filter(worklist_id, filter_dict):
|
||||
criteria = filter_dict.pop('filter_criteria')
|
||||
filter_dict['list_id'] = worklist_id
|
||||
filter = api_base.entity_create(models.WorklistFilter, filter_dict)
|
||||
|
||||
# Create criteria for the filter
|
||||
filter = api_base.entity_get(models.WorklistFilter, filter.id)
|
||||
filter.criteria = []
|
||||
for criterion in criteria:
|
||||
@ -567,20 +569,23 @@ def create_filter(worklist_id, filter_dict):
|
||||
def update_filter(filter_id, update):
|
||||
old_filter = api_base.entity_get(models.WorklistFilter, filter_id)
|
||||
if 'filter_criteria' in update:
|
||||
new_ids = [criterion.id for criterion in update['filter_criteria']]
|
||||
# Change the criteria for this filter. If an ID is provided, change
|
||||
# the criterion to match the provided criterion. If no ID is provided,
|
||||
# create a new criterion and add it to the filter.
|
||||
for criterion in update['filter_criteria']:
|
||||
criterion_dict = criterion.as_dict(omit_unset=True)
|
||||
if 'id' in criterion_dict:
|
||||
existing = api_base.entity_get(models.FilterCriterion,
|
||||
criterion['id'])
|
||||
if existing.as_dict() != criterion_dict:
|
||||
api_base.entity_update(models.FilterCriterion,
|
||||
criterion_dict['id'],
|
||||
criterion_dict)
|
||||
id = criterion_dict.pop('id')
|
||||
api_base.entity_update(models.FilterCriterion,
|
||||
id, criterion_dict)
|
||||
else:
|
||||
created = api_base.entity_create(models.FilterCriterion,
|
||||
criterion_dict)
|
||||
criterion.id = created
|
||||
old_filter.criteria.append(created)
|
||||
|
||||
# Remove criteria which aren't in the provided set
|
||||
new_ids = [criterion.id for criterion in update['filter_criteria']]
|
||||
for criterion in old_filter.criteria:
|
||||
if criterion.id not in new_ids:
|
||||
old_filter.criteria.remove(criterion)
|
||||
|
@ -51,9 +51,11 @@ class Subscription(WorkerTaskBase):
|
||||
if resource == 'timeline_event':
|
||||
event = db_api.entity_get(models.TimeLineEvent, resource_id,
|
||||
session=session)
|
||||
subscribers = sub_api.subscription_get_all_subscriber_ids(
|
||||
'story', event.story_id, session=session)
|
||||
self.handle_timeline_events(session, event, author, subscribers)
|
||||
if event.story_id is not None:
|
||||
subscribers = sub_api.subscription_get_all_subscriber_ids(
|
||||
'story', event.story_id, session=session)
|
||||
self.handle_timeline_events(
|
||||
session, event, author, subscribers)
|
||||
|
||||
elif resource == 'project_group':
|
||||
subscribers = sub_api.subscription_get_all_subscriber_ids(
|
||||
|
Loading…
x
Reference in New Issue
Block a user