• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / fx-private-relay / d4d9f278-d845-4992-8c81-4f3757c427a1

08 Sep 2025 02:07PM UTC coverage: 86.303% (-1.8%) from 88.121%
d4d9f278-d845-4992-8c81-4f3757c427a1

Pull #5842

circleci

joeherm
fix(deploy): Update CircleCI to use common Dockerfile for building frontend
Pull Request #5842: fix(deploy): Unify Dockerfiles

2744 of 3951 branches covered (69.45%)

Branch coverage included in aggregate %.

17910 of 19981 relevant lines covered (89.64%)

9.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.11
/frontend/src/components/dashboard/SubdomainPicker.tsx
1
import { useOverlayTriggerState } from "react-stately";
1✔
2
import { useState } from "react";
1✔
3
import styles from "./SubdomainPicker.module.scss";
1✔
4
import Illustration from "./images/man-laptop-email.svg";
1✔
5
import { ProfileData } from "../../hooks/api/profile";
6
import { SubdomainSearchForm } from "./subdomain/SearchForm";
1✔
7
import { SubdomainConfirmationModal } from "./subdomain/ConfirmationModal";
1✔
8
import { getRuntimeConfig } from "../../config";
1✔
9
import Image from "../Image";
1✔
10
import { useL10n } from "../../hooks/l10n";
1✔
11
import Link from "next/link";
1✔
12
import { useFlaggedAnchorLinks } from "../../hooks/flaggedAnchorLinks";
1✔
13

14
export type Props = {
15
  profile: ProfileData;
16
  onCreate: (subdomain: string) => void;
17
};
18

19
/**
20
 * Allows the user to search for available subdomains, and pops up a modal to claim it if available.
21
 */
22
export const SubdomainPicker = (props: Props) => {
45✔
23
  const l10n = useL10n();
55✔
24
  const [chosenSubdomain, setChosenSubdomain] = useState("");
55✔
25
  const [partialSubdomain, setPartialSubdomain] = useState("");
55✔
26

27
  const modalState = useOverlayTriggerState({});
55✔
28

29
  // When <SubdomainPicker> gets added to the page, if there's an anchor link in the
30
  // URL pointing to register a subdomain, scroll to that banner:
31
  useFlaggedAnchorLinks([props.profile], ["mpp-choose-subdomain"]);
55✔
32

33
  if (
55✔
34
    !props.profile.has_premium ||
86✔
35
    // Don't show if the user already has a subdomain set,
36
    // unless they *just* set it, i.e. when the modal is still
37
    // open and showing a confirmation:
38
    (typeof props.profile.subdomain === "string" && !modalState.isOpen)
39
  ) {
40
    return null;
28✔
41
  }
42

43
  const onPick = (subdomain: string) => {
27✔
44
    setChosenSubdomain(subdomain);
1✔
45
    modalState.open();
1✔
46
  };
47

48
  const onConfirm = () => {
27✔
49
    props.onCreate(chosenSubdomain);
×
50
  };
51

52
  const onType = (_partial: string) => {
27✔
53
    setPartialSubdomain(_partial);
9✔
54
  };
55

56
  const dialog = modalState.isOpen ? (
27✔
57
    <SubdomainConfirmationModal
58
      subdomain={chosenSubdomain}
59
      isOpen={modalState.isOpen}
60
      isSet={typeof props.profile.subdomain === "string"}
61
      onClose={() => modalState.close()}
×
62
      onConfirm={onConfirm}
63
      onComplete={() => modalState.close()}
×
64
    />
65
  ) : null;
66

67
  return (
68
    <div className={styles.card} id="mpp-choose-subdomain">
69
      <div className={styles.description}>
70
        <p aria-hidden={true} className={styles["action-step"]}>
71
          {l10n.getString("banner-set-email-domain-headline-action-needed")}
72
        </p>
73
        <h3>{l10n.getString("banner-set-email-domain-headline")} </h3>
74
        <div className={styles.lead}>
75
          <dl className={styles["instruction-item"]}>
76
            <dt>
77
              <strong>
78
                {l10n.getString("banner-set-email-domain-step-one-headline")}
79
              </strong>
80
            </dt>
81
            <dd>{l10n.getString("banner-set-email-domain-step-one-body")}</dd>
82
          </dl>
83
          <dl className={styles["instruction-item"]}>
84
            <dt>
85
              <strong>
86
                {l10n.getString("banner-set-email-domain-step-two-headline")}
87
              </strong>
88
            </dt>
89
            <dd>
90
              {l10n.getString("banner-set-email-domain-step-two-body", {
91
                mozmail: "mozmail.com",
92
              })}
93
            </dd>
94
          </dl>
95
        </div>
96
        <Link
97
          href="https://support.mozilla.org/en-US/kb/register-your-own-domain-firefox-relay-premium"
98
          target="_blank"
99
        >
100
          {l10n.getString("banner-set-email-domain-learn-more")}
101
        </Link>
102
      </div>
103
      <div className={styles.search}>
104
        <div className={styles.example} aria-hidden={true}>
105
          ***@
106
          <span className={styles["subdomain-part"]}>
107
            {partialSubdomain !== ""
27✔
108
              ? partialSubdomain
109
              : l10n.getString("banner-set-email-domain-placeholder")}
110
          </span>
111
          .{getRuntimeConfig().mozmailDomain}
112
        </div>
113
        <div className={styles["input-wrapper"]}>
114
          <SubdomainSearchForm onType={onType} onPick={onPick} />
115
        </div>
116
        <Image
117
          src={Illustration}
118
          width={200}
119
          className={styles.illustration}
120
          alt=""
121
        />
122
      </div>
123
      {dialog}
124
    </div>
125
  );
126
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc