fix(worklog): add full-date tooltip + hide event-time under 420px (Fable UX)
Two non-blocking UX improvements from the Fable gate on #5739: 1. Full date+time tooltip (title attr) on the worklog event-time label — the bare clock is date-ambiguous when a settled session is reviewed later or a run crosses midnight. New _activityFullClockLabel (range-guarded so a bad epoch never yields 'Invalid Date' in the tooltip) + test. 2. Hide the time label under 420px — its ~50px of fixed chrome squeezes the collapsed row's flexible preview toward zero on phones. Co-authored-by: rodboev.
This commit is contained in:
1 parent
a86324985e
commit
97fe772fdb
3 files changed
+50
No files matched your search
@@ -4118,6 +4118,13 @@ body.resizing .sidebar{transition:none!important;}
|
||||
white-space:nowrap;
|
||||
font-size:10px;
|
||||
}
|
||||
/* Narrow viewports: the ~50px of fixed time-label chrome squeezes the collapsed
|
||||
row's flexible preview (the most informative part) toward zero. Hide the label
|
||||
under ~420px; the full timing is still available in Compact/expanded review and
|
||||
via the title tooltip on wider screens. (#5739 Fable UX fix.) */
|
||||
@media (max-width:420px){
|
||||
.transparent-event-time{ display:none; }
|
||||
}
|
||||
.transparent-event-row .thinking-card-label{
|
||||
display:inline;
|
||||
flex:0 0 auto;
|
||||
|
||||
@@ -5568,6 +5568,18 @@ function _activityClockLabel(ts){
|
||||
if(!Number.isFinite(stamp)||stamp<=0)return'';
|
||||
try{return new Date(stamp*1000).toLocaleTimeString([], {hour:'numeric',minute:'2-digit'});}catch(_){return'';}
|
||||
}
|
||||
// Full date+time label for the worklog event-time tooltip (title attr). Guards the
|
||||
// same valid-Date range as _timestampSeconds so a bad epoch never yields "Invalid
|
||||
// Date" in the tooltip. (#5739)
|
||||
function _activityFullClockLabel(ts){
|
||||
const stamp=Number(ts);
|
||||
if(!Number.isFinite(stamp)||stamp<=0||stamp>8.64e12)return'';
|
||||
try{
|
||||
const d=new Date(stamp*1000);
|
||||
if(isNaN(d.getTime()))return'';
|
||||
return d.toLocaleString([], {year:'numeric',month:'short',day:'numeric',hour:'numeric',minute:'2-digit'});
|
||||
}catch(_){return'';}
|
||||
}
|
||||
function _timestampSeconds(value){
|
||||
if(value===undefined||value===null||value==='') return null;
|
||||
if(value instanceof Date){
|
||||
@@ -5663,6 +5675,11 @@ function _syncTransparentEventTimestamp(row, header, opts){
|
||||
timeEl.className='transparent-event-time';
|
||||
}
|
||||
timeEl.textContent=label;
|
||||
// Full date+time tooltip: the bare clock label is date-ambiguous when a settled
|
||||
// session is reviewed days later (or a run crosses midnight), and timing is the
|
||||
// whole point of this label. (#5739 Fable UX fix.)
|
||||
const fullLabel=_activityFullClockLabel(ts);
|
||||
if(fullLabel) timeEl.setAttribute('title',fullLabel); else timeEl.removeAttribute('title');
|
||||
timeEl.setAttribute('data-event-at',String(ts));
|
||||
timeEl.setAttribute('data-event-at-source',source);
|
||||
row.setAttribute('data-event-at',String(ts));
|
||||
|
||||
@@ -247,6 +247,7 @@ global._toolWorklogListEl = () => null;
|
||||
global._activityKeyForLiveTurn = () => 'activity-key';
|
||||
global._assistantTurnBlocks = () => null;
|
||||
eval(extractFunc('_activityClockLabel'));
|
||||
eval(extractFunc('_activityFullClockLabel'));
|
||||
eval(extractFunc('_timestampSeconds'));
|
||||
eval(extractFunc('_firstValidTimestampSeconds'));
|
||||
eval(extractFunc('_transparentEventTimestampSeconds'));
|
||||
@@ -458,6 +459,31 @@ process.stdout.write(JSON.stringify({
|
||||
assert data["normalLabel"]
|
||||
|
||||
|
||||
def test_full_clock_label_tooltip_includes_date_and_rejects_bad_epochs():
|
||||
# The worklog time label carries a full date+time tooltip (title attr) so a
|
||||
# settled session reviewed days later (or a run crossing midnight) is not
|
||||
# date-ambiguous. Bad epochs must yield '' (never 'Invalid Date'). (#5739 Fable.)
|
||||
data = _run_node(
|
||||
"""
|
||||
process.stdout.write(JSON.stringify({
|
||||
normal: _activityFullClockLabel(1700000901),
|
||||
huge: _activityFullClockLabel(1e20),
|
||||
zero: _activityFullClockLabel(0),
|
||||
negative: _activityFullClockLabel(-1),
|
||||
}));
|
||||
"""
|
||||
)
|
||||
|
||||
# a normal epoch yields a non-empty full label with the year present, no "Invalid Date"
|
||||
assert data["normal"]
|
||||
assert "Invalid Date" not in data["normal"]
|
||||
assert "2023" in data["normal"] or "2024" in data["normal"] or "2025" in data["normal"] or "2026" in data["normal"]
|
||||
# out-of-range / non-positive epochs yield empty string (no tooltip)
|
||||
assert data["huge"] == ""
|
||||
assert data["zero"] == ""
|
||||
assert data["negative"] == ""
|
||||
|
||||
|
||||
def test_settled_anchor_scene_rows_use_row_created_at_timestamps():
|
||||
data = _run_node(
|
||||
"""
|
||||
|
||||
Reference in new issue
Block a user