@ghub/identity-chrome 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/elements/account.d.ts +6 -0
- package/dist/elements/account.js +35 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -76,7 +76,9 @@ const account = document.querySelector("gp-account")!;
|
|
|
76
76
|
account.core = chrome;
|
|
77
77
|
account.product = "GAdvisory"; // your own name, from your catalogue entry
|
|
78
78
|
account.person = { name: user.name, email: user.email, id: user.id, avatarUrl: user.picture };
|
|
79
|
-
account.organisations = [
|
|
79
|
+
account.organisations = [
|
|
80
|
+
{ id: "org_1", name: "Hafen Labs", role: "Admin", iconUrl: "/orgs/org_1/avatar", active: true },
|
|
81
|
+
];
|
|
80
82
|
account.onSwitch = async (id) => switchOrganisation(id); // reject when it did not switch
|
|
81
83
|
account.onSignOut = async () => {
|
|
82
84
|
await signOut(); // reject when it failed: the popup says they are still signed in
|
|
@@ -90,7 +92,8 @@ and the account popup renders nothing without a person.
|
|
|
90
92
|
|
|
91
93
|
**The account popup shows mostly what the product passes**: the name and address from your
|
|
92
94
|
session, your organisations with the role your product gives them there (its own label, already in the
|
|
93
|
-
person's language and shown as given; none, and the row has no second line) and
|
|
95
|
+
person's language and shown as given; none, and the row has no second line) and their own picture
|
|
96
|
+
where they have one (`iconUrl`; the initial otherwise, and if it does not load), and your two actions.
|
|
94
97
|
Identity adds the picture, the colour of the initial, the links to its own account and set up
|
|
95
98
|
screens and the footer, so the popup still signs somebody out while Identity is down. The
|
|
96
99
|
picture is Identity's if the person has one, else yours, else a coloured initial whose tint
|
|
@@ -69,6 +69,12 @@ export interface AccountOrganisation {
|
|
|
69
69
|
* so the element has no list of its own. None, and the row has no second line.
|
|
70
70
|
*/
|
|
71
71
|
role?: string | null;
|
|
72
|
+
/**
|
|
73
|
+
* The organisation's own picture, absolute or relative to the page, http or
|
|
74
|
+
* https only. Drawn in place of the initial, which comes back if it does not
|
|
75
|
+
* load.
|
|
76
|
+
*/
|
|
77
|
+
iconUrl?: string | null;
|
|
72
78
|
active: boolean;
|
|
73
79
|
}
|
|
74
80
|
/** One of the product's own items in the popup, such as its profile or its settings. */
|
package/dist/elements/account.js
CHANGED
|
@@ -229,8 +229,9 @@ exports.ACCOUNT_CSS = `${contract_js_1.CONTRACT_CSS}
|
|
|
229
229
|
.wrap > .radios:last-child > .org:last-child { border-radius: 4px 4px 18px 18px; }
|
|
230
230
|
.org-mark {
|
|
231
231
|
display: grid; place-items: center; flex-shrink: 0; width: 32px; height: 32px; border-radius: 9px;
|
|
232
|
-
color: ${tint_js_1.AVATAR_INK}; font-size: 14px; font-weight: 600;
|
|
232
|
+
overflow: hidden; color: ${tint_js_1.AVATAR_INK}; font-size: 14px; font-weight: 600;
|
|
233
233
|
}
|
|
234
|
+
.org-mark img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
|
234
235
|
.org-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
|
235
236
|
.org-name { font-size: 14px; line-height: 20px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
236
237
|
.org-role { font-size: 12.5px; line-height: 17px; color: var(--_ink-2); }
|
|
@@ -352,6 +353,30 @@ function emailLine(email) {
|
|
|
352
353
|
}
|
|
353
354
|
return line;
|
|
354
355
|
}
|
|
356
|
+
/** An organisation's picture where it has one that loads, else its initial on its tint. */
|
|
357
|
+
function orgMark(one) {
|
|
358
|
+
const initial = initialOf(one.name);
|
|
359
|
+
const mark = (0, dom_js_1.element)("span", {
|
|
360
|
+
class: `org-mark t${String((0, tint_js_1.avatarTint)(one.id))}`,
|
|
361
|
+
"aria-hidden": "true",
|
|
362
|
+
});
|
|
363
|
+
const picture = productAddress(one.iconUrl);
|
|
364
|
+
if (picture === null) {
|
|
365
|
+
mark.textContent = initial;
|
|
366
|
+
return mark;
|
|
367
|
+
}
|
|
368
|
+
const image = (0, dom_js_1.element)("img", {
|
|
369
|
+
src: picture,
|
|
370
|
+
alt: "",
|
|
371
|
+
decoding: "async",
|
|
372
|
+
referrerpolicy: "no-referrer",
|
|
373
|
+
});
|
|
374
|
+
image.addEventListener("error", () => {
|
|
375
|
+
mark.textContent = initial;
|
|
376
|
+
}, { once: true });
|
|
377
|
+
mark.append(image);
|
|
378
|
+
return mark;
|
|
379
|
+
}
|
|
355
380
|
/** An address the product gave, absolute or relative to the page, and only ever http or https. */
|
|
356
381
|
function productAddress(value) {
|
|
357
382
|
if (typeof value !== "string" || value === "")
|
|
@@ -486,11 +511,17 @@ function organisationsOf(value) {
|
|
|
486
511
|
for (const one of value) {
|
|
487
512
|
if (typeof one !== "object" || one === null)
|
|
488
513
|
continue;
|
|
489
|
-
const { id, name, role, active } = one;
|
|
514
|
+
const { id, name, role, iconUrl, active } = one;
|
|
490
515
|
if (typeof id !== "string" || id === "" || typeof name !== "string" || name.trim() === "")
|
|
491
516
|
continue;
|
|
492
517
|
const label = typeof role === "string" && role.trim() !== "" ? role.trim() : null;
|
|
493
|
-
out.push({
|
|
518
|
+
out.push({
|
|
519
|
+
id,
|
|
520
|
+
name: name.trim(),
|
|
521
|
+
role: label,
|
|
522
|
+
iconUrl: typeof iconUrl === "string" && iconUrl !== "" ? iconUrl : null,
|
|
523
|
+
active: active === true,
|
|
524
|
+
});
|
|
494
525
|
}
|
|
495
526
|
// The active one first: the row says which one you are acting in.
|
|
496
527
|
const active = out.findIndex((one) => one.active);
|
|
@@ -1167,7 +1198,7 @@ function createAccountElementClass() {
|
|
|
1167
1198
|
text.append((0, dom_js_1.element)("span", { class: "org-name", title: one.name }, one.name));
|
|
1168
1199
|
if (one.role)
|
|
1169
1200
|
text.append((0, dom_js_1.element)("span", { class: "org-role" }, one.role));
|
|
1170
|
-
row.append((
|
|
1201
|
+
row.append(orgMark(one), text);
|
|
1171
1202
|
if (one.active) {
|
|
1172
1203
|
const tag = (0, dom_js_1.element)("span", { class: "active", "aria-hidden": "true" });
|
|
1173
1204
|
tag.append((0, dom_js_1.element)("span", { class: "check" }), labels.active);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghub/identity-chrome",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The shared header controls of the Gelhaus Solutions products: the apps picker and the account popup, as custom elements with shadow DOM and as React wrappers. The browser half (state, cache, the last list held for an outage) and the server half (the token calls and a route handler). No dependencies.",
|
|
5
5
|
"author": "Gelhaus Solutions (Enno Gelhaus) <egelhaus@ennogelhaus.de> (https://ennogelhaus.de)",
|
|
6
6
|
"homepage": "https://ennogelhaus.de",
|