mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
add disabled badge, extend expiry button to accounts
This commit is contained in:
parent
1e9d184508
commit
1ec5d2ca3f
40
api.go
40
api.go
@ -457,6 +457,36 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary Extend time before the user(s) expiry.
|
||||||
|
// @Produce json
|
||||||
|
// @Param extendExpiryDTO body extendExpiryDTO true "Extend expiry object"
|
||||||
|
// @Success 200 {object} boolResponse
|
||||||
|
// @Failure 400 {object} boolResponse
|
||||||
|
// @Failure 500 {object} boolResponse
|
||||||
|
// @Router /users/extend [post]
|
||||||
|
// @tags Users
|
||||||
|
func (app *appContext) ExtendExpiry(gc *gin.Context) {
|
||||||
|
var req extendExpiryDTO
|
||||||
|
app.info.Printf("Expiry extension requested for %d user(s)", len(req.Users))
|
||||||
|
gc.BindJSON(&req)
|
||||||
|
if req.Days == 0 && req.Hours == 0 && req.Minutes == 0 {
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, id := range req.Users {
|
||||||
|
if expiry, ok := app.storage.users[id]; ok {
|
||||||
|
app.storage.users[id] = expiry.Add(time.Duration(60*(req.Days*24+req.Hours)+req.Minutes) * time.Minute)
|
||||||
|
app.debug.Printf("Expiry extended for \"%s\"", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := app.storage.storeUsers(); err != nil {
|
||||||
|
app.err.Printf("Failed to store user duration: %s", err)
|
||||||
|
respondBool(500, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respondBool(204, true, gc)
|
||||||
|
}
|
||||||
|
|
||||||
// @Summary Creates a new Jellyfin user via invite code
|
// @Summary Creates a new Jellyfin user via invite code
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param newUserDTO body newUserDTO true "New user request object"
|
// @Param newUserDTO body newUserDTO true "New user request object"
|
||||||
@ -998,9 +1028,10 @@ func (app *appContext) GetUsers(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
for _, jfUser := range users {
|
for _, jfUser := range users {
|
||||||
user := respUser{
|
user := respUser{
|
||||||
ID: jfUser.ID,
|
ID: jfUser.ID,
|
||||||
Name: jfUser.Name,
|
Name: jfUser.Name,
|
||||||
Admin: jfUser.Policy.IsAdministrator,
|
Admin: jfUser.Policy.IsAdministrator,
|
||||||
|
Disabled: jfUser.Policy.IsDisabled,
|
||||||
}
|
}
|
||||||
user.LastActive = "n/a"
|
user.LastActive = "n/a"
|
||||||
if !jfUser.LastActivityDate.IsZero() {
|
if !jfUser.LastActivityDate.IsZero() {
|
||||||
@ -1009,6 +1040,9 @@ func (app *appContext) GetUsers(gc *gin.Context) {
|
|||||||
if email, ok := app.storage.emails[jfUser.ID]; ok {
|
if email, ok := app.storage.emails[jfUser.ID]; ok {
|
||||||
user.Email = email.(string)
|
user.Email = email.(string)
|
||||||
}
|
}
|
||||||
|
if expiry, ok := app.storage.users[jfUser.ID]; ok {
|
||||||
|
user.Expiry = app.formatDatetime(expiry)
|
||||||
|
}
|
||||||
|
|
||||||
resp.UserList = append(resp.UserList, user)
|
resp.UserList = append(resp.UserList, user)
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,35 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="modal-extend-expiry" class="modal">
|
||||||
|
<form class="modal-content card" id="form-extend-expiry" href="">
|
||||||
|
<span class="heading"><span id="header-extend-expiry"></span> <span class="modal-close">×</span></span>
|
||||||
|
<div class="content mt-half">
|
||||||
|
<label class="label supra" for="extend-expiry-days">{{ .strings.inviteDays }}</label>
|
||||||
|
<div class="select ~neutral !normal mb-1 mt-half">
|
||||||
|
<select id="extend-expiry-days">
|
||||||
|
<option>0</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="label supra" for="extend-expiry-hours">{{ .strings.inviteHours }}</label>
|
||||||
|
<div class="select ~neutral !normal mb-1 mt-half">
|
||||||
|
<select id="extend-expiry-hours">
|
||||||
|
<option>0</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="label supra" for="extend-expiry-minutes">{{ .strings.inviteMinutes }}</label>
|
||||||
|
<div class="select ~neutral !normal mb-1 mt-half">
|
||||||
|
<select id="extend-expiry-minutes">
|
||||||
|
<option>0</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label>
|
||||||
|
<input type="submit" class="unfocused">
|
||||||
|
<span class="button ~critical !normal full-width center supra submit">{{ .strings.submit }}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
<div id="modal-announce" class="modal">
|
<div id="modal-announce" class="modal">
|
||||||
<form class="modal-content card" id="form-announce" href="">
|
<form class="modal-content card" id="form-announce" href="">
|
||||||
<span class="heading"><span id="header-announce"></span> <span class="modal-close">×</span></span>
|
<span class="heading"><span id="header-announce"></span> <span class="modal-close">×</span></span>
|
||||||
@ -353,10 +382,11 @@
|
|||||||
<div class="card ~neutral !low accounts mb-1">
|
<div class="card ~neutral !low accounts mb-1">
|
||||||
<span class="heading">{{ .strings.accounts }}</span>
|
<span class="heading">{{ .strings.accounts }}</span>
|
||||||
<div class="fr">
|
<div class="fr">
|
||||||
<span class="button ~neutral !normal" id="accounts-add-user">{{ .quantityStrings.addUser.Singular }}</span>
|
<span class="button ~neutral !normal mb-half" id="accounts-add-user">{{ .quantityStrings.addUser.Singular }}</span>
|
||||||
<span class="button ~info !normal" id="accounts-announce">{{ .strings.announce }}</span>
|
<span class="button ~info !normal mb-half" id="accounts-announce">{{ .strings.announce }}</span>
|
||||||
<span class="button ~urge !normal" id="accounts-modify-user">{{ .strings.modifySettings }}</span>
|
<span class="button ~urge !normal mb-half" id="accounts-modify-user">{{ .strings.modifySettings }}</span>
|
||||||
<span class="button ~critical !normal" id="accounts-delete-user">{{ .quantityStrings.deleteUser.Singular }}</span>
|
<span class="button ~warning !normal mb-half" id="accounts-extend-expiry">{{ .strings.extendExpiry }}</span>
|
||||||
|
<span class="button ~critical !normal mb-half" id="accounts-delete-user">{{ .quantityStrings.deleteUser.Singular }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card ~neutral !normal accounts-header table-responsive mt-half">
|
<div class="card ~neutral !normal accounts-header table-responsive mt-half">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
@ -365,6 +395,7 @@
|
|||||||
<th><input type="checkbox" value="" id="accounts-select-all"></th>
|
<th><input type="checkbox" value="" id="accounts-select-all"></th>
|
||||||
<th>{{ .strings.username }}</th>
|
<th>{{ .strings.username }}</th>
|
||||||
<th>{{ .strings.emailAddress }}</th>
|
<th>{{ .strings.emailAddress }}</th>
|
||||||
|
<th>{{ .strings.expiry }}</th>
|
||||||
<th>{{ .strings.lastActiveTime }}</th>
|
<th>{{ .strings.lastActiveTime }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -22,9 +22,12 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"date": "Date",
|
"date": "Date",
|
||||||
"enabled": "Enabled",
|
"enabled": "Enabled",
|
||||||
|
"disabled": "Disabled",
|
||||||
|
"admin": "Admin",
|
||||||
"lastActiveTime": "Last Active",
|
"lastActiveTime": "Last Active",
|
||||||
"from": "From",
|
"from": "From",
|
||||||
"user": "User",
|
"user": "User",
|
||||||
|
"expiry": "Expiry",
|
||||||
"userExpiry": "User Expiry",
|
"userExpiry": "User Expiry",
|
||||||
"userExpiryDescription": "A specified amount of time after each signup, jfa-go will delete/disable the account. You can change this behaviour in settings.",
|
"userExpiryDescription": "A specified amount of time after each signup, jfa-go will delete/disable the account. You can change this behaviour in settings.",
|
||||||
"aboutProgram": "About",
|
"aboutProgram": "About",
|
||||||
@ -41,6 +44,7 @@
|
|||||||
"preview": "Preview",
|
"preview": "Preview",
|
||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
|
"extendExpiry": "Extend expiry",
|
||||||
"customizeEmails": "Customize Emails",
|
"customizeEmails": "Customize Emails",
|
||||||
"customizeEmailsDescription": "If you don't want to use jfa-go's email templates, you can create your own using Markdown.",
|
"customizeEmailsDescription": "If you don't want to use jfa-go's email templates, you can create your own using Markdown.",
|
||||||
"markdownSupported": "Markdown is supported.",
|
"markdownSupported": "Markdown is supported.",
|
||||||
@ -141,6 +145,14 @@
|
|||||||
"appliedSettings": {
|
"appliedSettings": {
|
||||||
"singular": "Applied settings to {n} user.",
|
"singular": "Applied settings to {n} user.",
|
||||||
"plural": "Applied settings to {n} users."
|
"plural": "Applied settings to {n} users."
|
||||||
|
},
|
||||||
|
"extendExpiry": {
|
||||||
|
"singular": "Extend expiry for {n} user",
|
||||||
|
"plural": "Extend expiry for {n} users"
|
||||||
|
},
|
||||||
|
"extendedExpiry": {
|
||||||
|
"singular": "Extended expiry for {n} user.",
|
||||||
|
"plural": "Extended expiry for {n} users."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,8 @@ type respUser struct {
|
|||||||
Email string `json:"email,omitempty" example:"jeff@jellyf.in"` // Email address of user (if available)
|
Email string `json:"email,omitempty" example:"jeff@jellyf.in"` // Email address of user (if available)
|
||||||
LastActive string `json:"last_active"` // Time of last activity on Jellyfin
|
LastActive string `json:"last_active"` // Time of last activity on Jellyfin
|
||||||
Admin bool `json:"admin" example:"false"` // Whether or not the user is Administrator
|
Admin bool `json:"admin" example:"false"` // Whether or not the user is Administrator
|
||||||
|
Expiry string `json:"expiry" example:"01/02/21 12:00"` // Expiry time of user, if applicable.
|
||||||
|
Disabled bool `json:"disabled"` // Whether or not the user is disabled.
|
||||||
}
|
}
|
||||||
|
|
||||||
type getUsersDTO struct {
|
type getUsersDTO struct {
|
||||||
@ -206,6 +208,9 @@ type customEmailDTO struct {
|
|||||||
Plaintext string `json:"plaintext"`
|
Plaintext string `json:"plaintext"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type getEmailDTO struct {
|
type extendExpiryDTO struct {
|
||||||
Lang string `json:"lang" example:"en-us"` // Language code. If not given, defaults ot one specified in settings.
|
Users []string `json:"users"` // List of user IDs to apply to.
|
||||||
|
Days int `json:"days" example:"1"` // Number of days to add.
|
||||||
|
Hours int `json:"hours" example:"2"` // Number of hours to add.
|
||||||
|
Minutes int `json:"minutes" example:"3"` // Number of minutes to add.
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
api.DELETE(p+"/users", app.DeleteUsers)
|
api.DELETE(p+"/users", app.DeleteUsers)
|
||||||
api.GET(p+"/users", app.GetUsers)
|
api.GET(p+"/users", app.GetUsers)
|
||||||
api.POST(p+"/users", app.NewUserAdmin)
|
api.POST(p+"/users", app.NewUserAdmin)
|
||||||
|
api.POST(p+"/users/extend", app.ExtendExpiry)
|
||||||
api.POST(p+"/invites", app.GenerateInvite)
|
api.POST(p+"/invites", app.GenerateInvite)
|
||||||
api.GET(p+"/invites", app.GetInvites)
|
api.GET(p+"/invites", app.GetInvites)
|
||||||
api.DELETE(p+"/invites", app.DeleteInvite)
|
api.DELETE(p+"/invites", app.DeleteInvite)
|
||||||
|
@ -57,6 +57,8 @@ window.availableProfiles = window.availableProfiles || [];
|
|||||||
window.modals.editor = new Modal(document.getElementById("modal-editor"));
|
window.modals.editor = new Modal(document.getElementById("modal-editor"));
|
||||||
|
|
||||||
window.modals.customizeEmails = new Modal(document.getElementById("modal-customize"));
|
window.modals.customizeEmails = new Modal(document.getElementById("modal-customize"));
|
||||||
|
|
||||||
|
window.modals.extendExpiry = new Modal(document.getElementById("modal-extend-expiry"));
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var inviteCreator = new createInvite();
|
var inviteCreator = new createInvite();
|
||||||
|
@ -6,6 +6,8 @@ interface User {
|
|||||||
email: string | undefined;
|
email: string | undefined;
|
||||||
last_active: string;
|
last_active: string;
|
||||||
admin: boolean;
|
admin: boolean;
|
||||||
|
disabled: boolean;
|
||||||
|
expiry: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class user implements User {
|
class user implements User {
|
||||||
@ -13,9 +15,11 @@ class user implements User {
|
|||||||
private _check: HTMLInputElement;
|
private _check: HTMLInputElement;
|
||||||
private _username: HTMLSpanElement;
|
private _username: HTMLSpanElement;
|
||||||
private _admin: HTMLSpanElement;
|
private _admin: HTMLSpanElement;
|
||||||
|
private _disabled: HTMLSpanElement;
|
||||||
private _email: HTMLInputElement;
|
private _email: HTMLInputElement;
|
||||||
private _emailAddress: string;
|
private _emailAddress: string;
|
||||||
private _emailEditButton: HTMLElement;
|
private _emailEditButton: HTMLElement;
|
||||||
|
private _expiry: HTMLTableDataCellElement;
|
||||||
private _lastActive: HTMLTableDataCellElement;
|
private _lastActive: HTMLTableDataCellElement;
|
||||||
id: string;
|
id: string;
|
||||||
private _selected: boolean;
|
private _selected: boolean;
|
||||||
@ -34,10 +38,21 @@ class user implements User {
|
|||||||
set admin(state: boolean) {
|
set admin(state: boolean) {
|
||||||
if (state) {
|
if (state) {
|
||||||
this._admin.classList.add("chip", "~info", "ml-1");
|
this._admin.classList.add("chip", "~info", "ml-1");
|
||||||
this._admin.textContent = "Admin";
|
this._admin.textContent = window.lang.strings("admin");
|
||||||
} else {
|
} else {
|
||||||
this._admin.classList.remove("chip", "~info", "ml-1");
|
this._admin.classList.remove("chip", "~info", "ml-1");
|
||||||
this._admin.textContent = ""
|
this._admin.textContent = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get disabled(): boolean { return this._disabled.classList.contains("chip"); }
|
||||||
|
set disabled(state: boolean) {
|
||||||
|
if (state) {
|
||||||
|
this._disabled.classList.add("chip", "~warning", "ml-1");
|
||||||
|
this._disabled.textContent = window.lang.strings("disabled");
|
||||||
|
} else {
|
||||||
|
this._disabled.classList.remove("chip", "~warning", "ml-1");
|
||||||
|
this._disabled.textContent = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +67,9 @@ class user implements User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get expiry(): string { return this._expiry.textContent; }
|
||||||
|
set expiry(value: string) { this._expiry.textContent = value; }
|
||||||
|
|
||||||
get last_active(): string { return this._lastActive.textContent; }
|
get last_active(): string { return this._lastActive.textContent; }
|
||||||
set last_active(value: string) { this._lastActive.textContent = value; }
|
set last_active(value: string) { this._lastActive.textContent = value; }
|
||||||
|
|
||||||
@ -62,16 +80,19 @@ class user implements User {
|
|||||||
this._row = document.createElement("tr") as HTMLTableRowElement;
|
this._row = document.createElement("tr") as HTMLTableRowElement;
|
||||||
this._row.innerHTML = `
|
this._row.innerHTML = `
|
||||||
<td><input type="checkbox" value=""></td>
|
<td><input type="checkbox" value=""></td>
|
||||||
<td><span class="accounts-username"></span> <span class="accounts-admin"></span></td>
|
<td><span class="accounts-username"></span> <span class="accounts-admin"></span> <span class="accounts-disabled"></span></td>
|
||||||
<td><i class="icon ri-edit-line accounts-email-edit"></i><span class="accounts-email-container ml-half"></span></td>
|
<td><i class="icon ri-edit-line accounts-email-edit"></i><span class="accounts-email-container ml-half"></span></td>
|
||||||
|
<td class="accounts-expiry"></td>
|
||||||
<td class="accounts-last-active"></td>
|
<td class="accounts-last-active"></td>
|
||||||
`;
|
`;
|
||||||
const emailEditor = `<input type="email" class="input ~neutral !normal stealth-input">`;
|
const emailEditor = `<input type="email" class="input ~neutral !normal stealth-input">`;
|
||||||
this._check = this._row.querySelector("input[type=checkbox]") as HTMLInputElement;
|
this._check = this._row.querySelector("input[type=checkbox]") as HTMLInputElement;
|
||||||
this._username = this._row.querySelector(".accounts-username") as HTMLSpanElement;
|
this._username = this._row.querySelector(".accounts-username") as HTMLSpanElement;
|
||||||
this._admin = this._row.querySelector(".accounts-admin") as HTMLSpanElement;
|
this._admin = this._row.querySelector(".accounts-admin") as HTMLSpanElement;
|
||||||
|
this._disabled = this._row.querySelector(".accounts-disabled") as HTMLSpanElement;
|
||||||
this._email = this._row.querySelector(".accounts-email-container") as HTMLInputElement;
|
this._email = this._row.querySelector(".accounts-email-container") as HTMLInputElement;
|
||||||
this._emailEditButton = this._row.querySelector(".accounts-email-edit") as HTMLElement;
|
this._emailEditButton = this._row.querySelector(".accounts-email-edit") as HTMLElement;
|
||||||
|
this._expiry = this._row.querySelector(".accounts-expiry") as HTMLTableDataCellElement;
|
||||||
this._lastActive = this._row.querySelector(".accounts-last-active") as HTMLTableDataCellElement;
|
this._lastActive = this._row.querySelector(".accounts-last-active") as HTMLTableDataCellElement;
|
||||||
this._check.onchange = () => { this.selected = this._check.checked; }
|
this._check.onchange = () => { this.selected = this._check.checked; }
|
||||||
|
|
||||||
@ -130,6 +151,8 @@ class user implements User {
|
|||||||
this.email = user.email || "";
|
this.email = user.email || "";
|
||||||
this.last_active = user.last_active;
|
this.last_active = user.last_active;
|
||||||
this.admin = user.admin;
|
this.admin = user.admin;
|
||||||
|
this.disabled = user.disabled;
|
||||||
|
this.expiry = user.expiry;
|
||||||
}
|
}
|
||||||
|
|
||||||
asElement = (): HTMLTableRowElement => { return this._row; }
|
asElement = (): HTMLTableRowElement => { return this._row; }
|
||||||
@ -152,6 +175,7 @@ export class accountsList {
|
|||||||
private _deleteUser = document.getElementById("accounts-delete-user") as HTMLSpanElement;
|
private _deleteUser = document.getElementById("accounts-delete-user") as HTMLSpanElement;
|
||||||
private _deleteNotify = document.getElementById("delete-user-notify") as HTMLInputElement;
|
private _deleteNotify = document.getElementById("delete-user-notify") as HTMLInputElement;
|
||||||
private _deleteReason = document.getElementById("textarea-delete-user") as HTMLTextAreaElement;
|
private _deleteReason = document.getElementById("textarea-delete-user") as HTMLTextAreaElement;
|
||||||
|
private _extendExpiry = document.getElementById("accounts-extend-expiry") as HTMLSpanElement;
|
||||||
private _modifySettings = document.getElementById("accounts-modify-user") as HTMLSpanElement;
|
private _modifySettings = document.getElementById("accounts-modify-user") as HTMLSpanElement;
|
||||||
private _modifySettingsProfile = document.getElementById("radio-use-profile") as HTMLInputElement;
|
private _modifySettingsProfile = document.getElementById("radio-use-profile") as HTMLInputElement;
|
||||||
private _modifySettingsUser = document.getElementById("radio-use-user") as HTMLInputElement;
|
private _modifySettingsUser = document.getElementById("radio-use-user") as HTMLInputElement;
|
||||||
@ -167,6 +191,24 @@ export class accountsList {
|
|||||||
private _addUserEmail = this._addUserForm.querySelector("input[type=email]") as HTMLInputElement;
|
private _addUserEmail = this._addUserForm.querySelector("input[type=email]") as HTMLInputElement;
|
||||||
private _addUserPassword = this._addUserForm.querySelector("input[type=password]") as HTMLInputElement;
|
private _addUserPassword = this._addUserForm.querySelector("input[type=password]") as HTMLInputElement;
|
||||||
|
|
||||||
|
private _count = 30;
|
||||||
|
private _populateNumbers = () => {
|
||||||
|
const fieldIDs = ["days", "hours", "minutes"];
|
||||||
|
const prefixes = ["extend-expiry-"];
|
||||||
|
for (let i = 0; i < fieldIDs.length; i++) {
|
||||||
|
for (let j = 0; j < prefixes.length; j++) {
|
||||||
|
const field = document.getElementById(prefixes[j] + fieldIDs[i]);
|
||||||
|
field.textContent = '';
|
||||||
|
for (let n = 0; n <= this._count; n++) {
|
||||||
|
const opt = document.createElement("option") as HTMLOptionElement;
|
||||||
|
opt.textContent = ""+n;
|
||||||
|
opt.value = ""+n;
|
||||||
|
field.appendChild(opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get selectAll(): boolean { return this._selectAll.checked; }
|
get selectAll(): boolean { return this._selectAll.checked; }
|
||||||
set selectAll(state: boolean) {
|
set selectAll(state: boolean) {
|
||||||
for (let id in this._users) {
|
for (let id in this._users) {
|
||||||
@ -193,6 +235,7 @@ export class accountsList {
|
|||||||
if (window.emailEnabled) {
|
if (window.emailEnabled) {
|
||||||
this._announceButton.classList.add("unfocused");
|
this._announceButton.classList.add("unfocused");
|
||||||
}
|
}
|
||||||
|
this._extendExpiry.classList.add("unfocused");
|
||||||
} else {
|
} else {
|
||||||
if (this._checkCount == Object.keys(this._users).length) {
|
if (this._checkCount == Object.keys(this._users).length) {
|
||||||
this._selectAll.checked = true;
|
this._selectAll.checked = true;
|
||||||
@ -207,6 +250,18 @@ export class accountsList {
|
|||||||
if (window.emailEnabled) {
|
if (window.emailEnabled) {
|
||||||
this._announceButton.classList.remove("unfocused");
|
this._announceButton.classList.remove("unfocused");
|
||||||
}
|
}
|
||||||
|
const list = this._collectUsers();
|
||||||
|
let anyNonExpiries = false;
|
||||||
|
for (let id of list) {
|
||||||
|
if (!this._users[id].expiry) {
|
||||||
|
anyNonExpiries = true;
|
||||||
|
this._extendExpiry.classList.add("unfocused");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!anyNonExpiries) {
|
||||||
|
this._extendExpiry.classList.remove("unfocused");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +449,39 @@ export class accountsList {
|
|||||||
window.modals.modifyUser.show();
|
window.modals.modifyUser.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extendExpiry = () => {
|
||||||
|
const list = this._collectUsers();
|
||||||
|
let applyList: string[] = [];
|
||||||
|
for (let id of list) {
|
||||||
|
if (this._users[id].expiry) {
|
||||||
|
applyList.push(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.getElementById("header-extend-expiry").textContent = window.lang.quantity("extendExpiry", applyList.length);
|
||||||
|
const form = document.getElementById("form-extend-expiry") as HTMLFormElement;
|
||||||
|
form.onsubmit = (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
let send = { "users": applyList }
|
||||||
|
for (let field of ["days", "hours", "minutes"]) {
|
||||||
|
send[field] = +(document.getElementById("extend-expiry-"+field) as HTMLSelectElement).value;
|
||||||
|
}
|
||||||
|
_post("/users/extend", send, (req: XMLHttpRequest) => {
|
||||||
|
if (req.readyState == 4) {
|
||||||
|
if (req.status != 200 && req.status != 204) {
|
||||||
|
window.notifications.customError("extendExpiryError", window.lang.notif("errorFailureCheckLogs"));
|
||||||
|
} else {
|
||||||
|
window.notifications.customSuccess("extendExpiry", window.lang.quantity("extendedExpiry", applyList.length));
|
||||||
|
}
|
||||||
|
window.modals.extendExpiry.close()
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
window.modals.extendExpiry.show();
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this._populateNumbers();
|
||||||
this._users = {};
|
this._users = {};
|
||||||
this._selectAll.checked = false;
|
this._selectAll.checked = false;
|
||||||
this._selectAll.onchange = () => { this.selectAll = this._selectAll.checked };
|
this._selectAll.onchange = () => { this.selectAll = this._selectAll.checked };
|
||||||
@ -440,6 +527,9 @@ export class accountsList {
|
|||||||
this._announceButton.onclick = this.announce;
|
this._announceButton.onclick = this.announce;
|
||||||
this._announceButton.classList.add("unfocused");
|
this._announceButton.classList.add("unfocused");
|
||||||
|
|
||||||
|
this._extendExpiry.onclick = this.extendExpiry;
|
||||||
|
this._extendExpiry.classList.add("unfocused");
|
||||||
|
|
||||||
if (!window.usernameEnabled) {
|
if (!window.usernameEnabled) {
|
||||||
this._addUserName.classList.add("unfocused");
|
this._addUserName.classList.add("unfocused");
|
||||||
this._addUserName = this._addUserEmail;
|
this._addUserName = this._addUserEmail;
|
||||||
|
@ -624,6 +624,14 @@ export class createInvite {
|
|||||||
}
|
}
|
||||||
set userExpiry(enabled: boolean) {
|
set userExpiry(enabled: boolean) {
|
||||||
this._userExpiryToggle.checked = enabled;
|
this._userExpiryToggle.checked = enabled;
|
||||||
|
const parent = this._userExpiryToggle.parentElement;
|
||||||
|
if (enabled) {
|
||||||
|
parent.classList.add("~urge");
|
||||||
|
parent.classList.remove("~neutral");
|
||||||
|
} else {
|
||||||
|
parent.classList.add("~neutral");
|
||||||
|
parent.classList.remove("~urge");
|
||||||
|
}
|
||||||
this._userDays.disabled = !enabled;
|
this._userDays.disabled = !enabled;
|
||||||
this._userHours.disabled = !enabled;
|
this._userHours.disabled = !enabled;
|
||||||
this._userMinutes.disabled = !enabled;
|
this._userMinutes.disabled = !enabled;
|
||||||
|
@ -77,6 +77,7 @@ declare interface Modals {
|
|||||||
announce: Modal;
|
announce: Modal;
|
||||||
editor: Modal;
|
editor: Modal;
|
||||||
customizeEmails: Modal;
|
customizeEmails: Modal;
|
||||||
|
extendExpiry: Modal;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Invite {
|
interface Invite {
|
||||||
@ -90,8 +91,8 @@ interface Invite {
|
|||||||
notifyCreation?: boolean;
|
notifyCreation?: boolean;
|
||||||
profile?: string;
|
profile?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
userDuration?: boolean;
|
userExpiry?: boolean;
|
||||||
userDurationTime?: string;
|
userExpiryTime?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface inviteList {
|
interface inviteList {
|
||||||
|
Loading…
Reference in New Issue
Block a user