From 7c76b58ab828d3602677367a988ed57d3f2102de Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Fri, 8 Sep 2023 14:29:25 +0100 Subject: [PATCH] invites: add "User Label" 1/2 Adds a "User Label" invite field, which is a label applied to users created with it. This commit contains everything apart from the code to apply it on account creation. --- api-invites.go | 4 ++++ html/admin.html | 5 +++++ lang/admin/en-us.json | 4 +++- models.go | 32 +++++++++++++++++--------------- storage.go | 1 + ts/modules/invites.ts | 27 ++++++++++++++++++++++++++- ts/typings/d.ts | 1 + 7 files changed, 57 insertions(+), 17 deletions(-) diff --git a/api-invites.go b/api-invites.go index 9a58336..0fda9fd 100644 --- a/api-invites.go +++ b/api-invites.go @@ -161,6 +161,9 @@ func (app *appContext) GenerateInvite(gc *gin.Context) { if req.Label != "" { invite.Label = req.Label } + if req.UserLabel != "" { + invite.UserLabel = req.UserLabel + } invite.Created = currentTime if req.MultipleUses { if req.NoLimit { @@ -261,6 +264,7 @@ func (app *appContext) GetInvites(gc *gin.Context) { Profile: inv.Profile, NoLimit: inv.NoLimit, Label: inv.Label, + UserLabel: inv.UserLabel, } if len(inv.UsedBy) != 0 { invite.UsedBy = map[string]int64{} diff --git a/html/admin.html b/html/admin.html index 0ad2aaf..5d7f9a3 100644 --- a/html/admin.html +++ b/html/admin.html @@ -589,6 +589,11 @@ +
+ +

{{ .strings.userLabelDescription }}

+ +
diff --git a/lang/admin/en-us.json b/lang/admin/en-us.json index 2e3169c..9a3bd22 100644 --- a/lang/admin/en-us.json +++ b/lang/admin/en-us.json @@ -41,6 +41,8 @@ "profile": "Profile", "unknown": "Unknown", "label": "Label", + "userLabel": "User Label", + "userLabelDescription": "Label to apply to users created with this invite.", "logs": "Logs", "announce": "Announce", "templates": "Templates", @@ -223,4 +225,4 @@ "plural": "Extended expiry for {n} users." } } -} \ No newline at end of file +} diff --git a/models.go b/models.go index d9ac8aa..d4f841e 100644 --- a/models.go +++ b/models.go @@ -48,21 +48,22 @@ type enableDisableUserDTO struct { } type generateInviteDTO struct { - Months int `json:"months" example:"0"` // Number of months - Days int `json:"days" example:"1"` // Number of days - Hours int `json:"hours" example:"2"` // Number of hours - Minutes int `json:"minutes" example:"3"` // Number of minutes - UserExpiry bool `json:"user-expiry"` // Whether or not user expiry is enabled - UserMonths int `json:"user-months,omitempty" example:"1"` // Number of months till user expiry - UserDays int `json:"user-days,omitempty" example:"1"` // Number of days till user expiry - UserHours int `json:"user-hours,omitempty" example:"2"` // Number of hours till user expiry - UserMinutes int `json:"user-minutes,omitempty" example:"3"` // Number of minutes till user expiry - SendTo string `json:"send-to" example:"jeff@jellyf.in"` // Send invite to this address or discord name - MultipleUses bool `json:"multiple-uses" example:"true"` // Allow multiple uses - NoLimit bool `json:"no-limit" example:"false"` // No invite use limit - RemainingUses int `json:"remaining-uses" example:"5"` // Remaining invite uses - Profile string `json:"profile" example:"DefaultProfile"` // Name of profile to apply on this invite - Label string `json:"label" example:"For Friends"` // Optional label for the invite + Months int `json:"months" example:"0"` // Number of months + Days int `json:"days" example:"1"` // Number of days + Hours int `json:"hours" example:"2"` // Number of hours + Minutes int `json:"minutes" example:"3"` // Number of minutes + UserExpiry bool `json:"user-expiry"` // Whether or not user expiry is enabled + UserMonths int `json:"user-months,omitempty" example:"1"` // Number of months till user expiry + UserDays int `json:"user-days,omitempty" example:"1"` // Number of days till user expiry + UserHours int `json:"user-hours,omitempty" example:"2"` // Number of hours till user expiry + UserMinutes int `json:"user-minutes,omitempty" example:"3"` // Number of minutes till user expiry + SendTo string `json:"send-to" example:"jeff@jellyf.in"` // Send invite to this address or discord name + MultipleUses bool `json:"multiple-uses" example:"true"` // Allow multiple uses + NoLimit bool `json:"no-limit" example:"false"` // No invite use limit + RemainingUses int `json:"remaining-uses" example:"5"` // Remaining invite uses + Profile string `json:"profile" example:"DefaultProfile"` // Name of profile to apply on this invite + Label string `json:"label" example:"For Friends"` // Optional label for the invite + UserLabel string `json:"user_label,omitempty" example:"Friend"` // Label to apply to users created w/ this invite. } type inviteProfileDTO struct { @@ -114,6 +115,7 @@ type inviteDTO struct { NotifyExpiry bool `json:"notify-expiry,omitempty"` // Whether to notify the requesting user of expiry or not NotifyCreation bool `json:"notify-creation,omitempty"` // Whether to notify the requesting user of account creation or not Label string `json:"label,omitempty" example:"For Friends"` // Optional label for the invite + UserLabel string `json:"user_label,omitempty" example:"Friend"` // Label to apply to users created w/ this invite. } type getInvitesDTO struct { diff --git a/storage.go b/storage.go index 4591c1b..74bfe2d 100644 --- a/storage.go +++ b/storage.go @@ -500,6 +500,7 @@ type Invite struct { Notify map[string]map[string]bool `json:"notify"` Profile string `json:"profile"` Label string `json:"label,omitempty"` + UserLabel string `json:"user_label,omitempty" example:"Friend"` // Label to apply to users created w/ this invite. Captchas map[string]Captcha // Map of Captcha IDs to images & answers IsReferral bool `json:"is_referral" badgerhold:"index"` ReferrerJellyfinID string `json:"referrer_id"` diff --git a/ts/modules/invites.ts b/ts/modules/invites.ts index 4d8143f..7c4edc0 100644 --- a/ts/modules/invites.ts +++ b/ts/modules/invites.ts @@ -39,6 +39,21 @@ class DOMInvite implements Invite { } } + private _userLabel: string = ""; + get user_label(): string { return this._userLabel; } + set user_label(label: string) { + this._userLabel = label; + const labelLabel = this._middle.querySelector(".user-label-label"); + const value = this._middle.querySelector(".user-label"); + if (label) { + labelLabel.textContent = window.lang.strings("userLabel"); + value.textContent = label; + } else { + labelLabel.textContent = ""; + value.textContent = ""; + } + } + private _code: string = "None"; get code(): string { return this._code; } set code(code: string) { @@ -351,6 +366,7 @@ class DOMInvite implements Invite {

${window.lang.strings("inviteDateCreated")}

${window.lang.strings("inviteRemainingUses")}

+

`; this._right = document.createElement('div') as HTMLDivElement; @@ -386,6 +402,9 @@ class DOMInvite implements Invite { if (invite.label) { this.label = invite.label; } + if (invite.user_label) { + this.user_label = invite.user_label; + } this.userExpiryTime = invite.userExpiryTime || ""; } @@ -486,6 +505,7 @@ function parseInvite(invite: { [f: string]: string | number | { [name: string]: parsed.code = invite["code"] as string; parsed.send_to = invite["send_to"] as string || ""; parsed.label = invite["label"] as string || ""; + parsed.user_label = invite["user_label"] as string || ""; let time = ""; let userExpiryTime = ""; const fields = ["months", "days", "hours", "minutes"]; @@ -530,6 +550,7 @@ export class createInvite { private _createButton = document.getElementById("create-submit") as HTMLSpanElement; private _profile = document.getElementById("create-profile") as HTMLSelectElement; private _label = document.getElementById("create-label") as HTMLInputElement; + private _userLabel = document.getElementById("create-user-label") as HTMLInputElement; private _months = document.getElementById("create-months") as HTMLSelectElement; private _days = document.getElementById("create-days") as HTMLSelectElement; @@ -572,6 +593,9 @@ export class createInvite { get label(): string { return this._label.value; } set label(label: string) { this._label.value = label; } + get user_label(): string { return this._userLabel.value; } + set user_label(label: string) { this._userLabel.value = label; } + get sendToEnabled(): boolean { return this._sendToEnabled.checked; } @@ -749,7 +773,8 @@ export class createInvite { "remaining-uses": this.uses, "send-to": this.sendToEnabled ? this.sendTo : "", "profile": this.profile, - "label": this.label + "label": this.label, + "user_label": this.user_label }; _post("/invites", send, (req: XMLHttpRequest) => { if (req.readyState == 4) { diff --git a/ts/typings/d.ts b/ts/typings/d.ts index 9befa20..9aed65d 100644 --- a/ts/typings/d.ts +++ b/ts/typings/d.ts @@ -129,6 +129,7 @@ interface Invite { notifyCreation?: boolean; profile?: string; label?: string; + user_label?: string; userExpiry?: boolean; userExpiryTime?: string; }