Commit 29258b2c authored by Leigh B Stoller's avatar Leigh B Stoller

Various tweaks to reservation UI:

* Allow start to be optional; means "now".

* When selecting the current day, disable hours in the past.

* Catch a few more form errors.

* When editing, the start time might be in the past. Do not consider
  that an error, just pass it through since the backend is okay with
  it.
parent 7c554b32
......@@ -198,8 +198,7 @@ sub DoReserve()
}
else {
usage()
if (! (defined($count) && defined($type) &&
defined($start) && defined($end)));
if (! (defined($count) && defined($type) && defined($end)));
if ($type !~ /^[-\w]+$/) {
fatal("Type is not a string");
......
#!/usr/bin/perl -wT
#
# Copyright (c) 2008-2016 University of Utah and the Flux Group.
# Copyright (c) 2008-2017 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
......@@ -647,12 +647,12 @@ sub Reserve($)
my ($count,$start,$end,$type);
if (!$update) {
foreach my $field ("count", "start", "end", "type") {
foreach my $field ("count", "end", "type") {
return GeniResponse->MalformedArgsResponse("Missing $field")
if (! (exists($argref->{$field}) && $argref->{$field} ne ""));
}
$count = $argref->{"count"};
$start = $argref->{"start"};
$start = $argref->{"start"} if (exists($argref->{"start"}));
$end = $argref->{"end"};
$type = $argref->{"type"};
......
<?php
#
# Copyright (c) 2006-2016 University of Utah and the Flux Group.
# Copyright (c) 2006-2017 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -217,6 +217,17 @@ class Aggregate
}
return $am_array;
}
function ThisAggregate()
{
global $DEFAULT_AGGREGATE_URN;
if (! ($aggregate = Aggregate::Lookup($DEFAULT_AGGREGATE_URN))) {
TBERROR("Aggregate::SupportsReservations: ".
"Could not load aggregate $urn!", 1);
}
return $aggregate;
}
}
#
......
......@@ -91,10 +91,20 @@ $(function ()
// Insert datepickers after html inserted.
$("#reserve-request-form #start_day").datepicker({
minDate: 0, /* earliest date is today */
showButtonPanel: true,
onSelect: function (dateString, dateobject) {
DateChange("#start_day");
modified_callback();
}
});
$("#reserve-request-form #end_day").datepicker({
minDate: 0, /* earliest date is today */
showButtonPanel: true,
onSelect: function (dateString, dateobject) {
DateChange("#end_day");
modified_callback();
}
});
/*
* Callback when something changes so that we can toggle the
......@@ -109,6 +119,44 @@ $(function ()
LoadReservations();
}
/*
* When the date selected is today, need to disable the hours
* before the current hour.
*/
function DateChange(which)
{
var date = $("#reserve-request-form " + which).datepicker("getDate");
var now = new Date();
var selecter;
if (which == "#start_day") {
selecter = "#reserve-request-form #start_hour";
}
else {
selecter = "#reserve-request-form #end_hour";
}
if (moment(date).isSame(Date.now(), "day")) {
for (var i = 0; i <= now.getHours(); i++) {
/*
* Before we disable the option, see if it is selected.
* If so, we want make the user re-select the hour.
*/
if ($(selecter + " option:selected").val() == i) {
$(selecter).val("");
}
$(selecter + " option[value='" + i + "']")
.attr("disabled", "disabled");
}
}
else {
for (var i = 0; i <= now.getHours(); i++) {
$(selecter + " option[value='" + i + "']")
.removeAttr("disabled");
}
}
}
//
// Check form validity. This does not check whether the reservation
// is valid.
......@@ -130,18 +178,36 @@ $(function ()
*/
var start_day = $('#reserve-request-form [name=start_day]').val();
var start_hour = $('#reserve-request-form [name=start_hour]').val();
if (start_day && start_hour) {
if (start_day && !start_hour) {
aptforms.GenerateFormErrors('#reserve-request-form',
{"start" : "Missing hour"});
return;
}
else if (!start_day && start_hour) {
aptforms.GenerateFormErrors('#reserve-request-form',
{"start" : "Missing day"});
return;
}
else if (start_day && start_hour) {
var start = moment(start_day, "MM/DD/YYYY");
start.hour(start_hour);
console.log("start", start);
$('#reserve-request-form [name=start]').val(start.format());
}
var end_day = $('#reserve-request-form [name=end_day]').val();
var end_hour = $('#reserve-request-form [name=end_hour]').val();
if (end_day && end_hour) {
if (end_day && !end_hour) {
aptforms.GenerateFormErrors('#reserve-request-form',
{"end" : "Missing hour"});
return;
}
else if (!end_day && end_hour) {
aptforms.GenerateFormErrors('#reserve-request-form',
{"end" : "Missing day"});
return;
}
else if (end_day && end_hour) {
var end = moment(end_day, "MM/DD/YYYY");
end.hour(end_hour);
console.log("end", end);
$('#reserve-request-form [name=end]').val(end.format());
}
aptforms.CheckForm('#reserve-request-form', "reserve",
......@@ -284,6 +350,12 @@ $(function ()
$('#reserve-request-form [name=end_hour]')
.val(end.format("H"));
console.log(start, end);
// Set the hour selectors properly in the datepicker object.
$("#reserve-request-form #start_day")
.datepicker("setDate", start.format("MM/DD/YYYY"));
$("#reserve-request-form #end_day")
.datepicker("setDate", end.format("MM/DD/YYYY"));
};
sup.ShowWaitWait();
var xmlthing = sup.CallServerMethod(null, "reserve",
......
<?php
#
# Copyright (c) 2000-2016 University of Utah and the Flux Group.
# Copyright (c) 2000-2017 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -55,17 +55,27 @@ function Do_Reserve()
$formfields = $ajax_args["formfields"];
$errors = array();
error_log(print_r($formfields, TRUE));
#
# All fields required,
#
$required = array("pid", "count", "start", "end",
"cluster", "type");
$required = array("pid", "count", "end", "cluster", "type");
foreach ($required as $field) {
if (!isset($formfields[$field]) || $formfields[$field] == "") {
$errors[$field] = "Missing field";
}
}
#
# Update mode; we get the idx of the current reservation.
#
if (isset($formfields["idx"])) {
$idx = $formfields["idx"];
if (!TBvalid_integer($idx)) {
$errors["error"] = "Bad index for reservation update";
}
}
# Admins do not need a reason.
if (!ISADMIN() &&
(!isset($formfields["reason"]) || $formfields["reason"] == "")) {
......@@ -82,10 +92,16 @@ function Do_Reserve()
if (!TBvalid_integer($formfields["count"])) {
$errors["count"] = TBFieldErrorString();
}
$start_ascii = $formfields["start"];
$start = strtotime($formfields["start"]);
if (!$start) {
$errors["start"] = "Cannot parse date";
if (isset($formfields["start"]) && $formfields["start"] != "") {
$start_ascii = $formfields["start"];
$start = strtotime($formfields["start"]);
if (!$start) {
$errors["start"] = "Cannot parse date";
}
elseif ($start < time() && !isset($idx)) {
# In update mode, just let it through.
$errors["start"] = "In the past";
}
}
$end_ascii = $formfields["end"];
$end = strtotime($formfields["end"]);
......@@ -112,15 +128,6 @@ function Do_Reserve()
!$project->AccessCheck($this_user, $TB_PROJECT_CREATEEXPT)) {
$errors["error"] = "Not enough permission in project";
}
#
# Update mode; we get the idx of the current reservation.
#
if (isset($formfields["idx"])) {
$idx = $formfields["idx"];
if (!TBvalid_integer($idx)) {
$errors["error"] = "Bad index for reservation update";
}
}
if (count($errors)) {
SPITAJAX_ERROR(2, $errors);
return;
......@@ -142,7 +149,8 @@ function Do_Reserve()
#
$args = "-t " . escapeshellarg($formfields["type"]) . " ".
(isset($idx) ? "-u $idx " : "") .
"-s $start -e $end $pid " . $formfields["count"];
(isset($start) ? "-s $start " : "") .
" -e $end $pid " . $formfields["count"];
#
# Do a precheck.
......
......@@ -47,6 +47,7 @@ if (!ISADMIN()) {
# Verify page arguments. Cluster is a domain that we turn into a URN.
#
$optargs = OptionalPageArguments("edit", PAGEARG_BOOLEAN,
"debug", PAGEARG_BOOLEAN,
"cluster", PAGEARG_STRING,
"project", PAGEARG_PROJECT,
"idx", PAGEARG_INTEGER);
......@@ -103,6 +104,9 @@ echo "</script>\n";
if ($edit) {
$ams = array($aggregate);
}
elseif (isset($debug) && $debug) {
$ams = array(Aggregate::ThisAggregate());
}
else {
$ams = Aggregate::SupportsReservations();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment