mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
activity: partially functional frontend code
doesn't fill in all the blanks yet, but almost there ish. Filters & stuff not done yet, just loads everything.
This commit is contained in:
parent
274324557c
commit
a73dfddd3f
@ -263,6 +263,7 @@ func (app *appContext) GenerateInvite(gc *gin.Context) {
|
|||||||
SourceType: ActivityAdmin,
|
SourceType: ActivityAdmin,
|
||||||
Source: gc.GetString("jfId"),
|
Source: gc.GetString("jfId"),
|
||||||
InviteCode: invite.Code,
|
InviteCode: invite.Code,
|
||||||
|
Value: invite.Label,
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -778,7 +778,7 @@
|
|||||||
<span class="button ~neutral @low settings-section-button justify-between mb-2" id="setting-about"><span class="flex">{{ .strings.aboutProgram }} <i class="ri-information-line ml-2"></i></span></span>
|
<span class="button ~neutral @low settings-section-button justify-between mb-2" id="setting-about"><span class="flex">{{ .strings.aboutProgram }} <i class="ri-information-line ml-2"></i></span></span>
|
||||||
<span class="button ~neutral @low settings-section-button justify-between mb-2" id="setting-profiles"><span class="flex">{{ .strings.userProfiles }} <i class="ri-user-line ml-2"></i></span></span>
|
<span class="button ~neutral @low settings-section-button justify-between mb-2" id="setting-profiles"><span class="flex">{{ .strings.userProfiles }} <i class="ri-user-line ml-2"></i></span></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card ~neutral @low col overflow">
|
<div class="card ~neutral @low col overflow" id="activity-card-list">
|
||||||
<div class="card ~urge @low">
|
<div class="card ~urge @low">
|
||||||
<div class="flex justify-between mb-2">
|
<div class="flex justify-between mb-2">
|
||||||
<span class="heading text-2xl activity-title">Account Created: <a href="/fixme" class="activity-url">"hrfee"</a></span>
|
<span class="heading text-2xl activity-title">Account Created: <a href="/fixme" class="activity-url">"hrfee"</a></span>
|
||||||
|
@ -55,6 +55,8 @@
|
|||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"donate": "Donate",
|
"donate": "Donate",
|
||||||
"unlink": "Unlink Account",
|
"unlink": "Unlink Account",
|
||||||
|
"deleted": "Deleted",
|
||||||
|
"disabled": "Disabled",
|
||||||
"sendPWR": "Send Password Reset",
|
"sendPWR": "Send Password Reset",
|
||||||
"noResultsFound": "No Results Found",
|
"noResultsFound": "No Results Found",
|
||||||
"contactThrough": "Contact through:",
|
"contactThrough": "Contact through:",
|
||||||
@ -131,7 +133,20 @@
|
|||||||
"buildTime": "Build Time",
|
"buildTime": "Build Time",
|
||||||
"builtBy": "Built By",
|
"builtBy": "Built By",
|
||||||
"loginNotAdmin": "Not an Admin?",
|
"loginNotAdmin": "Not an Admin?",
|
||||||
"referrer": "Referrer"
|
"referrer": "Referrer",
|
||||||
|
"accountLinked": "{user}: {contactMethod} linked",
|
||||||
|
"accountUnlinked": "{user}: {contactMethod} removed",
|
||||||
|
"accountResetPassword": "{user} reset their password",
|
||||||
|
"accountChangedPassword": "{user} changed their password",
|
||||||
|
"accountCreated": "Account created: {user}",
|
||||||
|
"accountDeleted": "Account deleted: {user}",
|
||||||
|
"accountDisabled": "Account disabled: {user}",
|
||||||
|
"accountReEnabled": "Account re-enabled: {user}",
|
||||||
|
"accountExpired": "Account expired: {user}",
|
||||||
|
"userDeleted": "User was deleted.",
|
||||||
|
"userDisabled": "User was disabled",
|
||||||
|
"inviteCreated": "Invite created: {invite}",
|
||||||
|
"inviteDeleted": "Invite deleted: {invite}"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"changedEmailAddress": "Changed email address of {n}.",
|
"changedEmailAddress": "Changed email address of {n}.",
|
||||||
@ -168,6 +183,7 @@
|
|||||||
"errorApplyUpdate": "Failed to apply update, try manually.",
|
"errorApplyUpdate": "Failed to apply update, try manually.",
|
||||||
"errorCheckUpdate": "Failed to check for update.",
|
"errorCheckUpdate": "Failed to check for update.",
|
||||||
"errorNoReferralTemplate": "Profile doesn't contain referral template, add one in settings.",
|
"errorNoReferralTemplate": "Profile doesn't contain referral template, add one in settings.",
|
||||||
|
"errorLoadActivities": "Failed to load activities.",
|
||||||
"updateAvailable": "A new update is available, check settings.",
|
"updateAvailable": "A new update is available, check settings.",
|
||||||
"noUpdatesAvailable": "No new updates available."
|
"noUpdatesAvailable": "No new updates available."
|
||||||
},
|
},
|
||||||
|
@ -53,7 +53,7 @@ type Activity struct {
|
|||||||
SourceType ActivitySource
|
SourceType ActivitySource
|
||||||
Source string
|
Source string
|
||||||
InviteCode string // Only set for ActivityCreation
|
InviteCode string // Only set for ActivityCreation
|
||||||
Value string // Used for ActivityContactLinked, "email/discord/telegram/matrix"
|
Value string // Used for ActivityContactLinked, "email/discord/telegram/matrix", and Create/DeleteInvite, where it's the label.
|
||||||
Time time.Time
|
Time time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
ts/admin.ts
10
ts/admin.ts
@ -5,6 +5,7 @@ import { Tabs } from "./modules/tabs.js";
|
|||||||
import { inviteList, createInvite } from "./modules/invites.js";
|
import { inviteList, createInvite } from "./modules/invites.js";
|
||||||
import { accountsList } from "./modules/accounts.js";
|
import { accountsList } from "./modules/accounts.js";
|
||||||
import { settingsList } from "./modules/settings.js";
|
import { settingsList } from "./modules/settings.js";
|
||||||
|
import { activityList } from "./modules/activity.js";
|
||||||
import { ProfileEditor } from "./modules/profiles.js";
|
import { ProfileEditor } from "./modules/profiles.js";
|
||||||
import { _get, _post, notificationBox, whichAnimationEvent } from "./modules/common.js";
|
import { _get, _post, notificationBox, whichAnimationEvent } from "./modules/common.js";
|
||||||
import { Updater } from "./modules/update.js";
|
import { Updater } from "./modules/update.js";
|
||||||
@ -89,6 +90,8 @@ var inviteCreator = new createInvite();
|
|||||||
|
|
||||||
var accounts = new accountsList();
|
var accounts = new accountsList();
|
||||||
|
|
||||||
|
var activity = new activityList();
|
||||||
|
|
||||||
window.invites = new inviteList();
|
window.invites = new inviteList();
|
||||||
|
|
||||||
var settings = new settingsList();
|
var settings = new settingsList();
|
||||||
@ -122,7 +125,7 @@ const tabs: { url: string, reloader: () => void }[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: "activity",
|
url: "activity",
|
||||||
reloader: () => {console.log("FIXME: Reload Activity")}
|
reloader: activity.reload
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: "settings",
|
url: "settings",
|
||||||
@ -171,6 +174,7 @@ const login = new Login(window.modals.login as Modal, "/", window.loginAppearanc
|
|||||||
login.onLogin = () => {
|
login.onLogin = () => {
|
||||||
console.log("Logged in.");
|
console.log("Logged in.");
|
||||||
window.updater = new Updater();
|
window.updater = new Updater();
|
||||||
|
// FIXME: Decide whether to autoload activity or not
|
||||||
setInterval(() => { window.invites.reload(); accounts.reload(); }, 30*1000);
|
setInterval(() => { window.invites.reload(); accounts.reload(); }, 30*1000);
|
||||||
const currentTab = window.tabs.current;
|
const currentTab = window.tabs.current;
|
||||||
switch (currentTab) {
|
switch (currentTab) {
|
||||||
@ -183,7 +187,9 @@ login.onLogin = () => {
|
|||||||
case "settings":
|
case "settings":
|
||||||
settings.reload();
|
settings.reload();
|
||||||
break;
|
break;
|
||||||
// FIXME: Reload activity
|
case "activity": // FIXME: fix URL clash with route
|
||||||
|
activity.reload();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { _get, toDateString } from "../modules/common.js";
|
||||||
|
|
||||||
export interface activity {
|
export interface activity {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
@ -28,9 +30,11 @@ export class Activity { // FIXME: Add "implements"
|
|||||||
private _card: HTMLElement;
|
private _card: HTMLElement;
|
||||||
private _title: HTMLElement;
|
private _title: HTMLElement;
|
||||||
private _time: HTMLElement;
|
private _time: HTMLElement;
|
||||||
|
private _timeUnix: number;
|
||||||
private _sourceType: HTMLElement;
|
private _sourceType: HTMLElement;
|
||||||
private _source: HTMLElement;
|
private _source: HTMLElement;
|
||||||
private _referrer: HTMLElement;
|
private _referrer: HTMLElement;
|
||||||
|
private _expiryTypeBadge: HTMLElement;
|
||||||
private _act: activity;
|
private _act: activity;
|
||||||
|
|
||||||
get type(): string { return this._act.type; }
|
get type(): string { return this._act.type; }
|
||||||
@ -43,24 +47,87 @@ export class Activity { // FIXME: Add "implements"
|
|||||||
if (i-1 == mood) this._card.classList.add(moodColours[i]);
|
if (i-1 == mood) this._card.classList.add(moodColours[i]);
|
||||||
else this._card.classList.remove(moodColours[i]);
|
else this._card.classList.remove(moodColours[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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}", `<a href="/accounts/user/${this._act.user_id}">FIXME</a>`);
|
||||||
|
this._title.innerHTML = innerHTML;
|
||||||
|
} else if (this.type == "contactLinked" || this.type == "contactUnlinked") {
|
||||||
|
let platform = this._act.type;
|
||||||
|
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}", `<a href="/accounts/user/${this._act.user_id}">FIXME</a>`).replace("{contactMethod}", platform);
|
||||||
|
this._title.innerHTML = innerHTML;
|
||||||
|
} else if (this.type == "creation") {
|
||||||
|
this._title.innerHTML = window.lang.strings("accountCreated").replace("{user}", `<a href="/accounts/user/${this._act.user_id}">FIXME</a>`);
|
||||||
|
if (this.source_type == "user") {
|
||||||
|
this._referrer.innerHTML = `<span class="supra mr-2">${window.lang.strings("referrer")}</span><a href="/accounts/${this._source}">FIXME</a>`;
|
||||||
|
} else {
|
||||||
|
this._referrer.textContent = ``;
|
||||||
|
}
|
||||||
|
} else if (this.type == "deletion") {
|
||||||
|
if (this.source_type == "daemon") {
|
||||||
|
this._title.innerHTML = window.lang.strings("accountExpired").replace("{user}", `<a href="/accounts/user/${this._act.user_id}">FIXME</a>`);
|
||||||
|
this._expiryTypeBadge.classList.add("~critical");
|
||||||
|
this._expiryTypeBadge.classList.remove("~warning");
|
||||||
|
this._expiryTypeBadge.textContent = window.lang.strings("deleted");
|
||||||
|
} else {
|
||||||
|
this._title.innerHTML = window.lang.strings("accountDeleted").replace("{user}", `<a href="/accounts/user/${this._act.user_id}">FIXME</a>`);
|
||||||
|
}
|
||||||
|
} else if (this.type == "enabled") {
|
||||||
|
this._title.innerHTML = window.lang.strings("accountReEnabled").replace("{user}", `<a href="/accounts/user/${this._act.user_id}">FIXME</a>`);
|
||||||
|
} else if (this.type == "disabled") {
|
||||||
|
if (this.source_type == "daemon") {
|
||||||
|
this._title.innerHTML = window.lang.strings("accountExpired").replace("{user}", `<a href="/accounts/user/${this._act.user_id}">FIXME</a>`);
|
||||||
|
this._expiryTypeBadge.classList.add("~warning");
|
||||||
|
this._expiryTypeBadge.classList.remove("~critical");
|
||||||
|
this._expiryTypeBadge.textContent = window.lang.strings("disabled");
|
||||||
|
} else {
|
||||||
|
this._title.innerHTML = window.lang.strings("accountDisabled").replace("{user}", `<a href="/accounts/user/${this._act.user_id}">FIXME</a>`);
|
||||||
|
}
|
||||||
|
} else if (this.type == "createInvite") {
|
||||||
|
this._title.innerHTML = window.lang.strings("inviteCreated").replace("{invite}", `<a href="/accounts/user/${this.invite_code}">${this.value || this.invite_code}</a>`);
|
||||||
|
} else if (this.type == "deleteInvite") {
|
||||||
|
|
||||||
|
this._title.innerHTML = window.lang.strings("inviteDeleted").replace("{invite}", this.value || this.invite_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*} else if (this.source_type == "admin") {
|
||||||
|
// FIXME: Handle contactLinked/Unlinked, creation/deletion, enable/disable, createInvite/deleteInvite
|
||||||
|
} else if (this.source_type == "anon") {
|
||||||
|
this._referrer.innerHTML = ``;
|
||||||
|
} else if (this.source_type == "daemon") {
|
||||||
|
// FIXME: Handle deleteInvite, disabled, deletion
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
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; }
|
get source_type(): string { return this._act.source_type; }
|
||||||
set source_type(v: string) {
|
set source_type(v: string) {
|
||||||
this._act.source_type = v;
|
this._act.source_type = v;
|
||||||
if (v == "user") {
|
|
||||||
if (this.type == "creation") {
|
|
||||||
this._referrer.innerHTML = `<span class="supra mr-2">${window.lang.strings("referrer")}</span><a href="/accounts/${this._source}">FIXME</a>`;
|
|
||||||
} else if (this.type == "contactLinked" || this.type == "contactUnlinked" || this.type == "changePassword" || this.type == "resetPassword") {
|
|
||||||
// FIXME: Reflect in title
|
|
||||||
}
|
}
|
||||||
} else if (v == "admin") {
|
|
||||||
// FIXME: Handle contactLinked/Unlinked, creation/deletion, enable/disable, createInvite/deleteInvite
|
get invite_code(): string { return this._act.invite_code; }
|
||||||
} else if (v == "anon") {
|
set invite_code(v: string) {
|
||||||
this._referrer.innerHTML = ``;
|
this._act.invite_code = v;
|
||||||
} else if (v == "daemon") {
|
|
||||||
// FIXME: Handle deleteInvite, disabled, deletion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get value(): string { return this._act.value; }
|
||||||
|
set value(v: string) {
|
||||||
|
this._act.value = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(act: activity) {
|
constructor(act: activity) {
|
||||||
@ -69,7 +136,7 @@ export class Activity { // FIXME: Add "implements"
|
|||||||
this._card.classList.add("card", "@low");
|
this._card.classList.add("card", "@low");
|
||||||
this._card.innerHTML = `
|
this._card.innerHTML = `
|
||||||
<div class="flex justify-between mb-2">
|
<div class="flex justify-between mb-2">
|
||||||
<span class="heading text-2xl activity-title"></span>
|
<span class="heading text-2xl activity-title"></span><span class="activity-expiry-type badge"></span>
|
||||||
<span class="text-sm font-medium activity-time" aria-label="${window.lang.strings("date")}"></span>
|
<span class="text-sm font-medium activity-time" aria-label="${window.lang.strings("date")}"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
@ -87,6 +154,7 @@ export class Activity { // FIXME: Add "implements"
|
|||||||
this._sourceType = this._card.querySelector(".activity-source-type");
|
this._sourceType = this._card.querySelector(".activity-source-type");
|
||||||
this._source = this._card.querySelector(".activity-source");
|
this._source = this._card.querySelector(".activity-source");
|
||||||
this._referrer = this._card.querySelector(".activity-referrer");
|
this._referrer = this._card.querySelector(".activity-referrer");
|
||||||
|
this._expiryTypeBadge = this._card.querySelector(".activity-expiry-type");
|
||||||
|
|
||||||
this.update(act);
|
this.update(act);
|
||||||
}
|
}
|
||||||
@ -94,9 +162,41 @@ export class Activity { // FIXME: Add "implements"
|
|||||||
update = (act: activity) => {
|
update = (act: activity) => {
|
||||||
// FIXME
|
// FIXME
|
||||||
this._act = act;
|
this._act = act;
|
||||||
|
this.source_type = act.source_type;
|
||||||
|
this.invite_code = act.invite_code;
|
||||||
|
this.value = act.value;
|
||||||
this.type = act.type;
|
this.type = act.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
asElement = () => { return this._card; };
|
asElement = () => { return this._card; };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ActivitiesDTO {
|
||||||
|
activities: activity[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class activityList {
|
||||||
|
private _activityList: HTMLElement;
|
||||||
|
|
||||||
|
reload = () => {
|
||||||
|
_get("/activity", null, (req: XMLHttpRequest) => {
|
||||||
|
if (req.readyState != 4) return;
|
||||||
|
if (req.status != 200) {
|
||||||
|
window.notifications.customError("loadActivitiesError", window.lang.notif("errorLoadActivities"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let resp = req.response as ActivitiesDTO;
|
||||||
|
this._activityList.textContent = ``;
|
||||||
|
|
||||||
|
for (let act of resp.activities) {
|
||||||
|
const activity = new Activity(act);
|
||||||
|
this._activityList.appendChild(activity.asElement());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._activityList = document.getElementById("activity-card-list");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user