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

Add optional label for invites

Requested in #38.
This commit is contained in:
Harvey Tindall 2021-01-24 15:55:45 +00:00
parent ea262ca60b
commit dd96d71280
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
8 changed files with 51 additions and 17 deletions

4
api.go
View File

@ -532,6 +532,9 @@ func (app *appContext) GenerateInvite(gc *gin.Context) {
_, err = strconv.Atoi(string(inviteCode[0])) _, err = strconv.Atoi(string(inviteCode[0]))
} }
var invite Invite var invite Invite
if req.Label != "" {
invite.Label = req.Label
}
invite.Created = currentTime invite.Created = currentTime
if req.MultipleUses { if req.MultipleUses {
if req.NoLimit { if req.NoLimit {
@ -732,6 +735,7 @@ func (app *appContext) GetInvites(gc *gin.Context) {
Created: app.formatDatetime(inv.Created), Created: app.formatDatetime(inv.Created),
Profile: inv.Profile, Profile: inv.Profile,
NoLimit: inv.NoLimit, NoLimit: inv.NoLimit,
Label: inv.Label,
} }
if len(inv.UsedBy) != 0 { if len(inv.UsedBy) != 0 {
invite.UsedBy = inv.UsedBy invite.UsedBy = inv.UsedBy

View File

@ -200,7 +200,7 @@ sup.\~critical, .text-critical {
max-width: 40%; max-width: 40%;
min-width: 10rem; min-width: 10rem;
display: flex; display: flex;
justify-content: center; justify-content: start;
align-items: center; align-items: center;
} }

View File

@ -219,12 +219,14 @@
<option>0</option> <option>0</option>
</select> </select>
</div> </div>
<label class="label supra" for="create-label"> {{ .strings.label }}</label>
<input type="text" id="create-label" class="input ~neutral !normal mb-1 mt-half">
</div> </div>
<div class="card ~neutral !normal col"> <div class="card ~neutral !normal col">
<label class="label supra" for="create-uses">{{ .strings.inviteNumberOfUses }}</label> <label class="label supra" for="create-uses">{{ .strings.inviteNumberOfUses }}</label>
<div class="flex-expand mb-1 mt-half"> <div class="flex-expand mb-1 mt-half">
<input type="number" min="0" id="create-uses" class="input ~neutral !normal mr-1" value=1> <input type="number" min="0" id="create-uses" class="input ~neutral !normal mr-1" value=1>
<label for="create-inf-uses" class="button ~neutral !normal"> <label for="create-inf-uses" class="button ~neutral !normal" title="Set uses to infinite">
<span></span> <span></span>
<input type="checkbox" class="unfocused" id="create-inf-uses" aria-label="Set uses to infinite"> <input type="checkbox" class="unfocused" id="create-inf-uses" aria-label="Set uses to infinite">
</label> </label>

View File

@ -36,6 +36,7 @@
"success": "Success", "success": "Success",
"error": "Error", "error": "Error",
"unknown": "Unknown", "unknown": "Unknown",
"label": "Label",
"modifySettings": "Modify Settings", "modifySettings": "Modify Settings",
"modifySettingsDescription": "Apply settings from an existing profile, or source them directly from a user.", "modifySettingsDescription": "Apply settings from an existing profile, or source them directly from a user.",
"applyHomescreenLayout": "Apply homescreen layout", "applyHomescreenLayout": "Apply homescreen layout",

View File

@ -38,6 +38,7 @@ type generateInviteDTO struct {
NoLimit bool `json:"no-limit" example:"false"` // No invite use limit NoLimit bool `json:"no-limit" example:"false"` // No invite use limit
RemainingUses int `json:"remaining-uses" example:"5"` // Remaining invite uses RemainingUses int `json:"remaining-uses" example:"5"` // Remaining invite uses
Profile string `json:"profile" example:"DefaultProfile"` // Name of profile to apply on this invite 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
} }
type inviteProfileDTO struct { type inviteProfileDTO struct {
@ -67,18 +68,19 @@ type newProfileDTO struct {
} }
type inviteDTO struct { type inviteDTO struct {
Code string `json:"code" example:"sajdlj23423j23"` // Invite code Code string `json:"code" example:"sajdlj23423j23"` // Invite code
Days int `json:"days" example:"1"` // Number of days till expiry Days int `json:"days" example:"1"` // Number of days till expiry
Hours int `json:"hours" example:"2"` // Number of hours till expiry Hours int `json:"hours" example:"2"` // Number of hours till expiry
Minutes int `json:"minutes" example:"3"` // Number of minutes till expiry Minutes int `json:"minutes" example:"3"` // Number of minutes till expiry
Created string `json:"created" example:"01/01/20 12:00"` // Date of creation Created string `json:"created" example:"01/01/20 12:00"` // Date of creation
Profile string `json:"profile" example:"DefaultProfile"` // Profile used on this invite Profile string `json:"profile" example:"DefaultProfile"` // Profile used on this invite
UsedBy [][]string `json:"used-by,omitempty"` // Users who have used this invite UsedBy [][]string `json:"used-by,omitempty"` // Users who have used this invite
NoLimit bool `json:"no-limit,omitempty"` // If true, invite can be used any number of times NoLimit bool `json:"no-limit,omitempty"` // If true, invite can be used any number of times
RemainingUses int `json:"remaining-uses,omitempty"` // Remaining number of uses (if applicable) RemainingUses int `json:"remaining-uses,omitempty"` // Remaining number of uses (if applicable)
Email string `json:"email,omitempty"` // Email the invite was sent to (if applicable) Email string `json:"email,omitempty"` // Email the invite was sent to (if applicable)
NotifyExpiry bool `json:"notify-expiry,omitempty"` // Whether to notify the requesting user of expiry or not 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 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
} }
type getInvitesDTO struct { type getInvitesDTO struct {

View File

@ -41,6 +41,7 @@ type Invite struct {
UsedBy [][]string `json:"used-by"` UsedBy [][]string `json:"used-by"`
Notify map[string]map[string]bool `json:"notify"` Notify map[string]map[string]bool `json:"notify"`
Profile string `json:"profile"` Profile string `json:"profile"`
Label string `json:"label,omitempty"`
} }
type Lang struct { type Lang struct {

View File

@ -25,6 +25,17 @@ export class DOMInvite implements Invite {
document.dispatchEvent(inviteDeletedEvent); document.dispatchEvent(inviteDeletedEvent);
} }
}) })
private _label: string = "";
get label(): string { return this._label; }
set label(label: string) {
this._label = label;
const linkEl = this._codeArea.querySelector("a") as HTMLAnchorElement;
if (label == "") {
linkEl.textContent = this.code.replace(/-/g, '-');
} else {
linkEl.textContent = label;
}
}
private _code: string = "None"; private _code: string = "None";
get code(): string { return this._code; } get code(): string { return this._code; }
@ -36,7 +47,9 @@ export class DOMInvite implements Invite {
} }
this._codeLink = codeLink + "invite/" + code; this._codeLink = codeLink + "invite/" + code;
const linkEl = this._codeArea.querySelector("a") as HTMLAnchorElement; const linkEl = this._codeArea.querySelector("a") as HTMLAnchorElement;
linkEl.textContent = code.replace(/-/g, '-'); if (this.label == "") {
linkEl.textContent = code.replace(/-/g, '-');
}
linkEl.href = this._codeLink; linkEl.href = this._codeLink;
} }
private _codeLink: string; private _codeLink: string;
@ -345,6 +358,9 @@ export class DOMInvite implements Invite {
this.profile = invite.profile; this.profile = invite.profile;
this.remainingUses = invite.remainingUses; this.remainingUses = invite.remainingUses;
this.usedBy = invite.usedBy; this.usedBy = invite.usedBy;
if (invite.label) {
this.label = invite.label;
}
} }
asElement = (): HTMLDivElement => { return this._container; } asElement = (): HTMLDivElement => { return this._container; }
@ -443,6 +459,7 @@ function parseInvite(invite: { [f: string]: string | number | string[][] | boole
let parsed: Invite = {}; let parsed: Invite = {};
parsed.code = invite["code"] as string; parsed.code = invite["code"] as string;
parsed.email = invite["email"] as string || ""; parsed.email = invite["email"] as string || "";
parsed.label = invite["label"] as string || "";
let time = ""; let time = "";
const fields = ["days", "hours", "minutes"]; const fields = ["days", "hours", "minutes"];
for (let i = 0; i < fields.length; i++) { for (let i = 0; i < fields.length; i++) {
@ -468,6 +485,7 @@ export class createInvite {
private _infUsesWarning = document.getElementById('create-inf-uses-warning') as HTMLParagraphElement; private _infUsesWarning = document.getElementById('create-inf-uses-warning') as HTMLParagraphElement;
private _createButton = document.getElementById("create-submit") as HTMLSpanElement; private _createButton = document.getElementById("create-submit") as HTMLSpanElement;
private _profile = document.getElementById("create-profile") as HTMLSelectElement; private _profile = document.getElementById("create-profile") as HTMLSelectElement;
private _label = document.getElementById("create-label") as HTMLInputElement;
private _days = document.getElementById("create-days") as HTMLSelectElement; private _days = document.getElementById("create-days") as HTMLSelectElement;
private _hours = document.getElementById("create-hours") as HTMLSelectElement; private _hours = document.getElementById("create-hours") as HTMLSelectElement;
@ -492,6 +510,9 @@ export class createInvite {
} }
} }
get label(): string { return this._label.value; }
set label(label: string) { this._label.value = label; }
get sendToEnabled(): boolean { get sendToEnabled(): boolean {
return this._sendToEnabled.checked; return this._sendToEnabled.checked;
} }
@ -599,7 +620,8 @@ export class createInvite {
"no-limit": this.infiniteUses, "no-limit": this.infiniteUses,
"remaining-uses": this.uses, "remaining-uses": this.uses,
"email": this.sendToEnabled ? this.sendTo : "", "email": this.sendToEnabled ? this.sendTo : "",
"profile": this.profile "profile": this.profile,
"label": this.label
}; };
_post("/invites", send, (req: XMLHttpRequest) => { _post("/invites", send, (req: XMLHttpRequest) => {
if (req.readyState == 4) { if (req.readyState == 4) {
@ -623,6 +645,7 @@ export class createInvite {
this._createButton.onclick = this.create; this._createButton.onclick = this.create;
this.sendTo = ""; this.sendTo = "";
this.uses = 1; this.uses = 1;
this.label = "";
this._days.onchange = this._checkDurationValidity; this._days.onchange = this._checkDurationValidity;
this._hours.onchange = this._checkDurationValidity; this._hours.onchange = this._checkDurationValidity;

View File

@ -86,6 +86,7 @@ interface Invite {
notifyExpiry?: boolean; notifyExpiry?: boolean;
notifyCreation?: boolean; notifyCreation?: boolean;
profile?: string; profile?: string;
label?: string;
} }
interface inviteList { interface inviteList {