1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-22 17:10:10 +00:00

accounts: show list row of search filters, click to remove

any filters in your search box will show as little button/chip things on
the row below. Clicking them will remove them from the search.
This commit is contained in:
Harvey Tindall 2023-06-13 22:27:08 +01:00
parent ff62f8821a
commit 8ac3bb9711
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
3 changed files with 96 additions and 13 deletions

View File

@ -584,7 +584,6 @@
<div class="row"> <div class="row">
<span class="text-3xl font-bold mr-2 col">{{ .strings.accounts }}</span> <span class="text-3xl font-bold mr-2 col">{{ .strings.accounts }}</span>
<input type="search" class="col sm field ~neutral @low input search ml-2 mr-2" id="accounts-search" placeholder="{{ .strings.search }}"> <input type="search" class="col sm field ~neutral @low input search ml-2 mr-2" id="accounts-search" placeholder="{{ .strings.search }}">
<button type="button" class="button ~neutral @low center ml-2 mr-2 hidden"><span id="accounts-sort-by-field"></span> <span class="ml-2">&times;</span></button>
</div> </div>
<div class="row"> <div class="row">
<span class="col sm button ~neutral @low center mb-2" id="accounts-add-user">{{ .quantityStrings.addUser.Singular }}</span> <span class="col sm button ~neutral @low center mb-2" id="accounts-add-user">{{ .quantityStrings.addUser.Singular }}</span>
@ -611,6 +610,10 @@
<span class="col sm button ~critical @low center mb-2" id="accounts-delete-user">{{ .quantityStrings.deleteUser.Singular }}</span> <span class="col sm button ~critical @low center mb-2" id="accounts-delete-user">{{ .quantityStrings.deleteUser.Singular }}</span>
</div> </div>
</div> </div>
<div class="row">
<button type="button" class="button ~neutral @low center ml-2 mr-2 hidden"><span id="accounts-sort-by-field"></span> <span class="ml-2">&times;</span></button>
<span id="accounts-filter-area"></span>
</div>
<div class="card @low accounts-header table-responsive mt-8"> <div class="card @low accounts-header table-responsive mt-8">
<table class="table text-base leading-4"> <table class="table text-base leading-4">
<thead> <thead>

View File

@ -37,6 +37,8 @@
"advancedSettings": "Advanced Settings", "advancedSettings": "Advanced Settings",
"lastActiveTime": "Last Active", "lastActiveTime": "Last Active",
"from": "From", "from": "From",
"after": "After",
"before": "Before",
"user": "User", "user": "User",
"expiry": "Expiry", "expiry": "Expiry",
"userExpiry": "User Expiry", "userExpiry": "User Expiry",
@ -115,7 +117,8 @@
"templateEnterName": "Enter a name to save this template.", "templateEnterName": "Enter a name to save this template.",
"accessJFA": "Access jfa-go", "accessJFA": "Access jfa-go",
"accessJFASettings": "Cannot be changed as either \"Admin Only\" or \"Allow All\" has been set in Settings > General.", "accessJFASettings": "Cannot be changed as either \"Admin Only\" or \"Allow All\" has been set in Settings > General.",
"sortingBy": "Sorting By" "sortingBy": "Sorting By",
"clickToRemoveFilter": "Click to remove this filter."
}, },
"notifications": { "notifications": {
"changedEmailAddress": "Changed email address of {n}.", "changedEmailAddress": "Changed email address of {n}.",

View File

@ -806,6 +806,20 @@ export class accountsList {
string: true, string: true,
date: false date: false
}, },
"username": {
name: "Username",
getter: "name",
bool: false,
string: true,
date: false
},
"name": {
name: "Username",
getter: "name",
bool: false,
string: true,
date: false
},
"admin": { "admin": {
name: "Admin", name: "Admin",
getter: "admin", getter: "admin",
@ -871,19 +885,12 @@ export class accountsList {
} }
} }
const filterArea = document.getElementById("accounts-filter-area");
filterArea.textContent = "";
query = query.toLowerCase(); query = query.toLowerCase();
let result: string[] = [...this._ordering]; let result: string[] = [...this._ordering];
// console.log("initial:", result); // console.log("initial:", result);
if (!(query.includes(":"))) {
let cachedResult = [...result];
for (let id of cachedResult) {
const u = this._users[id];
if (!u.matchesSearch(query as string)) {
result.splice(result.indexOf(id), 1);
}
}
return result;
}
// const words = query.split(" "); // const words = query.split(" ");
let words: string[] = []; let words: string[] = [];
@ -910,7 +917,15 @@ export class accountsList {
if (lastQuote != -1) { if (lastQuote != -1) {
continue; continue;
} else { } else {
words.push(query.substring(queryStart, i+1).replace(/['"]/g, "")); let end = i+1;
if (query[i] == " ") {
end = i;
while (i+1 < query.length && query[i+1] == " ") {
i += 1;
}
}
words.push(query.substring(queryStart, end).replace(/['"]/g, ""));
console.log("pushed", words);
queryStart = -1; queryStart = -1;
} }
} }
@ -918,6 +933,16 @@ export class accountsList {
query = ""; query = "";
for (let word of words) { for (let word of words) {
if (!word.includes(":")) {
let cachedResult = [...result];
for (let id of cachedResult) {
const u = this._users[id];
if (!u.matchesSearch(word)) {
result.splice(result.indexOf(id), 1);
}
}
continue;
}
const split = [word.substring(0, word.indexOf(":")), word.substring(word.indexOf(":")+1)]; const split = [word.substring(0, word.indexOf(":")), word.substring(word.indexOf(":")+1)];
if (!(split[0] in queries)) continue; if (!(split[0] in queries)) continue;
@ -935,6 +960,24 @@ export class accountsList {
boolState = false; boolState = false;
} }
if (isBool) { if (isBool) {
// FIXME: Generate filter card for each filter class
const filterCard = document.createElement("span");
filterCard.ariaLabel = window.lang.strings("clickToRemoveFilter");
filterCard.classList.add("button", "~" + (boolState ? "positive" : "critical"), "@high", "center", "ml-2", "mr-2");
filterCard.innerHTML = `
<span class="font-bold mr-2">${queryFormat.name}</span>
<i class="text-2xl ri-${boolState? "checkbox" : "close"}-circle-fill"></i>
`;
filterCard.addEventListener("click", () => {
for (let quote of [`"`, `'`, ``]) {
this._search.value = this._search.value.replace(split[0] + ":" + quote + split[1] + quote, "");
}
this._search.oninput((null as Event));
})
filterArea.appendChild(filterCard);
// console.log("is bool, state", boolState); // console.log("is bool, state", boolState);
// So removing elements doesn't affect us // So removing elements doesn't affect us
let cachedResult = [...result]; let cachedResult = [...result];
@ -952,6 +995,22 @@ export class accountsList {
} }
} }
if (queryFormat.string) { if (queryFormat.string) {
const filterCard = document.createElement("span");
filterCard.ariaLabel = window.lang.strings("clickToRemoveFilter");
filterCard.classList.add("button", "~neutral", "@low", "center", "ml-2", "mr-2", "h-full");
filterCard.innerHTML = `
<span class="font-bold mr-2">${queryFormat.name}:</span> "${split[1]}"
`;
filterCard.addEventListener("click", () => {
for (let quote of [`"`, `'`, ``]) {
this._search.value = this._search.value.replace(split[0] + ":" + quote + split[1] + quote, "");
}
this._search.oninput((null as Event));
})
filterArea.appendChild(filterCard);
let cachedResult = [...result]; let cachedResult = [...result];
for (let id of cachedResult) { for (let id of cachedResult) {
const u = this._users[id]; const u = this._users[id];
@ -977,6 +1036,24 @@ export class accountsList {
let date: Date = (Date as any).fromString(split[1]) as Date; let date: Date = (Date as any).fromString(split[1]) as Date;
console.log("Read", attempt, "and", date); console.log("Read", attempt, "and", date);
if ("invalid" in (date as any)) continue; if ("invalid" in (date as any)) continue;
const filterCard = document.createElement("span");
filterCard.ariaLabel = window.lang.strings("clickToRemoveFilter");
filterCard.classList.add("button", "~neutral", "@low", "center", "ml-2", "mr-2", "h-full");
filterCard.innerHTML = `
<span class="font-bold mr-2">${queryFormat.name}:</span> ${(compareType == 1) ? window.lang.strings("after")+" " : ((compareType == -1) ? window.lang.strings("before")+" " : "")}${split[1]}
`;
filterCard.addEventListener("click", () => {
for (let quote of [`"`, `'`, ``]) {
this._search.value = this._search.value.replace(split[0] + ":" + quote + split[1] + quote, "");
}
this._search.oninput((null as Event));
})
filterArea.appendChild(filterCard);
let cachedResult = [...result]; let cachedResult = [...result];
for (let id of cachedResult) { for (let id of cachedResult) {
const u = this._users[id]; const u = this._users[id];