Skip to content

Commit 22b2d99

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; and - 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; and - gives users the options to suppress the banner for a day, until the next version, or permanently. Fixes #15137
1 parent 3d43025 commit 22b2d99

5 files changed

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

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)