fix(widgets): widget dates in the user's time zone #23

Merged
KofTwentyTwo merged 1 commits from fix/widget-timezone into develop 2026-10-14 17:37:51 +00:00
2 changed files with 8 additions and 6 deletions

No files matched your search

@@ -19,7 +19,6 @@ package com.kingsrook.qbits.marketing.widgets;
import java.io.Serializable;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
@@ -95,7 +94,7 @@ public final class MarketingWidgets
public static final String CAMPAIGN_RESULTS = "marketing_campaign_results";
public static final String CONTENT_PROPOSAL = "marketing_content_proposal";
private static final DateTimeFormatter WHEN_FORMAT = DateTimeFormatter.ofPattern("MMM d, yyyy h:mm a 'UTC'", Locale.US).withZone(ZoneOffset.UTC);
private static final DateTimeFormatter WHEN_FORMAT = DateTimeFormatter.ofPattern("MMM d, yyyy h:mm a z", Locale.US);
public static final List<String> HOME_WIDGETS = List.of(NEEDS_ATTENTION, CAMPAIGNS, AGENT_ACTIVITY, CONFIGURATION);
@@ -203,12 +202,14 @@ public final class MarketingWidgets
/*******************************************************************************
** A date-time for people: "Oct 14, 2026 4:53 PM UTC" (empty when null).
** A date-time for people, in the user's time zone (the session's, else the
** instance's), as the record screens show it: "Oct 14, 2026 11:53 AM CDT"
** (empty when null).
*******************************************************************************/
static String when(Object value)
{
Instant instant = ValueUtils.getValueAsInstant(value);
return (instant == null ? "" : WHEN_FORMAT.format(instant));
return (instant == null ? "" : WHEN_FORMAT.withZone(ValueUtils.getSessionOrInstanceZoneId()).format(instant));
}
@@ -256,10 +256,11 @@ class EndToEndFlowTest extends BaseMarketingTest
com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput proposalInput = new com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput()
.withWidgetMetaData(com.kingsrook.qqq.backend.core.context.QContext.getQInstance().getWidget(com.kingsrook.qbits.marketing.widgets.MarketingWidgets.CONTENT_PROPOSAL));
proposalInput.setQueryParams(new java.util.HashMap<>(java.util.Map.of("id", String.valueOf(contentId))));
String proposal = ((com.kingsrook.qqq.backend.core.model.dashboard.widgets.RawHTML) new com.kingsrook.qqq.backend.core.actions.dashboard.RenderWidgetAction()
com.kingsrook.qqq.backend.core.context.QContext.getQSession().setValue(com.kingsrook.qqq.backend.core.model.session.QSession.VALUE_KEY_USER_TIMEZONE, "America/Chicago");
String proposal =((com.kingsrook.qqq.backend.core.model.dashboard.widgets.RawHTML) new com.kingsrook.qqq.backend.core.actions.dashboard.RenderWidgetAction()
.execute(proposalInput).getWidgetData()).getHtml();
assertThat(proposal).as("a used-up approval is not shown as not approved").contains("used by an execution").doesNotContain("Not approved")
.containsPattern("[A-Z][a-z]{2} [0-9]{1,2}, [0-9]{4} [0-9]{1,2}:[0-9]{2} [AP]M UTC");
.containsPattern("[A-Z][a-z]{2} [0-9]{1,2}, [0-9]{4} [0-9]{1,2}:[0-9]{2} [AP]M C[DS]T");
///////////////////////////////////////////////////////////////////
// 7. recorded outcomes: the provider acceptance (test data) and //