Skip to content

Commit 1c51abb

Browse files
feat(nimbus): Advertise nimbus-devtools
Because: - nimbus-devtools now can inform Experimenter what version is installed as of mozilla-extensions/nimbus-devtools#56; - we want users to update their version of nimbus-devtools to the latest and greatest this commit: - adds a banner that informs the user if a new version of nimbus-devtools is released; - adds a banner that informs the user about nimbus-devtools if they don't have it installed; - gives users the options to suppress the banner for a day, until the next version, or permanently. Fixes #15137
1 parent 3d43025 commit 1c51abb

4 files changed

Lines changed: 164 additions & 0 deletions

File tree

experimenter/experimenter/nimbus_ui/static/js/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as bootstrap from "bootstrap";
88
import "htmx.org";
99
import "bootstrap-select";
1010
import { setupReadonlyJsonEditors } from "./codemirror_utils.js";
11+
import { setupDevtoolsBanner } from "./nimbus_devtools.js";
1112

1213
window.bootstrap = bootstrap;
1314
const setupThemeSwitcher = () => {
@@ -98,6 +99,7 @@ const setupHTMXLoadingOverlay = () => {
9899
};
99100

100101
$(() => {
102+
void setupDevtoolsBanner();
101103
setupThemeSwitcher();
102104
setupTooltips();
103105
setupToasts();
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
const AVAILABLE_NIMBUS_DEVTOOLS_VERSION = [0, 4, 0];
2+
const COOKIE_NAME = "nimbus-devtools";
3+
const ONE_DAY = 60 * 60 * 24;
4+
5+
function closeBanner(banner) {
6+
banner.classList.add("d-none");
7+
}
8+
9+
async function remindLater(banner) {
10+
await cookieStore.set({
11+
name: COOKIE_NAME,
12+
sameSite: "strict",
13+
maxAge: ONE_DAY,
14+
15+
value: JSON.stringify({
16+
dismiss: true,
17+
}),
18+
});
19+
20+
closeBanner(banner);
21+
}
22+
23+
async function remindNextVersion(banner) {
24+
await cookieStore.set({
25+
name: COOKIE_NAME,
26+
sameSite: "strict",
27+
value: JSON.stringify({
28+
remindIfNewer: AVAILABLE_NIMBUS_DEVTOOLS_VERSION,
29+
}),
30+
});
31+
32+
closeBanner(banner);
33+
}
34+
35+
async function dismiss(banner) {
36+
await cookieStore.set({
37+
name: "nimbus-devtools",
38+
sameSite: "strict",
39+
value: JSON.stringify({
40+
dismiss: true,
41+
}),
42+
});
43+
44+
closeBanner(banner);
45+
}
46+
47+
/**
48+
* Compare two version 3-tuples.
49+
*
50+
* @param {[Number, Number, Number]} a The first version to compare.
51+
* @param {[Number, Number, Number]} b The second version to compare.
52+
*
53+
* @returns {-1 | 0 | 1} -1 if a < b, 0 if a == b, 1 if a > b
54+
*/
55+
function versionCompare(a, b) {
56+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
57+
}
58+
59+
async function getCookie() {
60+
const cookie = await cookieStore.get("nimbus-devtools").catch((e) => null);
61+
if (cookie?.value) {
62+
try {
63+
return JSON.parse(cookie.value);
64+
} catch (e) {
65+
console.error(`Invalid cookie '${cookie}'`, e);
66+
await cookieStore.delete("nimbus-devtools");
67+
}
68+
}
69+
70+
return null;
71+
}
72+
73+
export async function setupDevtoolsBanner() {
74+
const cookie = await getCookie();
75+
76+
if (cookie?.dismiss) {
77+
return;
78+
}
79+
80+
if (
81+
cookie?.remindIfNewer &&
82+
Array.isArray(cookie.remindIfNewer) &&
83+
versionCompare(AVAILABLE_NIMBUS_DEVTOOLS_VERSION, cookie.remindIfNewer) <= 0
84+
) {
85+
return;
86+
}
87+
88+
if (
89+
window.__NIMBUS_DEVTOOLS__ &&
90+
versionCompare(
91+
AVAILABLE_NIMBUS_DEVTOOLS_VERSION,
92+
window.__NIMBUS_DEVTOOLS__.version,
93+
) <= 0
94+
) {
95+
return;
96+
}
97+
98+
const banner = document.getElementById("nimbus-devtools-banner");
99+
100+
banner.classList.remove("d-none");
101+
102+
if (window.__NIMBUS_DEVTOOLS__?.version) {
103+
banner.querySelector(".old-version-placeholder").textContent =
104+
window.__NIMBUS_DEVTOOLS__.version.join(".");
105+
banner
106+
.querySelector(".nimbus-devtools-needs-update")
107+
.classList.remove("d-none");
108+
} else {
109+
banner
110+
.querySelector(".nimbus-devtools-needs-install")
111+
.classList.remove("d-none");
112+
}
113+
114+
banner
115+
.querySelectorAll(".new-version-placeholder")
116+
.forEach(
117+
(el) => (el.textContent = AVAILABLE_NIMBUS_DEVTOOLS_VERSION.join(".")),
118+
);
119+
120+
banner
121+
.querySelector(".remind-later-btn")
122+
.addEventListener("click", () => remindLater(banner));
123+
124+
banner
125+
.querySelector(".remind-next-version-btn")
126+
.addEventListener("click", () => remindNextVersion(banner));
127+
128+
banner
129+
.querySelector(".dismiss-btn")
130+
.addEventListener("click", () => dismiss(banner));
131+
132+
banner
133+
.querySelector(".new-version-link")
134+
.addEventListener("click", () => closeBanner(banner));
135+
}

experimenter/experimenter/nimbus_ui/templates/common/header.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{% load static %}
22

33
{% include 'glean/opt_out_alert.html' %}
4+
{% include "nimbus_devtools/banner.html" %}
45

56
<nav class="navbar navbar-expand-xl">
67
<div class="container-fluid">
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<div id="nimbus-devtools-banner"
2+
class="alert alert-success bg-transparent text-success d-none">
3+
<div class="nimbus-devtools-needs-install d-none">
4+
<p>nimbus-devtools is either uninstalled or out-of-date.</p>
5+
<p>
6+
You can download the latest version of nimbus-devtools:
7+
<a href="https://github.com/mozilla-extensions/nimbus-devtools/releases/latest"
8+
target="_blank"
9+
class="new-version-link">v<span class="new-version-placeholder"></span></a>
10+
</p>
11+
</div>
12+
<div class="nimbus-devtools-needs-update d-none">
13+
<p>
14+
Your version of nimbus-devtools (v<span class="old-version-placeholder"></span>) is out of date.
15+
</p>
16+
<p>
17+
A new version is available:
18+
<a href="https://github.com/mozilla-extensions/nimbus-devtools/releases/latest"
19+
target="_blank"
20+
class="new-version-link">v<span class="new-version-placeholder"></span></a>
21+
</p>
22+
</div>
23+
<button class="btn btn-primary me-2 remind-later-btn">Remind me tomorrow</button>
24+
<button class="btn btn-danger me-2 remind-next-version-btn">Don't remind me about this version</button>
25+
<button class="btn btn-danger me-2 dismiss-btn">Dismiss</button>
26+
</div>

0 commit comments

Comments
 (0)