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)
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