def searchExisting(hash = []):
	'''Search using an acknowledgement number (for users who have booked a room)'''
	# The hash doesn't change, so it's only calculated the first time
	if not hash:
		send('Session request', baseUrl + '/home')
		data = {
			'ackNum': args.key[0],
			'lastName': args.key[1],
		}
		resp = send('Finding reservation', Request(baseUrl + '/reservation/find', toJS(data).encode('utf8'), {'Content-Type': 'application/json'}))
		try:
			respData = fromJS(resp.read())
		except Exception as e:
			raise RuntimeError("Failed to decode reservation: %s" % e)
		if respData.get('ackNum', None) != args.key[0]:
			raise RuntimeError("Reservation not found. Are your acknowledgement number and surname correct?")
		if 'hash' not in respData:
			raise RuntimeError("Hash missing from reservation data")
		hash.append(respData['hash'])

	data = {
		'blockMap': {
			'blocks': [{
				'blockId': '0',
				'checkIn': args.checkin,
				'checkOut': args.checkout,
				'numberOfGuests': str(args.guests),
				'numberOfRooms': str(args.rooms),
				'numberOfChildren': str(args.children),
			}]
		},
	}
	send('Loading existing reservation', baseUrl + "/r/%s/%s" % (args.key[0], hash[0]))
	send('Search', Request(baseUrl + '/rooms/select/search', toJS(data).encode('utf8'), headers = {'Content-Type': 'application/json'}))
Ejemplo n.º 2
0
def searchExisting(hash = []):
	'''Search using an acknowledgement number (for users who have booked a room)'''
	# The hash doesn't change, so it's only calculated the first time
	if not hash:
		send('Session request', baseUrl + '/home')
		data = {
			'ackNum': args.key[0],
			'lastName': args.key[1],
		}
		resp = send('Finding reservation', Request(baseUrl + '/reservation/find', toJS(data).encode('utf8'), {'Content-Type': 'application/json'}))
		try:
			respData = fromJS(resp.read())
		except Exception as e:
			raise RuntimeError("Failed to decode reservation: %s" % e)
		if respData.get('ackNum', None) != args.key[0]:
			raise RuntimeError("Reservation not found. Are your acknowledgement number and surname correct?")
		if 'hash' not in respData:
			raise RuntimeError("Hash missing from reservation data")
		hash.append(respData['hash'])

	data = {
		'blockMap': {
			'blocks': [{
				'blockId': '0',
				'checkIn': args.checkin,
				'checkOut': args.checkout,
				'numberOfGuests': str(args.guests),
				'numberOfRooms': str(args.rooms),
				'numberOfChildren': str(args.children),
			}]
		},
	}
	send('Loading existing reservation', baseUrl + "/r/%s/%s" % (args.key[0], hash[0]))
	send('Search', Request(baseUrl + '/rooms/select/search', toJS(data).encode('utf8'), headers = {'Content-Type': 'application/json'}))
Ejemplo n.º 3
0
 def js(self):
     print "$(%s).highcharts(" % toJS("#" + self._id),
     js = toJS(self._m, sort_keys=True, indent=4, cls=CustomEncoder)
     # Unwrap raw data. See the comment above in CustomEncoder for the reason for this insanity
     js = re.sub(
         re.escape(toJS(raw.wrapper)).replace("\\%s", "(.*)"), lambda match: fromJS('"%s"' % match.group(1)), js
     )
     print js
     print ");"
Ejemplo n.º 4
0
def searchSavedMenubox(handler):
	handler.wrappers = False
	handler.log = False
	if not handler.session['user']: return

	yours = [{'name': search.name, 'id': search.id, 'query': search.query} for search in SavedSearch.loadAll(userid = handler.session['user'].id)]
	others = [{'name': search.name, 'id': search.id, 'query': search.query, 'username': search.user.username, 'gravatar': search.user.getAvatar(16)} for search in SavedSearch.loadAll(public = True) if handler.session['user'] in search.followers]
	otherTotal = len(filter(lambda search: search.user != handler.session['user'], SavedSearch.loadAll(public = True)))

	print toJS({'yours': yours, 'others': others, 'otherTotal': otherTotal})
Ejemplo n.º 5
0
def adminCronRun(handler, p_name):
	handler.title('Run cron job')
	requirePriv(handler, 'Admin')

	print "<script type=\"text/javascript\">"
	print "job_name = %s;" % toJS(p_name)
	print "</script>"

	print "<div id=\"output\"></div>"
Ejemplo n.º 6
0
    def publish(self, handler, sprint, type, **extraArgs):
        data = {"type": type, "user": handler.session["user"].username}
        data.update(extraArgs)

        channel = EventPublisher.formatChannelName(sprint.project.name)
        try:
            self.conn.publish(channel, toJS(data))
        except Exception:
            pass
Ejemplo n.º 7
0
def sprintRetrospectiveRender(handler, sprintid, p_id, p_catid, p_body = None, p_good = None):
	def die(msg):
		print msg
		done()

	handler.wrappers = False
	if p_id != 'new':
		p_id = to_int(p_id, 'id', die)
	p_catid = to_int(p_catid, 'catid', die)
	if p_good is not None:
		p_good = to_bool(p_good)
	if not handler.session['user']:
		die("You must be logged in to modify sprint info")

	sprintid = int(sprintid)
	sprint = Sprint.load(sprintid)
	if not sprint or sprint.isHidden(handler.session['user']):
		die("There is no sprint with ID %d" % sprintid)
	elif sprint.owner != handler.session['user'] and (p_body is not None or p_good is not None):
		die("Only the scrummaster can edit the retrospective")
	elif not (sprint.isReview() or sprint.isOver()):
		die("The retrospective isn't available until the sprint is in review")

	if p_id == 'new':
		if p_body is None or p_good is None:
			die("Missing body/good")
		entry = RetroEntry(p_catid, p_body, p_good)
	else:
		entry = RetroEntry.load(p_id)
		if p_body is not None:
			entry.body = p_body
		if p_good is not None:
			entry.good = p_good

		if entry.body == '':
			entry.delete()
			handler.responseCode = 299
			print toJS({'id': entry.id, 'deleted': True});
			return

	entry.save()
	handler.responseCode = 299
	print toJS({'id': entry.id, 'body': Markdown.render(entry.body), 'good': entry.good})
Ejemplo n.º 8
0
def run(handler, p_command, p_path, p_mode = ''):
	handler.wrappers = False

	if not handler.session['user']:
		print toJS({'error': 'You must be logged in to use the shell'})
		return

	# This is already checked in the "su" command, but could be spoofed by the user
	if p_mode == 'admin' and not (handler.session['user'].hasPrivilege('Admin') or ('impersonator' in handler.session and handler.session['impersonator'].hasPrivilege('Admin'))):
		print toJS({'error': "You need the Admin privilege"})
		return

	if 'shell' not in handler.session: # Shell context
		handler.session['shell'] = {}
	handler.session['shell']['handler'] = handler;
	handler.session['shell']['path'] = p_path
	handler.session['shell']['mode'] = p_mode

	parts = split(p_command)
	testCommands = filterCommands(parts, p_mode)

	if len(testCommands) == 0:
		print toJS({'error': 'Unrecognized command'})
	elif len(testCommands) > 1:
		print toJS({'error': 'Ambiguous command'})
	else:
		syntax, fn, doc = testCommands[0]
		args = [y for (x, y) in zip(syntax, parts) if x == '_']
		w = ResponseWriter()
		mode = None
		rtn = {}

		try:
			mode = fn(handler.session['shell'], *args)
		except CommandError, e:
			w.done()
			print toJS({'error': str(e)})
			return
		except Redirect, e:
			rtn['redirect'] = e.target
Ejemplo n.º 9
0
def adminReplPost(handler, p_code):
	def makeStr(v):
		if isinstance(v, list):
			return "<ul>%s</ul>" % ''.join("<li>%s</li>" % item for item in v)
		return str(v)

	handler.wrappers = False

	p_code = re.sub('^!([A-Za-z]+)$', 'from \\1 import \\1', p_code)
	match = re.match('!([A-Za-z ]+)$', p_code)
	if match:
		parts = match.group(1).split(' ')
		res = []
		for part in parts:
			w = ResponseWriter()
			adminReplPost(handler, "!%s" % part)
			res.append(fromJS(w.done()))
		print toJS(res)
		done()

	if 'admin-repl' not in handler.session:
		print toJS({'code': highlightCode(p_code), 'stdout': '', 'stderr': ['Session Expired', 'REPL session no longer exists'], 'vars': {}})
		done()

	writer = ResponseWriter()
	try:
		Event.repl(handler, p_code)
		exec compile(p_code, '<admin repl>', 'single') in handler.session['admin-repl']
		stderr = ''
	except:
		stderr = map(str, [sys.exc_info()[0].__name__, sys.exc_info()[1]])
	stdout = writer.done()

	vars = sorted([(k, pformat(v), makeStr(v)) for (k, v) in handler.session['admin-repl'].items() if k != '__builtins__'], lambda (k1, v1, vs1), (k2, v2, vs2): cmp(k1, k2))
	print toJS({'code': highlightCode(p_code), 'stdout': stdout, 'stderr': stderr, 'vars': vars})
Ejemplo n.º 10
0
def showSprintRetrospective(handler, id):
	requirePriv(handler, 'User')
	id = int(id)
	sprint = Sprint.load(id)
	if not sprint or sprint.isHidden(handler.session['user']):
		ErrorBox.die('Sprints', "No sprint with ID <b>%d</b>" % id)
	elif not sprint.canView(handler.session['user']):
		ErrorBox.die('Private', "You must be a sprint member to view this sprint")
	editing = (sprint.owner == handler.session['user'])

	handler.title(sprint.safe.name)
	drawNavArrows(sprint, handler.session['user'], 'retrospective')
	print tabs(sprint, ('wrapup', 'retrospective'))

	Markdown.head()
	print "<script type=\"text/javascript\">"
	print "var sprint_id = %d;" % sprint.id
	print "var editing = %s;" % toJS(editing)
	print "</script>"

	if not (sprint.isReview() or sprint.isOver()):
		ErrorBox.die('Sprint Open', "The retrospective isn't available until the sprint is in review")

	retro = Retrospective.load(sprint)
	if retro is None:
		if editing:
			print "<form method=\"post\" action=\"/sprints/%d/retrospective/start\">" % sprint.id
			print Button("Start Retrospective").post().positive()
			print "</form>"
		else:
			print ErrorBox("This sprint has no retrospective")
		done()

	print "The sprint retrospective asks two main questions:<br>"
	print "<ul class=\"retrospective-list\">"
	print "<li class=\"good\">What went well during the sprint?</li>"
	print "<li class=\"bad\">What could be improved in the next sprint?</li>"
	print "</ul>"
	if editing:
		print "For now the list of categories is fixed; eventually you'll be able to modify them per-sprint. Click an existing item to edit it, or the margin icon to toggle it. Fill in the text area at the end of the category to add a new item; clear a text area to delete it. <a href=\"/help/markdown\">Markdown</a> is available if necessary"

	print "<div class=\"retrospective markdown\">"
	for category, entries in retro.iteritems():
		print "<div class=\"category\" data-id=\"%d\">" % category.id
		print "<div class=\"name\">%s</div>" % stripTags(category.name)
		for entry in sorted(entries, key = lambda entry: 0 if entry.good else 1):
			print "<div class=\"entry %s\" data-id=\"%d\"><textarea>%s</textarea></div>" % ('good' if entry.good else 'bad', entry.id, stripTags(entry.body))
		if not editing and len(entries) == 0:
			print "<div class=\"none\">No entries</div>"
		print "</div>"
	print "</div>"
Ejemplo n.º 11
0
def apiSprintInfo(handler, id):
	def die(msg):
		print toJS({'error': msg})
		done()

	id = int(id)
	handler.wrappers = False

	sprint = Sprint.load(id)
	if not sprint or sprint.isHidden(handler.session['user']):
		die("No sprint with ID %d" % id)

	abbrName = sprint.name.strip()
	if abbrName.startswith(sprint.project.name):
		abbrName = abbrName[len(sprint.project.name):].strip()

	print toJS({
			'id': sprint.id,
			'name': sprint.name,
			'abbreviated name': abbrName,
			'start': sprint.start,
			'end': sprint.end
			})
Ejemplo n.º 12
0
def apiSprintsList(handler, calendar = False, start = None, end = None, _ = None):
	def die(msg):
		print toJS({'error': msg})
		done()

	handler.wrappers = False
	start = int(start) if start else None
	end = int(end) if end else None

	sprints = filter(lambda sprint: not sprint.isHidden(handler.session['user']), Sprint.loadAll())
	if start and end:
		sprints = filter(lambda sprint: (start <= sprint.start <= end) or (start <= sprint.end <= end), sprints)

	rtn = [{'id': sprint.id,
	        'title': "%s - %s" % (sprint.project.name, sprint.name) if calendar else sprint.name,
	        'start': tsToDate(sprint.start).strftime('%Y-%m-%d'),
	        'end': tsToDate(sprint.end).strftime('%Y-%m-%d'),
	        'active': sprint.isActive(),
	        'member': handler.session['user'] in sprint.members
	       } for sprint in sprints]
	if calendar:
		for entry in rtn:
			entry.update({'color': 'green' if entry['member'] and entry['active'] else '#36c;'})
	print toJS(rtn)
def searchExisting():
	'''Search using an acknowledgement number (for users who have booked a room)'''
	data = {
		'blockMap': {
			'blocks': [{
				'blockId': '0',
				'checkIn': args.checkin,
				'checkOut': args.checkout,
				'numberOfGuests': str(args.guests),
				'numberOfRooms': str(args.rooms),
				'numberOfChildren': str(args.children),
			}]
		},
	}
	send('Loading existing reservation', baseUrl + "/r/%s/%s" % tuple(args.key))
	send('Search', Request(baseUrl + '/rooms/select/search', toJS(data).encode('utf8'), headers = {'Content-Type': 'application/json'}))
Ejemplo n.º 14
0
def searchExisting(hash = []):
	'''Search using an acknowledgement number (for users who have booked a room)'''
	# The hash doesn't change, so it's only calculated the first time
	if not hash:
		send('Session request', baseUrl + '/home')
		data = {
			'ackNum': args.key,
			'lastName': args.surname,
		}
		resp = send('Finding reservation', Request(baseUrl + '/reservation/find', toJS(data), {'Content-Type': 'application/json'}))
		try:
			respData = fromJS(resp.read())
		except Exception, e:
			raise RuntimeError("Failed to decode reservation: %s" % e)
		if respData.get('ackNum', None) != args.key:
			raise RuntimeError("Reservation not found. Are your acknowledgement number and surname correct?")
		if 'hash' not in respData:
			raise RuntimeError("Hash missing from reservation data")
		hash.append(respData['hash'])
Ejemplo n.º 15
0
def showSprintHistory(handler, id, assigned = None):
	requirePriv(handler, 'User')
	id = int(id)
	sprint = Sprint.load(id)
	if not sprint or sprint.isHidden(handler.session['user']):
		ErrorBox.die('Sprints', "No sprint with ID <b>%d</b>" % id)
	elif not sprint.canView(handler.session['user']):
		ErrorBox.die('Private', "You must be a sprint member to view this sprint")
	tasks = sprint.getTasks(includeDeleted = True)

	handler.title(sprint.safe.name)
	drawNavArrows(sprint, handler.session['user'], 'history')

	Chart.include()
	chart = TaskChart('chart', sprint.getTasks())
	chart.js()
	print "<script type=\"text/javascript\">"
	tasksByAssigned = {member.username: [task.id for task in tasks if member in task.assigned] for member in sprint.members}
	print "var tasks_by_assigned = %s;" % toJS(tasksByAssigned)
	print "$(document).ready(function() {"
	if assigned:
		print "    $('%s').addClass('selected');" % ', '.join("#filter-assigned a[assigned=\"%s\"]" % username for username in assigned.split(','))
	print "    setup_filter_buttons();"
	print "    apply_filters();"
	print "});"
	print "</script>"

	print tabs(sprint, 'history')
	if len(tasks) == 0:
		print ErrorBox("This sprint has no tasks")
		print "<br>"
		return

	print "<div id=\"filter-assigned\">"
	print "<a class=\"fancy danger\" href=\"#\"><img src=\"/static/images/cross.png\">&nbsp;None</a>"
	for member in sorted(sprint.members):
		print "<a class=\"fancy\" assigned=\"%s\" href=\"/sprints/%d/history?assigned=%s\"><img src=\"%s\">&nbsp;%s</a>" % (member.username, id, member.username, member.getAvatar(16), member.username)
	print "</div><br>"

	chart.placeholder()
	showHistory(tasks, True)
	print "<br>"
Ejemplo n.º 16
0
def games(handler):
	def makeEvent(game):
		event = {'log': splitext(game.logFilename)[0],
		         'title': game.friendlyName,
		         'start': game.start.strftime('%Y-%m-%dT%H:%M:%S')}
		if game.finished:
			event['end'] = game.end
		else:
			event['end'] = datetime.utcnow()
			event['color'] = '#d4604a'
		event['end'] = event['end'].strftime('%Y-%m-%dT%H:%M:%S')
		return event

	events = [makeEvent(game) for game in getGames().values()]
	handler.jsOnReady("makeCalendar(%s);" % toJS(events))

	print "<script src=\"/static/third-party/moment.js\" type=\"text/javascript\"></script>"
	print "<link href=\"/static/third-party/fullcalendar.css\" rel=\"stylesheet\" type=\"text/css\" />"
	print "<script src=\"/static/third-party/fullcalendar.js\" type=\"text/javascript\"></script>"
	print "<div id=\"calendar\"></div>"
	print "<br><br>"
Ejemplo n.º 17
0
def showBacklog(handler, id, search = None, devEdit = False):
	requirePriv(handler, 'User')
	id = int(id)
	sprint = Sprint.load(id)
	if not sprint or sprint.isHidden(handler.session['user']):
		ErrorBox.die('Sprints', "No sprint with ID <b>%d</b>" % id)
	elif not sprint.canView(handler.session['user']):
		ErrorBox.die('Private', "You must be a sprint member to view this sprint")

	# Redirect to search help page if searched for empty string
	if search == '':
		redirect('/help/search')

	handler.title(sprint.safe.name)
	drawNavArrows(sprint, handler.session['user'], '')

	tasks = sprint.getTasks()
	editable = sprint.canEdit(handler.session['user']) or (devEdit and isDevMode(handler))
	search = Search(sprint, search)

	print "<script src=\"/settings/sprints.js\" type=\"text/javascript\"></script>"

	print "<script type=\"text/javascript\">"
	print "var sprintid = %d;" % id
	print "var currentUser = %s;" % toJS(handler.session['user'].username if handler.session['user'] else None)
	print "var totalTasks = %d;" % len(tasks)

	# True is a placeholder for the dynamic tokens (status, assigned)
	print "var searchTokens = %s;" % toJS(filter(None, [search.getBaseString() if search.hasBaseString() else None] + [True] + ["%s:%s" % (filt.getKey(), filt.value) for filt in search.getAll() if filt.getKey() not in ('status', 'assigned')]))
	print "var searchDescriptions = %s;" % toJS(filter(None, ["matching %s" % search.getBaseString() if search.hasBaseString() else None] + [True] + [filt.description() for filt in search.getAll()]))

	print "TaskTable.init({link_hours_status: %s});" % toJS(not sprint.isPlanning())
	print "$('document').ready(function() {"
	if search.has('assigned'):
		print "    $('%s').addClass('selected');" % ', '.join("#filter-assigned a[assigned=\"%s\"]" % user.username for user in search.get('assigned').users + ([handler.session['user']] if search.get('assigned').currentUser else []))
	if search.has('status'):
		print "    $('%s').addClass('selected');" % ', '.join("#filter-status a[status=\"%s\"]" % status.name for status in search.get('status').statuses)
	print "    apply_filters();"
	print "});"
	print "</script>"

	print "<div id=\"selected-task-box\">"
	print "<span></span>"
	print Button('history', id = 'selected-history').positive()
	print Button('highlight', id = 'selected-highlight').positive()
	print Button('mass edit', id = 'selected-edit').positive()
	print Button('cancel', id = 'selected-cancel') #.negative()
	print "</div>"

	print "<div class=\"backlog-tabs\">"
	print tabs(sprint, 'backlog')
	print "<input type=\"text\" id=\"search\" value=\"%s\">" % search.getFullString().replace('"', '&quot;')
	print "</div>"

	undelay(handler)

	print InfoBox('Loading...', id = 'post-status', close = True)

	avail = Availability(sprint) if sprint.isActive() else None
	dayStart = Weekday.today().date()
	print "<div id=\"filter-assigned\">"
	print "<a class=\"fancy danger\" href=\"#\"><img src=\"/static/images/cross.png\">&nbsp;None</a>"
	for member in sorted(sprint.members):
		cls = ['fancy']
		if not sprint.isPlanning() and avail and avail.get(member, dayStart) == 0:
			cls.append('away')
		print "<a class=\"%s\" assigned=\"%s\" href=\"/sprints/%d?search=assigned:%s\"><img src=\"%s\">&nbsp;%s</a>" % (' '.join(cls), member.username, id, member.username, member.getAvatar(16), member.username)
	print "</div><br>"

	print "<div id=\"filter-status\">"
	print "<a class=\"fancy danger\" href=\"#\"><img src=\"/static/images/cross.png\">&nbsp;None</a>"
	for status in sorted(statuses.values()):
		print "<a class=\"fancy\" status=\"%s\" href=\"/sprints/%d?search=status:%s\"><img src=\"%s\">%s</a>" % (status.name, id, status.name.replace(' ', '-'), status.getIcon(), status.text)
	print "</div><br>"

	if handler.session['user'].hasPrivilege('Admin') and 'deleted' in sprint.flags:
		print "<form method=\"post\" action=\"/admin/projects/%d/cancel-deletion/%d\">" % (sprint.project.id, sprint.id)
		print WarningBox("This sprint is flagged for deletion during nightly cleanup. %s" % Button('Cancel').mini().post())
		print "</form>"
	if sprint.isPlanning():
		if sprint.isActive():
			print InfoBox("Today is <b>sprint planning</b> &mdash; tasks aren't finalized until the end of the day")
		else:
			daysTillPlanning = (tsToDate(sprint.start) - getNow()).days + 1
			print InfoBox("The sprint has <b>not begun</b> &mdash; planning is %s. All changes are considered to have been made midnight of plan day" % ('tomorrow' if daysTillPlanning == 1 else "in %d days" % daysTillPlanning))
	elif sprint.isReview():
		print InfoBox("Today is <b>sprint review</b> &mdash; this is the last day to make changes to the backlog. All open tasks will be deferred at the end of the day")
	elif not sprint.isOver():
		noHours = filter(lambda task: task.stillOpen() and task.hours == 0, tasks)
		if noHours != []:
			print WarningBox("There are <a href=\"/sprints/%d?search=status:not-started,in-progress,blocked hours:0\">open tasks with no hour estimate</a>" % sprint.id)

	tasks = search.filter(tasks)

	if isDevMode(handler):
		print Button('#all-tasks borders', "javascript:$('#all-tasks, #all-tasks tr td').css('border', '1px solid #f00').css('border-collapse', 'collapse');").negative()
		if not editable:
			print Button('make editable', "/sprints/%d?devEdit" % id).negative()
		elif devEdit:
			print Button('make uneditable', "/sprints/%d" % id).negative()

		print "<div class=\"debugtext\">"
		print "start: %d (%s)<br>" % (sprint.start, tsToDate(sprint.start))
		print "end: %d (%s)<br>" % (sprint.end, tsToDate(sprint.end))
		print "</div>"

	showing = ResponseWriter()
	print "<span id=\"task-count\"></span>"
	# save-search href set by update_task_count()
	print "<a class=\"save-search\"><img src=\"/static/images/save.png\" title=\"Save search\"></a>"
	print "<a class=\"cancel-search\" href=\"/sprints/%d\"><img src=\"/static/images/cross.png\" title=\"Clear search\"></a>" % id
	showing = showing.done()

	print TaskTable(sprint, editable = editable, tasks = tasks, tableID = 'all-tasks', dateline = showing, taskClasses = {task: ['highlight'] for task in (search.get('highlight').tasks if search.has('highlight') else [])}, debug = isDevMode(handler), groupActions = True, taskModActions = True, index = True, goal = True, status = True, name = True, assigned = True, historicalHours = True, hours = True, devEdit = devEdit)
Ejemplo n.º 18
0
def dynJS(handler):
	handler.wrappers = False
	handler.log = False
	handler.contentType = 'text/javascript'

	print "function get_websocket_port() {return %s;}" % toJS(PORT if WebSocket.available() else False)
Ejemplo n.º 19
0
def header(handler, includes):
	if handler.pageTitle is None:
		title = bodyTitle = 'Spades'
	else:
		bodyTitle = handler.pageTitle
		title = "%s - Spades" % bodyTitle

	print "<!DOCTYPE html>"
	print "<html>"
	print "<head>"
	print "<meta charset=\"utf-8\" />"
	print "<title>%s</title>" % title
	print "<link rel=\"shortcut icon\" href=\"/static/images/favicon.ico\">"

	# jQuery
	print "<script src=\"//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js\"></script>"
	print "<link rel=\"stylesheet\" href=\"//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css\" />"
	print "<script src=\"//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>"
	print "<script src=\"/static/third-party/jquery.ui.position.js\"></script>"
	print "<script src=\"/static/third-party/jquery.contextMenu.js\"></script>"
	print "<link rel=\"stylesheet\" href=\"/static/third-party/jquery.contextMenu.css\" />"

	print "<script src=\"/static/third-party/barn.js\"></script>"

	# Bootstrap
	print "<link rel=\"stylesheet\" href=\"//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css\" integrity=\"sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==\" crossorigin=\"anonymous\">"
	print "<link rel=\"stylesheet\" href=\"//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css\" integrity=\"sha384-aUGj/X2zp5rLCbBxumKTCw2Z50WgIr1vs/PFN4praOTvYXWlVyh2UtNUU0KAUhAX\" crossorigin=\"anonymous\">"
	print "<script src=\"//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js\" integrity=\"sha512-K1qjQ+NcF2TYO/eI3M6v8EiNYZfA95pQumfvcVrTHtwQVDG+aHRqLi/ETn2uB+1JqwYqVG3LIvdm9lj6imS/pQ==\" crossorigin=\"anonymous\"></script>"

	print "<script src=\"/dyn.js\"></script>"

	for filename in includes['less']:
		print "<link rel=\"stylesheet/less\" type=\"text/css\" href=\"%s\" />" % filename
	# for filename in includes['css']:
		# print "<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\" />" % filename
	for filename in includes['js']:
		print "<script src=\"%s\" type=\"text/javascript\"></script>" % filename

	for fn in handler.wrapperData['headerFns']:
		fn()

	if handler.wrapperData['jsOnLoad'] or handler.wrapperData['jsOnReady']:
		print "<script type=\"text/javascript\">"
		if handler.wrapperData['jsOnLoad']:
			print "$(window).load(function() {setTimeout(function() {"
			for js in handler.wrapperData['jsOnLoad']:
				if hasattr(js, '__call__'):
					js()
				else:
					print "    %s" % js
			print "}, 0)});"
		if handler.wrapperData['jsOnReady']:
			print "$(document).ready(function() {"
			for js in handler.wrapperData['jsOnReady']:
				if hasattr(js, '__call__'):
					js()
				else:
					print "    %s" % js
			print "});"
		print "</script>"

	# Less
	print "<link rel=\"stylesheet/less\" type=\"text/css\" href=\"/static/style.less\">"
	print "<link rel=\"stylesheet\" type=\"text/css\" href=\"/static/syntax-highlighting.css\">"
	print "<script type=\"text/javascript\">"
	print "less = %s;" % toJS({'env': 'production', 'async': False, 'dumpLineNumbers': 'comments'})
	print "</script>"
	print "<script src=\"/static/third-party/less.js\" type=\"text/javascript\"></script>"

	print "</head>"
	print "<body>"
	print "<div class=\"content\">"

	print "<div class=\"topbar\">"
	print "<h1>%s</h1>" % bleach.clean(bodyTitle)
	print "<div class=\"links\"><a href=\"/games\">Games</a> | <a href=\"/players\">Players</a> | <a href=\"/settings\">Settings</a></div>"
	print "</div>"
Ejemplo n.º 20
0
	def broadcast(data):
		for handler in handlers:
			handler.write_message(toJS(data))
Ejemplo n.º 21
0
	def sendChannel(self, channel, data):
		if 'channel' not in data:
			data['channel'] = channel
		if 'now' not in data:
			data['now'] = int(time.mktime(datetime.now().timetuple()) * 1000) # Javascript times are in ms
		self.write_message(toJS(data))
Ejemplo n.º 22
0
	def out(self):
		sprintDays = [day.date() for day in self.sprint.getDays()]

		# Make sure only people in assignedList are assigned to tasks
		# If everyone assigned to the task is missing from assignedList, assign it to the first person in the list
		# (this should probably be the scrummaster)
		for tasks in self.tasks.values():
			for task in tasks:
				task.assigned &= set(self.assignedList)
				if len(task.assigned) == 0:
					task.assigned = {self.assignedList[0]}

		if self.check('historicalHours'):
			if self.sprint.isActive() or self.check('devEdit'):
				days = [
					('ereyesterday', Weekday.shift(-2)),
					('yesterday', Weekday.shift(-1)),
					('today', Weekday.today())
				]
			elif self.sprint.isPlanning():
				start = tsToDate(self.sprint.start)
				ereyesterday, yesterday, today = Weekday.shift(-2, start), Weekday.shift(-1, start), start
				days = [
					('pre-plan', ereyesterday),
					('pre-plan', yesterday),
					('planning', today)
				]
			else:
				end = tsToDate(self.sprint.end)
				ereyesterday, yesterday, today = Weekday.shift(-2, end), Weekday.shift(-1, end), end
				days = [
					(ereyesterday.strftime('%A').lower(), ereyesterday),
					(yesterday.strftime('%A').lower(), yesterday),
					(today.strftime('%A').lower(), today)
				]
		elif self.check('hours'):
			days = [(None, None)]
		else:
			days = []

		print "<script type=\"text/javascript\">"
		print "status_texts = Array();"
		for statusBlock in statusMenu:
			for statusName in statusBlock:
				status = statuses[statusName]
				print "status_texts['%s'] = '%s';" % (status.name, status.text)
		print "goal_imgs = Array();"
		print "goal_imgs[0] = '/static/images/tag-none.png';"
		for goal in self.sprint.getGoals():
			print "goal_imgs[%d] = '/static/images/tag-%s.png';" % (goal.id, goal.color)
		print "goal_texts = Array();"
		print "goal_texts[0] = \"None\";"
		for goal in self.sprint.getGoals():
			print "goal_texts[%d] = %s;" % (goal.id, toJS(goal.name))
		print "</script>"

		print "<ul id=\"status-menu\" class=\"contextMenu\">"
		for statusBlock in statusMenu:
			for statusName in statusBlock:
				status = statuses[statusName]
				cls = 'separator' if statusBlock != statusMenu[0] and statusName == statusBlock[0] else ''
				print "<li class=\"%s\"><a href=\"#%s\" style=\"background-image:url('%s');\">%s</a></li>" % (cls, status.name, status.getIcon(), status.text)
		print "</ul>"

		print "<ul id=\"goal-menu\" class=\"contextMenu\">"
		print "<li><a href=\"#0\" style=\"background-image:url('/static/images/tag-none.png');\">None</a></li>"
		for goal in self.sprint.getGoals():
			if goal.name != '':
				print "<li><a href=\"#%s\" style=\"background-image:url('/static/images/tag-%s.png');\">%s</a></li>" % (goal.id, goal.color, goal.safe.name if len(goal.safe.name) <= 40 else "%s..." % goal.safe.name[:37])
		print "</ul>"

		print "<ul id=\"assigned-menu\" class=\"contextMenu\">"
		for user in sorted(self.assignedList):
			print "<li><a href=\"#%s\" style=\"background-image:url('%s');\">%s</a></li>" % (user.username, user.getAvatar(16), user.username)
		print "</ul>"

		tblClasses = ['tasktable']
		if self.editable:
			tblClasses.append('editable')
		print "<table border=0 cellspacing=0 cellpadding=2 %sclass=\"%s\">" % (('id="%s" ' % self.tableID) if self.tableID else '', ' '.join(tblClasses))
		print "<thead>"
		if any(x for x, y in days):
			print "<tr class=\"dateline nodrop nodrag\">"
			print "<td colspan=\"%d\">&nbsp;</td>" % (1 + self.check('name') + self.check('assigned'))
			for (x, y) in days:
				if x is not None:
					print "<td class=\"%s\">%s</td>" % (x, x)
			print "<td>&nbsp;</td>"
			print "</tr>"
		if any(y for x, y in days) or self.dateline is not None:
			print "<tr class=\"dateline2 nodrop nodrag\">"
			print "<td colspan=\"%d\">" % (1 + self.check('name') + self.check('assigned'))
			if self.dateline is not None:
				print self.dateline
			print "</td>"
			for (x, y) in days:
				if y is None:
					print "<td>&nbsp;</td>"
				else:
					print "<td class=\"%s\">%s<br>Day %s of %s</td>" % (x, formatDate(y), sprintDays.index(y.date())+1 if y.date() in sprintDays else 0, len(sprintDays))
			print "<td>&nbsp;</td>"
			print "</tr>"
		print "</thead>"

		print "<tbody>"
		for (group, groupTasks) in self.tasks.iteritems():
			cls = ['group']
			if not group.deletable:
				cls.append('fixed')
			print "<tr class=\"%s\" id=\"group%d\" groupid=\"%d\">" % (' '.join(cls), group.id, group.id)
			print "<td colspan=\"%d\">" % (1 + self.check('name') + self.check('assigned') + len(days))
			if self.check('debug'):
				print "<small class=\"debugtext\">(%d, %d)</small>&nbsp;" % (group.id, group.seq)
			if self.check('checkbox'):
				print "<input type=\"checkbox\"></input>"
			print "<img src=\"/static/images/collapse.png\">"
			print "<span>%s</span>" % group.name
			print "</td>"
			print "<td class=\"actions\">"
			if self.editable and self.check('groupActions'):
				print "<a href=\"/groups/new?after=%d\"><img src=\"/static/images/group-new.png\" title=\"New Group\"></a>" % group.id
				print "<a href=\"/groups/%d\"><img src=\"/static/images/group-edit.png\" title=\"Edit Group\"></a>" % group.id
				print "<a href=\"/tasks/new?group=%d\"><img src=\"/static/images/task-new.png\" title=\"New Task\"></a>" % group.id
			print "</td>"
			print "</tr>"

			for task in groupTasks:
				classes = ['task']
				if task in self.taskClasses:
					classes += self.taskClasses[task]
				if getNow() - tsToDate(task.timestamp) < timedelta(hours = 23):
					classes.append('changed-today')

				print "<tr class=\"%s\" id=\"task%d\" taskid=\"%d\" revid=\"%d\" groupid=\"%d\" goalid=\"%d\" status=\"%s\" assigned=\"%s\">" % (' '.join(classes), task.id, task.id, task.revision, task.groupid or 0, task.goal.id if task.goal else 0, task.stat.name, ' '.join(sorted(user.username for user in task.assigned)))

				print "<td class=\"flags\">"
				if self.check('debug'):
					print "<small class=\"debugtext\">(%d, %d, %d)</small>&nbsp;" % (task.id, task.seq, task.revision)
				if self.check('checkbox'):
					print "<input type=\"checkbox\"></input>"
				if self.check('index'):
					print "<span class=\"task-index badge\"></span>&nbsp;"
				if self.check('goal'):
					print "<img id=\"goal_%d\" class=\"goal\" src=\"/static/images/tag-%s.png\" title=\"%s\">&nbsp;" % ((task.goal.id, task.goal.color, task.goal.safe.name) if task.goal else (0, 'none', 'None'))
				if self.check('status'):
					print "<img id=\"status_%d\" class=\"status\" src=\"%s\" title=\"%s\">" % (task.id, task.stat.icon, task.stat.text)
				print "</td>"

				if self.check('name'):
					print "<td class=\"name\"><span id=\"name_span_%d\">%s</span></td>" % (task.id, task.safe.name)
				if self.check('assigned'):
					print "<td class=\"assigned\"><span>"
					if len(task.assigned) == 1:
						print list(task.assigned)[0].str('member', False, "assigned_span_%d" % task.id)
					else:
						assignedStr = ' '.join(sorted(user.username for user in task.assigned))
						print "<img src=\"/static/images/team.png\" class=\"user\">"
						print "<span id=\"assigned_span_%d\" class=\"username\" username=\"%s\" title=\"%s\">team (%d)</span>" % (task.id, assignedStr, assignedStr, len(task.assigned))
					print "</span></td>"

				for lbl, day in days:
					dayTask = task.getRevisionAt(day) if day else task
					previousTask = task.getRevisionAt(Weekday.shift(-1, day)) if day else None
					classes = ['hours']
					if lbl is not None:
						classes.append(lbl)
					if dayTask and previousTask and dayTask.hours != previousTask.hours:
						classes.append('changed')

					if not dayTask:
						print "<td class=\"%s\">&ndash;</td>" % ' '.join(classes)
					elif self.editable and lbl in ('today', 'planning', None):
						print "<td class=\"%s\" nowrap>" % ' '.join(classes)
						print "<div>"
						print "<img amt=\"4\" src=\"/static/images/arrow-up.png\">"
						print "<img amt=\"-4\" src=\"/static/images/arrow-down.png\">"
						print "</div>"
						print "<input type=\"text\" name=\"hours[%d]\" value=\"%d\">" % (task.id, task.hours)
						print "<div>"
						print "<img amt=\"8\" src=\"/static/images/arrow-top.png\">"
						print "<img amt=\"-8\" src=\"/static/images/arrow-bottom.png\">"
						print "</div>"
						print "</td>"
						print "</td>"
					else:
						print "<td class=\"%s\">%s</td>" % (' '.join(classes), dayTask.hours)

				print "<td class=\"actions\">"
				if task.id:
					print "<a href=\"/tasks/%d\" target=\"_blank\"><img src=\"/static/images/task-history.png\" title=\"History\"></a>" % task.id
				if self.check('taskModActions') and self.editable:
					print "<a href=\"javascript:TaskTable.delete_task(%d);\"><img src=\"/static/images/task-delete.png\" title=\"Delete Task\"></a>" % task.id
				for icon, pattern, url in zip(*settings.autolink):
					for match in re.finditer(pattern, task.name, re.IGNORECASE):
						print "<a href=\"%s\" target=\"_blank\"><img src=\"/static/images/%s.png\"></a>" % (Template(url).safe_substitute(match.groupdict()), icon)
				print "<img class=\"saving\" src=\"/static/images/loading.gif\">"
				print "</td>"
				print "</tr>"

		# Spacer so rows can be dragged to the bottom
		print "<tr><td colspan=\"%d\">&nbsp;</td></tr>" % (2 + self.check('name') + self.check('assigned') + len(days))
		print "</tbody>"
		print "</table>"
Ejemplo n.º 23
0
 def die(msg):
     print toJS({"error": msg})
     done()
Ejemplo n.º 24
0
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> &mdash; 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> &mdash; 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> &mdash; 2-4 fields are a new task. The fields can appear in any order:<ul>"
    print "<li><b>name</b> &mdash; The name of the task</li>"
    print "<li><b>hours</b> &mdash; The number of hours this task will take</li>"
    print "<li><b>assignee</b> &mdash; 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> &mdash; 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> &mdash; 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> &mdash; 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>"
Ejemplo n.º 25
0
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>"
Ejemplo n.º 26
0
	def die(msg):
		print toJS({'error': msg})
		done()
Ejemplo n.º 27
0
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">&nbsp;</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>"
Ejemplo n.º 28
0
def header(handler, includes):
	print "<!DOCTYPE html>"
	print "<html>"
	print "<head>"
	print "<title>$title$</title>"
	print "<link rel=\"stylesheet\" type=\"text/css\" href=\"/static/syntax-highlighting.css\">"
	print "<link rel=\"shortcut icon\" href=\"/static/images/favicon.ico\">"

	print "<script src=\"/static/jquery.js\" type=\"text/javascript\"></script>"
	print "<script src=\"/static/jquery-migrate-1.1.1.min.js\" type=\"text/javascript\"></script>"
	print "<link rel=\"stylesheet\" href=\"/static/jquery-ui-1.10.1.custom.css\">"
	print "<script src=\"/static/jquery-ui-1.10.1.custom.min.js\" type=\"text/javascript\"></script>"
	print "<link href=\"/static/jquery.contextMenu.css\" rel=\"stylesheet\" type=\"text/css\" />"
	print "<script src=\"/static/jquery.contextMenu.js\"></script>"
	print "<script src=\"/static/jquery.mousewheel-min.js\"></script>"
	print "<script src=\"/static/jquery.terminal-0.4.23.js\"></script>"
	print "<link href=\"/static/jquery.terminal.css\" rel=\"stylesheet\" type=\"text/css\" />"
	print "<script src=\"/static/jquery.ba-bbq.js\"></script>"

	print "<script src=\"/static/bootstrap-dropdown.js\" type=\"text/javascript\"></script>"
	print "<link rel=\"stylesheet\" type=\"text/css\" href=\"/static/bootstrap.css\">"

	print "<link rel=\"stylesheet\" href=\"/static/chosen/chosen.css\" />"
	print "<script src=\"/static/chosen/chosen.jquery.js\" type=\"text/javascript\"></script>"

	print "<script src=\"/static/noty/jquery.noty.js\"></script>"
	print "<script src=\"/static/noty/layouts/bottomCenter.js\"></script>"
	print "<script src=\"/static/noty/themes/default.js\"></script>"
	print "<script src=\"/static/noty/themes/sprint.js\"></script>"

	print "<script src=\"/dyn.js\" type=\"text/javascript\"></script>"
	print "<script src=\"/static/script.js\" type=\"text/javascript\"></script>"
	print "<script src=\"/static/shell.js\" type=\"text/javascript\"></script>"

	print "<style type=\"text/css\">"
	if handler.session['user']:
		print ".username[username~=\"%s\"] {" % handler.session['user'].username
		print "    color: #C00;"
		print "    font-weight: bold;"
		print "}"
	print "</style>"

	for filename in includes['less']:
		print "<link rel=\"stylesheet/less\" type=\"text/css\" href=\"%s\" />" % filename
	# for filename in includes['css']:
		# print "<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\" />" % filename
	for filename in includes['js']:
		print "<script src=\"%s\" type=\"text/javascript\"></script>" % filename

	print "<link rel=\"stylesheet/less\" type=\"text/css\" href=\"/static/style.less\">"
	print "<script type=\"text/javascript\">"
	print "less = {"
	print "    env: '%s'," % ('development' if isDevMode(handler) else 'production')
	print "    async: false,"
	print "    dumpLineNumbers: 'comments'"
	print "};"
	print "</script>"
	print "<script src=\"/static/less.js\" type=\"text/javascript\"></script>"

	changes = list(getChanges(handler, handler.path))
	if changes:
		print "<script src=\"/static/changelog.js\"></script>"
		print "<script type=\"text/javascript\">"
		print "$(document).ready(function() {"
		fmt = "%%(message)s<div style=\"text-align: right; font-size: 6pt\"><a target=\"_blank\" href=\"%s\">%%(hash)s</a></div>" % gitURL
		for change in changes:
			print "    showChangelog(%s);" % toJS(fmt % {'hash': change.hash, 'message': change.message})
		print "});"
		print "</script>"

	print "</head>"
	print "<body>"
	print "<div id=\"shell\"></div>"
	print "<div id=\"frame\">"

	print "<div id=\"main_a\">"
	if handler.session['user']:
		print "<div class=\"avatar\">"
		print "<img class=\"avatar\" src=\"%s\">" % handler.session['user'].getAvatar()
		print "<div class=\"subavatar\">"
		if 'impersonator' in handler.session:
			print "<img class=\"subavatar\" src=\"%s\" onClick=\"unimpersonate();\" title=\"Unimpersonate\">" % handler.session['impersonator'].getAvatar()
		else:
			unreadMessages = Message.loadAll(userid = handler.session['user'].id, read = False)
			if len(unreadMessages) > 0:
				print "<a class=\"inbox\" href=\"/messages/inbox\">%d</a>" % len(unreadMessages)
		print "</div>"
		print "</div>"
	print "<div class=\"navigation\">"
	print "<div class=\"ident\">"
	if handler.session['user']:
		print "Logged in as %s" % handler.session['user']
	else:
		print "<a href=\"/login\">Not logged in</a>"
	print "</div>"

	if (option('dev') or isDevMode(handler)) and handler.session['user'] and handler.session['user'].hasPrivilege('Dev'):
		if isDevMode(handler):
			print "<div class=\"devwarning\" onClick=\"buildmode('production')\">"
			print "Development"
			print "</div>"
		else:
			print "<div class=\"prodwarning\" onClick=\"buildmode('development')\">"
			print "Production"
			print "</div>"

	print "<div class=\"topmenu\">"
	print menu.render(handler, handler.path)
	print "</div>"
	print "</div>"
	print "</div>"

	print "<div id=\"main_b\"></div>"

	print "<div id=\"main_c\">"

	if settings.systemMessage:
		print "<div class=\"sysmessage\">%s</div>" % settings.systemMessage

	print "<div id=\"main_d\">"

	print "<h1>$bodytitle$</h1>"
Ejemplo n.º 29
0
		hash.append(respData['hash'])

	data = {
		'blockMap': {
			'blocks': [{
				'blockId': '0',
				'checkIn': args.checkin,
				'checkOut': args.checkout,
				'numberOfGuests': str(args.guests),
				'numberOfRooms': str(args.rooms),
				'numberOfChildren': str(args.children),
			}]
		}
	}
	send('Loading existing reservation', baseUrl + "/r/%s/%s" % (args.key, hash[0]))
	send('Search', Request(baseUrl + '/rooms/select/search', toJS(data), headers = {'Content-Type': 'application/json'}))
	return send('List', baseUrl + '/list/hotels')

def parseResults(resp):
	parser = PasskeyParser(resp)
	if not parser.json:
		raise RuntimeError("Failed to find search results")

	hotels = fromJS(parser.json)

	print "Results:   (%s)" % datetime.now()
	alerts = []

	print "   %-15s %-10s %-80s %s" % ('Distance', 'Price', 'Hotel', 'Room')
	for hotel in hotels:
		for block in hotel['blocks']:
Ejemplo n.º 30
0
def sprintsJS(handler):
    handler.wrappers = False
    handler.log = False
    handler.contentType = "text/javascript"

    print "bugzilla_url = %s;" % toJS(settings.bugzillaURL or "")
Ejemplo n.º 31
0
			rtn['redirect'] = e.target
			rtn['postdata'] = e.data
			rtn['success_msg'] = e.successMsg
		except:
			w.done()
			raise

		rtn['output'] = w.done()
		if mode is not None:
			if type(mode) == tuple:
				rtn['mode'], rtn['prompt'] = mode
			else:
				rtn['mode'] = rtn['prompt'] = mode
		if 'redirect' in rtn and rtn['output'] == '':
			rtn['output'] = clr('Posting...' if 'postdata' in rtn else 'Redirecting...', 'yellow')
		print toJS(rtn)

def filterCommands(parts, mode = ''):
	rtn = commands.get(mode, []) + commands.get('*', [])
	rtn = filter(lambda (syntax, fn, doc): len(syntax) == len(parts) and all(x.startswith(y) for (x, y) in zip(syntax, parts) if x != '_'), rtn)
	return rtn

def getUser(username):
	user = User.load(username = username)
	if not user:
		fail("No user named %s" % username)
	return user

def nameLookup(cls, name, key = 'name', **attrs):
	rows = cls.loadAll(**attrs)
	rows = filter(lambda row: getattr(row, key).lower().startswith(name.lower()), rows)
Ejemplo n.º 32
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)
Ejemplo n.º 33
0
	def sendChannel(channel, data):
		if not 'channel' in data:
			data['channel'] = channel
		for handler in channels.get(channel, []):
			handler.write_message(toJS(data))
Ejemplo n.º 34
0
	def js(self):
		print "<script type=\"text/javascript\">"
		print "$(document).ready(function() {",
		print "new Highcharts.Chart(",
		print re.sub('"(?:\\\\n)*function\(\) {(.*)}(?:\\\\n)*"', lambda match: fromJS(match.group(0)), toJS(self._m, sort_keys = True, indent = 4)),
		print ");",
		print "});"
		print "</script>"