diff --git a/app/components/lobbyside-staff-widget/index.hbs b/app/components/lobbyside-staff-widget/index.hbs deleted file mode 100644 index 5947f43b45..0000000000 --- a/app/components/lobbyside-staff-widget/index.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{#if this.shouldShow}} -
-{{/if}} \ No newline at end of file diff --git a/app/components/lobbyside-staff-widget/index.ts b/app/components/lobbyside-staff-widget/index.ts deleted file mode 100644 index 6437fc7942..0000000000 --- a/app/components/lobbyside-staff-widget/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import Component from '@glimmer/component'; -import { service } from '@ember/service'; -import { action } from '@ember/object'; -import type AuthenticatorService from 'codecrafters-frontend/services/authenticator'; - -const ALLOWED_USERNAMES = ['vishaag', 'dronaxis']; -const LOBBYSIDE_SCRIPT_ID = 'lobbyside-staff-widget-script'; - -export default class LobbysideStaffWidgetComponent extends Component { - @service declare authenticator: AuthenticatorService; - - get shouldShow(): boolean { - const user = this.authenticator.currentUser; - - if (!user) { - return false; - } - - return user.isStaff || ALLOWED_USERNAMES.includes(user.username); - } - - @action - insertScript(): void { - if (document.getElementById(LOBBYSIDE_SCRIPT_ID)) { - this.syncVisitorData(); - - return; - } - - const script = document.createElement('script'); - script.id = LOBBYSIDE_SCRIPT_ID; - script.src = 'https://lobbyside.com/widget.js'; - script.dataset['companyId'] = '665ad94a-a863-4d0e-98e5-ff3eeac3f264'; - script.onload = () => this.syncVisitorData(); - document.body.appendChild(script); - } - - @action - removeScript(): void { - const script = document.getElementById(LOBBYSIDE_SCRIPT_ID); - - if (script) { - script.remove(); - } - } - - private syncVisitorData(): void { - const user = this.authenticator.currentUser; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (!user || !(window as any)['Lobbyside']) { - return; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const lobbyside = (window as any).Lobbyside; - - lobbyside.setVisitor({ - email: user.primaryEmailAddress || '', - name: user.name || user.githubName || '', - github: user.githubUsername || '', - }); - } -} diff --git a/app/components/lobbyside-widget/index.hbs b/app/components/lobbyside-widget/index.hbs index 5947f43b45..01a00b947e 100644 --- a/app/components/lobbyside-widget/index.hbs +++ b/app/components/lobbyside-widget/index.hbs @@ -1,3 +1,3 @@ {{#if this.shouldShow}} -
+
{{/if}} \ No newline at end of file diff --git a/app/components/lobbyside-widget/index.ts b/app/components/lobbyside-widget/index.ts index e0bbf83f93..c85341dfe0 100644 --- a/app/components/lobbyside-widget/index.ts +++ b/app/components/lobbyside-widget/index.ts @@ -1,57 +1,81 @@ import Component from '@glimmer/component'; import { service } from '@ember/service'; import { action } from '@ember/object'; +import { userIsStaffOrAllowlisted } from 'codecrafters-frontend/utils/staff-allowlist'; import type AuthenticatorService from 'codecrafters-frontend/services/authenticator'; -const LOBBYSIDE_SCRIPT_ID = 'lobbyside-widget-script'; +declare global { + interface Window { + Lobbyside?: { + setVisitor(visitor: { email: string; name: string; github: string }): void; + }; + } +} + +export type LobbysideAudience = 'everyone' | 'staff'; + +export interface LobbysideWidgetSignature { + Element: HTMLDivElement; + Args: { + widgetId: string; + audience?: LobbysideAudience; + }; +} -export default class LobbysideWidgetComponent extends Component { +export default class LobbysideWidgetComponent extends Component { @service declare authenticator: AuthenticatorService; + get scriptId(): string { + return `lobbyside-widget-${this.args.widgetId}`; + } + get shouldShow(): boolean { + if ((this.args.audience ?? 'everyone') === 'staff') { + return userIsStaffOrAllowlisted(this.authenticator.currentUser); + } + return true; } @action insertScript(): void { - if (document.getElementById(LOBBYSIDE_SCRIPT_ID)) { + if (document.getElementById(this.scriptId)) { this.syncVisitorData(); return; } const script = document.createElement('script'); - script.id = LOBBYSIDE_SCRIPT_ID; + script.id = this.scriptId; script.src = 'https://lobbyside.com/widget.js'; - script.dataset['companyId'] = 'f6948b5a-eac2-4f92-8fce-54d4fb3bdaa4'; + script.dataset['widgetId'] = this.args.widgetId; script.onload = () => this.syncVisitorData(); document.body.appendChild(script); } @action removeScript(): void { - const script = document.getElementById(LOBBYSIDE_SCRIPT_ID); - - if (script) { - script.remove(); - } + document.getElementById(this.scriptId)?.remove(); } - private syncVisitorData(): void { + @action + syncVisitorData(): void { const user = this.authenticator.currentUser; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (!user || !(window as any)['Lobbyside']) { + if (!user || !window.Lobbyside) { return; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const lobbyside = (window as any).Lobbyside; - - lobbyside.setVisitor({ + window.Lobbyside.setVisitor({ email: user.primaryEmailAddress || '', name: user.name || user.githubName || '', github: user.githubUsername || '', }); } } + +declare module '@glint/environment-ember-loose/registry' { + export default interface Registry { + LobbysideWidget: typeof LobbysideWidgetComponent; + } +} diff --git a/app/services/beacon.ts b/app/services/beacon.ts index 3d714560b1..b60a3fd632 100644 --- a/app/services/beacon.ts +++ b/app/services/beacon.ts @@ -2,6 +2,7 @@ import Service, { service } from '@ember/service'; import type RouterService from '@ember/routing/router-service'; import type RouteInfo from '@ember/routing/route-info'; import RouteInfoMetadata, { HelpscoutBeaconVisibility } from 'codecrafters-frontend/utils/route-info-metadata'; +import { userIsStaffOrAllowlisted } from 'codecrafters-frontend/utils/staff-allowlist'; import type AuthenticatorService from 'codecrafters-frontend/services/authenticator'; export default class HelpscoutBeaconService extends Service { @@ -9,10 +10,8 @@ export default class HelpscoutBeaconService extends Service { @service declare router: RouterService; get shouldShowBeacon(): boolean { - // Staff users and specific users see the Lobbyside widget instead of HelpScout - const user = this.authenticator.currentUser; - - if (user?.isStaff || user?.username === 'vishaag' || user?.username === 'dronaxis') { + // Staff and allowlisted users see the Lobbyside widget instead of HelpScout + if (userIsStaffOrAllowlisted(this.authenticator.currentUser)) { return false; } diff --git a/app/templates/application.hbs b/app/templates/application.hbs index 67768c4202..40dcadeb22 100644 --- a/app/templates/application.hbs +++ b/app/templates/application.hbs @@ -22,8 +22,9 @@ {{/if}} - - + + + {{! Enable this to debug ember-animated animations }} {{! }} diff --git a/app/utils/staff-allowlist.ts b/app/utils/staff-allowlist.ts new file mode 100644 index 0000000000..76f3732795 --- /dev/null +++ b/app/utils/staff-allowlist.ts @@ -0,0 +1,11 @@ +import type UserModel from 'codecrafters-frontend/models/user'; + +export const STAFF_ALLOWLIST_USERNAMES = ['vishaag', 'dronaxis']; + +export function userIsStaffOrAllowlisted(user: UserModel | null | undefined): boolean { + if (!user) { + return false; + } + + return user.isStaff || STAFF_ALLOWLIST_USERNAMES.includes(user.username); +}