Skip to content

Commit

Permalink
SAK-46140 Add simple date shifter to provide some level of automation…
Browse files Browse the repository at this point in the history
… for Date Manager (sakaiproject#9708)
  • Loading branch information
plukasew authored Aug 31, 2021
1 parent 8c4c8ae commit b178261
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@
}
}

#dateShifterDays {
box-sizing: content-box;
width: 5ch;
}

/*Start of Site Group Manager*/
.wizard-step-active {
background-color: var(--sakai-primary-color-1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,9 @@ modal.confirm.instruction = You are about to modify the following course dates:
page.instructions = Edit dates in batch

success.message = The dates were updated successfully.

dateshifter.label.before=Shift dates by
dateshifter.label.after=day(s). Remember to click Save Changes at the bottom of the page to save your adjustments.
dateshifter.all.button=Apply to all dates
dateshifter.visible.button=Apply to expanded sections only
dateshifter.error.nonnumeric=Please enter a non-zero whole number between -9999 and 9999.
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,44 @@ DTMN.initDatePicker = function(updates, notModified)
DTMN.attachDatePicker(selector, updates, notModified);
spinner.classList.remove("spinPlaceholder");
}, 25); // delay 25ms to give browser time to render the spinner
});
});
$(target).on("shown.bs.collapse", function()
{
DTMN.validateShiftInput();
});
$(target).on("hidden.bs.collapse", function()
{
DTMN.validateShiftInput();
});
}
}
};

DTMN.initShifter = function(updates, notModified)
{
DTMN.validShiftRegex = /^-{0,1}\d{1,4}$/;

DTMN.shiftErrorBanner = document.getElementById("dateShifterError");
DTMN.shiftInput = document.getElementById("dateShifterDays");
DTMN.shiftAllBtn = document.getElementById("shiftAllDates");
DTMN.shiftVisibleBtn = document.getElementById("shiftVisibleDates");

DTMN.shiftInput.addEventListener("input", function()
{
DTMN.validateShiftInput();
}, false);

DTMN.shiftAllBtn.addEventListener("click", function()
{
DTMN.handleShiftButtonClick(this, DTMN.collapseElements, updates, notModified);
}, false);

DTMN.shiftVisibleBtn.addEventListener("click", function()
{
DTMN.handleShiftButtonClick(this, DTMN.findExpandedSections(), updates, notModified);
}, false);
};

DTMN.attachDatePicker = function(selector, updates, notModified)
{
$(selector).each(function (idx, elt) {
Expand Down Expand Up @@ -105,3 +138,119 @@ DTMN.attachDatePicker = function(selector, updates, notModified)
}
});
};

DTMN.handleShiftButtonClick = function(button, collapseElements, updates, notModified)
{
DTMN.disableShiftControls(button);
window.setTimeout(function()
{
for (let i = 0; i < collapseElements.length; i++)
{
// use setTimeout() to space out the function calls so the browser doesn't report the page as unresponsive
// the last function will remove the spinner and re-enable the button
window.setTimeout(function() { DTMN.shiftDates(updates, notModified, collapseElements[i].id, button, i === collapseElements.length - 1); }, 10);
}
}, 25);
};

DTMN.validateShiftInput = function()
{
const val = DTMN.shiftInput.value;
if (val === "" || val === "-")
{
DTMN.hideShiftError();
DTMN.disableShiftButtons();
return;
}
else if (!val.match(DTMN.validShiftRegex))
{
DTMN.showShiftError();
DTMN.disableShiftButtons();
return;
}

const days = parseInt(val);

DTMN.hideShiftError();

DTMN.shiftAllBtn.disabled = days === 0;

DTMN.shiftVisibleBtn.disabled = days === 0 || DTMN.findExpandedSections().length === 0;
};

DTMN.findExpandedSections = function()
{
return DTMN.collapseElements.filter(function (e) { return e.getAttribute("aria-expanded") === "true"; });
};

DTMN.hideShiftError = function()
{
DTMN.shiftErrorBanner.classList.add("hidden");
DTMN.shiftErrorBanner.removeAttribute("role");
};

DTMN.showShiftError = function()
{
DTMN.shiftErrorBanner.classList.remove("hidden");
DTMN.shiftErrorBanner.setAttribute("role", "alert");
};

DTMN.disableShiftControls = function(button)
{
DTMN.shiftInput.disabled = true;
DTMN.disableShiftButtons();
button.classList.add("spinButton");
};

DTMN.disableShiftButtons = function()
{
DTMN.shiftAllBtn.disabled = true;
DTMN.shiftVisibleBtn.disabled = true;
};

DTMN.enableShiftControls = function(button)
{
button.classList.remove("spinButton");
DTMN.validateShiftInput();
DTMN.shiftInput.disabled = false;
};

DTMN.shiftDates = function(updates, notModified, rootElementId, button, enableButton)
{
// validate input again just in case
if (!DTMN.shiftInput.value.match(DTMN.validShiftRegex))
{
DTMN.showShiftError();
DTMN.disableShiftButtons();
return;
}

const days = parseInt(DTMN.shiftInput.value);

// attach any missing datepickers
const rootElement = "#" + rootElementId;
DTMN.attachDatePicker(rootElement + " .datepicker:not(.hasDatepicker)", updates, notModified);

$(rootElement + " .datepicker.hasDatepicker").each(function()
{
const pickerDate = $(this).datepicker("getDate");
if (pickerDate !== null)
{
const newDate = new Date(Number(pickerDate));
newDate.setDate(newDate.getDate() + days);
$(this).datepicker("setDate", newDate);

// setDate doesn't cause the hidden field that stores the date to update, so we have to do it ourselves
// find the associated hidden field, set it, trigger the onchange event manually
const $td = $(this).closest('td');
const $hidden = $td.find('input[type=hidden]');
$hidden.val(moment(newDate).format());
$hidden.change();
}
});

if (enableButton)
{
DTMN.enableShiftControls(button);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@
<h1 th:text="#{page.instructions}">Add/Edit Options in batch</h1>
</div>

<div class="date-manager-shifter panel-group">
<p>
<div class="sak-banner-error hidden" id="dateShifterError">
<span th:text="#{dateshifter.error.nonnumeric}"></span>
</div>
<label>
<span th:text="#{dateshifter.label.before}" th:remove="tag"></span>
<input id="dateShifterDays" type="text"></input>
<span th:text="#{dateshifter.label.after}" th:remove="tag"></span>
</label>
</p>
<button id="shiftAllDates" th:text="#{dateshifter.all.button}" disabled></button>
<button id="shiftVisibleDates" th:text="#{dateshifter.visible.button}" disabled></button>
</div>

<form class="panel-group" id="date-manager-form" method="POST">
<div class="sak-banner-error hidden" id="form-errors">
<span th:text="#{errors.instruction}">Your update could not be saved due to the following errors:</span>
Expand Down Expand Up @@ -234,6 +249,7 @@ <h4 th:text="#{modal.confirm}" class="modal-title">Confirm</h4>
var notModified = [];

DTMN.initDatePicker(updates, notModified);
DTMN.initShifter(updates, notModified);

function printErrors() {
$('.errors').empty();
Expand Down

0 comments on commit b178261

Please sign in to comment.