Skip to content

Commit 9c92112

Browse files
authored
refactor(front): set proper timestamps for workflow pipelines (#117)
1 parent 5308ada commit 9c92112

File tree

14 files changed

+146
-48
lines changed

14 files changed

+146
-48
lines changed

front/assets/js/activity_monitor/items/item.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ function renderDebug(item, state) {
143143
}
144144
}
145145

146-
function relativeTime(time) {
147-
return `<relative-time datetime="${time}"></relative-time>`
146+
function timeAgo(time) {
147+
return `<time-ago datetime="${time}"></time-ago>`
148148
}
149149

150150
function renderPipeline(item, state) {
@@ -178,7 +178,7 @@ function renderPipeline(item, state) {
178178
<div class="w-25-l">
179179
<div class="flex flex-row-reverse-l items-center">
180180
<img src="${item.user_icon_path}" class="db br-100 ba b--black-50" width="32" height="32">
181-
<div class="f5 gray ml2 ml3-m ml0-l mr3-l tr-l">${relativeTime(item.created_at)} <br> by ${escapeHtml(item.user_name)}</div>
181+
<div class="f5 gray ml2 ml3-m ml0-l mr3-l tr-l">${timeAgo(item.created_at)} <br> by ${escapeHtml(item.user_name)}</div>
182182
</div>
183183
</div>
184184
</div>

front/assets/js/agents/components/activity_item.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ const PipelineActivity = (props: ActivityProps) => {
117117
height="32"
118118
/>
119119
<div className="f5 gray ml2 ml3-m ml0-l mr3-l tr-l">
120-
<relative-time dateTime={item.createdAt}/>
120+
<time-ago datetime={item.createdAt}/>
121121
<br/> by {item.userName}
122122
</div>
123123
</div>
@@ -227,7 +227,7 @@ export const DebugActivity = (props: ActivityProps) => {
227227
height="32"
228228
/>
229229
<div className="f5 gray ml2 ml3-m ml0-l mr3-l tr-l">
230-
<relative-time dateTime={props.item.createdAt}/>
230+
<time-ago datetime={props.item.createdAt}/>
231231
<br/> by {props.item.userName}
232232
</div>
233233
</div>

front/assets/js/app.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import $ from "jquery";
55
import { install } from '@github/hotkey';
66
import { Userpilot } from "userpilot"
77

8+
import { defineTimeAgoElement } from "./time_ago";
89
import { Tippy } from "./tippy";
910
import { JumpTo } from "./jump_to/jump_to";
1011
import { Pollman } from "./pollman";
@@ -475,10 +476,7 @@ export var App = {
475476
})
476477
}
477478

478-
// This has to be required at the bottom of the body element
479-
// therefore we require it within App.run() function
480-
require("time-elements");
481-
479+
defineTimeAgoElement()
482480
managePageHeaderShaddows()
483481
enableMagicBreadcrumbs()
484482
maybeEnableUserpilot()

front/assets/js/custom_types/time-elements.d.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// eslint-disable-next-line
2+
import * as preact from "preact";
3+
import { h } from "preact";
4+
// In place for time-ago element defined in /assets/time_ago.js. Without these definitions relative-time element will not be visible for JSX.
5+
6+
interface TimeAgoProps extends h.JSX.HTMLAttributes<HTMLElement> {
7+
datetime: string;
8+
}
9+
// eslint-disable-next-line
10+
declare module "preact" {
11+
namespace JSX {
12+
interface IntrinsicElements {
13+
[`time-ago`]: TimeAgoProps;
14+
}
15+
}
16+
}

front/assets/js/time_ago.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
class TimeAgo extends HTMLElement {
2+
constructor() {
3+
super();
4+
this.datetime = this.getAttribute("datetime");
5+
this.locale = this.getAttribute("locale") || "en"; // Default locale: English
6+
this.updateTime = this.updateTime.bind(this);
7+
}
8+
9+
connectedCallback() {
10+
this.updateTime();
11+
this.interval = setInterval(this.updateTime, 1000);
12+
}
13+
14+
disconnectedCallback() {
15+
clearInterval(this.interval);
16+
}
17+
18+
updateTime() {
19+
if (!this.datetime) {
20+
this.textContent = "";
21+
return;
22+
}
23+
24+
const date = new Date(this.datetime);
25+
if (isNaN(date)) {
26+
this.textContent = "Invalid date";
27+
return;
28+
}
29+
30+
this.textContent = this.decorateRelative(date);
31+
}
32+
33+
decorateRelative(date) {
34+
const now = new Date();
35+
const diffInSeconds = Math.floor((now - date) / 1000);
36+
const daysDifference = Math.floor(diffInSeconds / 86400);
37+
38+
return daysDifference > 3 ? this.formatFullDate(date) : this.formatRelativeTime(diffInSeconds);
39+
}
40+
41+
formatRelativeTime(seconds) {
42+
const rtf = new Intl.RelativeTimeFormat(this.locale, { numeric: "auto" });
43+
44+
if (Math.abs(seconds) < 60) return rtf.format(-seconds, "second");
45+
if (Math.abs(seconds) < 3600) return rtf.format(-Math.floor(seconds / 60), "minute");
46+
if (Math.abs(seconds) < 86400) return rtf.format(-Math.floor(seconds / 3600), "hour");
47+
return rtf.format(-Math.floor(seconds / 86400), "day");
48+
}
49+
50+
formatFullDate(date) {
51+
const options = { weekday: "short", day: "numeric", month: "short", year: "numeric" };
52+
const formattedDate = date.toLocaleDateString(this.locale, options);
53+
54+
const [weekday, month, day, year] = formattedDate.replaceAll(",", "").split(" ");
55+
const suffixedDay = day + this.ordinalSuffix(parseInt(day, 10));
56+
57+
return `on ${weekday} ${suffixedDay} ${month} ${year}`;
58+
}
59+
60+
ordinalSuffix(day) {
61+
if ([11, 12, 13].includes(day)) return "th";
62+
switch (day % 10) {
63+
case 1: return "st";
64+
case 2: return "nd";
65+
case 3: return "rd";
66+
default: return "th";
67+
}
68+
}
69+
}
70+
71+
export function defineTimeAgoElement() {
72+
customElements.define("time-ago", TimeAgo);
73+
}

front/assets/package-lock.json

Lines changed: 0 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

front/assets/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
"querystringify": "^2.1.1",
5252
"react-router-dom": "^6.3.0",
5353
"semver": "^7.5.4",
54-
"time-elements": "^1.2.0",
5554
"tippy.js": "^6.3.7",
5655
"tom-select": "^2.0.3",
5756
"userpilot": "^1.3.5",

front/lib/front/utils.ex

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,10 @@ defmodule Front.Utils do
271271
end
272272

273273
@doc """
274-
Decorates a date in seconds in a relative format.
274+
Decorates a date in seconds or a DateTime in a relative format.
275+
If more than 3 days compared to the current date, display the whole date
276+
in: Weekday, Day Month Year format.
277+
275278
## Examples
276279
iex> alias Front.Utils, as: Utils
277280
iex> Utils.decorate_relative(0)
@@ -280,14 +283,40 @@ defmodule Front.Utils do
280283
""
281284
iex> Utils.decorate_relative(1616425200)
282285
"2 days ago"
286+
287+
iex> Utils.decorate_relative(~U[2025-03-07 22:05:26.833945Z])
288+
"Fri 07th Mar 2025"
283289
"""
284-
@spec decorate_relative(integer | float | nil) :: String.t()
290+
@spec decorate_relative(integer | float | DateTime.t() | nil) :: String.t()
285291
def decorate_relative(0), do: ""
286292
def decorate_relative(nil), do: ""
287293

288-
def decorate_relative(seconds) do
294+
def decorate_relative(seconds) when is_integer(seconds) do
289295
seconds
290296
|> DateTime.from_unix!()
291-
|> Timex.format!("{relative}", :relative)
297+
|> decorate_relative()
298+
end
299+
300+
def decorate_relative(date) do
301+
if Timex.diff(DateTime.utc_now(), date, :days) > 3 do
302+
unssufixed_date = Timex.format!(date, "%a %d %b %Y", :strftime)
303+
[weekday, day, month, year] = String.split(unssufixed_date, " ")
304+
305+
suffixed_day = day <> ordinal_suffix(String.to_integer(day))
306+
"on #{weekday} #{suffixed_day} #{month} #{year}"
307+
else
308+
Timex.format!(date, "{relative}", :relative)
309+
end
310+
end
311+
312+
defp ordinal_suffix(day) when day in [11, 12, 13], do: "th"
313+
314+
defp ordinal_suffix(day) do
315+
case rem(day, 10) do
316+
1 -> "st"
317+
2 -> "nd"
318+
3 -> "rd"
319+
_ -> "th"
320+
end
292321
end
293322
end

front/lib/front_web/templates/audit/index.html.eex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
<div><%= event.description %></div>
3939
</div>
4040
<div class="tr">
41-
<relative-time datetime="<%= DateTime.from_unix!(event.timestamp) %>" month="short" day="numeric" year="numeric" hour="numeric" minute="numeric" second="numeric" ></relative-time>
41+
<time-ago datetime="<%= DateTime.from_unix!(event.timestamp) %>" ></time-ago>
4242
<div><span><%= event.medium %> &middot; <%= event.ip_address %></span></div>
4343
</div>
4444
</div>

0 commit comments

Comments
 (0)