mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-11-09 20:00:12 +00:00
Compare commits
4 Commits
0946b3a1da
...
baf5e6a593
Author | SHA1 | Date | |
---|---|---|---|
baf5e6a593 | |||
850bb8f44e | |||
b17d8424e9 | |||
d2253ff069 |
@ -79,8 +79,9 @@ func (app *appContext) CreateProfile(gc *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
profile := Profile{
|
profile := Profile{
|
||||||
FromUser: user.Name,
|
FromUser: user.Name,
|
||||||
Policy: user.Policy,
|
Policy: user.Policy,
|
||||||
|
Homescreen: req.Homescreen,
|
||||||
}
|
}
|
||||||
app.debug.Printf("Creating profile from user \"%s\"", user.Name)
|
app.debug.Printf("Creating profile from user \"%s\"", user.Name)
|
||||||
if req.Homescreen {
|
if req.Homescreen {
|
||||||
|
40
api-users.go
40
api-users.go
@ -45,8 +45,13 @@ func (app *appContext) NewUserAdmin(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
id := user.ID
|
id := user.ID
|
||||||
profile := app.storage.GetDefaultProfile()
|
profile := app.storage.GetDefaultProfile()
|
||||||
// Check profile isn't empty
|
if req.Profile != "" && req.Profile != "none" {
|
||||||
if profile.Policy.BlockedTags != nil {
|
if p, ok := app.storage.GetProfileKey(req.Profile); ok {
|
||||||
|
profile = p
|
||||||
|
} else {
|
||||||
|
app.debug.Printf("Couldn't find profile \"%s\", using default", req.Profile)
|
||||||
|
}
|
||||||
|
|
||||||
status, err = app.jf.SetPolicy(id, profile.Policy)
|
status, err = app.jf.SetPolicy(id, profile.Policy)
|
||||||
if !(status == 200 || status == 204 || err == nil) {
|
if !(status == 200 || status == 204 || err == nil) {
|
||||||
app.err.Printf("%s: Failed to set user policy (%d): %v", req.Username, status, err)
|
app.err.Printf("%s: Failed to set user policy (%d): %v", req.Username, status, err)
|
||||||
@ -64,7 +69,6 @@ func (app *appContext) NewUserAdmin(gc *gin.Context) {
|
|||||||
app.storage.SetEmailsKey(id, EmailAddress{Addr: req.Email, Contact: true})
|
app.storage.SetEmailsKey(id, EmailAddress{Addr: req.Email, Contact: true})
|
||||||
}
|
}
|
||||||
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||||
profile := app.storage.GetDefaultProfile()
|
|
||||||
if profile.Ombi == nil {
|
if profile.Ombi == nil {
|
||||||
profile.Ombi = map[string]interface{}{}
|
profile.Ombi = map[string]interface{}{}
|
||||||
}
|
}
|
||||||
@ -305,22 +309,18 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
if !ok {
|
if !ok {
|
||||||
profile = app.storage.GetDefaultProfile()
|
profile = app.storage.GetDefaultProfile()
|
||||||
}
|
}
|
||||||
if profile.Policy.BlockedTags != nil {
|
app.debug.Printf("Applying policy from profile \"%s\"", invite.Profile)
|
||||||
app.debug.Printf("Applying policy from profile \"%s\"", invite.Profile)
|
status, err = app.jf.SetPolicy(id, profile.Policy)
|
||||||
status, err = app.jf.SetPolicy(id, profile.Policy)
|
if !((status == 200 || status == 204) && err == nil) {
|
||||||
if !((status == 200 || status == 204) && err == nil) {
|
app.err.Printf("%s: Failed to set user policy (%d): %v", req.Code, status, err)
|
||||||
app.err.Printf("%s: Failed to set user policy (%d): %v", req.Code, status, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if profile.Configuration.GroupedFolders != nil && len(profile.Displayprefs) != 0 {
|
app.debug.Printf("Applying homescreen from profile \"%s\"", invite.Profile)
|
||||||
app.debug.Printf("Applying homescreen from profile \"%s\"", invite.Profile)
|
status, err = app.jf.SetConfiguration(id, profile.Configuration)
|
||||||
status, err = app.jf.SetConfiguration(id, profile.Configuration)
|
if (status == 200 || status == 204) && err == nil {
|
||||||
if (status == 200 || status == 204) && err == nil {
|
status, err = app.jf.SetDisplayPreferences(id, profile.Displayprefs)
|
||||||
status, err = app.jf.SetDisplayPreferences(id, profile.Displayprefs)
|
}
|
||||||
}
|
if !((status == 200 || status == 204) && err == nil) {
|
||||||
if !((status == 200 || status == 204) && err == nil) {
|
app.err.Printf("%s: Failed to set configuration template (%d): %v", req.Code, status, err)
|
||||||
app.err.Printf("%s: Failed to set configuration template (%d): %v", req.Code, status, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
// if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
||||||
@ -1010,13 +1010,13 @@ func (app *appContext) ApplySettings(gc *gin.Context) {
|
|||||||
if req.From == "profile" {
|
if req.From == "profile" {
|
||||||
// Check profile exists & isn't empty
|
// Check profile exists & isn't empty
|
||||||
profile, ok := app.storage.GetProfileKey(req.Profile)
|
profile, ok := app.storage.GetProfileKey(req.Profile)
|
||||||
if !ok || profile.Policy.BlockedTags == nil {
|
if !ok {
|
||||||
app.err.Printf("Couldn't find profile \"%s\" or profile was empty", req.Profile)
|
app.err.Printf("Couldn't find profile \"%s\" or profile was empty", req.Profile)
|
||||||
respond(500, "Couldn't find profile", gc)
|
respond(500, "Couldn't find profile", gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.Homescreen {
|
if req.Homescreen {
|
||||||
if profile.Configuration.GroupedFolders == nil || len(profile.Displayprefs) == 0 {
|
if !profile.Homescreen {
|
||||||
app.err.Printf("No homescreen saved in profile \"%s\"", req.Profile)
|
app.err.Printf("No homescreen saved in profile \"%s\"", req.Profile)
|
||||||
respond(500, "No homescreen template available", gc)
|
respond(500, "No homescreen template available", gc)
|
||||||
return
|
return
|
||||||
|
@ -222,7 +222,6 @@ func (d *DiscordDaemon) NewTempInvite(ageSeconds, maxUses int) (inviteURL, iconU
|
|||||||
}
|
}
|
||||||
// FIXME: Fix CSS, and handle no icon
|
// FIXME: Fix CSS, and handle no icon
|
||||||
iconURL = guild.IconURL("256")
|
iconURL = guild.IconURL("256")
|
||||||
fmt.Println("GOT ICON", iconURL)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -31,7 +31,6 @@ require (
|
|||||||
github.com/hrfee/jfa-go/linecache v0.0.0-20230421170108-d800b97f69b6
|
github.com/hrfee/jfa-go/linecache v0.0.0-20230421170108-d800b97f69b6
|
||||||
github.com/hrfee/jfa-go/logger v0.0.0-20230421170108-d800b97f69b6
|
github.com/hrfee/jfa-go/logger v0.0.0-20230421170108-d800b97f69b6
|
||||||
github.com/hrfee/jfa-go/ombi v0.0.0-20230421170108-d800b97f69b6
|
github.com/hrfee/jfa-go/ombi v0.0.0-20230421170108-d800b97f69b6
|
||||||
github.com/hrfee/mediabrowser v0.3.8
|
|
||||||
github.com/itchyny/timefmt-go v0.1.5
|
github.com/itchyny/timefmt-go v0.1.5
|
||||||
github.com/lithammer/shortuuid/v3 v3.0.7
|
github.com/lithammer/shortuuid/v3 v3.0.7
|
||||||
github.com/mailgun/mailgun-go/v4 v4.9.0
|
github.com/mailgun/mailgun-go/v4 v4.9.0
|
||||||
@ -84,6 +83,7 @@ require (
|
|||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/gorilla/websocket v1.5.0 // indirect
|
github.com/gorilla/websocket v1.5.0 // indirect
|
||||||
|
github.com/hrfee/mediabrowser v0.3.10 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.13.1 // indirect
|
github.com/klauspost/compress v1.13.1 // indirect
|
||||||
|
4
go.sum
4
go.sum
@ -216,6 +216,10 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
|||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hrfee/mediabrowser v0.3.8 h1:y0iBCb6jE3QKcsiCJSYva2fFPHRn4UA+sGRzoPuJ/Dk=
|
github.com/hrfee/mediabrowser v0.3.8 h1:y0iBCb6jE3QKcsiCJSYva2fFPHRn4UA+sGRzoPuJ/Dk=
|
||||||
github.com/hrfee/mediabrowser v0.3.8/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
|
github.com/hrfee/mediabrowser v0.3.8/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
|
||||||
|
github.com/hrfee/mediabrowser v0.3.9 h1:ecBUd7LMjQrh+9SFRen2T2DzQqI7W8J7vV2lGExD0YU=
|
||||||
|
github.com/hrfee/mediabrowser v0.3.9/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
|
||||||
|
github.com/hrfee/mediabrowser v0.3.10 h1:MUrgZQVY3mk76Bhn7PsZ4LFRhtGitkZA4FP+1qg1HFo=
|
||||||
|
github.com/hrfee/mediabrowser v0.3.10/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
|
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
|
||||||
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
||||||
|
@ -29,6 +29,11 @@
|
|||||||
<input type="text" class="field input ~neutral @high mt-4 mb-2" placeholder="{{ .strings.username }}" id="add-user-user">
|
<input type="text" class="field input ~neutral @high mt-4 mb-2" placeholder="{{ .strings.username }}" id="add-user-user">
|
||||||
<input type="email" class="field input ~neutral @high mt-4 mb-2" placeholder="{{ .strings.emailAddress }}">
|
<input type="email" class="field input ~neutral @high mt-4 mb-2" placeholder="{{ .strings.emailAddress }}">
|
||||||
<input type="password" class="field input ~neutral @high mb-4" placeholder="{{ .strings.password }}" id="add-user-password">
|
<input type="password" class="field input ~neutral @high mb-4" placeholder="{{ .strings.password }}" id="add-user-password">
|
||||||
|
<label class="label supra">{{ .strings.profile }}</label>
|
||||||
|
<div class="select ~neutral @low mb-2 mt-4">
|
||||||
|
<select id="add-user-profile">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<label>
|
<label>
|
||||||
<input type="submit" class="unfocused">
|
<input type="submit" class="unfocused">
|
||||||
<span class="button ~urge @low full-width center supra submit">{{ .strings.create }}</span>
|
<span class="button ~urge @low full-width center supra submit">{{ .strings.create }}</span>
|
||||||
@ -76,7 +81,7 @@
|
|||||||
<form class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3" id="form-modify-user" href="">
|
<form class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3" id="form-modify-user" href="">
|
||||||
<span class="heading"><span id="header-modify-user"></span> <span class="modal-close">×</span></span>
|
<span class="heading"><span id="header-modify-user"></span> <span class="modal-close">×</span></span>
|
||||||
<p class="content my-4">{{ .strings.modifySettingsDescription }}</p>
|
<p class="content my-4">{{ .strings.modifySettingsDescription }}</p>
|
||||||
<div class="flex-row mb-4">
|
<div class="flex flex-row mb-4">
|
||||||
<label class="flex-row-group mr-2">
|
<label class="flex-row-group mr-2">
|
||||||
<input type="radio" name="modify-user-source" class="unfocused" id="radio-use-profile" checked>
|
<input type="radio" name="modify-user-source" class="unfocused" id="radio-use-profile" checked>
|
||||||
<span class="button ~neutral @high supra full-width center">{{ .strings.profile }}</span>
|
<span class="button ~neutral @high supra full-width center">{{ .strings.profile }}</span>
|
||||||
|
@ -286,6 +286,9 @@ func migrateToBadger(app *appContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range app.storage.deprecatedProfiles {
|
for k, v := range app.storage.deprecatedProfiles {
|
||||||
|
if v.Configuration.GroupedFolders != nil || len(v.Displayprefs) != 0 {
|
||||||
|
v.Homescreen = true
|
||||||
|
}
|
||||||
app.storage.SetProfileKey(k, v)
|
app.storage.SetProfileKey(k, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ type newUserDTO struct {
|
|||||||
MatrixContact bool `json:"matrix_contact"` // Whether or not to use matrix for notifications/pwrs
|
MatrixContact bool `json:"matrix_contact"` // Whether or not to use matrix for notifications/pwrs
|
||||||
CaptchaID string `json:"captcha_id"` // Captcha ID (if enabled)
|
CaptchaID string `json:"captcha_id"` // Captcha ID (if enabled)
|
||||||
CaptchaText string `json:"captcha_text"` // Captcha text (if enabled)
|
CaptchaText string `json:"captcha_text"` // Captcha text (if enabled)
|
||||||
|
Profile string `json:"profile"` // Profile (for admins only)
|
||||||
}
|
}
|
||||||
|
|
||||||
type newUserResponse struct {
|
type newUserResponse struct {
|
||||||
|
@ -330,6 +330,9 @@ func (st *Storage) GetProfileKey(k string) (Profile, bool) {
|
|||||||
// fmt.Printf("Failed to find profile: %v\n", err)
|
// fmt.Printf("Failed to find profile: %v\n", err)
|
||||||
ok = false
|
ok = false
|
||||||
}
|
}
|
||||||
|
if result.Policy.BlockedTags == nil {
|
||||||
|
result.Policy.BlockedTags = []interface{}{}
|
||||||
|
}
|
||||||
return result, ok
|
return result, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,6 +474,7 @@ type Profile struct {
|
|||||||
Admin bool `json:"admin,omitempty" badgerhold:"index"`
|
Admin bool `json:"admin,omitempty" badgerhold:"index"`
|
||||||
LibraryAccess string `json:"libraries,omitempty"`
|
LibraryAccess string `json:"libraries,omitempty"`
|
||||||
FromUser string `json:"fromUser,omitempty"`
|
FromUser string `json:"fromUser,omitempty"`
|
||||||
|
Homescreen bool `json:"homescreen"`
|
||||||
Policy mediabrowser.Policy `json:"policy,omitempty"`
|
Policy mediabrowser.Policy `json:"policy,omitempty"`
|
||||||
Configuration mediabrowser.Configuration `json:"configuration,omitempty"`
|
Configuration mediabrowser.Configuration `json:"configuration,omitempty"`
|
||||||
Displayprefs map[string]interface{} `json:"displayprefs,omitempty"`
|
Displayprefs map[string]interface{} `json:"displayprefs,omitempty"`
|
||||||
|
@ -765,6 +765,7 @@ export class accountsList {
|
|||||||
private _addUserName = this._addUserForm.querySelector("input[type=text]") as HTMLInputElement;
|
private _addUserName = this._addUserForm.querySelector("input[type=text]") as HTMLInputElement;
|
||||||
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 _addUserProfile = this._addUserForm.querySelector("select") as HTMLSelectElement;
|
||||||
|
|
||||||
// Columns for sorting.
|
// Columns for sorting.
|
||||||
private _columns: { [className: string]: Column } = {};
|
private _columns: { [className: string]: Column } = {};
|
||||||
@ -987,7 +988,7 @@ export class accountsList {
|
|||||||
// FIXME: Generate filter card for each filter class
|
// FIXME: Generate filter card for each filter class
|
||||||
const filterCard = document.createElement("span");
|
const filterCard = document.createElement("span");
|
||||||
filterCard.ariaLabel = window.lang.strings("clickToRemoveFilter");
|
filterCard.ariaLabel = window.lang.strings("clickToRemoveFilter");
|
||||||
filterCard.classList.add("button", "~" + (boolState ? "positive" : "critical"), "@high", "center", "m-2");
|
filterCard.classList.add("button", "~" + (boolState ? "positive" : "critical"), "@high", "center", "mx-2", "h-full");
|
||||||
filterCard.innerHTML = `
|
filterCard.innerHTML = `
|
||||||
<span class="font-bold mr-2">${queryFormat.name}</span>
|
<span class="font-bold mr-2">${queryFormat.name}</span>
|
||||||
<i class="text-2xl ri-${boolState? "checkbox" : "close"}-circle-fill"></i>
|
<i class="text-2xl ri-${boolState? "checkbox" : "close"}-circle-fill"></i>
|
||||||
@ -1021,7 +1022,7 @@ export class accountsList {
|
|||||||
if (queryFormat.string) {
|
if (queryFormat.string) {
|
||||||
const filterCard = document.createElement("span");
|
const filterCard = document.createElement("span");
|
||||||
filterCard.ariaLabel = window.lang.strings("clickToRemoveFilter");
|
filterCard.ariaLabel = window.lang.strings("clickToRemoveFilter");
|
||||||
filterCard.classList.add("button", "~neutral", "@low", "center", "m-2", "h-full");
|
filterCard.classList.add("button", "~neutral", "@low", "center", "mx-2", "h-full");
|
||||||
filterCard.innerHTML = `
|
filterCard.innerHTML = `
|
||||||
<span class="font-bold mr-2">${queryFormat.name}:</span> "${split[1]}"
|
<span class="font-bold mr-2">${queryFormat.name}:</span> "${split[1]}"
|
||||||
`;
|
`;
|
||||||
@ -1252,7 +1253,8 @@ export class accountsList {
|
|||||||
const send = {
|
const send = {
|
||||||
"username": this._addUserName.value,
|
"username": this._addUserName.value,
|
||||||
"email": this._addUserEmail.value,
|
"email": this._addUserEmail.value,
|
||||||
"password": this._addUserPassword.value
|
"password": this._addUserPassword.value,
|
||||||
|
"profile": this._addUserProfile.value,
|
||||||
};
|
};
|
||||||
for (let field in send) {
|
for (let field in send) {
|
||||||
if (!send[field]) {
|
if (!send[field]) {
|
||||||
@ -1402,6 +1404,9 @@ export class accountsList {
|
|||||||
this._announceButton.nextElementSibling.children[0].classList.add("unfocused");
|
this._announceButton.nextElementSibling.children[0].classList.add("unfocused");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (list.length > 0) {
|
||||||
|
this._announceButton.innerHTML = `${window.lang.strings("announce")} <i class="ml-2 ri-arrow-drop-down-line"></i>`;
|
||||||
|
}
|
||||||
const dList = document.getElementById("accounts-announce-templates") as HTMLDivElement;
|
const dList = document.getElementById("accounts-announce-templates") as HTMLDivElement;
|
||||||
dList.textContent = '';
|
dList.textContent = '';
|
||||||
for (let name of list) {
|
for (let name of list) {
|
||||||
@ -1733,6 +1738,15 @@ export class accountsList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _populateAddUserProfiles = () => {
|
||||||
|
this._addUserProfile.textContent = "";
|
||||||
|
let innerHTML = `<option value="none">${window.lang.strings("inviteNoProfile")}</option>`;
|
||||||
|
for (let i = 0; i < window.availableProfiles.length; i++) {
|
||||||
|
innerHTML += `<option value="${window.availableProfiles[i]}" ${i == 0 ? "selected" : ""}>${window.availableProfiles[i]}</option>`;
|
||||||
|
}
|
||||||
|
this._addUserProfile.innerHTML = innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._populateNumbers();
|
this._populateNumbers();
|
||||||
this._users = {};
|
this._users = {};
|
||||||
@ -1743,7 +1757,10 @@ export class accountsList {
|
|||||||
document.addEventListener("accounts-reload", this.reload);
|
document.addEventListener("accounts-reload", this.reload);
|
||||||
document.addEventListener("accountCheckEvent", () => { this._checkCount++; this._checkCheckCount(); });
|
document.addEventListener("accountCheckEvent", () => { this._checkCount++; this._checkCheckCount(); });
|
||||||
document.addEventListener("accountUncheckEvent", () => { this._checkCount--; this._checkCheckCount(); });
|
document.addEventListener("accountUncheckEvent", () => { this._checkCount--; this._checkCheckCount(); });
|
||||||
this._addUserButton.onclick = window.modals.addUser.toggle;
|
this._addUserButton.onclick = () => {
|
||||||
|
this._populateAddUserProfiles();
|
||||||
|
window.modals.addUser.toggle();
|
||||||
|
};
|
||||||
this._addUserForm.addEventListener("submit", this._addUser);
|
this._addUserForm.addEventListener("submit", this._addUser);
|
||||||
|
|
||||||
this._deleteNotify.onchange = () => {
|
this._deleteNotify.onchange = () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user