Skip to content

Commit dd6d143

Browse files
Add color blocks to the AWS session selection page (#30)
* Add session selector colorize * Bump to 0.1.2 * Update README.md and add a screenshot * Fix format (#32) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent fdace5d commit dd6d143

File tree

8 files changed

+181
-27
lines changed

8 files changed

+181
-27
lines changed

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
# AWS management console colorize
22

3-
Chrome and Firefox extensions to change the header and footer colors of the AWS management console.
4-
You can change the header and footer colors of the AWS management console to your preference.
5-
This is to differentiate between multiple session ARNs.
6-
This is inspired by [gcp-console-colorize](https://github.com/yfuruyama/gcp-console-colorize).
3+
Chrome and Firefox extensions to change and add colors in the AWS management console.
4+
Those extensions offers the following features:
75

8-
![screenshot](screenshot.png)
6+
- Change the header and footer colors of the AWS management console.
7+
- Add color blocks to the AWS session selection page.
8+
9+
These allow you to differentiate between multiple session ARNs.
10+
These are inspired by [gcp-console-colorize](https://github.com/yfuruyama/gcp-console-colorize).
11+
12+
![A screenshot in the AWS management console](screenshots/management_console.png)
13+
![A screenshot in the AWS session selection page](screenshots/session_selection_page.png)
914

1015
## Download
1116

entrypoints/content.ts

Lines changed: 156 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,140 @@
11
import { z } from "zod";
2-
import { getColorSettingsFromStorage } from "@/modules/color_settings.ts";
3-
import { matches, MessageType } from "@/modules/lib.ts";
2+
import {
3+
getColorSettingsFromStorage,
4+
colorSettingZodType,
5+
} from "@/modules/color_settings.ts";
6+
import {
7+
signinMatchPattern,
8+
matches,
9+
MessageType,
10+
matchURL,
11+
} from "@/modules/lib.ts";
412

513
type GetHTMLElementType = () => HTMLElement | null;
614

7-
function runChangeBackgroundColor(
15+
function changeColorElement(
16+
colorElement: HTMLDivElement,
17+
colorSetting: z.TypeOf<typeof colorSettingZodType>,
18+
awsUIRestorePointerEvents: HTMLElement,
19+
) {
20+
awsUIRestorePointerEvents.style.display = "flex";
21+
awsUIRestorePointerEvents.style.justifyContent = "space-between";
22+
colorElement.style.backgroundColor = colorSetting.hexColor;
23+
colorElement.style.width = `${awsUIRestorePointerEvents.offsetHeight}px`;
24+
}
25+
26+
async function runChangeSessionsSelectorColor(): Promise<boolean> {
27+
const colorSettings = await getColorSettingsFromStorage();
28+
29+
if (colorSettings === null) {
30+
return false;
31+
}
32+
33+
const awsUIRestorePointerEventsList = document.querySelectorAll<HTMLElement>(
34+
"div[class^='awsui_restore-pointer-events']",
35+
);
36+
37+
if (awsUIRestorePointerEventsList.length === 0) {
38+
return false;
39+
}
40+
41+
for (const awsUIRestorePointerEvents of awsUIRestorePointerEventsList) {
42+
const awsAccountTextContent = ["span", "a"]
43+
.flatMap((t) => {
44+
return Array.from(awsUIRestorePointerEvents.getElementsByTagName(t));
45+
})
46+
.map(({ textContent }) => textContent)
47+
.find((textContent) => textContent !== null);
48+
49+
if (awsAccountTextContent === undefined) {
50+
continue;
51+
}
52+
53+
const sessionCardSessionCardUsername =
54+
awsUIRestorePointerEvents.querySelector(
55+
"p[class^='session-card_session_card_username']",
56+
);
57+
58+
if (sessionCardSessionCardUsername === null) {
59+
continue;
60+
}
61+
62+
const colorSetting = colorSettings.find(({ sessionARN }) => {
63+
const awsAccountID = awsAccountTextContent
64+
.replaceAll("-", "")
65+
.replace("(", "")
66+
.replace(")", "");
67+
return (
68+
sessionARN.includes(`:${awsAccountID}:`) &&
69+
sessionARN.endsWith(`/${sessionCardSessionCardUsername.textContent}`)
70+
);
71+
});
72+
const colorElementClassName = "aws-console-colorize-color-element";
73+
const colorElement = awsUIRestorePointerEvents
74+
.getElementsByClassName(colorElementClassName)
75+
.item(0);
76+
77+
if (colorElement instanceof HTMLDivElement) {
78+
if (colorSetting === undefined) {
79+
colorElement.remove();
80+
continue;
81+
}
82+
83+
changeColorElement(colorElement, colorSetting, awsUIRestorePointerEvents);
84+
continue;
85+
}
86+
87+
if (colorSetting === undefined) {
88+
continue;
89+
}
90+
91+
const newColorElement = document.createElement("div");
92+
newColorElement.className = colorElementClassName;
93+
changeColorElement(
94+
newColorElement,
95+
colorSetting,
96+
awsUIRestorePointerEvents,
97+
);
98+
awsUIRestorePointerEvents.appendChild(newColorElement);
99+
}
100+
101+
return true;
102+
}
103+
104+
async function changeSessionsSelectorColor() {
105+
if (await runChangeSessionsSelectorColor()) {
106+
return;
107+
}
108+
109+
const mutationObserveTargetID = "__next";
110+
const mutationObserveTarget = document.getElementById(
111+
mutationObserveTargetID,
112+
);
113+
114+
if (mutationObserveTarget === null) {
115+
throw new Error(`Can't get ${mutationObserveTargetID}`);
116+
}
117+
118+
new MutationObserver(async (_, observer) => {
119+
if (await runChangeSessionsSelectorColor()) {
120+
observer.disconnect();
121+
}
122+
}).observe(mutationObserveTarget, { childList: true, subtree: true });
123+
}
124+
125+
async function onSessionsSelectorMessage(message: MessageType) {
126+
switch (message) {
127+
case MessageType.getSessionARN:
128+
return;
129+
case MessageType.changeColor:
130+
await changeSessionsSelectorColor();
131+
return;
132+
default:
133+
throw new Error(`Incorrect message ${message}`);
134+
}
135+
}
136+
137+
function runChangeConsoleBackgroundColor(
8138
color: string,
9139
getElement: GetHTMLElementType,
10140
): boolean {
@@ -18,7 +148,7 @@ function runChangeBackgroundColor(
18148
return true;
19149
}
20150

21-
async function changeColor(sessionARN: string) {
151+
async function changeConsoleColor(sessionARN: string) {
22152
const colorSettings = await getColorSettingsFromStorage();
23153
const colorSetting = colorSettings?.find((c) => {
24154
return c.sessionARN === sessionARN;
@@ -43,7 +173,7 @@ async function changeColor(sessionARN: string) {
43173
];
44174

45175
for (const c of mutationObserverConfigs) {
46-
if (runChangeBackgroundColor(hexColor, c.getElement)) {
176+
if (runChangeConsoleBackgroundColor(hexColor, c.getElement)) {
47177
continue;
48178
}
49179

@@ -56,29 +186,45 @@ async function changeColor(sessionARN: string) {
56186
}
57187

58188
new MutationObserver((_, observer) => {
59-
if (runChangeBackgroundColor(hexColor, c.getElement)) {
189+
if (runChangeConsoleBackgroundColor(hexColor, c.getElement)) {
60190
observer.disconnect();
61191
}
62192
}).observe(mutationObserveTarget, { childList: true });
63193
}
64194
}
65195

66-
async function onMessage(
196+
async function onConsoleMessage(
67197
sessionARN: string,
68198
message: MessageType,
69199
): Promise<string | undefined> {
70200
switch (message) {
71201
case MessageType.getSessionARN:
72202
return sessionARN;
73203
case MessageType.changeColor:
74-
await changeColor(sessionARN);
204+
await changeConsoleColor(sessionARN);
75205
return;
76206
default:
77207
throw new Error(`Incorrect message ${message}`);
78208
}
79209
}
80210

81211
async function main() {
212+
if (matchURL(signinMatchPattern, document.documentURI)) {
213+
if (
214+
!document.documentURI.includes(".signin.aws.amazon.com/sessions/selector")
215+
) {
216+
return;
217+
}
218+
219+
browser.runtime.onMessage.addListener(async (message) => {
220+
return await onSessionsSelectorMessage(
221+
MessageType[message as keyof typeof MessageType],
222+
);
223+
});
224+
await changeSessionsSelectorColor();
225+
return;
226+
}
227+
82228
const awscSessionData = document.querySelector(
83229
'meta[name="awsc-session-data"]',
84230
);
@@ -91,12 +237,12 @@ async function main() {
91237
.object({ sessionARN: z.string() })
92238
.parse(JSON.parse(awscSessionData.content)).sessionARN;
93239
browser.runtime.onMessage.addListener(async (message) => {
94-
return await onMessage(
240+
return await onConsoleMessage(
95241
sessionARN,
96242
MessageType[message as keyof typeof MessageType],
97243
);
98244
});
99-
await changeColor(sessionARN);
245+
await changeConsoleColor(sessionARN);
100246
}
101247

102248
export default defineContentScript({ matches, main });

entrypoints/popup/App.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
colorSettingsZodType,
88
getColorSettingsFromStorage,
99
} from "@/modules/color_settings.ts";
10-
import { matches, MessageType } from "@/modules/lib.ts";
10+
import { matches, MessageType, matchURL } from "@/modules/lib.ts";
1111
import "react-color-palette/css";
1212
import "./App.css";
1313

@@ -106,9 +106,7 @@ async function sendMessageToContentScript(
106106
}
107107

108108
const filteredMatches = matches.filter((m) => {
109-
return new RegExp(m.replaceAll("*", ".*")).exec(
110-
z.string().parse(tabs[0].url),
111-
);
109+
return matchURL(m, z.string().parse(tabs[0].url));
112110
});
113111
return 0 < filteredMatches.length
114112
? await browser.tabs.sendMessage(z.number().parse(tabs[0].id), message)

modules/color_settings.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import type { StorageItemKey } from "@wxt-dev/storage";
22
import { z } from "zod";
33

4-
export const colorSettingsZodType = z.array(
5-
z.object({
6-
sessionARN: z.string(),
7-
hexColor: z.string(),
8-
}),
9-
);
4+
export const colorSettingZodType = z.object({
5+
sessionARN: z.string(),
6+
hexColor: z.string(),
7+
});
8+
export const colorSettingsZodType = z.array(colorSettingZodType);
109
const nullableColorSettingsZodType = colorSettingsZodType.nullable();
1110
export const colorSettingsStorageItemKey: StorageItemKey = "sync:colorSettings";
1211

modules/lib.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ export enum MessageType {
55
changeColor = "changeColor",
66
}
77

8+
export const signinMatchPattern = "*://*.signin.aws.amazon.com/*";
89
export const matches: Manifest.ContentScript["matches"] = [
910
"*://*.console.aws.amazon.com/*",
11+
signinMatchPattern,
1012
];
13+
14+
export function matchURL(matchPattern: string, url: string): boolean {
15+
return new RegExp(matchPattern.replaceAll("*", ".*")).exec(url) !== null;
16+
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"name": "aws-management-console-colorize",
3-
"description": "Chrome and Firefox extensions to change the header and footer colors of the AWS management console",
3+
"description": "Chrome and Firefox extensions to change and add colors in the AWS management console.",
44
"private": true,
5-
"version": "0.1.1",
5+
"version": "0.1.2",
66
"author": "Masaya Suzuki",
77
"license": "MIT",
88
"type": "module",
26.6 KB
Loading

0 commit comments

Comments
 (0)