mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
referrals: add "use expiry" option
adds an option when enabling referrals to use the duration of the source invited (i.e., months, days, hours) for the referral invite. If enabled, the user won't be able to make a new referral link after it expires. For referrals enabled for new users via a profile, the clock starts ticking as soon as the account is created.
This commit is contained in:
parent
d0de1142ae
commit
a66c522b73
@ -45,14 +45,24 @@ func (app *appContext) checkInvites() {
|
|||||||
app.storage.SetInvitesKey(data.Code, data)
|
app.storage.SetInvitesKey(data.Code, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.IsReferral {
|
if data.IsReferral && (!data.UseReferralExpiry || data.ReferrerJellyfinID == "") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
expiry := data.ValidTill
|
expiry := data.ValidTill
|
||||||
if !currentTime.After(expiry) {
|
if !currentTime.After(expiry) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
app.debug.Printf("Housekeeping: Deleting old invite %s", data.Code)
|
app.debug.Printf("Housekeeping: Deleting old invite %s", data.Code)
|
||||||
|
|
||||||
|
// Disable referrals for the user if UseReferralExpiry is enabled, so no new ones are made.
|
||||||
|
if data.IsReferral && data.UseReferralExpiry && data.ReferrerJellyfinID != "" {
|
||||||
|
user, ok := app.storage.GetEmailsKey(data.ReferrerJellyfinID)
|
||||||
|
if ok {
|
||||||
|
user.ReferralTemplateKey = ""
|
||||||
|
app.storage.SetEmailsKey(data.ReferrerJellyfinID, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
notify := data.Notify
|
notify := data.Notify
|
||||||
if emailEnabled && app.config.Section("notifications").Key("enabled").MustBool(false) && len(notify) != 0 {
|
if emailEnabled && app.config.Section("notifications").Key("enabled").MustBool(false) && len(notify) != 0 {
|
||||||
app.debug.Printf("%s: Expiry notification", data.Code)
|
app.debug.Printf("%s: Expiry notification", data.Code)
|
||||||
@ -136,6 +146,13 @@ func (app *appContext) checkInvite(code string, used bool, username string) bool
|
|||||||
}
|
}
|
||||||
wait.Wait()
|
wait.Wait()
|
||||||
}
|
}
|
||||||
|
if inv.IsReferral && inv.ReferrerJellyfinID != "" && inv.UseReferralExpiry {
|
||||||
|
user, ok := app.storage.GetEmailsKey(inv.ReferrerJellyfinID)
|
||||||
|
if ok {
|
||||||
|
user.ReferralTemplateKey = ""
|
||||||
|
app.storage.SetEmailsKey(inv.ReferrerJellyfinID, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
match = false
|
match = false
|
||||||
app.storage.DeleteInvitesKey(code)
|
app.storage.DeleteInvitesKey(code)
|
||||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||||
|
@ -130,15 +130,17 @@ func (app *appContext) DeleteProfile(gc *gin.Context) {
|
|||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param profile path string true "name of profile to enable referrals for."
|
// @Param profile path string true "name of profile to enable referrals for."
|
||||||
// @Param invite path string true "invite code to create referral template from."
|
// @Param invite path string true "invite code to create referral template from."
|
||||||
|
// @Param useExpiry path string true "with-expiry or none."
|
||||||
// @Success 200 {object} boolResponse
|
// @Success 200 {object} boolResponse
|
||||||
// @Failure 400 {object} stringResponse
|
// @Failure 400 {object} stringResponse
|
||||||
// @Failure 500 {object} stringResponse
|
// @Failure 500 {object} stringResponse
|
||||||
// @Router /profiles/referral/{profile}/{invite} [post]
|
// @Router /profiles/referral/{profile}/{invite}/{useExpiry} [post]
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @tags Profiles & Settings
|
// @tags Profiles & Settings
|
||||||
func (app *appContext) EnableReferralForProfile(gc *gin.Context) {
|
func (app *appContext) EnableReferralForProfile(gc *gin.Context) {
|
||||||
profileName := gc.Param("profile")
|
profileName := gc.Param("profile")
|
||||||
invCode := gc.Param("invite")
|
invCode := gc.Param("invite")
|
||||||
|
useExpiry := gc.Param("useExpiry") == "with-expiry"
|
||||||
inv, ok := app.storage.GetInvitesKey(invCode)
|
inv, ok := app.storage.GetInvitesKey(invCode)
|
||||||
if !ok {
|
if !ok {
|
||||||
respond(400, "Invalid invite code", gc)
|
respond(400, "Invalid invite code", gc)
|
||||||
@ -154,9 +156,15 @@ func (app *appContext) EnableReferralForProfile(gc *gin.Context) {
|
|||||||
|
|
||||||
// Generate new code for referral template
|
// Generate new code for referral template
|
||||||
inv.Code = GenerateInviteCode()
|
inv.Code = GenerateInviteCode()
|
||||||
|
expiryDelta := inv.ValidTill.Sub(inv.Created)
|
||||||
inv.Created = time.Now()
|
inv.Created = time.Now()
|
||||||
|
if useExpiry {
|
||||||
|
inv.ValidTill = inv.Created.Add(expiryDelta)
|
||||||
|
} else {
|
||||||
inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour)
|
inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour)
|
||||||
|
}
|
||||||
inv.IsReferral = true
|
inv.IsReferral = true
|
||||||
|
inv.UseReferralExpiry = useExpiry
|
||||||
// Since this is a template for multiple users, ReferrerJellyfinID is not set.
|
// Since this is a template for multiple users, ReferrerJellyfinID is not set.
|
||||||
// inv.ReferrerJellyfinID = ...
|
// inv.ReferrerJellyfinID = ...
|
||||||
|
|
||||||
|
@ -746,21 +746,37 @@ func (app *appContext) GetMyReferral(gc *gin.Context) {
|
|||||||
// Since this key is shared between users in a profile, we make a copy.
|
// Since this key is shared between users in a profile, we make a copy.
|
||||||
user, ok := app.storage.GetEmailsKey(gc.GetString("jfId"))
|
user, ok := app.storage.GetEmailsKey(gc.GetString("jfId"))
|
||||||
err = app.storage.db.Get(user.ReferralTemplateKey, &inv)
|
err = app.storage.db.Get(user.ReferralTemplateKey, &inv)
|
||||||
if !ok || err != nil {
|
if !ok || err != nil || user.ReferralTemplateKey == "" {
|
||||||
app.debug.Printf("Ignoring referral request, couldn't find template.")
|
app.debug.Printf("Ignoring referral request, couldn't find template.")
|
||||||
respondBool(400, false, gc)
|
respondBool(400, false, gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inv.Code = GenerateInviteCode()
|
inv.Code = GenerateInviteCode()
|
||||||
|
expiryDelta := inv.ValidTill.Sub(inv.Created)
|
||||||
inv.Created = time.Now()
|
inv.Created = time.Now()
|
||||||
|
if inv.UseReferralExpiry {
|
||||||
|
inv.ValidTill = inv.Created.Add(expiryDelta)
|
||||||
|
} else {
|
||||||
inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour)
|
inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour)
|
||||||
|
}
|
||||||
inv.IsReferral = true
|
inv.IsReferral = true
|
||||||
inv.ReferrerJellyfinID = gc.GetString("jfId")
|
inv.ReferrerJellyfinID = gc.GetString("jfId")
|
||||||
app.storage.SetInvitesKey(inv.Code, inv)
|
app.storage.SetInvitesKey(inv.Code, inv)
|
||||||
} else if time.Now().After(inv.ValidTill) {
|
} else if time.Now().After(inv.ValidTill) {
|
||||||
// 3. We found an invite for us, but it's expired.
|
// 3. We found an invite for us, but it's expired.
|
||||||
// We delete it from storage, and put it back with a fresh code and expiry.
|
// We delete it from storage, and put it back with a fresh code and expiry.
|
||||||
|
// If UseReferralExpiry is enabled, we delete it and return nothing.
|
||||||
app.storage.DeleteInvitesKey(inv.Code)
|
app.storage.DeleteInvitesKey(inv.Code)
|
||||||
|
if inv.UseReferralExpiry {
|
||||||
|
user, ok := app.storage.GetEmailsKey(gc.GetString("jfId"))
|
||||||
|
if ok {
|
||||||
|
user.ReferralTemplateKey = ""
|
||||||
|
app.storage.SetEmailsKey(gc.GetString("jfId"), user)
|
||||||
|
}
|
||||||
|
app.debug.Printf("Ignoring referral request, expired.")
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
inv.Code = GenerateInviteCode()
|
inv.Code = GenerateInviteCode()
|
||||||
inv.Created = time.Now()
|
inv.Created = time.Now()
|
||||||
inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour)
|
inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour)
|
||||||
@ -771,5 +787,6 @@ func (app *appContext) GetMyReferral(gc *gin.Context) {
|
|||||||
RemainingUses: inv.RemainingUses,
|
RemainingUses: inv.RemainingUses,
|
||||||
NoLimit: inv.NoLimit,
|
NoLimit: inv.NoLimit,
|
||||||
Expiry: inv.ValidTill.Unix(),
|
Expiry: inv.ValidTill.Unix(),
|
||||||
|
UseExpiry: inv.UseReferralExpiry,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
24
api-users.go
24
api-users.go
@ -367,6 +367,19 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
emailStore.ReferralTemplateKey = profile.ReferralTemplateKey
|
emailStore.ReferralTemplateKey = profile.ReferralTemplateKey
|
||||||
// Store here, just incase email are disabled (whether this is even possible, i don't know)
|
// Store here, just incase email are disabled (whether this is even possible, i don't know)
|
||||||
app.storage.SetEmailsKey(id, emailStore)
|
app.storage.SetEmailsKey(id, emailStore)
|
||||||
|
|
||||||
|
// If UseReferralExpiry is enabled, create the ref now so the clock starts ticking
|
||||||
|
refInv := Invite{}
|
||||||
|
err = app.storage.db.Get(profile.ReferralTemplateKey, &refInv)
|
||||||
|
if refInv.UseReferralExpiry {
|
||||||
|
refInv.Code = GenerateInviteCode()
|
||||||
|
expiryDelta := refInv.ValidTill.Sub(refInv.Created)
|
||||||
|
refInv.Created = time.Now()
|
||||||
|
refInv.ValidTill = refInv.Created.Add(expiryDelta)
|
||||||
|
refInv.IsReferral = true
|
||||||
|
refInv.ReferrerJellyfinID = id
|
||||||
|
app.storage.SetInvitesKey(refInv.Code, refInv)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
// if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
||||||
@ -729,10 +742,11 @@ func (app *appContext) ExtendExpiry(gc *gin.Context) {
|
|||||||
// @Param EnableDisableReferralDTO body EnableDisableReferralDTO true "List of users"
|
// @Param EnableDisableReferralDTO body EnableDisableReferralDTO true "List of users"
|
||||||
// @Param mode path string true "mode of template sourcing from 'invite' or 'profile'."
|
// @Param mode path string true "mode of template sourcing from 'invite' or 'profile'."
|
||||||
// @Param source path string true "invite code or profile name, depending on what mode is."
|
// @Param source path string true "invite code or profile name, depending on what mode is."
|
||||||
|
// @Param useExpiry path string true "with-expiry or none."
|
||||||
// @Success 200 {object} boolResponse
|
// @Success 200 {object} boolResponse
|
||||||
// @Failure 400 {object} boolResponse
|
// @Failure 400 {object} boolResponse
|
||||||
// @Failure 500 {object} boolResponse
|
// @Failure 500 {object} boolResponse
|
||||||
// @Router /users/referral/{mode}/{source} [post]
|
// @Router /users/referral/{mode}/{source}/{useExpiry} [post]
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @tags Users
|
// @tags Users
|
||||||
func (app *appContext) EnableReferralForUsers(gc *gin.Context) {
|
func (app *appContext) EnableReferralForUsers(gc *gin.Context) {
|
||||||
@ -740,7 +754,7 @@ func (app *appContext) EnableReferralForUsers(gc *gin.Context) {
|
|||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
mode := gc.Param("mode")
|
mode := gc.Param("mode")
|
||||||
source := gc.Param("source")
|
source := gc.Param("source")
|
||||||
|
useExpiry := gc.Param("useExpiry") == "with-expiry"
|
||||||
baseInv := Invite{}
|
baseInv := Invite{}
|
||||||
if mode == "profile" {
|
if mode == "profile" {
|
||||||
profile, ok := app.storage.GetProfileKey(source)
|
profile, ok := app.storage.GetProfileKey(source)
|
||||||
@ -768,10 +782,16 @@ func (app *appContext) EnableReferralForUsers(gc *gin.Context) {
|
|||||||
// 2. Generate referral invite.
|
// 2. Generate referral invite.
|
||||||
inv := baseInv
|
inv := baseInv
|
||||||
inv.Code = GenerateInviteCode()
|
inv.Code = GenerateInviteCode()
|
||||||
|
expiryDelta := inv.ValidTill.Sub(inv.Created)
|
||||||
inv.Created = time.Now()
|
inv.Created = time.Now()
|
||||||
|
if useExpiry {
|
||||||
|
inv.ValidTill = inv.Created.Add(expiryDelta)
|
||||||
|
} else {
|
||||||
inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour)
|
inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour)
|
||||||
|
}
|
||||||
inv.IsReferral = true
|
inv.IsReferral = true
|
||||||
inv.ReferrerJellyfinID = u
|
inv.ReferrerJellyfinID = u
|
||||||
|
inv.UseReferralExpiry = useExpiry
|
||||||
app.storage.SetInvitesKey(inv.Code, inv)
|
app.storage.SetInvitesKey(inv.Code, inv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,11 @@
|
|||||||
<div class="select ~neutral @low mb-4 unfocused">
|
<div class="select ~neutral @low mb-4 unfocused">
|
||||||
<select id="enable-referrals-user-invites"></select>
|
<select id="enable-referrals-user-invites"></select>
|
||||||
</div>
|
</div>
|
||||||
|
<label class="switch mb-4">
|
||||||
|
<input type="checkbox" id="enable-referrals-user-expiry">
|
||||||
|
<span>{{ .strings.useInviteExpiry }}</span>
|
||||||
|
<span class="flex flex-row support mt-2">{{ .strings.useInviteExpiryNote }}</span>
|
||||||
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input type="submit" class="unfocused">
|
<input type="submit" class="unfocused">
|
||||||
<span class="button ~urge @low full-width center supra submit">{{ .strings.apply }}</span>
|
<span class="button ~urge @low full-width center supra submit">{{ .strings.apply }}</span>
|
||||||
@ -144,6 +149,11 @@
|
|||||||
<div class="select ~neutral @low mb-4 mt-2">
|
<div class="select ~neutral @low mb-4 mt-2">
|
||||||
<select id="enable-referrals-profile-invites"></select>
|
<select id="enable-referrals-profile-invites"></select>
|
||||||
</div>
|
</div>
|
||||||
|
<label class="switch mb-4">
|
||||||
|
<input type="checkbox" id="enable-referrals-profile-expiry">
|
||||||
|
<span>{{ .strings.useInviteExpiry }}</span>
|
||||||
|
<span class="flex flex-row support mt-2">{{ .strings.useInviteExpiryNote }}</span>
|
||||||
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input type="submit" class="unfocused">
|
<input type="submit" class="unfocused">
|
||||||
<span class="button ~urge @low full-width center supra submit">{{ .strings.apply }}</span>
|
<span class="button ~urge @low full-width center supra submit">{{ .strings.apply }}</span>
|
||||||
|
@ -155,7 +155,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="card @low dark:~d_neutral unfocused" id="card-referrals">
|
<div class="card @low dark:~d_neutral unfocused" id="card-referrals">
|
||||||
<span class="heading mb-2">{{ .strings.referrals }}</span>
|
<span class="heading mb-2">{{ .strings.referrals }}</span>
|
||||||
<aside class="aside ~neutral my-4 col">{{ .strings.referralsDescription }}</aside>
|
<aside class="aside ~neutral my-4 col user-referrals-description"></aside>
|
||||||
<div class="row flex-expand">
|
<div class="row flex-expand">
|
||||||
<div class="user-referrals-info"></div>
|
<div class="user-referrals-info"></div>
|
||||||
<div class="grid my-2">
|
<div class="grid my-2">
|
||||||
|
@ -76,6 +76,8 @@
|
|||||||
"disableReferrals": "Disable Referrals",
|
"disableReferrals": "Disable Referrals",
|
||||||
"enableReferralsDescription": "Give users a personal referral link similiar to an invite, to send to friends/family. Can be sourced from a referral template in a profile, or from an existing invite.",
|
"enableReferralsDescription": "Give users a personal referral link similiar to an invite, to send to friends/family. Can be sourced from a referral template in a profile, or from an existing invite.",
|
||||||
"enableReferralsProfileDescription": "Give users created with this profile a personal referral link similiar to an invite, to send to friends/family. Create an invite with the desired settings, then select it here. Each referral will then be based on this invite. You can delete the invite once complete.",
|
"enableReferralsProfileDescription": "Give users created with this profile a personal referral link similiar to an invite, to send to friends/family. Create an invite with the desired settings, then select it here. Each referral will then be based on this invite. You can delete the invite once complete.",
|
||||||
|
"useInviteExpiry": "Set expiry from profile/invite",
|
||||||
|
"useInviteExpiryNote": "By default, invites expire after 90 days but can be renewed by the user. Enable for the referral to be disabled after the time set.",
|
||||||
"applyHomescreenLayout": "Apply homescreen layout",
|
"applyHomescreenLayout": "Apply homescreen layout",
|
||||||
"sendDeleteNotificationEmail": "Send notification message",
|
"sendDeleteNotificationEmail": "Send notification message",
|
||||||
"sendDeleteNotifiationExample": "Your account has been deleted.",
|
"sendDeleteNotifiationExample": "Your account has been deleted.",
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
"resetSentDescription": "If an account with the given username/contact method exists, a password reset link has been sent via all contact methods available. The code will expire in 30 minutes.",
|
"resetSentDescription": "If an account with the given username/contact method exists, a password reset link has been sent via all contact methods available. The code will expire in 30 minutes.",
|
||||||
"changePassword": "Change Password",
|
"changePassword": "Change Password",
|
||||||
"referralsDescription": "Invite friends & family to Jellyfin with this link. Come back here for a new one if it expires.",
|
"referralsDescription": "Invite friends & family to Jellyfin with this link. Come back here for a new one if it expires.",
|
||||||
|
"referralsWithExpiryDescription": "Invite friends & family to Jellyfin with this link. The link will be disabled once it expires.",
|
||||||
"copyReferral": "Copy Link",
|
"copyReferral": "Copy Link",
|
||||||
"invitedBy": "You were invited by user {user}."
|
"invitedBy": "You were invited by user {user}."
|
||||||
},
|
},
|
||||||
|
@ -424,7 +424,8 @@ type GetMyReferralRespDTO struct {
|
|||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
RemainingUses int `json:"remaining_uses"`
|
RemainingUses int `json:"remaining_uses"`
|
||||||
NoLimit bool `json:"no_limit"`
|
NoLimit bool `json:"no_limit"`
|
||||||
Expiry int64 `json:"expiry"` // Come back after this time to get a new referral
|
Expiry int64 `json:"expiry"` // Come back after this time to get a new referral (if UseExpiry, a new one can't be made).
|
||||||
|
UseExpiry bool `json:"use_expiry"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type EnableDisableReferralDTO struct {
|
type EnableDisableReferralDTO struct {
|
||||||
|
@ -229,9 +229,9 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
}
|
}
|
||||||
api.POST(p+"/matrix/login", app.MatrixLogin)
|
api.POST(p+"/matrix/login", app.MatrixLogin)
|
||||||
if app.config.Section("user_page").Key("referrals").MustBool(false) {
|
if app.config.Section("user_page").Key("referrals").MustBool(false) {
|
||||||
api.POST(p+"/users/referral/:mode/:source", app.EnableReferralForUsers)
|
api.POST(p+"/users/referral/:mode/:source/:useExpiry", app.EnableReferralForUsers)
|
||||||
api.DELETE(p+"/users/referral", app.DisableReferralForUsers)
|
api.DELETE(p+"/users/referral", app.DisableReferralForUsers)
|
||||||
api.POST(p+"/profiles/referral/:profile/:invite", app.EnableReferralForProfile)
|
api.POST(p+"/profiles/referral/:profile/:invite/:useExpiry", app.EnableReferralForProfile)
|
||||||
api.DELETE(p+"/profiles/referral/:profile", app.DisableReferralForProfile)
|
api.DELETE(p+"/profiles/referral/:profile", app.DisableReferralForProfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,7 +667,7 @@ type Invite struct {
|
|||||||
Captchas map[string]Captcha // Map of Captcha IDs to images & answers
|
Captchas map[string]Captcha // Map of Captcha IDs to images & answers
|
||||||
IsReferral bool `json:"is_referral" badgerhold:"index"`
|
IsReferral bool `json:"is_referral" badgerhold:"index"`
|
||||||
ReferrerJellyfinID string `json:"referrer_id"`
|
ReferrerJellyfinID string `json:"referrer_id"`
|
||||||
ReferrerTemplateForProfile string
|
UseReferralExpiry bool `json:"use_referral_expiry"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Captcha struct {
|
type Captcha struct {
|
||||||
|
@ -783,6 +783,7 @@ export class accountsList {
|
|||||||
private _userSelect = document.getElementById("modify-user-users") as HTMLSelectElement;
|
private _userSelect = document.getElementById("modify-user-users") as HTMLSelectElement;
|
||||||
private _referralsProfileSelect = document.getElementById("enable-referrals-user-profiles") as HTMLSelectElement;
|
private _referralsProfileSelect = document.getElementById("enable-referrals-user-profiles") as HTMLSelectElement;
|
||||||
private _referralsInviteSelect = document.getElementById("enable-referrals-user-invites") as HTMLSelectElement;
|
private _referralsInviteSelect = document.getElementById("enable-referrals-user-invites") as HTMLSelectElement;
|
||||||
|
private _referralsExpiry = document.getElementById("enable-referrals-user-expiry") as HTMLInputElement;
|
||||||
private _searchBox = document.getElementById("accounts-search") as HTMLInputElement;
|
private _searchBox = document.getElementById("accounts-search") as HTMLInputElement;
|
||||||
private _search: Search;
|
private _search: Search;
|
||||||
|
|
||||||
@ -1578,7 +1579,7 @@ export class accountsList {
|
|||||||
send["from"] = "invite";
|
send["from"] = "invite";
|
||||||
send["id"] = this._referralsInviteSelect.value;
|
send["id"] = this._referralsInviteSelect.value;
|
||||||
}
|
}
|
||||||
_post("/users/referral/" + send["from"] + "/" + (send["id"] ? send["id"] : send["profile"]), send, (req: XMLHttpRequest) => {
|
_post("/users/referral/" + send["from"] + "/" + (send["id"] ? send["id"] : send["profile"]) + "/" + (this._referralsExpiry.checked ? "with-expiry" : "none"), send, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
toggleLoader(button);
|
toggleLoader(button);
|
||||||
if (req.status == 400) {
|
if (req.status == 400) {
|
||||||
@ -1593,6 +1594,7 @@ export class accountsList {
|
|||||||
};
|
};
|
||||||
this._enableReferralsProfile.checked = true;
|
this._enableReferralsProfile.checked = true;
|
||||||
this._enableReferralsInvite.checked = false;
|
this._enableReferralsInvite.checked = false;
|
||||||
|
this._referralsExpiry.checked = false;
|
||||||
window.modals.enableReferralsUser.show();
|
window.modals.enableReferralsUser.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +225,7 @@ export class ProfileEditor {
|
|||||||
|
|
||||||
enableReferrals = (name: string) => {
|
enableReferrals = (name: string) => {
|
||||||
const referralsInviteSelect = document.getElementById("enable-referrals-profile-invites") as HTMLSelectElement;
|
const referralsInviteSelect = document.getElementById("enable-referrals-profile-invites") as HTMLSelectElement;
|
||||||
|
const referralsExpiry = document.getElementById("enable-referrals-profile-expiry") as HTMLInputElement;
|
||||||
_get("/invites", null, (req: XMLHttpRequest) => {
|
_get("/invites", null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState != 4 || req.status != 200) return;
|
if (req.readyState != 4 || req.status != 200) return;
|
||||||
|
|
||||||
@ -257,7 +258,7 @@ export class ProfileEditor {
|
|||||||
"invite": referralsInviteSelect.value
|
"invite": referralsInviteSelect.value
|
||||||
};
|
};
|
||||||
|
|
||||||
_post("/profiles/referral/" + send["profile"] + "/" + send["invite"], send, (req: XMLHttpRequest) => {
|
_post("/profiles/referral/" + send["profile"] + "/" + send["invite"] + "/" + (referralsExpiry.checked ? "with-expiry" : "none"), send, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
toggleLoader(button);
|
toggleLoader(button);
|
||||||
if (req.status == 400) {
|
if (req.status == 400) {
|
||||||
@ -270,6 +271,7 @@ export class ProfileEditor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
referralsExpiry.checked = false;
|
||||||
window.modals.profiles.close();
|
window.modals.profiles.close();
|
||||||
window.modals.enableReferralsProfile.show();
|
window.modals.enableReferralsProfile.show();
|
||||||
};
|
};
|
||||||
|
15
ts/user.ts
15
ts/user.ts
@ -116,6 +116,7 @@ interface MyReferral {
|
|||||||
remaining_uses: number;
|
remaining_uses: number;
|
||||||
no_limit: boolean;
|
no_limit: boolean;
|
||||||
expiry: number;
|
expiry: number;
|
||||||
|
use_expiry: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ContactDTO {
|
interface ContactDTO {
|
||||||
@ -252,6 +253,7 @@ class ReferralCard {
|
|||||||
private _url: string;
|
private _url: string;
|
||||||
private _expiry: Date;
|
private _expiry: Date;
|
||||||
private _expiryUnix: number;
|
private _expiryUnix: number;
|
||||||
|
private _useExpiry: boolean;
|
||||||
private _remainingUses: number;
|
private _remainingUses: number;
|
||||||
private _noLimit: boolean;
|
private _noLimit: boolean;
|
||||||
|
|
||||||
@ -259,6 +261,7 @@ class ReferralCard {
|
|||||||
private _infoArea: HTMLDivElement;
|
private _infoArea: HTMLDivElement;
|
||||||
private _remainingUsesEl: HTMLSpanElement;
|
private _remainingUsesEl: HTMLSpanElement;
|
||||||
private _expiryEl: HTMLSpanElement;
|
private _expiryEl: HTMLSpanElement;
|
||||||
|
private _descriptionEl: HTMLSpanElement;
|
||||||
|
|
||||||
get code(): string { return this._code; }
|
get code(): string { return this._code; }
|
||||||
set code(c: string) {
|
set code(c: string) {
|
||||||
@ -295,10 +298,21 @@ class ReferralCard {
|
|||||||
this._expiryEl.textContent = toDateString(this._expiry);
|
this._expiryEl.textContent = toDateString(this._expiry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get use_expiry(): boolean { return this._useExpiry; }
|
||||||
|
set use_expiry(v: boolean) {
|
||||||
|
this._useExpiry = v;
|
||||||
|
if (v) {
|
||||||
|
this._descriptionEl.textContent = window.lang.strings("referralsWithExpiryDescription");
|
||||||
|
} else {
|
||||||
|
this._descriptionEl.textContent = window.lang.strings("referralsDescription");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor(card: HTMLElement) {
|
constructor(card: HTMLElement) {
|
||||||
this._card = card;
|
this._card = card;
|
||||||
this._button = this._card.querySelector(".user-referrals-button") as HTMLButtonElement;
|
this._button = this._card.querySelector(".user-referrals-button") as HTMLButtonElement;
|
||||||
this._infoArea = this._card.querySelector(".user-referrals-info") as HTMLDivElement;
|
this._infoArea = this._card.querySelector(".user-referrals-info") as HTMLDivElement;
|
||||||
|
this._descriptionEl = this._card.querySelector(".user-referrals-description") as HTMLSpanElement;
|
||||||
|
|
||||||
this._infoArea.innerHTML = `
|
this._infoArea.innerHTML = `
|
||||||
<div class="row my-3">
|
<div class="row my-3">
|
||||||
@ -344,6 +358,7 @@ class ReferralCard {
|
|||||||
this.no_limit = referral.no_limit;
|
this.no_limit = referral.no_limit;
|
||||||
this.expiry = referral.expiry;
|
this.expiry = referral.expiry;
|
||||||
this._card.classList.remove("unfocused");
|
this._card.classList.remove("unfocused");
|
||||||
|
this.use_expiry = referral.use_expiry;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user