예제 #1
0
def create_outage(request):
    """ Create a reservation for a user. """
    try:
        start, end = extract_times(request.POST)
    except Exception as e:
        return HttpResponseBadRequest(str(e))
    tool = get_object_or_404(Tool, name=request.POST.get('tool_name'))
    # Create the new reservation:
    outage = ScheduledOutage()
    outage.creator = request.user
    outage.category = request.POST.get('category', '')[:200]
    outage.tool = tool
    outage.start = start
    outage.end = end

    # If there was a problem in saving the reservation then return the error...
    policy_problem = check_policy_to_create_outage(outage)
    if policy_problem:
        return HttpResponseBadRequest(policy_problem)

    # Make sure there is at least an outage title
    if not request.POST.get('title'):
        dictionary = {'categories': ScheduledOutageCategory.objects.all()}
        return render(request, 'calendar/scheduled_outage_information.html',
                      dictionary)

    outage.title = request.POST['title']
    outage.details = request.POST.get('details', '')

    outage.save()
    return HttpResponse()
예제 #2
0
def past_comments_and_tasks(request):
    start, end = extract_times(request.GET,
                               start_required=False,
                               end_required=False)
    search = request.GET.get("search")
    if not start and not end and not search:
        return HttpResponseBadRequest(
            "Please enter a search keyword, start date or end date.")
    tool_id = request.GET.get("tool_id")
    try:
        tasks = Task.objects.filter(tool_id=tool_id)
        comments = Comment.objects.filter(tool_id=tool_id, staff_only=False)
        if start:
            tasks = tasks.filter(creation_time__gt=start)
            comments = comments.filter(creation_date__gt=start)
        if end:
            tasks = tasks.filter(creation_time__lt=end)
            comments = comments.filter(creation_date__lt=end)
        if search:
            tasks = tasks.filter(problem_description__icontains=search)
            comments = comments.filter(content__icontains=search)
    except:
        return HttpResponseBadRequest("Task and comment lookup failed.")
    past = list(chain(tasks, comments))
    past.sort(key=lambda x: getattr(x, "creation_time", None) or getattr(
        x, "creation_date", None))
    past.reverse()
    dictionary = {"past": past}
    return render(request, "tool_control/past_tasks_and_comments.html",
                  dictionary)
예제 #3
0
def create_reservation(request):
	""" Create a reservation for a user. """
	try:
		start, end = extract_times(request.POST)
		item_type = request.POST['item_type']
		item_id = request.POST.get('item_id')
	except Exception as e:
		return HttpResponseBadRequest(str(e))
	return create_item_reservation(request, start, end, ReservationItemType(item_type), item_id)
예제 #4
0
def past_comments_and_tasks(request):
	try:
		start, end = extract_times(request.GET)
	except:
		return HttpResponseBadRequest('Please enter a start and end date.')
	tool_id = request.GET.get('tool_id')
	try:
		tasks = Task.objects.filter(tool_id=tool_id, creation_time__gt=start, creation_time__lt=end)
		comments = Comment.objects.filter(tool_id=tool_id, creation_date__gt=start, creation_date__lt=end)
	except:
		return HttpResponseBadRequest('Task and comment lookup failed.')
	past = list(chain(tasks, comments))
	past.sort(key=lambda x: getattr(x, 'creation_time', None) or getattr(x, 'creation_date', None))
	past.reverse()
	dictionary = {
		'past': past,
	}
	return render(request, 'tool_control/past_tasks_and_comments.html', dictionary)
예제 #5
0
def usage_data_history(request, tool_id):
    """ This method return a dictionary of headers and rows containing run_data information for Usage Events """
    csv_export = bool(request.POST.get("csv", False))
    start, end = extract_times(request.POST,
                               start_required=False,
                               end_required=False)
    last = request.POST.get("data_history_last")
    user_id = request.POST.get("data_history_user_id")
    if not last and not start and not end:
        # Default to last 25 records
        last = 25
    usage_events = UsageEvent.objects.filter(
        tool_id=tool_id, end__isnull=False).order_by("-end")
    if start:
        usage_events = usage_events.filter(
            end__gte=beginning_of_the_day(start))
    if end:
        usage_events = usage_events.filter(end__lte=end_of_the_day(end))
    if user_id:
        try:
            usage_events = usage_events.filter(user_id=int(user_id))
        except ValueError:
            pass
    if last:
        try:
            last = int(last)
        except ValueError:
            last = 25
        usage_events = usage_events[:last]
    table_result = BasicDisplayTable()
    table_result.add_header(("user", "User"))
    table_result.add_header(("date", "Date"))
    for usage_event in usage_events:
        if usage_event.run_data:
            usage_data = {}
            try:
                user_data = f"{usage_event.user.first_name} {usage_event.user.last_name}"
                date_data = usage_event.end.astimezone(
                    timezone.get_current_timezone()).strftime(
                        "%m/%d/%Y @ %I:%M %p")
                run_data: Dict = loads(usage_event.run_data)
                for question_key, question in run_data.items():
                    if "user_input" in question:
                        if question["type"] == "group":
                            for sub_question in question["questions"]:
                                table_result.add_header(
                                    (sub_question["name"],
                                     sub_question["title"]))
                            for index, user_inputs in question[
                                    "user_input"].items():
                                if index == "0":
                                    # Special case here the "initial" group of user inputs will go along with the rest of the non-group user inputs
                                    for name, user_input in user_inputs.items(
                                    ):
                                        usage_data[name] = user_input
                                else:
                                    # For the other groups of user inputs, we have to add a whole new row
                                    group_usage_data = {}
                                    for name, user_input in user_inputs.items(
                                    ):
                                        group_usage_data[name] = user_input
                                    if group_usage_data:
                                        group_usage_data["user"] = user_data
                                        group_usage_data["date"] = date_data
                                        table_result.add_row(group_usage_data)
                        else:
                            table_result.add_header(
                                (question_key, question["title"]))
                            usage_data[question_key] = question["user_input"]
                if usage_data:
                    usage_data["user"] = user_data
                    usage_data["date"] = date_data
                    table_result.add_row(usage_data)
            except JSONDecodeError:
                tool_control_logger.debug("error decoding run_data: " +
                                          usage_event.run_data)
    if csv_export:
        response = table_result.to_csv()
        filename = f"tool_usage_data_export_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.csv"
        response["Content-Disposition"] = f'attachment; filename="{filename}"'
        return response
    else:
        dictionary = {
            "tool_id": tool_id,
            "data_history_start": start,
            "data_history_end": end,
            "data_history_last": str(last),
            "usage_data_table": table_result,
            "data_history_user":
            User.objects.get(id=user_id) if user_id else None,
            "users": User.objects.filter(is_active=True)
        }
        return render(request, "tool_control/usage_data.html", dictionary)
예제 #6
0
def create_reservation(request):
    """ Create a reservation for a user. """
    try:
        start, end = extract_times(request.POST)
    except Exception as e:
        return HttpResponseBadRequest(str(e))
    tool = get_object_or_404(Tool, name=request.POST.get('tool_name'))
    explicit_policy_override = False
    if request.user.is_staff:
        try:
            user = User.objects.get(id=request.POST['impersonate'])
        except:
            user = request.user
        try:
            explicit_policy_override = request.POST[
                'explicit_policy_override'] == 'true'
        except:
            pass
    else:
        user = request.user
    # Create the new reservation:
    new_reservation = Reservation()
    new_reservation.user = user
    new_reservation.creator = request.user
    new_reservation.tool = tool
    new_reservation.start = start
    new_reservation.end = end
    new_reservation.short_notice = determine_insufficient_notice(tool, start)
    policy_problems, overridable = check_policy_to_save_reservation(
        None, new_reservation, user, explicit_policy_override)

    # If there was a problem in saving the reservation then return the error...
    if policy_problems:
        return render(
            request, 'calendar/policy_dialog.html', {
                'policy_problems': policy_problems,
                'overridable': overridable and request.user.is_staff
            })

    # All policy checks have passed.

    # If the user only has one project then associate it with the reservation.
    # Otherwise, present a dialog box for the user to choose which project to associate.
    active_projects = user.active_projects()
    if len(active_projects) == 1:
        new_reservation.project = active_projects[0]
    else:
        try:
            new_reservation.project = Project.objects.get(
                id=request.POST['project_id'])
        except:
            return render(request, 'calendar/project_choice.html',
                          {'active_projects': active_projects})

    # Make sure the user is actually enrolled on the project. We wouldn't want someone
    # forging a request to reserve against a project they don't belong to.
    if new_reservation.project not in new_reservation.user.active_projects():
        return render(request, 'calendar/project_choice.html',
                      {'active_projects': active_projects()})

    configured = (request.POST.get('configured') == "true")
    # If a reservation is requested and the tool does not require configuration...
    if not tool.is_configurable():
        new_reservation.save()
        return HttpResponse()

    # If a reservation is requested and the tool requires configuration that has not been submitted...
    elif tool.is_configurable() and not configured:
        configuration_information = tool.get_configuration_information(
            user=user, start=start)
        return render(request, 'calendar/configuration.html',
                      configuration_information)

    # If a reservation is requested and configuration information is present also...
    elif tool.is_configurable() and configured:
        new_reservation.additional_information, new_reservation.self_configuration = extract_configuration(
            request)
        # Reservation can't be short notice if the user is configuring the tool themselves.
        if new_reservation.self_configuration:
            new_reservation.short_notice = False
        new_reservation.save()
        return HttpResponse()

    return HttpResponseBadRequest(
        "Reservation creation failed because invalid parameters were sent to the server."
    )
예제 #7
0
def create_outage(request):
	""" Create an outage. """
	try:
		start, end = extract_times(request.POST)
		item_type = ReservationItemType(request.POST['item_type'])
		item_id = request.POST.get('item_id')
	except Exception as e:
		return HttpResponseBadRequest(str(e))
	item = get_object_or_404(item_type.get_object_class(), id=item_id)
	# Create the new reservation:
	outage = ScheduledOutage()
	outage.creator = request.user
	outage.category = request.POST.get('category', '')[:200]
	outage.outage_item = item
	outage.start = start
	outage.end = end

	# If there is a policy problem for the outage then return the error...
	policy_problem = check_policy_to_create_outage(outage)
	if policy_problem:
		return HttpResponseBadRequest(policy_problem)

	# Make sure there is at least an outage title
	if not request.POST.get('title'):
		dictionary = {
			'categories': ScheduledOutageCategory.objects.all(),
			'recurrence_intervals': recurrence_frequency_display,
			'recurrence_date_start': start.date(),
		}
		return render(request, 'calendar/scheduled_outage_information.html', dictionary)

	outage.title = request.POST['title']
	outage.details = request.POST.get('details', '')

	if request.POST.get('recurring_outage') == 'on':
		# we have to remove tz before creating rules otherwise 8am would become 7am after DST change for example.
		start_no_tz = outage.start.replace(tzinfo=None)
		end_no_tz = outage.end.replace(tzinfo=None)

		submitted_frequency = request.POST.get('recurrence_frequency')
		submitted_date_until = request.POST.get('recurrence_until', None)
		date_until = end.replace(hour=0, minute=0, second=0)
		if submitted_date_until:
			date_until = localize(datetime.strptime(submitted_date_until, '%m/%d/%Y'))
		date_until += timedelta(days=1, seconds=-1) # set at the end of the day
		by_week_day = None
		if submitted_frequency == 'DAILY_WEEKDAYS':
			by_week_day = (rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR)
		elif submitted_frequency == 'DAILY_WEEKENDS':
			by_week_day = (rrule.SA, rrule.SU)
		frequency = recurrence_frequencies.get(submitted_frequency, rrule.DAILY)
		rules: Iterable[datetime] = rrule.rrule(dtstart=start, freq=frequency, interval=int(request.POST.get('recurrence_interval',1)), until=date_until, byweekday=by_week_day)
		for rule in list(rules):
			recurring_outage = ScheduledOutage()
			recurring_outage.creator = outage.creator
			recurring_outage.category = outage.category
			recurring_outage.outage_item = outage.outage_item
			recurring_outage.title = outage.title
			recurring_outage.details = outage.details
			recurring_outage.start = localize(start_no_tz.replace(year=rule.year, month=rule.month, day=rule.day))
			recurring_outage.end = localize(end_no_tz.replace(year=rule.year, month=rule.month, day=rule.day))
			recurring_outage.save()
	else:
		outage.save()

	return HttpResponse()