memberships: modal for errors (#133)
* unpolished version of error modal rendering
* rework of html files. template implemented
* new html files
* minor fixes.
* minor fixes
* title changes
diff --git a/core/auth/memberships/.gitignore b/core/auth/memberships/.gitignore
index 6ce208d..fd1862e 100644
--- a/core/auth/memberships/.gitignore
+++ b/core/auth/memberships/.gitignore
@@ -1,2 +1,3 @@
*.db
memberships*
+!memberships-tmpl/
\ No newline at end of file
diff --git a/core/auth/memberships/main.go b/core/auth/memberships/main.go
index f8f2cff..7cb7538 100644
--- a/core/auth/memberships/main.go
+++ b/core/auth/memberships/main.go
@@ -9,6 +9,7 @@
"html/template"
"log"
"net/http"
+ "net/url"
"regexp"
"strings"
@@ -23,11 +24,8 @@
var apiPort = flag.Int("api-port", 8081, "Port to listen on for API requests")
var dbPath = flag.String("db-path", "memberships.db", "Path to SQLite file")
-//go:embed index.html
-var indexHTML string
-
-//go:embed group.html
-var groupHTML string
+//go:embed memberships-tmpl/*
+var tmpls embed.FS
//go:embed static
var staticResources embed.FS
@@ -563,6 +561,34 @@
return true, nil
}
+type templates struct {
+ group *template.Template
+ user *template.Template
+}
+
+func parseTemplates(fs embed.FS) (templates, error) {
+ base, err := template.ParseFS(fs, "memberships-tmpl/base.html")
+ if err != nil {
+ return templates{}, err
+ }
+ parse := func(path string) (*template.Template, error) {
+ if b, err := base.Clone(); err != nil {
+ return nil, err
+ } else {
+ return b.ParseFS(fs, path)
+ }
+ }
+ user, err := parse("memberships-tmpl/user.html")
+ if err != nil {
+ return templates{}, err
+ }
+ group, err := parse("memberships-tmpl/group.html")
+ if err != nil {
+ return templates{}, err
+ }
+ return templates{group, user}, nil
+}
+
func (s *Server) homePageHandler(w http.ResponseWriter, r *http.Request) {
loggedInUser, err := getLoggedInUser(r)
if err != nil {
@@ -578,6 +604,7 @@
http.Error(w, "User Not Logged In", http.StatusUnauthorized)
return
}
+ errorMsg := r.URL.Query().Get("errorMessage")
vars := mux.Vars(r)
user := strings.ToLower(vars["username"])
// TODO(dtabidze): should check if username exists or not.
@@ -592,11 +619,6 @@
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- tmpl, err := template.New("index").Parse(indexHTML)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
transitiveGroups, err := s.store.GetAllTransitiveGroupsForUser(user)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -608,15 +630,23 @@
TransitiveGroups []Group
LoggedInUserPage bool
CurrentUser string
+ ErrorMessage string
+ AdditionalCSS bool
}{
OwnerGroups: ownerGroups,
MembershipGroups: membershipGroups,
TransitiveGroups: transitiveGroups,
LoggedInUserPage: loggedInUserPage,
CurrentUser: user,
+ ErrorMessage: errorMsg,
+ AdditionalCSS: false,
}
- w.Header().Set("Content-Type", "text/html")
- if err := tmpl.Execute(w, data); err != nil {
+ templates, err := parseTemplates(tmpls)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ if err := templates.user.Execute(w, data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@@ -639,12 +669,16 @@
var group Group
group.Name = r.PostFormValue("group-name")
if err := isValidGroupName(group.Name); err != nil {
- http.Error(w, err.Error(), http.StatusBadRequest)
+ // http.Error(w, err.Error(), http.StatusBadRequest)
+ redirectURL := fmt.Sprintf("/user/%s?errorMessage=%s", loggedInUser, url.QueryEscape(err.Error()))
+ http.Redirect(w, r, redirectURL, http.StatusFound)
return
}
group.Description = r.PostFormValue("description")
if err := s.store.CreateGroup(loggedInUser, group); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ // http.Error(w, err.Error(), http.StatusInternalServerError)
+ redirectURL := fmt.Sprintf("/user/%s?errorMessage=%s", loggedInUser, url.QueryEscape(err.Error()))
+ http.Redirect(w, r, redirectURL, http.StatusFound)
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
@@ -656,6 +690,7 @@
http.Error(w, "User Not Logged In", http.StatusUnauthorized)
return
}
+ errorMsg := r.URL.Query().Get("errorMessage")
vars := mux.Vars(r)
groupName := vars["group-name"]
exists, err := s.store.DoesGroupExist(groupName)
@@ -664,11 +699,11 @@
return
}
if !exists {
- errorMsg := fmt.Sprintf("group with the name '%s' not found", groupName)
+ errorMsg = fmt.Sprintf("group with the name '%s' not found", groupName)
http.Error(w, errorMsg, http.StatusNotFound)
return
}
- tmpl, err := template.New("group").Parse(groupHTML)
+ // tmpl, err := template.New("group").Parse(groupHTML)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -711,6 +746,7 @@
AvailableGroups []string
TransitiveGroups []Group
ChildGroups []Group
+ ErrorMessage string
}{
GroupName: groupName,
Description: description,
@@ -719,8 +755,14 @@
AvailableGroups: availableGroups,
TransitiveGroups: transitiveGroups,
ChildGroups: childGroups,
+ ErrorMessage: errorMsg,
}
- if err := tmpl.Execute(w, data); err != nil {
+ templates, err := parseTemplates(tmpls)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ if err := templates.group.Execute(w, data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@@ -750,7 +792,8 @@
}
err := s.store.RemoveFromGroupToGroup(parentGroup, childGroup)
if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ redirectURL := fmt.Sprintf("/group/%s?errorMessage=%s", parentGroup, url.QueryEscape(err.Error()))
+ http.Redirect(w, r, redirectURL, http.StatusFound)
return
}
http.Redirect(w, r, "/group/"+parentGroup, http.StatusSeeOther)
@@ -778,7 +821,8 @@
}
err := s.store.RemoveUserFromTable(username, groupName, tableName)
if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ redirectURL := fmt.Sprintf("/group/%s?errorMessage=%s", groupName, url.QueryEscape(err.Error()))
+ http.Redirect(w, r, redirectURL, http.StatusFound)
return
}
http.Redirect(w, r, "/group/"+groupName, http.StatusSeeOther)
@@ -806,7 +850,8 @@
}
err := s.store.RemoveUserFromTable(username, groupName, tableName)
if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ redirectURL := fmt.Sprintf("/group/%s?errorMessage=%s", groupName, url.QueryEscape(err.Error()))
+ http.Redirect(w, r, redirectURL, http.StatusFound)
return
}
http.Redirect(w, r, "/group/"+groupName, http.StatusSeeOther)
@@ -853,7 +898,8 @@
return
}
if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ redirectURL := fmt.Sprintf("/group/%s?errorMessage=%s", groupName, url.QueryEscape(err.Error()))
+ http.Redirect(w, r, redirectURL, http.StatusFound)
return
}
http.Redirect(w, r, "/group/"+groupName, http.StatusSeeOther)
@@ -886,7 +932,8 @@
return
}
if err := s.store.AddChildGroup(parentGroup, childGroup); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ redirectURL := fmt.Sprintf("/group/%s?errorMessage=%s", parentGroup, url.QueryEscape(err.Error()))
+ http.Redirect(w, r, redirectURL, http.StatusFound)
return
}
http.Redirect(w, r, "/group/"+parentGroup, http.StatusSeeOther)
diff --git a/core/auth/memberships/memberships-tmpl/base.html b/core/auth/memberships/memberships-tmpl/base.html
new file mode 100644
index 0000000..39a7755
--- /dev/null
+++ b/core/auth/memberships/memberships-tmpl/base.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en" data-theme="light">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>{{ block "title" . }}{{ end }}</title>
+ <link rel="stylesheet" href="/static/pico.2.0.6.min.css">
+ <link rel="stylesheet" href="/static/main.css">
+</head>
+<body class="container">
+ {{- block "content" . }}
+ {{- end }}
+ {{ if ne .ErrorMessage "" }}
+ <dialog id="error-message" open>
+ <article>
+ <h2>Error</h2>
+ <p id="error-message-content">{{ .ErrorMessage }}</p>
+ <footer>
+ <button id="error-cancel-button" class="secondary error-cancel-button">Close</button>
+ </footer>
+ </article>
+ </dialog>
+ {{ end }}
+ <script src="/static/main.js"></script>
+</body>
+</html>
diff --git a/core/auth/memberships/group.html b/core/auth/memberships/memberships-tmpl/group.html
similarity index 89%
rename from core/auth/memberships/group.html
rename to core/auth/memberships/memberships-tmpl/group.html
index 42a2e38..2f5c89a 100644
--- a/core/auth/memberships/group.html
+++ b/core/auth/memberships/memberships-tmpl/group.html
@@ -1,14 +1,8 @@
-<!DOCTYPE html>
-<html lang="en" data-theme="light">
-<head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Group Membership Managment</title>
- <link rel="stylesheet" href="/static/pico.2.0.6.min.css">
- <link rel="stylesheet" href="/static/main.css">
-</head>
-<body class="container">
- {{- $parentGroupName := .GroupName }}
+{{ define "title" }}
+ Group - {{ .GroupName }}
+{{ end }}
+{{ define "content" }}
+{{- $parentGroupName := .GroupName }}
<div>
<h2 class="headline">{{ .GroupName }} Group Management</h2>
<p class="description">{{ .Description }}</p>
@@ -110,6 +104,4 @@
</footer>
</article>
</dialog>
- <script src="/static/main.js"></script>
-</body>
-</html>
+{{ end }}
diff --git a/core/auth/memberships/index.html b/core/auth/memberships/memberships-tmpl/user.html
similarity index 81%
rename from core/auth/memberships/index.html
rename to core/auth/memberships/memberships-tmpl/user.html
index cd3cf50..53a89be 100644
--- a/core/auth/memberships/index.html
+++ b/core/auth/memberships/memberships-tmpl/user.html
@@ -1,12 +1,7 @@
-<!DOCTYPE html>
-<html lang="en" data-theme="light">
-<head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Group Managment</title>
- <link rel="stylesheet" href="/static/pico.2.0.6.min.css">
-</head>
-<body class="container">
+{{ define "title" }}
+ User - {{ .CurrentUser }}
+{{ end }}
+{{- define "content" -}}
<h1>User: {{ .CurrentUser }}</h1>
{{ if .LoggedInUserPage }}
<form action="/create-group" method="post">
@@ -56,5 +51,4 @@
</tr>
{{- end -}}
</table>
-</body>
-</html>
+{{- end }}
diff --git a/core/auth/memberships/static/main.js b/core/auth/memberships/static/main.js
index e4ea2ca..52dd1d8 100644
--- a/core/auth/memberships/static/main.js
+++ b/core/auth/memberships/static/main.js
@@ -45,3 +45,11 @@
});
});
});
+
+document.addEventListener("DOMContentLoaded", function () {
+ var errorCancelButton = document.getElementById("error-cancel-button");
+ var errorMessageDialog = document.getElementById("error-message");
+ errorCancelButton.addEventListener("click", function () {
+ errorMessageDialog.close();
+ });
+});