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 `${this._act.username || this._act.user_id.substring(0, 5)}`; }; _genSrcUserText = (): string => { return `${this._act.source_username || this._act.source.substring(0, 5)}`; }; _genUserLink = (): string => { return `${this._genUserText()}`; }; _genSrcUserLink = (): string => { return `${this._genSrcUserText()}`; }; private _renderInvText = (): string => { return `${this.value || this.invite_code || "???"}`; }; private _genInvLink = (): string => { return `${this._renderInvText()}`; }; 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 = `${window.lang.strings("referrer")}${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 = `IP${v}`; } 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 = `