Пример #1
0
def taskEditPost(handler, ids, p_hours, p_status, p_goal, p_assigned=[], p_include={}):
    handler.title("Edit tasks")
    requirePriv(handler, "Write")

    allIDs = map(int, uniq(ids.split(",")))
    ids = map(lambda i: to_int(i, "include", ErrorBox.die), p_include.keys())
    if not set(ids) <= set(allIDs):
        ErrorBox.die("Included tasks don't match query arguments")

    tasks = dict((id, Task.load(id)) for id in ids)
    if not all(tasks.values()):
        ids = [str(id) for (id, task) in tasks.iteritems() if not task]
        ErrorBox.die(
            "No %s with %s %s"
            % ("task" if len(ids) == 1 else "tasks", "ID" if len(ids) == 1 else "IDs", ", ".join(ids))
        )
    tasks = [tasks[id] for id in ids]
    if len(set(task.sprint for task in tasks)) > 1:
        ErrorBox.die("All tasks must be in the same sprint")
    sprint = (tasks[0] if len(tasks) > 0 else Task.load(allIDs[0])).sprint
    if sprint.isHidden(handler.session["user"]):
        ErrorBox.die(
            "No %s with %s %s"
            % ("task" if len(ids) == 1 else "tasks", "ID" if len(ids) == 1 else "IDs", ", ".join(ids))
        )
    if not sprint.canEdit(handler.session["user"]):
        ErrorBox.die("You don't have permission to modify this sprint")

    assignedids = set(to_int(i, "assigned", ErrorBox.die) for i in p_assigned)

    changes = {
        "assigned": False if assignedids == set() else {User.load(assignedid) for assignedid in assignedids},
        "hours": False if p_hours == "" else int(p_hours),
        "status": False if p_status == "" else p_status,
        "goal": False if p_goal == "" else Goal.load(int(p_goal)),
    }

    if changes["assigned"] and not all(changes["assigned"]):
        ErrorBox.die("Invalid assignee")
    if changes["assigned"] and not set(changes["assigned"]).issubset(sprint.members):
        ErrorBox.die("Unable to assign tasks to non-sprint members")
    if changes["goal"] and changes["goal"].sprint != sprint:
        ErrorBox.die("Unable to set goal to a goal outside the sprint")

    changed = set()
    for task in tasks:
        for field, value in changes.iteritems():
            if value is not False and getattr(task, field) != value:
                setattr(task, field, value)
                changed.add(task)
                Event.taskUpdate(handler, task, field, value)

    if len(changed) == 0:
        delay(handler, WarningBox("No changes necessary", close=3, fixed=True))
    else:
        for task in changed:
            task.saveRevision(handler.session["user"])
        delay(handler, SuccessBox("Updated %d %s" % (len(changed), "task" if len(changed) == 1 else "tasks")))
    redirect("/sprints/%d" % sprint.id)
Пример #2
0
def sprintPost(handler, sprintid, p_id, p_rev_id, p_field, p_value):
	def die(msg):
		print msg
		done()

	handler.wrappers = False
	sprintid = to_int(sprintid, 'sprintid', die)
	p_id = to_int(p_id, 'id', die)
	p_rev_id = to_int(p_rev_id, 'rev_id', die)

	if not handler.session['user']:
		die("You must be logged in to modify tasks")

	sprint = Sprint.load(sprintid)
	if not sprint or sprint.isHidden(handler.session['user']):
		die("There is no sprint with ID %d" % sprintid)
	elif not (sprint.isActive() or sprint.isPlanning()):
		die("Unable to modify inactive sprint")
	elif not sprint.canEdit(handler.session['user']):
		die("You don't have permission to modify this sprint")

	# Special case group moves; p_id is the group ID, not task
	task = None
	if p_field != 'groupmove':
		task = Task.load(p_id)
		if not task:
			die("Task %d does not exist" % p_id)
		if task.sprint != sprint:
			die("Attempting to modify task outside the specified sprint")
		if task.revision != p_rev_id: #TODO Implement collision support
			die("Collision with %s detected. Changes not saved" % task.creator)

	if p_value.strip() == '':
		die("Value cannot be empty")

	if p_field in ['status', 'name', 'goal', 'assigned', 'hours', 'deleted']:
		for case in switch(p_field):
			if case('status') or case('name'):
				parsedValue = p_value
				break
			elif case('goal'):
				parsedValue = None
				if p_value != '0':
					parsedValue = Goal.load(to_int(p_value, 'goal', die))
					if not parsedValue:
						die("Unknown goal: <b>%s</b>" % stripTags(p_value))
					if parsedValue.sprint != sprint:
						die("Attempting to use goal outside the specified sprint")
				break
			elif case('assigned'):
				parsedValue = set(User.load(username = username) for username in p_value.split(' '))
				if not all(parsedValue):
					die("Unknown user(s): <b>%s</b>" % stripTags(p_value))
				break
			elif case('hours'):
				parsedValue = int(p_value)
				break
			elif case('deleted'):
				parsedValue = True if p_value == 'true' else False if p_value == 'false' else die("Bad value for field 'deleted'")
				break

		if task.__getattribute__(p_field) != parsedValue: # Only save if the field has changed
			task.__setattr__(p_field, parsedValue)

			# Is this within the 5-minute window, by the same user?
			# If we're in pre-planning, the task's timestamp will be in the future, so (ts - task.timestamp) will be negative, which satisfies the check
			if task.creator == handler.session['user'] and (dateToTs(getNow()) - task.timestamp) < 5*60:
				task.save()
			else:
				task.saveRevision(handler.session['user'])

			Event.taskUpdate(handler, task, p_field, parsedValue)

	elif p_field == 'taskmove':
		if ':' not in p_value:
			die("Malformed value")
		newGroupID, newSeq = map(lambda i: to_int(i, 'value', die), p_value.split(':', 1))
		newGroup = Group.load(newGroupID)
		if not newGroup:
			die("No group with ID %d" % newGroupID)
		maxSeq = len(Task.loadAll(groupid = newGroup.id))
		if task.group != newGroup:
			maxSeq += 1
		if not 1 <= newSeq <= maxSeq:
			die("Bad sequence number")

		task.move(newSeq, newGroup)

	elif p_field == 'groupmove':
		group = Group.load(p_id)
		if not group:
			die("Group %d does not exist" % p_id)
		if group.sprint != sprint:
			die("Attempting to modify group outside the specified sprint")

		newSeq = to_int(p_value, 'value', die)
		if not 1 <= newSeq <= len(sprint.getGroups()):
			die("Bad sequence number")

		group.move(newSeq)

	else:
		die("Unexpected field name: %s" % stripTags(p_field))

	handler.responseCode = 299
	if task is not None:
		print task.revision
Пример #3
0
def distributeUpdate(handler, p_sprint, p_targetUser=None, p_task=None):
    def die(msg):
        print toJS({"error": msg})
        done()

    handler.title("Distribute Tasks")
    requirePriv(handler, "Write")
    handler.wrappers = False
    handler.contentType = "application/json"

    sprintid = int(p_sprint)
    sprint = Sprint.load(sprintid)
    if not sprint or sprint.isHidden(handler.session["user"]):
        die("No sprint with ID %d" % sprintid)
    if not sprint.canEdit(handler.session["user"]):
        die("Unable to edit sprint")

        # Make changes
    if p_targetUser != None and p_task != None:
        task = Task.load(int(p_task))
        if not task:
            die("Invalid task ID")

        if p_targetUser == "deferred":
            task.status = "deferred"
            task.hours = 0
            if task.creator == handler.session["user"] and (dateToTs(getNow()) - task.timestamp) < 5 * 60:
                task.save()
            else:
                task.saveRevision(handler.session["user"])
            Event.taskUpdate(handler, task, "status", task.status)
        else:
            userid = to_int(p_targetUser, "targetUser", die)
            user = User.load(userid)
            if not user:
                die("No user with ID %d" % userid)

            task.assigned = {user}
            if task.creator == handler.session["user"] and (dateToTs(getNow()) - task.timestamp) < 5 * 60:
                task.save()
            else:
                task.saveRevision(handler.session["user"])
            Event.taskUpdate(handler, task, "assigned", task.assigned)

    def makeTaskMap(task):
        return {
            "id": task.id,
            "groupid": task.group.id,
            "hours": task.hours,
            "name": task.name,
            "important": task.hours > 8,
            "team": len(task.assigned) > 1,
        }

        # Return current info

    tasks = filter(lambda task: task.stillOpen(), sprint.getTasks())
    avail = Availability(sprint)

    deferredTasks = filter(lambda task: task.status == "deferred", sprint.getTasks())
    m = {
        "deferred": {
            "username": "******",
            "groups": [
                {"id": group.id, "name": group.name}
                for group in sorted(
                    (group for group in set(task.group for task in deferredTasks)), key=lambda group: group.seq
                )
            ],
            "tasks": [makeTaskMap(task) for task in deferredTasks],
        }
    }

    for user in sprint.members:
        userTasks = filter(lambda task: user in task.assigned, tasks)
        m[user.id] = {
            "username": user.username,
            "hours": sum(task.hours for task in userTasks),
            "availability": avail.getAllForward(getNow().date(), user),
            "groups": [
                {"id": group.id, "name": group.name}
                for group in sorted(
                    (group for group in set(task.group for task in userTasks)), key=lambda group: group.seq
                )
            ],
            "tasks": [makeTaskMap(task) for task in userTasks],
        }

    print toJS(m)