Beispiel #1
0
def newGroupPost(handler, p_group, p_name):
	def die(msg):
		print msg
		done()

	handler.title('New Group')
	requirePriv(handler, 'User')
	handler.wrappers = False

	predid = to_int(p_group, 'group', die)
	pred = Group.load(predid)
	if not pred:
		die("No group with ID <b>%d</b>" % predid)
	elif p_name.strip() == '':
		die("Group must have a non-empty name")

	group = Group(pred.sprint.id, p_name, pred.seq + 1)
	group.save()

	handler.responseCode = 299
	delay(handler, """
<script type=\"text/javascript\">
$(document).ready(function() {
	$('#group%d').effect('highlight', {}, 3000);
});
</script>""" % group.id)
	print "/sprints/%d#group%d" % (group.sprint.id, group.id)
	Event.newGroup(handler, group)
Beispiel #2
0
def newTaskMany(handler, group, p_body, dryrun=False):
    def die(msg):
        print msg
        done()

    handler.wrappers = False
    requirePriv(handler, "User")
    id = int(group)

    defaultGroup = Group.load(id)
    if not defaultGroup or defaultGroup.sprint.isHidden(handler.session["user"]):
        die("No group with ID <b>%d</b>" % id)

    sprint = defaultGroup.sprint
    if 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")

    group = defaultGroup
    groups = [group]
    newGroups = []
    tasks = {group: []}
    sep = "|"
    lines = map(lambda x: x.strip(" \r\n"), p_body.split("\n"))
    errors = []
    defaultAssigned = {handler.session["user"] if handler.session["user"] in sprint.members else sprint.owner}

    for line in lines:
        if line == "":
            group = defaultGroup
        elif line[0] == "#":  # Comment
            continue
        elif len(line) == 1:  # Separator
            sep = line[0]
        elif (
            line[0] == "[" and line[-1] == "]" and set(line[1:-1].split(" ")) <= set(u.username for u in sprint.members)
        ):  # Default assigned
            defaultAssigned = {User.load(username=username) for username in line[1:-1].split(" ")}
        elif line[-1] == ":":  # Group
            line = line[:-1]
            group = Group.load(sprintid=sprint.id, name=line)
            if not group:  # Check if new group already defined
                for newGroup in newGroups:
                    if newGroup.name == line:
                        group = newGroup
                        break
            if not group:  # Make new group
                group = Group(sprint.id, line)
                newGroups.append(group)
                group.id = -len(newGroups)
            if not group in groups:  # First time this group has been used in the script
                groups.append(group)
                tasks[group] = []
        else:
            parts = line.split(sep)
            name, assigned, status, hours = None, None, None, None
            if not 2 <= len(parts) <= 4:
                errors.append("Unable to parse (field count mismatch): %s" % stripTags(line))
                continue
            for part in parts:
                part = part.strip()
                if part == "":
                    errors.append("Unable to parse (empty field): %s" % stripTags(line))
                    continue

                    # Hours
                if hours is None:
                    try:
                        hours = int(part)
                        continue
                    except ValueError:
                        pass

                    # Status
                if status is None and part.lower() in statuses:
                    status = part.lower()
                    continue

                    # Assigned
                if assigned is None and set(part.split(" ")) <= set(u.username for u in sprint.members):
                    assigned = set(User.load(username=username) for username in part.split(" "))
                    continue

                    # Name
                if name is None:
                    name = part
                    continue

                errors.append("Unable to parse (no field match on '%s'): %s" % (stripTags(part), stripTags(line)))

            if assigned is None:
                assigned = defaultAssigned
            if status is None:
                status = "not started"
            if name is None or hours is None:
                errors.append("Unable to parse (missing required fields): %s" % stripTags(line))
            if not any(v is None for v in (name, assigned, status, hours)):
                tasks[group].append((name, assigned, status, hours))

    if dryrun:
        handler.log = False
        numTasks = sum(len(taskSet) for taskSet in tasks.values())
        taskHours = sum(
            hours for taskSet in tasks.values() for name, assigned, status, hours in taskSet if status != "deferred"
        )
        ownTaskHours = sum(
            hours
            for taskSet in tasks.values()
            for name, assigned, status, hours in taskSet
            if status != "deferred" and handler.session["user"] in assigned
        )
        avail = Availability(sprint)
        availHours = avail.getAllForward(getNow().date(), handler.session["user"])
        usedHours = sum(task.effectiveHours() for task in sprint.getTasks() if handler.session["user"] in task.assigned)
        availHours -= usedHours
        if errors:
            print ErrorBox("<br>".join(errors))
        if numTasks:
            box = InfoBox
            stats = "Adding %s " % pluralize(numTasks, "task", "tasks")
            if newGroups:
                stats += "and %s " % pluralize(len(newGroups), "group", "groups")
            stats += "for a total of %s" % pluralize(taskHours, "hour", "hours")
            if ownTaskHours != taskHours:
                stats += ", %s yours" % pluralize(ownTaskHours, "hour", "hours")
            if ownTaskHours:
                if availHours == 0:
                    stats += ". You have no future availability for these tasks"
                    box = WarningBox
                elif availHours < 0:
                    stats += ". You are already overcommitted by %s" % pluralize(-availHours, "hour", "hours")
                    box = WarningBox
                else:
                    stats += ", %d%% of your future availability" % (100 * ownTaskHours / availHours)
                    box = WarningBox if ownTaskHours > availHours else InfoBox
            print box(stats)
        elif not errors:
            print InfoBox('Waiting for tasks. Click "Help" above if needed')

        groupedTasks = OrderedDict(
            (
                group,
                [
                    Task(
                        group.id,
                        sprint.id,
                        handler.session["user"].id,
                        0,
                        name,
                        status,
                        hours,
                        {user.id for user in assigned},
                        1,
                        id=0,
                    )
                    for name, assigned, status, hours in tasks[group]
                ],
            )
            for group in groups
        )
        print TaskTable(sprint, False, tasks=groupedTasks, status=True, name=True, assigned=True, hours=True)

    elif errors:
        die("There are unparseable lines in the task script. See the preview for more information")
    else:
        # There's some weirdness in the way groups auto-sequence that breaks when multiple groups are made without saving
        seq = maxOr(group.seq for group in sprint.getGroups()) + 1
        for group in newGroups:
            group.seq = seq
            seq += 1

        for group in groups:
            # Changing a group's ID will change its hash, so this pulls from tasks before saving the group in case it's new
            groupTasks = tasks[group]
            if group in newGroups:
                group.id = 0
            group.save()
            for name, assigned, status, hours in groupTasks:
                task = Task(group.id, group.sprint.id, handler.session["user"].id, 0, name, status, hours)
                task.assigned |= assigned
                task.save()
                Event.newTask(handler, task)

        numGroups = len(newGroups)
        numTasks = sum(map(lambda g: len(g), tasks.values()))
        if numGroups > 0 and numGroups > 0:
            delay(
                handler,
                SuccessBox(
                    "Added %d %s, %d %s"
                    % (
                        numGroups,
                        "group" if numGroups == 1 else "groups",
                        numTasks,
                        "task" if numTasks == 1 else "tasks",
                    ),
                    close=3,
                    fixed=True,
                ),
            )
        elif numGroups > 0:
            delay(
                handler,
                SuccessBox("Added %d %s" % (numGroups, "group" if numGroups == 1 else "groups"), close=3, fixed=True),
            )
        elif numTasks > 0:
            delay(
                handler,
                SuccessBox("Added %d %s" % (numTasks, "task" if numTasks == 1 else "tasks"), close=3, fixed=True),
            )
        else:
            delay(handler, WarningBox("No changes", close=3, fixed=True))
        handler.responseCode = 299