From 89e70f6f7a00ba32d8190bb3e2350edf75ddecf0 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Wed, 23 Sep 2020 18:48:00 +0100 Subject: [PATCH] Add default profile functionality Default profile can be selected in settings. --- api.go | 40 ++++++++++++++++++++++++++++++++++----- config/config-base.json | 8 ++++---- data/templates/admin.html | 1 + main.go | 1 + storage.go | 11 +++++++++-- ts/settings.ts | 25 +++++++++++++++++++----- 6 files changed, 70 insertions(+), 16 deletions(-) diff --git a/api.go b/api.go index 17f927d..9fdb3ae 100644 --- a/api.go +++ b/api.go @@ -472,7 +472,9 @@ func (app *appContext) SetProfile(gc *gin.Context) { func (app *appContext) GetProfiles(gc *gin.Context) { app.storage.loadProfiles() app.debug.Println("Profiles requested") - out := map[string]map[string]interface{}{} + out := map[string]interface{}{ + "default_profile": app.storage.defaultProfile, + } for name, p := range app.storage.profiles { out[name] = map[string]interface{}{ "admin": p.Admin, @@ -484,6 +486,27 @@ func (app *appContext) GetProfiles(gc *gin.Context) { gc.JSON(200, out) } +func (app *appContext) SetDefaultProfile(gc *gin.Context) { + req := map[string]string{} + gc.BindJSON(&req) + app.info.Printf("Setting default profile to \"%s\"", req["name"]) + if _, ok := app.storage.profiles[req["name"]]; !ok { + app.err.Printf("Profile not found: \"%s\"", req["name"]) + respond(500, "Profile not found", gc) + return + } + for name, profile := range app.storage.profiles { + if name == req["name"] { + profile.Admin = true + app.storage.profiles[name] = profile + } else { + profile.Admin = false + } + } + app.storage.defaultProfile = req["name"] + gc.JSON(200, map[string]bool{"success": true}) +} + type newProfileReq struct { Name string `json:"name"` ID string `json:"id"` @@ -584,10 +607,17 @@ func (app *appContext) GetInvites(gc *gin.Context) { invites = append(invites, invite) } profiles := make([]string, len(app.storage.profiles)) - i := 0 - for p := range app.storage.profiles { - profiles[i] = p - i++ + if len(app.storage.profiles) != 0 { + profiles[0] = app.storage.defaultProfile + i := 1 + if len(app.storage.profiles) > 1 { + for p := range app.storage.profiles { + if p != app.storage.defaultProfile { + profiles[i] = p + i++ + } + } + } } resp := map[string]interface{}{ "profiles": profiles, diff --git a/config/config-base.json b/config/config-base.json index d2b568b..6d2baa1 100644 --- a/config/config-base.json +++ b/config/config-base.json @@ -608,7 +608,7 @@ "requires_restart": true, "type": "text", "value": "", - "description": "Location of stored user policy template (json)." + "description": "Deprecated. Location of stored user policy template (json)." }, "user_configuration": { "name": "userConfiguration", @@ -616,7 +616,7 @@ "requires_restart": true, "type": "text", "value": "", - "description": "Location of stored user configuration template (used for setting homescreen layout) (json)" + "description": "Deprecated. Location of stored user configuration template (used for setting homescreen layout) (json)" }, "user_displayprefs": { "name": "displayPreferences", @@ -624,7 +624,7 @@ "requires_restart": true, "type": "text", "value": "", - "description": "Location of stored displayPreferences template (also used for homescreen layout) (json)" + "description": "Deprecated. Location of stored displayPreferences template (also used for homescreen layout) (json)" }, "user_profiles": { "name": "User Profiles", @@ -632,7 +632,7 @@ "requires_restart": true, "type": "text", "value": "", - "description": "Location of stored user profiles (encompasses template and homescreen) (json)" + "description": "Location of stored user profiles (encompasses template and configuration and displayprefs) (json)" }, "custom_css": { "name": "Custom CSS", diff --git a/data/templates/admin.html b/data/templates/admin.html index b5df83c..531e08b 100644 --- a/data/templates/admin.html +++ b/data/templates/admin.html @@ -441,6 +441,7 @@ Name + Default From Admin? Libraries diff --git a/main.go b/main.go index da387ef..b80ccad 100644 --- a/main.go +++ b/main.go @@ -460,6 +460,7 @@ func start(asDaemon, firstCall bool) { api.GET("/getInvites", app.GetInvites) api.GET("/getProfiles", app.GetProfiles) api.POST("/setProfile", app.SetProfile) + api.POST("/setDefaultProfile", app.SetDefaultProfile) api.POST("/createProfile", app.CreateProfile) api.POST("/deleteProfile", app.DeleteProfile) api.POST("/setNotify", app.SetNotify) diff --git a/storage.go b/storage.go index c6772a9..f03671f 100644 --- a/storage.go +++ b/storage.go @@ -12,6 +12,7 @@ type Storage struct { invite_path, emails_path, policy_path, configuration_path, displayprefs_path, ombi_path, profiles_path string invites Invites profiles map[string]Profile + defaultProfile string emails, policy, configuration, displayprefs, ombi_template map[string]interface{} } @@ -24,6 +25,7 @@ type Profile struct { Policy map[string]interface{} `json:"policy,omitempty"` Configuration map[string]interface{} `json:"configuration,omitempty"` Displayprefs map[string]interface{} `json:"displayprefs,omitempty"` + Default bool `json:"default,omitempty"` } type Invite struct { @@ -90,6 +92,9 @@ func (st *Storage) storeOmbiTemplate() error { func (st *Storage) loadProfiles() error { err := loadJSON(st.profiles_path, &st.profiles) for name, profile := range st.profiles { + if profile.Default { + st.defaultProfile = name + } change := false if profile.Policy["IsAdministrator"] != nil { profile.Admin = profile.Policy["IsAdministrator"].(bool) @@ -112,8 +117,10 @@ func (st *Storage) loadProfiles() error { st.profiles[name] = profile } } - if err != nil { - panic(err) + if st.defaultProfile == "" { + for n := range st.profiles { + st.defaultProfile = n + } } return err } diff --git a/ts/settings.ts b/ts/settings.ts index ebd991e..3908994 100644 --- a/ts/settings.ts +++ b/ts/settings.ts @@ -143,10 +143,12 @@ const populateProfiles = (noTable?: boolean): void => _get("/getProfiles", null, if (this.readyState == 4 && this.status == 200) { const profileList = document.getElementById('profileList'); profileList.textContent = ''; - availableProfiles = []; + availableProfiles = [this.response["default_profile"]]; for (let name in this.response) { - availableProfiles.push(name); - if (!noTable) { + if (name != availableProfiles[0]) { + availableProfiles.push(name); + } + if (!noTable && name != "default_profile") { const profile: Profile = { Admin: this.response[name]["admin"], LibraryAccess: this.response[name]["libraries"], @@ -154,16 +156,28 @@ const populateProfiles = (noTable?: boolean): void => _get("/getProfiles", null, }; profileList.innerHTML += ` ${name} + ${profile.FromUser} ${profile.Admin ? "Yes" : "No"} ${profile.LibraryAccess} - + `; } } } }); +const setDefaultProfile = (name: string): void => _post("/setDefaultProfile", { "name": name }, function (): void { + if (this.readyState == 4) { + if (this.status != 200) { + (document.getElementById(`defaultProfile_${availableProfiles[0]}`) as HTMLInputElement).checked = true; + (document.getElementById(`defaultProfile_${name}`) as HTMLInputElement).checked = false; + } else { + generateInvites(); + } + } +}); + const deleteProfile = (name: string): void => _post("/deleteProfile", { "name": name }, function (): void { if (this.readyState == 4 && this.status == 200) { populateProfiles(); @@ -224,10 +238,11 @@ function storeProfile(): void { addAttr(button, "btn-primary"); rmAttr(button, "btn-success"); button.disabled = false; - populateProfiles(); userDefaultsModal.hide(); }, 1000); + populateProfiles(); + generateInvites(); } else { if ("error" in this.response) { button.textContent = this.response["error"];