def Sistema(): u = Usuario("Eduardo") u.boasVindas() g1 = Guest("Caio") g1.boasVindas() g1.descreve() g1.despedida() r1 = Regular("Felipe") r1.boasVindas() r1.dashboard() r1.descreve() r1.despedida() g2 = Group("Grupo Python") g2.boasVindas() g2.descreve() g2.groupBoard() g2.despedida() r2 = Root("root") r2.boasVindas() r2.descreve() r2.excluirTodos() r2.despedida()
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 add_group(user_id): if not r_server.zscore('user:set', user_id): return make_response('That user does not exist', 404) data = request.get_json(silent=False) if not data.get('name'): return make_response('\'name\' required.', 400) group = Group(data['name']) group.from_json(data) millis = int(round(time.time() * 1000)) if not r_server.zscore('group:%s:set' % user_id, group.name): r_server.zadd('group:%s:set' % user_id, group.name, millis) r_server.set('group:%s:%s' % (user_id, group.name), jsonpickle.encode(group)) return make_response("Group created.", 201, {'location': 'localhost:5000/%s/groups/%s' % (user_id, group.name)}) return make_response("That group already exist!", 400)
def testTwoGroups(self): group = Group(manager, name, position, imageFileName) group.addSingle({}) assert_equal(1, len(group.characters)) group2 = Group(manager, name, position, imageFileName) assert_equal(0, len(group2.characters)) assert_equal(1, len(group.characters))
def generate_company_with_groups(number): bosses = [Staff() for i in range(number)] companies = [Company() for i in range(number)] groups = [] # construct company gnames = ['董事会', '总经理', '副总经理', '市场总监', '技术总监', '副总经理', '财务部', '行政人事部', '商务部', '市场发展部', '客户服务部', '外部办事部', '产品研发部', '技术服务部', '系统集成部', '副总经理', '采购部', '生产部', '质检部'] for i in companies: temp_groups = [Group(name=j, companyId=i._id) for j in gnames] # set relation set_parent(temp_groups, [1], 0) set_parent(temp_groups, [2, 3, 4, 5], 1) set_parent(temp_groups, [6, 7, 8], 2) set_parent(temp_groups, [9, 10, 11], 3) set_parent(temp_groups, [12, 13, 14], 4) set_parent(temp_groups, [15, 16, 17], 5) groups += temp_groups group_data = [i.get_data_for_insert() for i in groups] print(group_data) for i in range(number): bosses[i].companyId = companies[i]._id # keng?? companies[i].userId = bosses[i]._id boss_data = [i.get_data_for_insert() for i in bosses] company_data = [i.get_data_for_insert() for i in companies] staff_sql = Staff.get_insert_sql() group_sql = Group.get_insert_sql() company_sql = Company.get_insert_sql() database.execute_change(staff_sql, tuple(boss_data)) database.execute_change(company_sql, tuple(company_data)) database.execute_change(group_sql, tuple(group_data)) return companies, groups
def __init__(self, Class, function, args=()): """Creates a group whose contents is retrieved from a function every time it is queried """ Group.__init__(self, Class) self.function = function self.args = args
class TestGroup(TestCase): def setUp(self): self.class_obj = Group("Cos101", 3) self.professor_obj = Professor("William", "Adams", "*****@*****.**", 65000, "Computer Science") def test_setProfessor_success(self): self.class_obj.set_professor(self.professor_obj) self.assertEqual(self.class_obj.get_professor(), self.professor_obj)
def __init__(self, canvas, num=0, color=VEH_ALIVE): Group.__init__(self, canvas) self.num_alive = num for n in range(num): veh = VehicleDraw(canvas, color, rand_on_screen('x'), rand_on_screen('y')) veh.random_dna() self.add_en(veh)
def add_group(self, n_agents, position, destination, color): """Adds a group of agents to the Simulation.""" group = Group(n_agents, position, destination, color) group.id = self.amount_groups self.groups.append(group) for agent in group.get_agents(): self.import_agent(agent) self.amount_groups += 1
def group_elves(elves): count = len(elves) groups = [] for i in range(0, 2 * int(count / 2), 2): group = Group([elves[i], elves[i + 1]], []) groups.append(group) if count % 2 == 1: group = Group([elves[-1]], []) groups.append(group) return groups
def test_z_addition_group(): n = 8 steps = 20 start_element = 5 z_n_group = Group(group_set=range(0, n), bin_operation=lambda x, y: (x + y) % n) cycle_steps = z_n_group.get_element_cycle_steps(start_element, steps) for step in cycle_steps: if (step == start_element): print() print(f"{step}", end=f" ")
def parseAcountFiles(self): Group.init() groups = [] for fileName in os.listdir(self.ACOUNTS_DIR): group = Group(fileName) for line in open(os.path.join(self.ACOUNTS_DIR, fileName), 'r'): acount = Acount(line) group.addAcount(acount) groups.append(group) return groups
def daily_job(): while (1): Auth.work() Capsule.work() Coin2Silver.work() GiftSend.work() Group.work() Heart.work() Silver2Coin.work() SilverBox.work() Task.work() # 休息0.5s,减少CPU占用 time.sleep(0.5)
def join_group(self, groupid, access_code): group = Group(group_name=None, host=None, group_id=groupid) # group.add_member returns a boolean of whether the access_code is correct or not group_playlist_id = group.add_member(self, access_code) if group_playlist_id is not None: self.groupIds.add(group.get_group_id()) # now make this user follow the host's group playlist headers = self.get_headers() result = requests.put( 'https://api.spotify.com/v1/playlists/{playlist_id}/followers' + group_playlist_id, headers=headers) self.store_user()
def build_group_objects(env1, admin_api_key1, group_links): """ Builds a list of Group objects that will be used to more quickly check for users in groups """ Groups_List = [] # initialize a python list of objects if not (group_links is None): for i in np.arange(0, np.shape(group_links)[0]): g1 = Group(group_links[i][0],group_links[i][1], group_links[i][2]) g1.add_users(get_users_in_group(env1, admin_api_key1, group_links[i])) Groups_List.append(g1) return Groups_List else: return None
def modify_group(): guid = request_int("Which group would you like to modify?") group = Group.get(guid) if group is None: print("There is no group with that id") return action = input("Would you like to ADD or Remove members?").lower() if "add" in action: while True: print_group_people_with_no_group() uuid = request_int( "Which person would you like to add? (-1 to finish add people):" ) if uuid is -1: return add_member(guid, uuid) if "remove" in action: while True: for person in group.members(): print(person.uuid(), " ", person.name()) uuid = request_int( "Which person would you like to remove? (-1 to finish removing people):" ) if uuid is -1: return remove_member(guid, uuid) else: print("Invalid action")
def remove_member(guid, uuid): group = Group.get(guid) if group is None: print("The group does not exist") return if not group.remove_member(uuid): print("removing person", uuid, " from group ", guid, " failed")
def set_mode(self, mode): CommandMode.validate(mode) group = self.group if group is None: group = Group('fake', 'fake', [self]) for device in group.devices: commands.add(device, CommandMode(mode))
def set_temperature(self, temperature): CommandTemperature.validate(temperature) group = self.group if group is None: group = Group('fake', 'fake', [self]) for device in group.devices: commands.add(device, CommandTemperature(temperature))
def cast(self, grp): '''Casts group from current type to requested group-type, eg GroupResolution -> GroupChange @param grp: Group being converted @type grp: Group @return: Group cast to the self type ''' return Group.clone(grp, self.get())
def getGroups(self): page = 1 while True: request = requests.get(Values.apiGroupsBaseUrl, params={ 'token': self.devToken, 'page': page }) if request.status_code != 200: return text = json.loads(request.text) jsonGroups = text['response'] if len(jsonGroups) == 0: break page = page + 1 for jsonGroup in jsonGroups: name = jsonGroup['name'] description = jsonGroup['description'] imageUrl = jsonGroup['image_url'] created_at = jsonGroup['created_at'] updated_at = jsonGroup['messages']['last_message_created_at'] groupId = jsonGroup['group_id'] jsonMembersList = jsonGroup['members'] membersList = [] for members in jsonMembersList: memberId = members['user_id'] memberName = members['nickname'] memberImageUrl = members['image_url'] memberRoles = members['roles'] member = Member(memberId, memberName, memberImageUrl, memberRoles) membersList.append(member) group = Group(name, description, imageUrl, created_at, updated_at, groupId, membersList) self.groups.append(group)
def __init__(self, index): self.boardIndex = index # index of the board; should be ordered as the clock distribution order self.boardEnable = True # enable or disable the readout of the entire board self.Connection = Connection() self.Connection.conetNode = index self.IRQPolicy = IRQPolicy() self.ChargeMode = ChargeMode() self.SAMCorrection = SAMCorrection() self.SAMFrequency = 1.6 # sampling rate in GS/s; must be 3.2, 1.6, 0.8, or 0.4 self.RecordLength = 1024 # number of samples digitized; must be N*16, for 4 <= N <= 256 self.TriggerType = TriggerType() self.IOLevel = IOLevel() self.MaxNumEventsBLT = 255 # max number of events to read in each block transfer over optical link self.GroupTriggerLogic = GroupTriggerLogic() self.TriggerCountVeto = TriggerCountVeto() self.groups = [Group() for _ in range(self.numGroups)] self.channels = [Channel() for _ in range(self.numChannels)]
def __init__(self, config, vaccination_schedule): self.groups = {} self.group_sizes = config["group_sizes"] self.groups_history = [] self.possible_vaccines = [ globals()[name.upper()] for name in vaccination_schedule.keys() ] for index, group_name in enumerate(config["groups"]): susceptible = config["group_sizes"][index] - config[ "starting_cases"][index] self.groups[group_name] = Group( group_name, config["num_contacts"][index], config["prob_transmission"][index], config["prob_severe"][index], config["prob_death"][index], config["prob_recovery"][index], susceptible, config["starting_cases"][index], possible_vaccines=self.possible_vaccines) self.groups_history.append( pd.DataFrame( columns=["susceptible", "cases", "recovered", "deaths"])) self.vaccination_schedule = vaccination_schedule self.config = config self.total_people = sum(config["group_sizes"]) self.time_step = 0 self.max_time_steps = config["max_time_steps"]
def reset(self, new_config=None): """Resets the environment. If no new config is passed, uses current one. Args: new_config (dict, optional):A new config. Defaults to None. """ config = new_config if new_config else self.config self.groups = {} self.group_sizes = config["group_sizes"] self.groups_history = [] for index, group_name in enumerate(config["groups"]): susceptible = config["group_sizes"][index] - config[ "starting_cases"][index] self.groups[group_name] = Group( group_name, config["num_contacts"][index], config["prob_transmission"][index], config["prob_severe"][index], config["prob_death"][index], config["prob_recovery"][index], susceptible, config["starting_cases"][index], possible_vaccines=self.possible_vaccines) self.groups_history.append( pd.DataFrame( columns=["susceptible", "cases", "recovered", "deaths"])) self.total_people = sum(config["group_sizes"]) self.time_step = 0
def cast(self,grp): '''Casts group from current type to requested group-type, eg GroupResolution -> GroupChange @param grp: Group being converted @type grp: Group @return: Group cast to the self type ''' return Group.clone(grp, self.get())
def alg(groups): exit_count = 0 for group in groups: all_representants = get_all_representants(groups) instance_and_nearest = [] new_group = Group() for sample in group.get_instances(): [nearest_rep] = knn.get_knn(1, sample, all_representants) if nearest_rep != group.get_representant(): nearest_g = get_group_by_representant(nearest_rep, groups) instance_and_nearest.append((sample, nearest_g)) if len(instance_and_nearest) == 0: exit_count = exit_count + 1 elif len(instance_and_nearest) == group.count_instances(): elements = group.get_instances() P, med = hama.pca([e[:-1] for e in elements], 1) normal_vector = P prototype = group.get_representant()[:-1] [d] = hama.proj(P, prototype, med) for inst in group.get_instances(): [di] = hama.proj(P, inst[:-1], med) if d < di: group.remove_instance(inst) new_group.add_instance(inst) else: for tupla in instance_and_nearest: bad_instance = tupla[0] nearest_g = tupla[1] # [new_nearest] = knn.get_knn(1, bad_instance, [nearest_g.get_representant(), group.get_representant()]) # if new_nearest == nearest_g.get_representant(): if nearest_g.get_representant() != group.get_representant() and nearest_g.get_classe() != group.get_classe(): group.remove_instance(bad_instance) new_group.add_instance(bad_instance) elif nearest_g.get_representant() != group.get_representant(): # mas são da mesma classe nearest_g.add_instance(bad_instance) group.remove_instance(bad_instance) # nearest_g.update_all() # group.update_all() if not new_group.is_empty(): new_group.update_all() groups.append(new_group) update_all_groups(groups) if exit_count != len(groups): return alg(groups) return groups
def groups(request): # Проверяем авторизован ли пользователь if auth.get_user(request).is_authenticated: # Выводим 'особую' страницу, когда у пользователя нет групп if not Group.objects.filter(group_admin=Admin.objects.get( admin_id=int(auth.get_user(request).username))).exists(): return render_to_response \ ('voidInfo.html', {'user_id': auth.get_user(request).username, 'group': True, 'donation':False, 'donater':False, 'showLastDonate':False}) #Проверяем наличие групп у пользователя if Group.objects.filter( group_admin=auth.get_user(request).username).exists(): #Получаем группы, связанные с админом data = Group.objects.filter( group_admin=auth.get_user(request).username) # Получаем аватарки групп links = {'data': []} ids = [] for group in data.values(): ids.append(str(group["group_id"])) ids = ','.join(ids) array = vk_group.getGroupsImg(ids) #Добавляем ссылку на фото и id группы for group in array: links['data'].append({ 'link': group['img'], 'group_id': group['id'] }) data = links #Добавляем последний донат data.update({ 'last_donate': Donation.objects.filter( donation_admin=auth.get_user(request).username)[:1] }) #Добавляем аутентифицированного юзера data.update({'user_id': auth.get_user(request).username}) return render_to_response('groups.html', data) #Если у пользователя нет групп else: data = ({'user_id': auth.get_user(request).username}) return render_to_response('groups.html', data) # Если пользователь не авторизован, перенаправялем его на главную страницу else: return redirect('/')
def createGroup( self, name = None, parent = None ): group = Group( self, name ) if parent: parent.children.add( group ) self.groups.add( group ) return group
def __parse_group_header(self, segment): """Parse the group header""" self.current_group = Group() header = GroupHeader() headerFieldList = segment.split( self.ediDocument.document_configuration.element_separator) self.__parse_segment(header, headerFieldList) self.current_group.header = header
def test_test_empty_group(self): wd = self.wd self.open_home_page(wd) self.login(wd, username="******", password="******") self.open_groups_page(wd) self.create_group(wd, Group(name="", header="", footer="")) self.return_to_groups(wd) self.logout(wd)
def read_file(file_path): with open(file_path, 'r') as myfile: groups_list = Groups() try: group_str_lst = myfile.read().split(sep="#") except: myfile = open(file_path, 'r') group_str_lst = myfile.read().split("#") print(myfile, myfile.read()) for g in group_str_lst: if len(g) == 0: continue g_list = g.splitlines() group = Group(g_list.pop(0)) group.add_member(g_list) groups_list.add_group(group) return groups_list
def __init__(self): self.clock = pygame.time.Clock() self.frame_tick = None self.previous_collide_verdicts = [] self.entities = Group() self.location_cells = Group() self.location_objects = Group() self.moving_colliders = Group() self.static_colliders = Group()
def send_welcome(message): global reachable_users, groups, state groups_dict = read_from_database() for group_id in groups_dict: g = Group() g.decode_from_json(groups_dict[group_id]) # print(g.id_lib) groups.update([(group_id, g)]) reachable_users = get_users() group_id = str(message.chat.id) if group_id in groups: print(groups[group_id]) group = groups[group_id] print(group.id_lib) bot.send_message(group.id, "Радий знову вас чути!") print_all_people(group_id) else: bot.send_message( message.chat.id, 'Всім привіт! Я - Debt Keeper Bot, радий знайомству!') bot.send_message( message.chat.id, 'Раджу всім додатися в список юзерів, щоб я міг надавати вам свої послуги.' ) bot.send_message( message.chat.id, 'Для цього напишіть команду /add та дотримуйтеся інструкцій.') group = Group() group.id = str(message.chat.id) groups.update([(group_id, group)]) save_to_database(groups) previous_solution.update([(str(message.chat.id), [(-1, -1, -1)])]) state.update([(str(message.from_user.id), str(message.chat.id))])
def check_room_fitness(schedule): counts = 0 for key, value in schedule.items(): _, group = key counts += 1 if value is not None and Group.groups[Group.get_id( group)].size > value['room'].size else 0 counts += 1 if value is not None and value['is_lab'] == value[ 'room'].is_lab else 0 return counts
def room_size_and_type_penalty(schedule): penalty = 0 for key, value in schedule.items(): _, group = key penalty += 1 if value is not None and Group.groups[Group.get_id( group)].size > value['room'].size else 0 penalty += 1 if value is not None and value['is_prac'] == value[ 'room'].is_prac else 0 return penalty
def deleteGroupPost(handler, id, p_newGroup = None): def die(msg): print msg done() handler.title('Manage Group') requirePriv(handler, 'User') handler.wrappers = False id = to_int(id, 'id', die) if p_newGroup is not None: p_newGroup = to_int(p_newGroup, 'newGroup', die) group = Group.load(id) if not group: ErrorBox.die('Invalid Group', "No group with ID <b>%d</b>" % id) if not group.deletable: ErrorBox.die('Invalid Group', "Group is not deletable") if len(group.sprint.getGroups()) == 1: ErrorBox.die('Invalid Group', "Cannot delete the last group in a sprint") tasks = group.getTasks() newGroup = None if p_newGroup == 0: # Delete tasks for task in tasks: task.deleted = True task.revise() elif p_newGroup is not None: # Move tasks newGroup = Group.load(p_newGroup) if not newGroup: ErrorBox.die('Invalid Group', "No group with ID <b>%d</b>" % p_newGroup) # Move all the tasks to the end of the new group seq = len(newGroup.getTasks()) for task in tasks: seq += 1 task.move(seq, newGroup) elif len(tasks): ErrorBox.die('Invalid Request', "Missing new group request argument") sprintid = group.sprintid group.delete() Event.deleteGroup(handler, group) redirect("/sprints/%d%s" % (sprintid, "#group%d" % newGroup.id if newGroup else ''))
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)
def csvParser(filePath): """ filePath is where the file is save, and it must include the name of the file Also, if the file name does not include "Members" or "Fincances", csvParser will throw an Exception """ print(filePath) fileName = os.path.split(filePath)[1] name = fileName.split(".")[0] csvfile = open(filePath, newline='') reader = csv.DictReader(csvfile) try: members = [] for row in reader: m = Member( row['name'], row['firstName'], row['surname'], row['eMail'], Date(int(row['birthDate'].split('/')[0]), int(row['birthDate'].split('/')[1]), int(row['birthDate'].split('/')[2])), bool(row['cotisation']), row['belongingGroups']) members.append(m) csvfile.close() return [Group(name, members), name] except: pass t = Table() for row in reader: try: t.addBalanceVerification(row['name'], row['iD'], float(row["cumul"]), float(row["balance"]), float(row['balanceGap']), int(row['date'].split('/')[0]), int(row['date'].split('/')[1]), int(row['date'].split('/')[2])) except: pass try: t.addFlux(row["name"], row['iD'], float(row['value']), row['shortInfo'], row['longInfo'], row['supplier'], float(row['iN']), float(row['out']), int(row['date'].split('/')[0]), int(row['date'].split('/')[1]), int(row['date'].split('/')[2])) except: pass csvfile.close() return [t, name] raise Exception("The file name or file content is invalid")
def create_group(): guid = Group().id() while True: print_group_people_with_no_group() uuid = request_int( "Which person would you like to add to the new group?(-1 to finish adding people): " ) if uuid == -1: return add_member(guid, uuid)
def renameGroupPost(handler, id, p_name): def die(msg): print msg done() handler.title('Manage Group') requirePriv(handler, 'User') id = int(id) group = Group.load(id) if not group: ErrorBox.die('Invalid Group', "No group with ID <b>%d</b>" % id) elif p_name.strip() == '': ErrorBox.die('Invalid Name', "Group must have a non-empty name") oldName = group.name group.name = p_name group.save() Event.renameGroup(handler, group, oldName) redirect("/sprints/%d#group%d" % (group.sprintid, group.id))
def get_groups(self, userID): connection = pymysql.connect(host=db.db_host, port=db.db_port, user=db.db_user, passwd=db.db_passwd, db=db.db_name) cursor = connection.cursor() SQL = "SELECT B.ID_GROUP, NAME_GROUP, ID_GROUP_ADMIN, IMAGE_GROUP FROM BELONG B, GROUPS G WHERE id_user = %s AND B.ID_GROUP = G.ID_GROUP" % str( userID) try: cursor.execute(SQL) except: return SQL groups = list() for row in cursor: group = Group() group.ID = row[0] group.NAME = row[1] group.ADMIN = row[2] group.IMAGE = row[3] cursor2 = connection.cursor() SQL = "SELECT ID_USER FROM BELONG WHERE ID_GROUP = %s" % str(row[0]) try: cursor2.execute(SQL) except: return SQL users = list() for value in cursor2: users.append(value[0]) group.USERS = users groups.append(group.serialize()) cursor.close() connection.close() return groups
def newGroup(handler, after): handler.title('New Group') requirePriv(handler, 'User') afterID = int(after) afterGroup = Group.load(afterID) if not afterGroup: ErrorBox.die('Invalid Group', "No group with ID <b>%d</b>" % afterID) print "<style type=\"text/css\">" print "table.list td.right > * {width: 400px;}" print "table.list td.right button {width: 200px;}" # Half of the above value print "</style>" print "<script type=\"text/javascript\">" print "next_url = '/sprints/%d';" % afterGroup.sprint.id print "</script>" print "<script src=\"/static/groups.js\" type=\"text/javascript\"></script>" print InfoBox('', id = 'post-status') print "<form method=\"post\" action=\"/groups/new\">" print "<table class=\"list\">" print "<tr><td class=\"left\">Sprint:</td><td class=\"right\"><select id=\"selectSprint\" disabled><option>%s</option></select></td></tr>" % afterGroup.sprint print "<tr><td class=\"left\">Predecessor:</td><td class=\"right\">" print "<select id=\"select-group\" name=\"group\" size=\"5\">" for sGroup in afterGroup.sprint.getGroups('name'): print "<option value=\"%d\"%s>%s</option>" % (sGroup.id, ' selected' if sGroup == afterGroup else '', sGroup.safe.name) print "</select>" print "</td></tr>" print "<tr><td class=\"left\">Name:</td><td class=\"right\"><input type=\"text\" name=\"name\" class=\"defaultfocus\"></td></tr>" print "<tr><td class=\"left\"> </td><td class=\"right\">" print Button('Save', id = 'save-button', type = 'button').positive() print Button('Cancel', id = 'cancel-button', type = 'button').negative() print "</td></tr>" print "</table>" print "</form>"
def assignGroupGoalPost(handler, id, p_goal): def die(msg): print msg done() handler.title('Manage Group') requirePriv(handler, 'User') handler.wrappers = False id = int(id) group = Group.load(id) if not group: ErrorBox.die('Invalid Group', "No group with ID <b>%d</b>" % id) if p_goal == '0': goal = None else: goal = Goal.load(int(p_goal)) if not goal: ErrorBox.die('Invalid Goal', "No goal with ID <b>%d</b>" % int(p_goal)) elif not goal.sprint == group.sprint: ErrorBox.die('Invalid Goal', "Selected goal is not part of the correct sprint") for task in group.getTasks(): if task.goal != goal: task.goal = goal if task.creator == handler.session['user'] and (dateToTs(getNow()) - task.timestamp) < 5*60: task.save() else: task.saveRevision(handler.session['user']) #TODO Event # NO redirect("/sprints/%d#group%d" % (group.sprintid, group.id))
def getGroups(self, orderby = 'seq'): from Group import Group return Group.loadAll(sprintid = self.id, orderby = orderby)
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
def editGroup(handler, id): requirePriv(handler, 'User') handler.title('Manage Group') id = int(id) group = Group.load(id) if not group: ErrorBox.die('Invalid Group', "No group with ID <b>%d</b>" % id) tasks = group.getTasks() chart = GroupGoalsChart(group) Chart.include() chart.js() print "<style type=\"text/css\">" print "table.list td.left {position: relative; top: 4px;}" print "table.list td.right *, button {width: 400px;}" print "table.list td.right button {width: 200px;}" # Half of the above value print "</style>" print "<h2>Edit Group</h2>" print "<form method=\"post\" action=\"/groups/%d/rename\">" % id print "<table class=\"list\">" print "<tr><td class=\"left\">Name:</td><td class=\"right\"><input type=\"text\" name=\"name\" value=\"%s\">" % (group.safe.name) print "<tr><td class=\"left\">Predecessor:</td><td class=\"right\">" #TODO Waiting on group moving print "<select name=\"predecessor\" disabled>" print "<option>%s</option>" % ('None' if group.seq == 1 else Group.load(sprintid = group.sprintid, seq = group.seq-1).safe.name) print "</select>" print "</td></tr>" print "<tr><td class=\"left\"> </td><td class=\"right\">" print Button('Save', type = 'submit').positive() print Button('Cancel', "/sprints/%d#group%d" % (group.sprintid, id), type = 'button').negative() print "</td></tr>" print "</table>" print "</form>" print "<h2>Assign Goal</h2>" print "This is a quick way to set all the tasks in the group to the same sprint goal. The current breakdown is:" chart.placeholder() # The default is whichever goal currently has the most occurrences defaultGoal = max((sum(task.goal == goal or False for task in tasks), goal) for goal in group.sprint.getGoals() + [None])[1] print "<form method=\"post\" action=\"/groups/%d/goal\">" % id for goal in group.sprint.getGoals(): if goal.name: print "<input type=\"radio\" id=\"goal%d\" name=\"goal\" value=\"%d\"%s> <label for=\"goal%d\"><img class=\"bumpdown\" src=\"/static/images/tag-%s.png\"> %s</label><br>" % (goal.id, goal.id, ' checked' if goal == defaultGoal else '', goal.id, goal.color, goal.name) print "<input type=\"radio\" id=\"goal0\" name=\"goal\" value=\"0\"%s> <label for=\"goal0\"><img class=\"bumpdown\" src=\"/static/images/tag-none.png\"> Other</label><br><br>" % ('' if defaultGoal else ' checked') print Button('Assign', type = 'submit').positive() print "</form>" print "<h2>Delete Group</h2>" if len(group.sprint.getGroups()) == 1: print "You can't delete the last group in a sprint" elif not group.deletable: print "This group is undeletable" else: print "<form method=\"post\" action=\"/groups/%d/delete\">" % id if len(tasks): print "This group has %d %s. Move %s to the <select name=\"newGroup\">" % (len(tasks), 'task' if len(tasks) == 1 else 'tasks', 'it' if len(tasks) == 1 else 'them') for thisGroup in group.sprint.getGroups('name'): if group == thisGroup: continue print "<option value=\"%d\">%s</option>" % (thisGroup.id, thisGroup.safe.name) print "<option value=\"0\">None (delete)</option>" print "</select> group<br><br>" print Button('Delete', type = 'submit') print "</form>"
def testStaticGroups(self): exampleGroup = Group(self.ExampleClass, self.base) self.assertEquals(str(exampleGroup.action("name", ())), str(['[FD]Chasm', '[FD]Oblivion', '|DM|Broski', '|DM|Dannyboy']))
def testEmptyGroupCreation(self): emptyGroup = Group(self.ExampleClass) self.assertEquals(emptyGroup.members(), [])
def testInvalidFilterParameter(self): exampleGroup = Group(self.ExampleClass, self.base) exampleFilter = Select(nsdfame=Contains("[FD]")) exampleQuery = exampleGroup.query(exampleFilter) self.assertRaises(self.Errors.InvalidProperty, exampleQuery.all)
def testQueries(self): exampleGroup = Group(self.ExampleClass, self.base) exampleFilter = Select(name=Contains("[FD]")) exampleQuery = exampleGroup.query(exampleFilter) self.assertEquals(str(exampleQuery.all().action("name", ())), str(['[FD]Chasm', '[FD]Oblivion']))
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
def testMaxMinsSelect(self): exampleGroup = Group(self.ExampleClass, self.base) exampleFilter = MaxMins(frags='<') exampleQuery = exampleGroup.query(exampleFilter) self.assertEquals(str(exampleQuery.all().action("name", ())), str(['[FD]Chasm', '[FD]Oblivion']))
def newTaskImport(handler, group, source=None, assigned=None): # 'assigned' is ignored, it's just in case the user gets here from a filtered backlog handler.title("New Tasks") requirePriv(handler, "User") id = int(group) print tabs.format(id).where("import") group = Group.load(id) if not group or group.sprint.isHidden(handler.session["user"]): ErrorBox.die("Invalid Group", "No group with ID <b>%d</b>" % id) sprint = group.sprint if not (sprint.isActive() or sprint.isPlanning()): ErrorBox.die("Sprint Closed", "Unable to modify inactive sprint") elif not sprint.canEdit(handler.session["user"]): ErrorBox.die("Permission Denied", "You don't have permission to modify this sprint") sprints = sprint.project.getSprints() sprintIdx = sprints.index(sprint) prevSprint = sprints[sprintIdx - 1] if sprintIdx > 0 else None if not source: print "Select a sprint to import from:<br><br>" print '<form method="get" action="/tasks/new/import">' print '<input type="hidden" name="group" value="%d">' % group.id print '<select name="source" id="import-source">' for projectIter in Project.getAllSorted(handler.session["user"], sprint.project): print '<optgroup label="%s">' % projectIter.safe.name for sprintIter in projectIter.getSprints(): print '<option value="%d"%s>%s</option>' % ( sprintIter.id, " selected" if sprintIter == prevSprint else "", sprintIter.safe.name, ) print "</optgroup>" print "</select>" print "<br><br>" print Button("Next").positive().post() print "</form>" else: id = int(source) source = Sprint.load(id) if not source: ErrorBox.die("Invalid Sprint", "No sprint with ID <b>%d</b>" % id) print '<script type="text/javascript">' nextURL = "/sprints/%d" % sprint.id if assigned: nextURL += "?search=assigned:%s" % stripTags(assigned.replace(" ", ",")) print "next_url = %s;" % toJS(nextURL) print 'post_url = "/tasks/new/import?group=%d&source=%d";' % (group.id, source.id) print "scrummaster = %s;" % toJS(sprint.owner.username) print "TaskTable.init();" print "</script>" print '<b>Source sprint</b>: <a href="/sprints/%d">%s</a><br>' % (source.id, source.name) print '<b>Target sprint</b>: <a href="/sprints/%d">%s</a><br><br>' % (sprint.id, sprint.name) print "All incomplete tasks are listed here, with their current values from the source sprint. You can change any of the fields before importing. Only checked tasks will be imported<br><br>" assignedList = [sprint.owner] + list(sprint.members - {sprint.owner}) print TaskTable( source, editable=True, assignedList=assignedList, checkbox=True, status=True, name=True, assigned=True, hours=True, debug=isDevMode(handler), ) print InfoBox("Loading...", id="post-status", close=True) print Button("Import", id="save-button", type="button").positive() print Button("Cancel", id="cancel-button", type="button").negative() print "</form><br><br>"
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
def newTaskMany(handler, group, assigned=None): handler.title("New Tasks") requirePriv(handler, "User") id = int(group) body = "" if "many-upload" in handler.session: body = handler.session["many-upload"] del handler.session["many-upload"] elif assigned: body = "[%s]\n" % stripTags(assigned) defaultGroup = Group.load(id) if not defaultGroup or defaultGroup.sprint.isHidden(handler.session["user"]): ErrorBox.die("Invalid Group", "No group with ID <b>%d</b>" % id) sprint = defaultGroup.sprint print '<script src="/static/jquery.typing-0.2.0.min.js" type="text/javascript"></script>' print '<script type="text/javascript">' nextURL = "/sprints/%d" % sprint.id if assigned: nextURL += "?search=assigned:%s" % stripTags(assigned.replace(" ", ",")) print "next_url = %s;" % toJS(nextURL) print "TaskTable.init();" print "</script>" print tabs.format(id).where("many") if not (sprint.isActive() or sprint.isPlanning()): ErrorBox.die("Sprint Closed", "Unable to modify inactive sprint") elif not sprint.canEdit(handler.session["user"]): ErrorBox.die("Permission Denied", "You don't have permission to modify this sprint") help = ResponseWriter() print "Each line needs to match the following syntax. Unparseable lines generate an error message in the preview and must be resolved before saving" print "<ul>" print "<li><b>X</b> — A single character changes the field separator to that character. The exception is #, which starts a comment. The default field separator is |, so that's used in the examples here</li>" print '<li><b>X...X:</b> — A line ending in a colon is a group name. All tasks after that line will be added to that group. If no group of that name exists, it will be created (the preview will label that group as "(NEW)"). A blank line switches back to the default group, which is the group you clicked the new task button on, %s' % defaultGroup.safe.name print "<li><b>X...X|X...X[|X...X[|X...X]]</b> — 2-4 fields are a new task. The fields can appear in any order:<ul>" print "<li><b>name</b> — The name of the task</li>" print "<li><b>hours</b> — The number of hours this task will take</li>" print "<li><b>assignee</b> — The person assigned to this task. If multiple people, separate usernames with spaces. This field is optional as long as <b>status</b> is also omitted; it defaults to the current user if a sprint member, or the scrummaster otherwise, unless overridden (see below)</li>" print '<li><b>status</b> — The initial status of the task. This field is optional; it defaults to "not started"</li>' print "</ul></li>" print "<li><b>[X...X]</b> — A username (or space-separated list of usernames) wrapped in brackets makes that user or group the default assignee for all tasks that don't specify an assignee</li>" print "<li><b>#...</b> — A line starting with a hash character is a comment, and is ignored. You can only comment out entire lines; a hash within a line does not start a comment at that point</li>" print "</ul>" print "You can also use the form above the textarea to upload a text file. The file will be used to fill the textarea, so it should match the syntax described above" print CollapsibleBox("Help", help.done()) print CollapsibleBox( "Groups", "<ul>%s</ul>" % "".join( "<li>%s</li>" % ("<b>%s</b> (default)" if group == defaultGroup else "%s") % group.safe.name for group in sprint.getGroups() ), ) print '<form id="upload-tasks" method="post" enctype="multipart/form-data" action="/tasks/new/many/upload?group=%d">' % defaultGroup.id print '<input type="file" name="data"><br><br>' print "</form>" print '<form id="write-tasks" method="post" action="/tasks/new/many?group=%d">' % defaultGroup.id print '<textarea id="many-body" name="body" class="defaultfocus">%s</textarea>' % body print '<div id="preview"></div>' print InfoBox("Loading...", id="post-status", close=True) print '<div id="new-task-many-buttons">' print Button("Save All", id="save-button", type="button").positive() print Button("Cancel", id="cancel-button", type="button").negative() print "</div>" print "</form>"
def test_populateClones(self): group2 = Group(manager, name, position, imageFileName) assert_equal(0, len(group2.characters)) group2.populateClones({}, 20) assert_equal(20, len(group2.characters))
def newTaskSingle(handler, group, assigned=""): handler.title("New Task") requirePriv(handler, "User") id = int(group) assigned = assigned.split(" ") print tabs.format(id).where("single") group = Group.load(id) if not group or group.sprint.isHidden(handler.session["user"]): ErrorBox.die("Invalid Group", "No group with ID <b>%d</b>" % id) sprint = group.sprint if not (sprint.isActive() or sprint.isPlanning()): ErrorBox.die("Sprint closed", "Unable to modify inactive sprint") elif not sprint.canEdit(handler.session["user"]): ErrorBox.die("Permission denied", "You don't have permission to modify this sprint") print '<script type="text/javascript">' nextURL = "/sprints/%d" % group.sprint.id if assigned: nextURL += "?search=assigned:%s" % ",".join(assigned) nextURL += "#group%d" % group.id print "next_url = %s;" % toJS(nextURL) print "</script>" print InfoBox("", id="post-status", close=True) print '<form method="post" action="/tasks/new/single">' print '<table class="list">' print '<tr><td class="left">Sprint:</td><td class="right"><select id="selectSprint" disabled><option>%s</option></select></td></tr>' % group.sprint print '<tr><td class="left">Group:</td><td class="right">' print '<select id="select-group" name="group" size="5">' for sGroup in group.sprint.getGroups("name"): print '<option value="%d"%s>%s</option>' % (sGroup.id, " selected" if sGroup == group else "", sGroup.safe.name) print "</select>" print "</td></tr>" print '<tr><td class="left">Name:</td><td class="right"><input type="text" name="name" class="defaultfocus"></td></tr>' print '<tr><td class="left">Sprint Goal:</td><td class="right">' print '<select id="select-goal" name="goal" size="5">' print '<option value="0" selected>None</option>' for goal in group.sprint.getGoals(): print '<option value="%d">%s</option>' % (goal.id, goal.safe.name) print "</select>" print "</td></tr>" print '<tr><td class="left">Status:</td><td class="right">' print '<select id="select-status" name="status" size="10">' first = True for statusSet in statusMenu: for name in statusSet: print '<option value="%s"%s>%s</option>' % (name, " selected" if first else "", statuses[name].text) first = False print "</status>" print "</td></tr>" print '<tr><td class="left">Assigned:</td><td class="right">' print '<select id="select-assigned" name="assigned[]" data-placeholder="Choose assignees (or leave blank to self-assign)" size="10" multiple>' for user in sorted(group.sprint.members): print '<option value="%d"%s>%s</option>' % ( user.id, " selected" if user.username in assigned else "", user.safe.username, ) print "</select>" print "</td></tr>" print '<tr><td class="left">Hours:</td><td class="right"><input type="text" name="hours" value="8"></td></tr>' print '<tr><td class="left"> </td><td class="right">' print Button("Save", id="save-button", type="button").positive() print Button("Cancel", id="cancel-button", type="button").negative() print "</td></tr>" print "</table>" print "</form>"