mirror of
https://github.com/hrfee/jfa-go.git
synced 2026-01-18 16:47:42 +01:00
693 lines
26 KiB
TypeScript
693 lines
26 KiB
TypeScript
import { _get, _post, _delete, toDateString } from "../modules/common.js";
|
|
import {
|
|
SearchConfiguration,
|
|
QueryType,
|
|
SearchableItem,
|
|
SearchableItems,
|
|
SearchableItemDataAttribute,
|
|
} from "../modules/search.js";
|
|
import { accountURLEvent } from "../modules/accounts.js";
|
|
import { inviteURLEvent } from "../modules/invites.js";
|
|
import { PaginatedList } from "./list.js";
|
|
|
|
declare var window: GlobalWindow;
|
|
|
|
const ACTIVITY_DEFAULT_SORT_FIELD = "time";
|
|
const ACTIVITY_DEFAULT_SORT_ASCENDING = false;
|
|
|
|
export interface activity {
|
|
id: string;
|
|
type: string;
|
|
user_id: string;
|
|
source_type: string;
|
|
source: string;
|
|
invite_code: string;
|
|
value: string;
|
|
time: number;
|
|
username: string;
|
|
source_username: string;
|
|
ip: string;
|
|
}
|
|
|
|
var activityTypeMoods = {
|
|
creation: 1,
|
|
deletion: -1,
|
|
disabled: -1,
|
|
enabled: 1,
|
|
contactLinked: 1,
|
|
contactUnlinked: -1,
|
|
changePassword: 0,
|
|
resetPassword: 0,
|
|
createInvite: 1,
|
|
deleteInvite: -1,
|
|
};
|
|
|
|
// window.lang doesn't exist at page load, so I made this a function that's invoked by activityList.
|
|
const queries = (): { [field: string]: QueryType } => {
|
|
return {
|
|
id: {
|
|
name: window.lang.strings("activityID"),
|
|
getter: "id",
|
|
bool: false,
|
|
string: true,
|
|
date: false,
|
|
},
|
|
title: {
|
|
name: window.lang.strings("title"),
|
|
getter: "title",
|
|
bool: false,
|
|
string: true,
|
|
date: false,
|
|
localOnly: true,
|
|
},
|
|
user: {
|
|
name: window.lang.strings("usersMentioned"),
|
|
getter: "mentionedUsers",
|
|
bool: false,
|
|
string: true,
|
|
date: false,
|
|
},
|
|
actor: {
|
|
name: window.lang.strings("actor"),
|
|
description: window.lang.strings("actorDescription"),
|
|
getter: "actor",
|
|
bool: false,
|
|
string: true,
|
|
date: false,
|
|
},
|
|
referrer: {
|
|
name: window.lang.strings("referrer"),
|
|
getter: "referrer",
|
|
bool: true,
|
|
string: true,
|
|
date: false,
|
|
},
|
|
time: {
|
|
name: window.lang.strings("date"),
|
|
getter: "time",
|
|
bool: false,
|
|
string: false,
|
|
date: true,
|
|
},
|
|
"account-creation": {
|
|
name: window.lang.strings("accountCreationFilter"),
|
|
getter: "accountCreation",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
"account-deletion": {
|
|
name: window.lang.strings("accountDeletionFilter"),
|
|
getter: "accountDeletion",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
"account-disabled": {
|
|
name: window.lang.strings("accountDisabledFilter"),
|
|
getter: "accountDisabled",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
"account-enabled": {
|
|
name: window.lang.strings("accountEnabledFilter"),
|
|
getter: "accountEnabled",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
"contact-linked": {
|
|
name: window.lang.strings("contactLinkedFilter"),
|
|
getter: "contactLinked",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
"contact-unlinked": {
|
|
name: window.lang.strings("contactUnlinkedFilter"),
|
|
getter: "contactUnlinked",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
"password-change": {
|
|
name: window.lang.strings("passwordChangeFilter"),
|
|
getter: "passwordChange",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
"password-reset": {
|
|
name: window.lang.strings("passwordResetFilter"),
|
|
getter: "passwordReset",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
"invite-created": {
|
|
name: window.lang.strings("inviteCreatedFilter"),
|
|
getter: "inviteCreated",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
"invite-deleted": {
|
|
name: window.lang.strings("inviteDeletedFilter"),
|
|
getter: "inviteDeleted",
|
|
bool: true,
|
|
string: false,
|
|
date: false,
|
|
},
|
|
};
|
|
};
|
|
|
|
// var moodColours = ["~warning", "~neutral", "~urge"];
|
|
|
|
export var activityReload = new CustomEvent("activity-reload");
|
|
|
|
export class Activity implements activity, SearchableItem {
|
|
private _card: HTMLElement;
|
|
private _title: HTMLElement;
|
|
private _time: HTMLElement;
|
|
private _timeUnix: number;
|
|
private _sourceType: HTMLElement;
|
|
private _source: HTMLElement;
|
|
private _referrer: HTMLElement;
|
|
private _expiryTypeBadge: HTMLElement;
|
|
private _delete: HTMLElement;
|
|
private _ip: HTMLElement;
|
|
private _act: activity;
|
|
|
|
_genUserText = (): string => {
|
|
return `<span class="font-medium">${this._act.username || this._act.user_id.substring(0, 5)}</span>`;
|
|
};
|
|
|
|
_genSrcUserText = (): string => {
|
|
return `<span class="font-medium">${this._act.source_username || this._act.source.substring(0, 5)}</span>`;
|
|
};
|
|
|
|
_genUserLink = (): string => {
|
|
return `<a role="link" tabindex="0" class="hover:underline cursor-pointer activity-pseudo-link-user" data-id="${this._act.user_id}" href="${window.pages.Base}${window.pages.Admin}/accounts?user=${this._act.user_id}">${this._genUserText()}</a>`;
|
|
};
|
|
|
|
_genSrcUserLink = (): string => {
|
|
return `<a role="link" tabindex="0" class="hover:underline cursor-pointer activity-pseudo-link-user" data-id="${this._act.user_id}" href="${window.pages.Base}${window.pages.Admin}/accounts?user=${this._act.source}">${this._genSrcUserText()}</a>`;
|
|
};
|
|
|
|
private _renderInvText = (): string => {
|
|
return `<span class="font-medium font-mono">${this.value || this.invite_code || "???"}</span>`;
|
|
};
|
|
|
|
private _genInvLink = (): string => {
|
|
return `<a role="link" tabindex="0" class="hover:underline cursor-pointer activity-pseudo-link-invite" data-id="${this.invite_code}" href="${window.pages.Base}${window.pages.Admin}/?invite=${this.invite_code}">${this._renderInvText()}</a>`;
|
|
};
|
|
|
|
get accountCreation(): boolean {
|
|
return this.type == "creation";
|
|
}
|
|
get accountDeletion(): boolean {
|
|
return this.type == "deletion";
|
|
}
|
|
get accountDisabled(): boolean {
|
|
return this.type == "disabled";
|
|
}
|
|
get accountEnabled(): boolean {
|
|
return this.type == "enabled";
|
|
}
|
|
get contactLinked(): boolean {
|
|
return this.type == "contactLinked";
|
|
}
|
|
get contactUnlinked(): boolean {
|
|
return this.type == "contactUnlinked";
|
|
}
|
|
get passwordChange(): boolean {
|
|
return this.type == "changePassword";
|
|
}
|
|
get passwordReset(): boolean {
|
|
return this.type == "resetPassword";
|
|
}
|
|
get inviteCreated(): boolean {
|
|
return this.type == "createInvite";
|
|
}
|
|
get inviteDeleted(): boolean {
|
|
return this.type == "deleteInvite";
|
|
}
|
|
|
|
get mentionedUsers(): string {
|
|
return (this.username + " " + this.source_username).toLowerCase();
|
|
}
|
|
|
|
get actor(): string {
|
|
let out = this.source_type + " ";
|
|
if (this.source_type == "admin" || this.source_type == "user") out += this.source_username;
|
|
return out.toLowerCase();
|
|
}
|
|
|
|
get referrer(): string {
|
|
if (this.type != "creation" || this.source_type != "user") return "";
|
|
return this.source_username.toLowerCase();
|
|
}
|
|
|
|
get type(): string {
|
|
return this._act.type;
|
|
}
|
|
set type(v: string) {
|
|
this._act.type = v;
|
|
|
|
let mood = activityTypeMoods[v]; // 1 = positive, 0 = neutral, -1 = negative
|
|
for (let el of [this._card, this._delete]) {
|
|
el.classList.remove("~warning");
|
|
el.classList.remove("~neutral");
|
|
el.classList.remove("~urge");
|
|
|
|
if (mood == -1) {
|
|
el.classList.add("~warning");
|
|
} else if (mood == 0) {
|
|
el.classList.add("~neutral");
|
|
} else if (mood == 1) {
|
|
el.classList.add("~urge");
|
|
}
|
|
}
|
|
|
|
/* for (let i = 0; i < moodColours.length; i++) {
|
|
if (i-1 == mood) this._card.classList.add(moodColours[i]);
|
|
else this._card.classList.remove(moodColours[i]);
|
|
} */
|
|
|
|
// lazy late addition, hide then unhide if needed
|
|
this._expiryTypeBadge.classList.add("unfocused");
|
|
if (this.type == "changePassword" || this.type == "resetPassword") {
|
|
let innerHTML = ``;
|
|
if (this.type == "changePassword") innerHTML = window.lang.strings("accountChangedPassword");
|
|
else innerHTML = window.lang.strings("accountResetPassword");
|
|
innerHTML = innerHTML.replace("{user}", this._genUserLink());
|
|
this._title.innerHTML = innerHTML;
|
|
} else if (this.type == "contactLinked" || this.type == "contactUnlinked") {
|
|
let platform = this.value;
|
|
if (platform == "email") {
|
|
platform = window.lang.strings("emailAddress");
|
|
} else {
|
|
platform = platform.charAt(0).toUpperCase() + platform.slice(1);
|
|
}
|
|
let innerHTML = ``;
|
|
if (this.type == "contactLinked") innerHTML = window.lang.strings("accountLinked");
|
|
else innerHTML = window.lang.strings("accountUnlinked");
|
|
innerHTML = innerHTML.replace("{user}", this._genUserLink()).replace("{contactMethod}", platform);
|
|
this._title.innerHTML = innerHTML;
|
|
} else if (this.type == "creation") {
|
|
this._title.innerHTML = window.lang.strings("accountCreated").replace("{user}", this._genUserLink());
|
|
if (this.source_type == "user") {
|
|
this._referrer.classList.remove("unfocused");
|
|
this._referrer.innerHTML = `<span class="supra">${window.lang.strings("referrer")}</span>${this._genSrcUserLink()}`;
|
|
} else {
|
|
this._referrer.classList.add("unfocused");
|
|
this._referrer.textContent = ``;
|
|
}
|
|
} else if (this.type == "deletion") {
|
|
if (this.source_type == "daemon") {
|
|
this._title.innerHTML = window.lang.strings("accountExpired").replace("{user}", this._genUserText());
|
|
this._expiryTypeBadge.classList.remove("unfocused");
|
|
this._expiryTypeBadge.classList.add("~critical");
|
|
this._expiryTypeBadge.classList.remove("~info");
|
|
this._expiryTypeBadge.textContent = window.lang.strings("deleted");
|
|
} else {
|
|
this._title.innerHTML = window.lang.strings("accountDeleted").replace("{user}", this._genUserText());
|
|
}
|
|
} else if (this.type == "enabled") {
|
|
this._title.innerHTML = window.lang.strings("accountReEnabled").replace("{user}", this._genUserLink());
|
|
} else if (this.type == "disabled") {
|
|
if (this.source_type == "daemon") {
|
|
this._title.innerHTML = window.lang.strings("accountExpired").replace("{user}", this._genUserLink());
|
|
this._expiryTypeBadge.classList.remove("unfocused");
|
|
this._expiryTypeBadge.classList.add("~info");
|
|
this._expiryTypeBadge.classList.remove("~critical");
|
|
this._expiryTypeBadge.textContent = window.lang.strings("disabled");
|
|
} else {
|
|
this._title.innerHTML = window.lang.strings("accountDisabled").replace("{user}", this._genUserLink());
|
|
}
|
|
} else if (this.type == "createInvite") {
|
|
this._title.innerHTML = window.lang.strings("inviteCreated").replace("{invite}", this._genInvLink());
|
|
} else if (this.type == "deleteInvite") {
|
|
let innerHTML = ``;
|
|
if (this.source_type == "daemon") {
|
|
innerHTML = window.lang.strings("inviteExpired");
|
|
} else {
|
|
innerHTML = window.lang.strings("inviteDeleted");
|
|
}
|
|
|
|
this._title.innerHTML = innerHTML.replace("{invite}", this._renderInvText());
|
|
}
|
|
}
|
|
|
|
get time(): number {
|
|
return this._timeUnix;
|
|
}
|
|
set time(v: number) {
|
|
this._timeUnix = v;
|
|
this._time.textContent = toDateString(new Date(v * 1000));
|
|
}
|
|
|
|
get source_type(): string {
|
|
return this._act.source_type;
|
|
}
|
|
set source_type(v: string) {
|
|
this._act.source_type = v;
|
|
if ((this.source_type == "anon" || this.source_type == "user") && this.type == "creation") {
|
|
this._sourceType.textContent = window.lang.strings("fromInvite");
|
|
} else if (this.source_type == "admin") {
|
|
this._sourceType.textContent = window.lang.strings("byAdmin");
|
|
} else if (this.source_type == "user" && this.type != "creation") {
|
|
this._sourceType.textContent = window.lang.strings("byUser");
|
|
} else if (this.source_type == "daemon") {
|
|
this._sourceType.textContent = window.lang.strings("byJfaGo");
|
|
}
|
|
}
|
|
|
|
get ip(): string {
|
|
return this._act.ip;
|
|
}
|
|
set ip(v: string) {
|
|
this._act.ip = v;
|
|
if (v) {
|
|
this._ip.classList.remove("unfocused");
|
|
this._ip.innerHTML = `<span class="supra">IP</span><span class="font-mono bg-inherit">${v}</span>`;
|
|
} else {
|
|
this._ip.classList.add("unfocused");
|
|
this._ip.textContent = ``;
|
|
}
|
|
}
|
|
|
|
get invite_code(): string {
|
|
return this._act.invite_code;
|
|
}
|
|
set invite_code(v: string) {
|
|
this._act.invite_code = v;
|
|
}
|
|
|
|
get value(): string {
|
|
return this._act.value;
|
|
}
|
|
set value(v: string) {
|
|
this._act.value = v;
|
|
}
|
|
|
|
get source(): string {
|
|
return this._act.source;
|
|
}
|
|
set source(v: string) {
|
|
this._act.source = v;
|
|
if ((this.source_type == "anon" || this.source_type == "user") && this.type == "creation") {
|
|
this._source.innerHTML = this._genInvLink();
|
|
} else if (
|
|
(this.source_type == "admin" || this.source_type == "user") &&
|
|
this._act.source != "" &&
|
|
this._act.source_username != ""
|
|
) {
|
|
this._source.innerHTML = this._genSrcUserLink();
|
|
}
|
|
}
|
|
|
|
get id(): string {
|
|
return this._act.id;
|
|
}
|
|
set id(v: string) {
|
|
this._act.id = v;
|
|
this._card.setAttribute(SearchableItemDataAttribute, v);
|
|
}
|
|
|
|
get user_id(): string {
|
|
return this._act.user_id;
|
|
}
|
|
set user_id(v: string) {
|
|
this._act.user_id = v;
|
|
}
|
|
|
|
get username(): string {
|
|
return this._act.username;
|
|
}
|
|
set username(v: string) {
|
|
this._act.username = v;
|
|
}
|
|
|
|
get source_username(): string {
|
|
return this._act.source_username;
|
|
}
|
|
set source_username(v: string) {
|
|
this._act.source_username = v;
|
|
}
|
|
|
|
get title(): string {
|
|
return this._title.textContent;
|
|
}
|
|
|
|
matchesSearch = (query: string): boolean => {
|
|
// console.log(this.title, "matches", query, ":", this.title.includes(query));
|
|
return (
|
|
this.title.toLowerCase().includes(query) ||
|
|
this.username.toLowerCase().includes(query) ||
|
|
this.source_username.toLowerCase().includes(query)
|
|
);
|
|
};
|
|
|
|
constructor(act: activity) {
|
|
this._card = document.createElement("div");
|
|
|
|
this._card.classList.add("card", "@low", "flex", "flex-col", "gap-2");
|
|
|
|
this._card.innerHTML = `
|
|
<div class="flex flex-row flex-wrap justify-between items-start gap-1">
|
|
<span class="heading truncate flex-initial md:text-2xl text-xl activity-title"></span>
|
|
<div class="flex flex-row flex-wrap gap-2">
|
|
<span class="activity-expiry-type badge self-stretch"></span>
|
|
<span class="font-medium md:text-sm text-xs activity-time" aria-label="${window.lang.strings("date")}"></span>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-row justify-between items-baseline">
|
|
<div class="flex flex-col md:flex-row gap-1 items-baseline">
|
|
<div class="flex flex-row gap-2 items-baseline">
|
|
<span class="supra activity-source-type"></span><span class="activity-source"></span>
|
|
</div>
|
|
<span class="activity-referrer flex flex-row gap-2 items-baseline"></span>
|
|
<span class="activity-ip flex flex-row gap-2 items-baseline"></span>
|
|
</div>
|
|
<div>
|
|
<button class="button @low hover:~critical rounded-full px-1 py-px activity-delete" aria-label="${window.lang.strings("delete")}"><i class="ri-close-line"></i></button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
this._title = this._card.querySelector(".activity-title");
|
|
this._time = this._card.querySelector(".activity-time");
|
|
this._sourceType = this._card.querySelector(".activity-source-type");
|
|
this._source = this._card.querySelector(".activity-source");
|
|
this._ip = this._card.querySelector(".activity-ip");
|
|
this._referrer = this._card.querySelector(".activity-referrer");
|
|
this._expiryTypeBadge = this._card.querySelector(".activity-expiry-type");
|
|
this._delete = this._card.querySelector(".activity-delete");
|
|
|
|
document.addEventListener("timefmt-change", () => {
|
|
this.time = this.time;
|
|
});
|
|
|
|
this._delete.addEventListener("click", this.delete);
|
|
|
|
this.update(act);
|
|
|
|
const pseudoUsers = this._card.getElementsByClassName(
|
|
"activity-pseudo-link-user",
|
|
) as HTMLCollectionOf<HTMLAnchorElement>;
|
|
const pseudoInvites = this._card.getElementsByClassName(
|
|
"activity-pseudo-link-invite",
|
|
) as HTMLCollectionOf<HTMLAnchorElement>;
|
|
|
|
for (let i = 0; i < pseudoUsers.length; i++) {
|
|
/*const navigate = (event: Event) => {
|
|
event.preventDefault()
|
|
window.tabs.switch("accounts");
|
|
document.dispatchEvent(accountURLEvent(pseudoUsers[i].getAttribute("data-id")));
|
|
window.history.pushState(null, document.title, pseudoUsers[i].getAttribute("data-href"));
|
|
}
|
|
pseudoUsers[i].onclick = navigate;
|
|
pseudoUsers[i].onkeydown = navigate;*/
|
|
}
|
|
for (let i = 0; i < pseudoInvites.length; i++) {
|
|
/*const navigate = (event: Event) => {
|
|
event.preventDefault();
|
|
window.invites.reload(() => {
|
|
window.tabs.switch("invites");
|
|
document.dispatchEvent(inviteURLEvent(pseudoInvites[i].getAttribute("data-id")));
|
|
window.history.pushState(null, document.title, pseudoInvites[i].getAttribute("data-href"));
|
|
});
|
|
}
|
|
pseudoInvites[i].onclick = navigate;
|
|
pseudoInvites[i].onkeydown = navigate;*/
|
|
}
|
|
}
|
|
|
|
update = (act: activity) => {
|
|
this._act = act;
|
|
this.source_type = act.source_type;
|
|
this.invite_code = act.invite_code;
|
|
this.time = act.time;
|
|
this.source = act.source;
|
|
this.value = act.value;
|
|
this.type = act.type;
|
|
this.ip = act.ip;
|
|
};
|
|
|
|
delete = () =>
|
|
_delete("/activity/" + this._act.id, null, (req: XMLHttpRequest) => {
|
|
if (req.readyState != 4) return;
|
|
if (req.status == 200) {
|
|
window.notifications.customSuccess("activityDeleted", window.lang.notif("activityDeleted"));
|
|
}
|
|
document.dispatchEvent(activityReload);
|
|
});
|
|
|
|
asElement = () => {
|
|
return this._card;
|
|
};
|
|
}
|
|
|
|
interface ActivitiesReqDTO extends PaginatedReqDTO {
|
|
type: string[];
|
|
}
|
|
|
|
interface ActivitiesDTO extends paginatedDTO {
|
|
activities: activity[];
|
|
}
|
|
|
|
export class activityList extends PaginatedList {
|
|
protected _container: HTMLElement;
|
|
protected _sortDirection = document.getElementById("activity-sort-direction") as HTMLButtonElement;
|
|
|
|
protected _ascending: boolean;
|
|
|
|
get activities(): { [id: string]: Activity } {
|
|
return this._search.items as { [id: string]: Activity };
|
|
}
|
|
// set activities(v: { [id: string]: Activity }) { this._search.items = v as SearchableItems; }
|
|
|
|
constructor() {
|
|
super({
|
|
loader: document.getElementById("activity-loader"),
|
|
loadMoreButtons: Array.from([
|
|
document.getElementById("activity-load-more") as HTMLButtonElement,
|
|
]) as Array<HTMLButtonElement>,
|
|
loadAllButtons: Array.from(
|
|
document.getElementsByClassName("activity-load-all"),
|
|
) as Array<HTMLButtonElement>,
|
|
refreshButton: document.getElementById("activity-refresh") as HTMLButtonElement,
|
|
filterArea: document.getElementById("activity-filter-area"),
|
|
searchOptionsHeader: document.getElementById("activity-search-options-header"),
|
|
searchBox: document.getElementById("activity-search") as HTMLInputElement,
|
|
recordCounter: document.getElementById("activity-record-counter"),
|
|
totalEndpoint: "/activity/count",
|
|
getPageEndpoint: "/activity",
|
|
itemsPerPage: 20,
|
|
maxItemsLoadedForSearch: 200,
|
|
appendNewItems: (resp: paginatedDTO) => {
|
|
let ordering: string[] = this._search.ordering;
|
|
for (let act of (resp as ActivitiesDTO).activities || []) {
|
|
this.activities[act.id] = new Activity(act);
|
|
ordering.push(act.id);
|
|
}
|
|
this._search.setOrdering(ordering, this._c.defaultSortField, this.ascending);
|
|
},
|
|
replaceWithNewItems: (resp: paginatedDTO) => {
|
|
// FIXME: Implement updates to existing elements, rather than just wiping each time.
|
|
|
|
// Remove existing items
|
|
for (let id of Object.keys(this.activities)) {
|
|
delete this.activities[id];
|
|
}
|
|
// And wipe their ordering
|
|
this._search.setOrdering([], this._c.defaultSortField, this.ascending);
|
|
this._c.appendNewItems(resp);
|
|
},
|
|
defaultSortField: ACTIVITY_DEFAULT_SORT_FIELD,
|
|
defaultSortAscending: ACTIVITY_DEFAULT_SORT_ASCENDING,
|
|
pageLoadCallback: (req: XMLHttpRequest) => {
|
|
if (req.readyState != 4) return;
|
|
if (req.status != 200) {
|
|
window.notifications.customError("loadActivitiesError", window.lang.notif("errorLoadActivities"));
|
|
return;
|
|
}
|
|
},
|
|
});
|
|
|
|
this._container = document.getElementById("activity-card-list");
|
|
document.addEventListener("activity-reload", () => this.reload());
|
|
|
|
let searchConfig: SearchConfiguration = {
|
|
filterArea: this._c.filterArea,
|
|
// Exclude this: We only sort by date, and don't want to show a redundant header indicating so.
|
|
// sortingByButton: this._sortingByButton,
|
|
searchOptionsHeader: this._c.searchOptionsHeader,
|
|
notFoundPanel: document.getElementById("activity-not-found"),
|
|
notFoundLocallyText: document.getElementById("activity-no-local-results"),
|
|
search: this._c.searchBox,
|
|
clearSearchButtonSelector: ".activity-search-clear",
|
|
serverSearchButtonSelector: ".activity-search-server",
|
|
queries: queries(),
|
|
setVisibility: null,
|
|
filterList: document.getElementById("activity-filter-list"),
|
|
// notFoundCallback: this._notFoundCallback,
|
|
onSearchCallback: null,
|
|
searchServer: null,
|
|
clearServerSearch: null,
|
|
};
|
|
|
|
this.initSearch(searchConfig);
|
|
|
|
this.ascending = this._c.defaultSortAscending;
|
|
this._sortDirection.addEventListener("click", () => (this.ascending = !this.ascending));
|
|
}
|
|
|
|
reload = (callback?: (resp: paginatedDTO) => void) => {
|
|
this._reload(callback);
|
|
};
|
|
|
|
loadMore = (loadAll: boolean = false, callback?: () => void) => {
|
|
this._loadMore(loadAll, callback);
|
|
};
|
|
|
|
loadAll = (callback?: (resp?: paginatedDTO) => void) => {
|
|
this._loadAll(callback);
|
|
};
|
|
|
|
get ascending(): boolean {
|
|
return this._ascending;
|
|
}
|
|
set ascending(v: boolean) {
|
|
this._ascending = v;
|
|
// Setting default sort makes sense, since this is the only sort ever being done.
|
|
this._c.defaultSortAscending = this.ascending;
|
|
this._sortDirection.innerHTML = `${window.lang.strings("sortDirection")} <i class="ri-arrow-${v ? "up" : "down"}-s-line"></i>`;
|
|
// NOTE: We don't actually re-sort the list here, instead just use setOrdering to apply this.ascending before a reload.
|
|
this._search.setOrdering(this._search.ordering, this._c.defaultSortField, this.ascending);
|
|
if (this._hasLoaded) {
|
|
if (this._search.inServerSearch) {
|
|
// Re-run server search as new, since we changed the sort.
|
|
this._search.searchServer(true);
|
|
} else {
|
|
this.reload();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*private _notFoundCallback = (notFound: boolean) => {
|
|
if (notFound) this._loadMoreButton.classList.add("unfocused");
|
|
else this._loadMoreButton.classList.remove("unfocused");
|
|
|
|
if (notFound && !this._lastPage) {
|
|
this._keepSearchingButton.classList.remove("unfocused");
|
|
this._keepSearchingDescription.classList.remove("unfocused");
|
|
} else {
|
|
this._keepSearchingButton.classList.add("unfocused");
|
|
this._keepSearchingDescription.classList.add("unfocused");
|
|
}
|
|
};*/
|
|
}
|