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

mozilla / blurts-server / 3301e8fe-9868-476c-990a-ab44e51f4a2d

pending completion
3301e8fe-9868-476c-990a-ab44e51f4a2d

push

circleci

GitHub
Merge pull request #3001 from mozilla/main

282 of 1768 branches covered (15.95%)

Branch coverage included in aggregate %.

451 of 451 new or added lines in 56 files covered. (100.0%)

959 of 4670 relevant lines covered (20.54%)

3.44 hits per line

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

0.0
/src/views/partials/settings.js
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4

5
import AppConstants from '../../appConstants.js'
6
import { getMessage } from '../../utils/fluent.js'
7

8
const emailNeedsVerificationSub = email => `
×
9
  <span class='verification-required'>
10
    ${getMessage('settings-email-verification-callout')}
11
  </span>
12

13
  <a class='js-settings-resend-email' data-email-id='${email.id}' href='#'>
14
    ${getMessage('settings-resend-email-verification-link')}
15
  </a>
16
`
17

18
const deleteButton = email => `
×
19
  <button
20
    data-subscriber-id='${email.subscriber_id}'
21
    data-email-id='${email.id}'
22
    class='settings-email-remove-button js-remove-email-button'
23
  >
24
    <img src='/images/icon-delete.svg'>
25
  </button>
26
`
27

28
const createEmailItem = (email, breachCounts) => `
×
29
  <li class='settings-email-item'>
30
    <strong>
31
      ${email.primary
×
32
          ? `${getMessage('settings-email-label-primary', { email: email.email })}`
33
          : email.email}
34
    </strong>
35
    ${email.verified
×
36
        ? getMessage('settings-email-number-of-breaches-info', {
37
            breachCount: breachCounts.get(email.email)
38
          })
39
        : emailNeedsVerificationSub(email)}
40

41
    ${email.primary ? '' : deleteButton(email)}
×
42
  </li>
43
`
44

45
// Moves the primary email to the front and sorts the rest alphabeticaly.
46
const getSortedEmails = emails => [...emails].sort((a, b) => {
×
47
  if (a.primary) {
×
48
    return -1
×
49
  }
50

51
  if (b.primary) {
×
52
    return 1
×
53
  }
54

55
  return a.email.localeCompare(b.email)
×
56
})
57

58
const createEmailList = (emails, breachCounts) => `
×
59
  <ul class='settings-email-list'>
60
    ${getSortedEmails(emails)
61
      .map(email => createEmailItem(email, breachCounts))
×
62
      .join('')}
63
  </ul>
64
`
65

66
/**
67
 * @param {string} csrfToken
68
 * @param {{ isChecked: boolean; option: unknown; }} options
69
 * @returns string
70
 */
71
const optionInput = (csrfToken, { isChecked, option }) => `
×
72
  <input
73
    ${isChecked ? 'checked' : ''}
×
74
    class='js-settings-alert-options-input'
75
    data-alert-option='${option}'
76
    data-csrf-token='${csrfToken}'
77
    name='settings-alert-options'
78
    type='radio'
79
  >
80
`
81

82
/**
83
 * @param {{ csrfToken: string; allEmailsToPrimary: boolean }} options
84
 * @returns string
85
 */
86
const alertOptions = ({ csrfToken, allEmailsToPrimary }) => `
×
87
  <div class='settings-alert-options'>
88
    <label class='settings-radio-input'>
89
    ${optionInput(csrfToken, {
90
      isChecked: !allEmailsToPrimary,
91
      option: 0
92
    })}
93
    <span class='settings-radio-label'>
94
      ${getMessage('settings-alert-preferences-option-one')}
95
    </span>
96
  </label>
97

98
  <label class='settings-radio-input'>
99
    ${optionInput(csrfToken, {
100
      isChecked: allEmailsToPrimary,
101
      option: 1
102
    })}
103
    <span class='settings-radio-label'>
104
      ${getMessage('settings-alert-preferences-option-two')}
105
    </span>
106
  </label>
107
  </div>
108
`
109

110
/**
111
 * @typedef {object} PartialData
112
 * @property {string} csrfToken
113
 * @property {boolean} allEmailsToPrimary
114
 */
115

116
/**
117
 * @param {PartialData} data
118
 * @returns string
119
 */
120
export const settings = data => {
×
121
  const { allEmailsToPrimary, breachCounts, csrfToken, emails, limit } = data
×
122

123
  return `
×
124
    <div class='settings js-settings' data-csrf-token='${csrfToken}'>
125
      <h2 class='settings-title'>${getMessage('settings-page-title')}</h2>
126

127
      <div class='settings-content'>
128
        <!-- Breach alert preferences -->
129
        <section>
130
          <h3 class='settings-section-title'>
131
            ${getMessage('settings-alert-preferences-title')}
132
          </h3>
133
          ${alertOptions({ csrfToken, allEmailsToPrimary })}
134
        </section>
135

136
        <hr>
137

138
        <!-- Monitored email addresses -->
139
        <section>
140
          <h3 class='settings-section-title'>
141
            ${getMessage('settings-email-list-title')}
142
          </h3>
143
          <p>${getMessage('settings-email-limit-info', { limit })}</p>
144

145
          ${createEmailList(emails, breachCounts)}
146
          <button
147
            class='primary settings-add-email-button' 
148
            data-dialog='addEmail' 
149
            ${emails.length >= limit ? 'disabled' : ''}
×
150
          >${getMessage('settings-add-email-button')}</a>
151
        </section>
152

153
        <hr>
154

155
        <!-- Deactivate account -->
156
        <section>
157
          <h3 class='settings-section-title'>
158
            ${getMessage('settings-deactivate-account-title')}
159
          </h3>
160
          <p>${getMessage('settings-deactivate-account-info')}</p>
161
          <a
162
            class='settings-link-fxa'
163
            href='${AppConstants.FXA_SETTINGS_URL}'
164
            target='_blank'
165
          >
166
            ${getMessage('settings-fxa-link-label')}
167
          </a>
168
        </section>
169
      </div>
170
    </div>
171
  `
172
}
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