Пример #1
0
def newTaskPost(handler, p_group, p_name, p_goal, p_status, p_hours, p_assigned=[]):
    def die(msg):
        print msg
        done()

    requirePriv(handler, "User")
    handler.wrappers = False

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

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

    if p_name.strip() == "":
        die("Task must have a non-empty name")

    assignedids = set(to_int(i, "assigned", die) for i in p_assigned)
    assigned = set(User.load(assignedid) for assignedid in assignedids)
    if assigned == set():
        assigned.add(handler.session["user"] if handler.session["user"] in sprint.members else sprint.owner)
    if not all(assigned):
        die("Invalid assignee")

    goalid = to_int(p_goal, "goal", die)
    if goalid != 0:
        goal = Goal.load(goalid)
        if not goal:
            die("No goal with ID <b>%d</b>" % goalid)
        if goal.sprint != group.sprint:
            die("Goal does not belong to the correct sprint")

    hours = to_int(p_hours, "hours", die)

    task = Task(groupid, group.sprintid, handler.session["user"].id, goalid, p_name, p_status, hours)
    task.assigned |= assigned
    task.save()

    handler.responseCode = 299
    delay(
        handler,
        """
<script type=\"text/javascript\">
$(document).ready(function() {
	$('#task%d').effect('highlight', {}, 3000);
});
</script>"""
        % task.id,
    )
    delay(handler, SuccessBox("Added task <b>%s</b>" % task.safe.name, close=3, fixed=True))
    Event.newTask(handler, task)
Пример #2
0
def newTaskImportPost(handler, group, source, p_data):
    def die(msg):
        print msg
        done()

    handler.title("Import Tasks")
    requirePriv(handler, "User")
    handler.wrappers = False

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

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

    id = int(source)
    source = Sprint.load(id)
    if not source:
        die("No sprint with ID <b>%d</b>" % id)

    try:
        data = fromJS(p_data)
    except ValueError:
        die("Improperly encoded data")
    if not isinstance(data, list) or not all(
        set(task.keys()) == {"name", "assigned", "status", "groupid", "hours"} for task in data
    ):
        die("Improperly encoded data")
    usernames = {user.username for user in sprint.members}
    if not all(
        set(task["assigned"].split(" ")) <= usernames
        and task["status"] in statuses
        and isinstance(task["groupid"], int)
        and Group.load(task["groupid"]) is not None
        and isinstance(task["hours"], int)
        and task["hours"] >= 0
        for task in data
    ):
        die("Invalid data")

    dataByGroup = {}
    for task in data:
        if task["groupid"] not in dataByGroup:
            dataByGroup[task["groupid"]] = []
        dataByGroup[task["groupid"]].append(task)

    newGroups = {}  # old sprint's group ID -> new sprint's new Group object
    for groupid in dataByGroup:
        oldGroup = Group.load(groupid)
        group = Group.load(sprintid=sprint.id, name=oldGroup.name)
        if not group:  # No group in this sprint with the right name
            if groupid in newGroups:  # Already made a new group
                group = newGroups[groupid]
            else:  # Need a new group
                group = newGroups[groupid] = Group(sprint.id, oldGroup.name)
                group.save()

        for taskData in dataByGroup[groupid]:
            task = Task(
                group.id,
                sprint.id,
                handler.session["user"].id,
                0,
                taskData["name"],
                taskData["status"],
                taskData["hours"],
                {User.load(username=username).id for username in taskData["assigned"].split(" ")},
            )
            task.save()
            Event.newTask(handler, task)

    numGroups, numTasks = len(newGroups), len(data)
    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
Пример #3
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