зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1549811 - Sorting element for about:logins. r=jaws,Pike,fluent-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D33110 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
0e618c5315
Коммит
6697fcac72
|
@ -23,7 +23,10 @@ login-list =
|
|||
[one] { $count } entry
|
||||
*[other] { $count } entries
|
||||
}
|
||||
|
||||
.last-changed-option = Last Changed
|
||||
.last-used-option = Last Used
|
||||
.name-option = Name
|
||||
.sort-label-text = Sort by:
|
||||
login-item =
|
||||
.cancel-button = Cancel
|
||||
.copied-password-button = ✓ Copied!
|
||||
|
|
|
@ -27,8 +27,12 @@
|
|||
<button id="create-login-button" data-l10n-id="create-login-button"></button>
|
||||
</header>
|
||||
<login-list data-l10n-id="login-list"
|
||||
data-l10n-attrs="count"
|
||||
data-l10n-args='{"count": 0}'></login-list>
|
||||
data-l10n-args='{"count": 0}'
|
||||
data-l10n-attrs="count,
|
||||
last-changed-option,
|
||||
last-used-option,
|
||||
name-option,
|
||||
sort-label-text"></login-list>
|
||||
<login-item data-l10n-id="login-item"
|
||||
data-l10n-args='{"timeCreated": 0, "timeChanged": 0, "timeUsed": 0}'
|
||||
data-l10n-attrs="cancel-button,
|
||||
|
@ -55,6 +59,14 @@
|
|||
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
|
||||
<link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-list.css">
|
||||
<div class="meta">
|
||||
<label for="login-sort">
|
||||
<span class="sort-label-text"></span>
|
||||
<select id="login-sort">
|
||||
<option class="name-option" value="name"/>
|
||||
<option class="last-used-option" value="last-used"/>
|
||||
<option class="last-changed-option" value="last-changed"/>
|
||||
</select>
|
||||
</label>
|
||||
<span class="count"></span>
|
||||
</div>
|
||||
<ol>
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
import LoginListItem from "chrome://browser/content/aboutlogins/components/login-list-item.js";
|
||||
import ReflectedFluentElement from "chrome://browser/content/aboutlogins/components/reflected-fluent-element.js";
|
||||
|
||||
const collator = new Intl.Collator();
|
||||
const sortFnOptions = {
|
||||
name: (a, b) => collator.compare(a.title, b.title),
|
||||
"last-used": (a, b) => (a.timeLastUsed < b.timeLastUsed),
|
||||
"last-changed": (a, b) => (a.timePasswordChanged < b.timePasswordChanged),
|
||||
};
|
||||
|
||||
export default class LoginList extends ReflectedFluentElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -25,6 +32,8 @@ export default class LoginList extends ReflectedFluentElement {
|
|||
|
||||
this.render();
|
||||
|
||||
this.shadowRoot.getElementById("login-sort")
|
||||
.addEventListener("change", this);
|
||||
window.addEventListener("AboutLoginsLoginSelected", this);
|
||||
window.addEventListener("AboutLoginsFilterLogins", this);
|
||||
}
|
||||
|
@ -66,6 +75,12 @@ export default class LoginList extends ReflectedFluentElement {
|
|||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "change": {
|
||||
const sort = event.target.value;
|
||||
this._logins = this._logins.sort((a, b) => sortFnOptions[sort](a, b));
|
||||
this.render();
|
||||
break;
|
||||
}
|
||||
case "AboutLoginsFilterLogins": {
|
||||
this._filter = event.detail.toLocaleLowerCase();
|
||||
this.render();
|
||||
|
@ -86,7 +101,11 @@ export default class LoginList extends ReflectedFluentElement {
|
|||
}
|
||||
|
||||
static get reflectedFluentIDs() {
|
||||
return ["count"];
|
||||
return ["count",
|
||||
"last-used-option",
|
||||
"last-changed-option",
|
||||
"name-option",
|
||||
"sort-label-text"];
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
|
|
|
@ -27,15 +27,23 @@ Test the login-list component
|
|||
let gLoginList;
|
||||
const TEST_LOGIN_1 = {
|
||||
guid: "123456789",
|
||||
origin: "https://example.com",
|
||||
origin: "https://abc-example.com",
|
||||
username: "user1",
|
||||
password: "pass1",
|
||||
title: "abc-example.com",
|
||||
// new Date("December 13, 2018").getTime()
|
||||
timeLastUsed: 1544677200000,
|
||||
timePasswordChanged: 1544677200000,
|
||||
};
|
||||
const TEST_LOGIN_2 = {
|
||||
guid: "987654321",
|
||||
origin: "https://example.com",
|
||||
username: "user2",
|
||||
password: "pass2",
|
||||
title: "example.com",
|
||||
// new Date("June 1, 2019").getTime()
|
||||
timeLastUsed: 1559361600000,
|
||||
timePasswordChanged: 1559361600000,
|
||||
};
|
||||
|
||||
add_task(async function setup() {
|
||||
|
@ -188,6 +196,29 @@ add_task(async function test_login_added_filtered() {
|
|||
ok(loginListItems[2].hidden, "login-list-item3 should be hidden");
|
||||
is(countSpan.textContent, "1", "Count should remain unchanged");
|
||||
});
|
||||
|
||||
add_task(async function test_sorted_list() {
|
||||
// sort by last used
|
||||
gLoginList.shadowRoot.getElementById("login-sort").selectedIndex = 1;
|
||||
let loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
|
||||
let timeUsed = loginListItems[0]._login.timeLastUsed;
|
||||
let timeUsed2 = loginListItems[1]._login.timeLastUsed;
|
||||
is(timeUsed2 > timeUsed, true, "Last used login should be displayed at top of list");
|
||||
|
||||
// sort by name
|
||||
gLoginList.shadowRoot.getElementById("login-sort").selectedIndex = 0;
|
||||
loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
|
||||
let title = loginListItems[0]._login.title;
|
||||
let title2 = loginListItems[1]._login.title;
|
||||
is(title.localeCompare(title2), -1, "Logins should be sorted alphabetically by hostname");
|
||||
|
||||
// sort by last changed
|
||||
gLoginList.shadowRoot.getElementById("login-sort").selectedIndex = 2;
|
||||
loginListItems = gLoginList.shadowRoot.querySelectorAll("login-list-item");
|
||||
let pwChanged = loginListItems[0]._login.timePasswordChanged;
|
||||
let pwChanged2 = loginListItems[1]._login.timePasswordChanged;
|
||||
is(pwChanged2 > pwChanged, true, "Login with most recently changed password should be displayed at top of list");
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
|
Загрузка…
Ссылка в новой задаче