Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/org/labkey/targetedms/view/instrumentCalendar.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
{
dependencies.add("internal/jQuery");
dependencies.add("targetedms/yearCalendar");
dependencies.add("TargetedMS/js/scheduleUtils.js");
}
%>

Expand Down Expand Up @@ -51,8 +52,8 @@
$('#delete-event').css('display', event.annotation ? '' : 'none');

$('#event-modal input[name="event-description"]').val(event.annotation ? event.annotation.description : '');
$('#event-modal input[name="event-start-date"]').val(startDate.getFullYear() + '-' + (startDate.getMonth() + 1 < 10 ? '0' : '') + (startDate.getMonth() + 1) + '-' + (startDate.getDate() < 10 ? '0' : '') + startDate.getDate());
$('#event-modal input[name="event-end-date"]').val(endDate.getFullYear() + '-' + (endDate.getMonth() + 1 < 10 ? '0' : '') + (endDate.getMonth() + 1) + '-' + (endDate.getDate() < 10 ? '0' : '') + endDate.getDate());
$('#event-modal input[name="event-start-date"]').val(ScheduleUtils.toDateValue(startDate));
$('#event-modal input[name="event-end-date"]').val(ScheduleUtils.toDateValue(endDate));
$('#annotation-save-error').text('');
$('#event-modal').modal();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ public void testSchedule() throws IOException, CommandException
{
String originalStart = getFormElement(START_DATE_TIME_FIELD.findElement(getDriver()));
String originalEnd = getFormElement(END_DATE_TIME_FIELD.findElement(getDriver()));
// Pin the 8AM/5PM defaults so a regression that zeroes or shifts the time is caught even on agents whose timezone would otherwise hide it.
assertTrue("Start field should default to 8AM, was: " + originalStart, originalStart.endsWith("T08:00"));
assertTrue("End field should default to 5PM, was: " + originalEnd, originalEnd.endsWith("T17:00"));
// Try scheduling over the first reservation and verify it is blocked
setFormElement(START_DATE_TIME_FIELD.findElement(getDriver()), originalStart.replace("-03T", "-02T"));
setFormElement(END_DATE_TIME_FIELD.findElement(getDriver()), originalEnd.replace("-03T", "-02T"));
Expand All @@ -197,6 +200,9 @@ public void testSchedule() throws IOException, CommandException

assertProjectEventCounts(2, 0);

// The event chip time range is rendered via DateFormat (the patched parseTime path); verify it shows the real 8AM-5PM range, not a zeroed 00:00 - 00:00 as happened in colon-labelled timezones.
assertEquals("Event chip should show the 8AM-5PM time range", "08:00 - 17:00", getText(Locator.css(".activeProjectEvent .event-date")));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude is concerned that this would fail if the server and browser are using different time zones. That's the Honolulu TZ config, so if that's passing, we should be fine.


doAndWaitForPageToLoad(() -> selectOptionByText(PROJECT_DROP_DOWN, PROJECT_2));

scheduleInstrument(yearMonth + "-04", false);
Expand Down
12 changes: 12 additions & 0 deletions webapp/TargetedMS/js/scheduleUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@
(function(window) {
const utils = {};

const pad = function(n) { return (n < 10 ? '0' : '') + n; };

// Date-only 'yyyy-MM-dd' wire form from local fields.
utils.toDateValue = function(date) {
return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate());
};

// Format a Date as datetime-local's fixed 'yyyy-MM-ddTHH:mm' wire form from local fields; avoids DateFormat, which zeroes the time in timezones whose label contains a colon (e.g. Honolulu).
utils.toDateTimeLocalValue = function(date) {
return utils.toDateValue(date) + 'T' + pad(date.getHours()) + ':' + pad(date.getMinutes());
};

// Convert a CSS color string (named, rgb, hex) to standard 6-digit HEX color (#RRGGBB)
utils.stringToColor = function(color) {
if (!color) return '#888888';
Expand Down
22 changes: 13 additions & 9 deletions webapp/TargetedMS/js/scheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,7 @@ $(function() {
let bgColor = e.event.extendedProps.project === project ? e.backgroundColor : 'gray';
const cl = e.event.extendedProps.project === project ? 'activeProjectEvent' : 'otherProjectEvent';
let textColor = ScheduleUtils.getContrastTextColor(ScheduleUtils.stringToColor(bgColor));
let timeFormatString = LABKEY.container.formats.timeFormat;
// Strip seconds and milliseconds
timeFormatString = timeFormatString.replace(':ss', '').replace('.SSS', '');
let dateStr = DateFormat.format.date(e.event.start, timeFormatString) + ' - ' + DateFormat.format.date(e.event.end, timeFormatString);
let dateStr = ScheduleUtils.formatTimeRange(e.event.start, e.event.end);
let style = 'background-color: ' + LABKEY.Utils.encodeHtml(bgColor) + '; color: ' + LABKEY.Utils.encodeHtml(textColor) + ';' + 'width: 100%';
content += '<div class="' + LABKEY.Utils.encodeHtml(cl) + '" style="' + style + ';">'
+ '<div class="event-date">' + LABKEY.Utils.encodeHtml(dateStr) + '</div>'
Expand Down Expand Up @@ -396,8 +393,8 @@ $(function() {
endDate.setDate(endDate.getDate() - 1);
}

let startDateFormatted = DateFormat.format.date(startDate, LABKEY.container.formats.dateTimeFormat);
let endDateFormatted = DateFormat.format.date(endDate, LABKEY.container.formats.dateTimeFormat);
let startDateFormatted = ScheduleUtils.toDateTimeLocalValue(startDate);
let endDateFormatted = ScheduleUtils.toDateTimeLocalValue(endDate);

// remove the old event log rows
removeEventLog();
Expand Down Expand Up @@ -581,6 +578,13 @@ $(function() {
});

function fetchInstrumentCosts(instrumentId, startDate, endDate) {
// Normalize to Date: callers pass either Date objects (hover) or seconds-less datetime-local strings (post-save), which DateFormat can't parse as-is.
const start = new Date(startDate);
const end = new Date(endDate);
// Bail on degenerate input so the cost log never renders $NaN or garbage dates (mirrors calculateAndRenderCostPreview).
if (isNaN(start.getTime()) || isNaN(end.getTime()) || end <= start) {
return;
}
LABKEY.Query.selectRows({
schemaName: 'targetedms',
queryName: 'instrumentRate',
Expand All @@ -595,7 +599,7 @@ $(function() {
}
let fee = data.rows[0].fee;
let rateType = data.rows[0].rateType;
let cost = fee * (Math.abs(new Date(endDate) - new Date(startDate))) / 1000 / 60 / 60;
let cost = fee * (Math.abs(end - start)) / 1000 / 60 / 60;

// query the rateType
LABKEY.Query.selectRows({
Expand All @@ -608,8 +612,8 @@ $(function() {
success: function (data) {
let setupFee = data.rows[0].setupFee;

let startDateFormatted = DateFormat.format.date(startDate, LABKEY.container.formats.dateTimeFormat);
let endDateFormatted = DateFormat.format.date(endDate, LABKEY.container.formats.dateTimeFormat);
let startDateFormatted = DateFormat.format.date(start, LABKEY.container.formats.dateTimeFormat);
let endDateFormatted = DateFormat.format.date(end, LABKEY.container.formats.dateTimeFormat);

let tableElt = document.getElementById('event-cost-table');
let rowElt = document.createElement('tr');
Expand Down
Loading