-
Notifications
You must be signed in to change notification settings - Fork 52
#6114 Improved my keys section #6121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -496,24 +496,69 @@ View.run( | |
| private addKeyRowsHtml = async (privateKeys: KeyInfoWithIdentity[]) => { | ||
| let html = ''; | ||
| const canRemoveKey = !this.clientConfiguration?.usesKeyManager(); | ||
|
|
||
| // 1. Parse and prepare data | ||
| const rows = []; | ||
| for (let i = 0; i < privateKeys.length; i++) { | ||
| const ki = privateKeys[i]; | ||
| const prv = await KeyUtil.parse(ki.private); | ||
| const created = new Date(prv.created); | ||
| const date = Str.monthName(created.getMonth()) + ' ' + created.getDate() + ', ' + created.getFullYear(); | ||
| const isExpired = KeyUtil.expired(prv); | ||
| rows.push({ | ||
| ki, | ||
| prv, | ||
| createdTime: prv.created, | ||
| dateStr: date, | ||
| isExpired, | ||
| originalIndex: i, | ||
| }); | ||
| } | ||
|
|
||
| // 2. Sort: newest to oldest | ||
| rows.sort((a, b) => b.createdTime - a.createdTime); | ||
|
|
||
| // 3. Build HTML | ||
| // Header row | ||
| html += ` | ||
| <div class="row key-list-header" style="font-weight: 600; padding: 5px 0; border-bottom: 2px solid #eee;"> | ||
| <div class="col-3">Email</div> | ||
| <div class="col-2">Created</div> | ||
| <div class="col-5">Fingerprint</div> | ||
| <div class="col-2">Status</div> | ||
| </div> | ||
| `; | ||
|
|
||
| for (const row of rows) { | ||
| const { ki, prv, dateStr, isExpired, originalIndex } = row; | ||
|
|
||
| let removeKeyBtn = ''; | ||
| if (canRemoveKey && privateKeys.length > 1) { | ||
| removeKeyBtn = `(<a href="#" class="action_remove_key" data-test="action-remove-key-${i}" data-fingerprint=${ki.fingerprints[0]} data-type="${ki.family}" data-id="${ki.id}" data-longid="${ki.longid}">remove</a>)`; | ||
| removeKeyBtn = `<a href="#" class="action_remove_key" style="margin-left: 5px;" data-test="action-remove-key-${originalIndex}" data-fingerprint=${ki.fingerprints[0]} data-type="${ki.family}" data-id="${ki.id}" data-longid="${ki.longid}">remove</a>`; | ||
| } | ||
|
|
||
| const escapedEmail = Xss.escape(prv.emails[0] || ''); | ||
| const escapedLink = `<a href="#" data-test="action-show-key-${i}" class="action_show_key" page="modules/my_key.htm" addurltext="&fingerprint=${ki.id}">${escapedEmail}</a>`; | ||
| const fpHtml = `fingerprint: <span class="good">${Str.spaced(Xss.escape(ki.fingerprints[0]))}</span>`; | ||
| const space = ` `; | ||
| html += `<div class="row key-content-row">`; | ||
| html += ` <div class="col-12">${escapedLink} from ${Xss.escape(date)}${space}${fpHtml}${space}${KeyUtil.statusHtml(ki.id, prv)}${space}${removeKeyBtn}</div>`; | ||
| const escapedLink = `<a href="#" data-test="action-show-key-${originalIndex}" class="action_show_key" page="modules/my_key.htm" addurltext="&fingerprint=${ki.id}">${escapedEmail}</a>`; | ||
| const fpHtml = `<span class="good" style="font-family: monospace;">${Str.spaced(Xss.escape(ki.fingerprints[0]))}</span>`; | ||
|
|
||
| const rowClass = isExpired ? 'key-content-row expired' : 'key-content-row'; | ||
| const opacityStyle = isExpired ? 'opacity: 0.7;' : ''; | ||
|
|
||
| // Compact layout: reduced padding via CSS (4px), no inline padding here. | ||
| // Added white-space: nowrap and overflow handling to keep single line. | ||
|
Comment on lines
+547
to
+548
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need for these comments, let's remove them |
||
| html += `<div class="row ${rowClass}" style="border-bottom: 1px solid #e6e6e6; align-items: center; ${opacityStyle}">`; | ||
| html += ` <div class="col-3" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">${escapedLink}</div>`; | ||
| html += ` <div class="col-2" style="white-space: nowrap;">${Xss.escape(dateStr)}</div>`; | ||
| html += ` <div class="col-5" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">${fpHtml}</div>`; | ||
| html += ` <div class="col-2" style="display: flex; justify-content: space-between; align-items: center; white-space: nowrap;"> | ||
| ${KeyUtil.statusHtml(ki.id, prv)} | ||
| ${removeKeyBtn} | ||
| </div>`; | ||
| html += `</div>`; | ||
| } | ||
|
|
||
| Xss.sanitizeAppend('.key_list', html); | ||
|
|
||
| $('.action_show_key').on( | ||
| 'click', | ||
| this.setHandler(async target => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,16 +28,16 @@ html { | |
| font-size: 14px; | ||
| } | ||
|
|
||
| #header-row .logo-row .subscription > span, | ||
| #header-row .logo-row .subscription > button { | ||
| #header-row .logo-row .subscription>span, | ||
| #header-row .logo-row .subscription>button { | ||
|
Comment on lines
+31
to
+32
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looks like broken css formatting - there should be spaces around |
||
| display: inline-block; | ||
| margin-left: 4px; | ||
| border: 1px solid #31a217; | ||
| border-radius: 3px; | ||
| padding: 0 5px; | ||
| } | ||
|
|
||
| #header-row .logo-row .subscription > button:focus { | ||
| #header-row .logo-row .subscription>button:focus { | ||
| outline: none; | ||
| box-shadow: inset 0 0 0 1px #fff; | ||
| } | ||
|
|
@@ -201,7 +201,7 @@ a.gray_link { | |
| margin: 0 auto !important; | ||
| } | ||
|
|
||
| .settings-icons-rows > div { | ||
| .settings-icons-rows>div { | ||
| min-width: 145px; | ||
| } | ||
|
|
||
|
|
@@ -533,7 +533,7 @@ body#settings .settings-border .row { | |
| } | ||
|
|
||
| body#settings .settings-border .key-content-row { | ||
| padding: 7px 0; | ||
| padding: 4px 0; | ||
| border-bottom: 1px solid #e6e6e6; | ||
| } | ||
|
|
||
|
|
@@ -544,6 +544,10 @@ body#settings .settings-border .key_list { | |
| height: 219px; | ||
| } | ||
|
|
||
| .key-content-row.expired { | ||
| opacity: 0.7; | ||
| } | ||
|
|
||
| #settings-row .box img.security-icon { | ||
| width: 70px; | ||
| } | ||
|
|
@@ -583,21 +587,21 @@ body#settings .settings-border .key_list { | |
| top: 28px; | ||
| } | ||
|
|
||
| @media (width <= 991px) { | ||
| @media (width <=991px) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and here too |
||
| .my-keys-row .settings-border { | ||
| margin: 35px auto !important; | ||
| width: 100% !important; | ||
| } | ||
| } | ||
|
|
||
| @media (width <= 776px) { | ||
| @media (width <=776px) { | ||
| #public-profile-indicator { | ||
| left: 0; | ||
| right: 0; | ||
| } | ||
| } | ||
|
|
||
| @media (width <= 448px) { | ||
| @media (width <=448px) { | ||
| #footer-row { | ||
| position: relative; | ||
| } | ||
|
|
@@ -608,7 +612,7 @@ body#settings .settings-border .key_list { | |
| font-size: 14px; | ||
| } | ||
|
|
||
| #settings.client > #banner { | ||
| #settings.client>#banner { | ||
| background: white; | ||
| margin-left: 0; | ||
| margin-right: 0; | ||
|
|
@@ -644,38 +648,38 @@ body#settings .settings-border .key_list { | |
| padding-bottom: 200px; | ||
| } | ||
|
|
||
| #settings.client .threads > p { | ||
| #settings.client .threads>p { | ||
| padding-left: 20px; | ||
| opacity: 0.7; | ||
| } | ||
|
|
||
| #settings.client .threads > .line { | ||
| #settings.client .threads>.line { | ||
| padding-left: 20px; | ||
| text-align: left; | ||
| border-top: 1px solid #31a217; | ||
| padding-right: 20px; | ||
| width: auto; | ||
| } | ||
|
|
||
| #settings.client .threads > .line:last-child { | ||
| #settings.client .threads>.line:last-child { | ||
| border-bottom: 1px solid #31a217; | ||
| } | ||
|
|
||
| #settings.client .threads > .line.loaded:hover { | ||
| #settings.client .threads>.line.loaded:hover { | ||
| background-color: #fff; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| #settings.client .threads > .line .loading { | ||
| #settings.client .threads>.line .loading { | ||
| display: inline-block; | ||
| } | ||
|
|
||
| #settings.client .threads > .line .from_container { | ||
| #settings.client .threads>.line .from_container { | ||
| display: inline-block; | ||
| width: 300px; | ||
| } | ||
|
|
||
| #settings.client .threads > .line .from_container .msg_count { | ||
| #settings.client .threads>.line .from_container .msg_count { | ||
| font-size: 90%; | ||
| opacity: 0.5; | ||
| padding-left: 8px; | ||
|
|
@@ -684,7 +688,7 @@ body#settings .settings-border .key_list { | |
| } | ||
|
|
||
| /* #settings.client .threads .line .subject { } */ | ||
| #settings.client .threads > .line .date { | ||
| #settings.client .threads>.line .date { | ||
| position: absolute; | ||
| right: 20px; | ||
| } | ||
|
|
@@ -697,8 +701,8 @@ body#settings .settings-border .key_list { | |
| border-top: 1px dotted #c0c0c0; | ||
| } | ||
|
|
||
| #settings.client .thread .message > iframe, | ||
| #settings.client .thread .reply > iframe { | ||
| #settings.client .thread .message>iframe, | ||
| #settings.client .thread .reply>iframe { | ||
| width: 100%; | ||
| border: none; | ||
| } | ||
|
|
@@ -722,12 +726,12 @@ body#settings .settings-border .key_list { | |
| cursor: pointer; | ||
| } | ||
|
|
||
| #settings.client > table { | ||
| #settings.client>table { | ||
| width: 100%; | ||
| min-height: 90%; | ||
| } | ||
|
|
||
| #settings.client > table td.menu { | ||
| #settings.client>table td.menu { | ||
| width: 200px; | ||
| min-width: 200px; | ||
| max-width: 200px; | ||
|
|
@@ -736,14 +740,14 @@ body#settings .settings-border .key_list { | |
| background: white; | ||
| } | ||
|
|
||
| #settings.client > table td.menu .button { | ||
| #settings.client>table td.menu .button { | ||
| min-width: 160px !important; | ||
| margin-bottom: 8px !important; | ||
| text-align: left !important; | ||
| white-space: nowrap; | ||
| } | ||
|
|
||
| #settings.client > table td.menu span.label { | ||
| #settings.client>table td.menu span.label { | ||
| margin-left: 0; | ||
| margin-bottom: 2px; | ||
| font-size: 12px; | ||
|
|
@@ -754,7 +758,7 @@ body#settings .settings-border .key_list { | |
| opacity: 0.7; | ||
| } | ||
|
|
||
| #settings.client > #banner > img { | ||
| #settings.client>#banner>img { | ||
| height: 32px; | ||
| width: 32px; | ||
| float: right; | ||
|
|
@@ -763,19 +767,19 @@ body#settings .settings-border .key_list { | |
| margin-left: 20px; | ||
| } | ||
|
|
||
| #settings.client > #banner > img.action_open_settings { | ||
| #settings.client>#banner>img.action_open_settings { | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| #settings.client > #banner > .action_finish_session { | ||
| #settings.client>#banner>.action_finish_session { | ||
| height: 32px; | ||
| margin-top: -6px; | ||
| float: right; | ||
| margin-left: 20px; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| #settings.client > #banner > .action_finish_session img { | ||
| #settings.client>#banner>.action_finish_session img { | ||
| height: 32px; | ||
| } | ||
|
|
||
|
|
@@ -847,4 +851,4 @@ span.fc-badge { | |
| .fc-badge-light-gray { | ||
| background-color: #bcbcbc; | ||
| color: #444 !important; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -851,7 +851,7 @@ AN8G3r5Htj8olot+jm9mIa5XLXWzMNUZgg== | |
| await addKeyPopup.waitAndType('@input-armored-key', updatedKey.privateKey); | ||
| await addKeyPopup.waitAndType('#input_passphrase', passphrase); | ||
| await addKeyPopup.waitAndClick('.action_add_private_key', { delay: 1 }); | ||
| await Util.sleep(1); | ||
| await settingsPage.waitAll('@action-show-key-1'); | ||
| await gmailPage.page.reload(); | ||
| await Util.sleep(3); | ||
| await gmailPage.waitTillGone('@webmail-notification-notify_expiring_keys'); | ||
|
|
@@ -2250,15 +2250,15 @@ AN8G3r5Htj8olot+jm9mIa5XLXWzMNUZgg== | |
| const title = await settingsPage.read('@container-overlay-prompt-text'); | ||
| expect(title).to.contain( | ||
| 'Failed to store newly generated key on FlowCrypt Email Key Manager, ' + | ||
| 'No key has been generated for [email protected] yet. Please ask your administrator.' | ||
| 'No key has been generated for [email protected] yet. Please ask your administrator.' | ||
| ); | ||
| await settingsPage.click('@action-show-overlay-details'); | ||
| await settingsPage.waitAll('@container-overlay-details'); | ||
| await Util.sleep(0.5); | ||
| const details = await settingsPage.read('@container-overlay-details'); | ||
| expect(details).to.contain( | ||
| `405 when PUT-ing https://localhost:${t.context.urls?.port}/flowcrypt-email-key-manager/v1/keys/private string: ` + | ||
| 'privateKey -> No key has been generated for [email protected] yet' | ||
| 'privateKey -> No key has been generated for [email protected] yet' | ||
| ); | ||
| expect(details).to.not.contain('PRIVATE KEY'); | ||
| }) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's use
col-6for fingerprint andcol-1for status column, as currently fingerprint isn't fully fit on 1280px screen width: