mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-06 16:32:31 +01:00
feature (plg_authenticate_local): revamp UX of the auth plugin
This commit is contained in:
parent
8076de59b3
commit
d4f5cb9ecf
3 changed files with 63 additions and 61 deletions
|
|
@ -35,16 +35,13 @@ func (this SimpleAuth) Setup() Form {
|
||||||
{
|
{
|
||||||
Name: "banner",
|
Name: "banner",
|
||||||
Type: "hidden",
|
Type: "hidden",
|
||||||
Description: fmt.Sprintf(`Manage your team members and their account permissions by visiting [/admin/simple-user-management](/admin/simple-user-management).
|
Description: fmt.Sprintf(`<pre>MANAGEMENT GUI: <a href="/admin/simple-user-management">/admin/simple-user-management</a>
|
||||||
<pre>
|
|
||||||
STATS:
|
STATS:
|
||||||
┌─────────────┐ ┌──────────────┐
|
┌─────────────┐ ┌──────────────┐
|
||||||
│ TOTAL USERS │ │ ACTIVE USERS │
|
│ TOTAL USERS │ │ ACTIVE USERS │
|
||||||
| %.4d │ | %.4d │
|
| %.4d │ | %.4d │
|
||||||
└─────────────┘ └──────────────┘
|
└─────────────┘ └──────────────┘
|
||||||
|
EMAIL SERVER: %t
|
||||||
MANAGEMENT GUI: <a href="/admin/simple-user-management">/admin/simple-user-management</a>
|
|
||||||
EMAIL SERVER : %t
|
|
||||||
</pre>`, nUsers, aUsers, isEmailSetup()),
|
</pre>`, nUsers, aUsers, isEmailSetup()),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
|
|
||||||
. "github.com/mickael-kerjean/filestash/server/common"
|
. "github.com/mickael-kerjean/filestash/server/common"
|
||||||
)
|
)
|
||||||
|
|
@ -67,20 +66,15 @@ func UserManagementHandler(ctx *App, res http.ResponseWriter, req *http.Request)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
referer := ""
|
|
||||||
if u, err := url.Parse(req.Header.Get("referer")); err == nil {
|
|
||||||
referer = u.Path
|
|
||||||
}
|
|
||||||
template.
|
template.
|
||||||
Must(template.New("app").Parse(Page(PAGE))).
|
Must(template.New("app").Parse(Page(PAGE))).
|
||||||
Execute(res, struct {
|
Execute(res, struct {
|
||||||
Users []User
|
Users []User
|
||||||
CurrentUser User
|
CurrentUser User
|
||||||
Referer string
|
BackURL string
|
||||||
}{
|
}{
|
||||||
Users: users,
|
Users: users,
|
||||||
CurrentUser: currentUser,
|
CurrentUser: currentUser,
|
||||||
Referer: referer,
|
BackURL: WithBase("/admin/backend"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,89 +1,91 @@
|
||||||
<style>
|
<style>
|
||||||
html { height: initial; }
|
html { height: initial; }
|
||||||
body { max-width: 800px; margin: 0 auto; text-align: left; padding-left: 10px; padding-right: 10px; }
|
body { max-width: 800px; margin: 0 auto; text-align: left; padding-left: 10px; padding-right: 10px; color: #57595A; }
|
||||||
|
.common_response_page { max-width: inherit; padding: 0; }
|
||||||
|
header { background: white; padding: 100px 50px 75px; border-bottom: 1px solid #e2e2e2; }
|
||||||
|
main { max-width: 1000px; margin: auto; width: 99%; }
|
||||||
h1 { margin-top: 10px; margin-bottom: 0; font-size: 2.3rem; }
|
h1 { margin-top: 10px; margin-bottom: 0; font-size: 2.3rem; }
|
||||||
p { margin: 7px 0; }
|
p { margin: 7px 0; }
|
||||||
table { width: 100%; margin: 30px auto 50px auto; padding: 0; }
|
table { width: 100%; margin: 30px auto 50px auto; padding: 0; }
|
||||||
table .disabled td:not([onclick]) { text-decoration: line-through; }
|
table .disabled td:not([onclick]) { text-decoration: line-through; }
|
||||||
table td.action { color: white; background: rgba(0, 0, 0, 0.8); border-radius: 30px; font-weight: bold; font-size: 0.7rem; cursor: pointer; }
|
table td.action { color: white; background: rgba(0, 0, 0, 0.3); border-radius: 10px; font-weight: bold; font-size: 0.7rem; cursor: pointer; }
|
||||||
form { width: 100%; padding: 0; }
|
form { width: 100%; padding: 0; }
|
||||||
thead { background: rgba(0, 0, 0, 0.04); color: rgba(0, 0, 0, 0.6); font-weight: normal; }
|
|
||||||
tbody tr:hover { background: rgba(255, 255, 255, 0.7); }
|
tbody tr:hover { background: rgba(255, 255, 255, 0.7); }
|
||||||
th { font-weight: normal; }
|
th { font-weight: bold; font-size: 0.8rem; color: rgba(0, 0, 0, 0.5); text-transform: uppercase; }
|
||||||
th, td { padding: 5px 10px; }
|
th, td { padding: 10px 10px; }
|
||||||
input[disabled], .common_response_page button[disabled] { background: rgba(0,0,0,0.1); }
|
input[disabled] { background: #d2d2d2; }
|
||||||
dialog { border: none !important; border-radius: 10px; box-shadow: 0 0 #0000, 0 0 #0000, 0 25px 50px -12px rgba(0, 0, 0, 0.25); padding: 20px 40px 35px 40px; width: 450px; background: #f2f3f5; z-index: 5; }
|
.banner-empty { margin-top: 50px; font-size: 1.2rem; color: rgba(0, 0, 0, 0.5); text-align: center; }
|
||||||
|
button { text-transform: uppercase; background: #9AD1ED; }
|
||||||
|
dialog { position: absolute; inset: 0; border: none !important; border-radius: 5px; box-shadow: 0 0 #0000, 0 0 #0000, 0 25px 50px -12px rgba(0, 0, 0, 0.25); padding: 20px 40px 35px 40px; width: 450px; background: #505457; z-index: 5; color: white; }
|
||||||
dialog[open] { animation: dialogin 0.2s ease forwards; }
|
dialog[open] { animation: dialogin 0.2s ease forwards; }
|
||||||
dialog[open] ~ .backdrop { display: block; }
|
|
||||||
@keyframes dialogin{
|
@keyframes dialogin{
|
||||||
0%{ opacity:0; transform: translateY(5px); }
|
0%{ opacity:0; transform: translateY(5px); }
|
||||||
100%{ opacity:1; transform: translateY(0); }
|
100%{ opacity:1; transform: translateY(0); }
|
||||||
}
|
}
|
||||||
dialog h1 { padding: 0; margin: 5px 0 20px 0; }
|
dialog h1 { padding: 0; margin: 5px 0 20px 0; }
|
||||||
.backdrop { display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0,0,0,0.4); z-index: 2; }
|
|
||||||
.transparency { opacity: 0.8; }
|
|
||||||
.center { text-align: center; }
|
.center { text-align: center; }
|
||||||
.pointer { cursor: pointer; }
|
.pointer { cursor: pointer; }
|
||||||
.button__round { border: 1px solid #313538; display: inline-block; width: 25px; height: 25px; line-height: 25px; text-align: center; border-radius: 50%; padding: 2px; box-shadow: 2px 2px rgba(0, 0, 0, 0.2); }
|
.button__round { border: 1px solid #313538; display: inline-block; width: 30px; height: 30px; line-height: 30px; text-align: center; border-radius: 50%; padding: 2px; box-shadow: 2px 2px rgba(0, 0, 0, 0.2); }
|
||||||
.banner { background: rgba(0, 0, 0, 0.02); border: 2px dashed rgba(0, 0, 0, 0.05); padding: 50px 0; text-align: center; margin-top: 30px; font-size: 1.2rem; color: rgba(0, 0, 0, 0.3); }
|
dialog .button__round { border-color: white; box-shadow: none; }
|
||||||
h1 span.pointer { float: right; }
|
h1 span.pointer { float: right; }
|
||||||
#modal-close { transform: rotate(45deg); }
|
#modal-close { transform: rotate(45deg); }
|
||||||
#back { position: absolute; top: 10px; left: 10px; color: inherit; text-decoration: none; }
|
#back { position: absolute; top: 10px; left: 10px; color: inherit; text-decoration: none; }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<dialog {{ if ne .CurrentUser.Email "" }}open{{ end }}>
|
<dialog closedby="any">
|
||||||
<h1>
|
<h1>
|
||||||
{{ if eq .CurrentUser.Email "" }}User Creation{{ else }}User Update{{ end }}
|
{{ if eq .CurrentUser.Email "" }}User Creation{{ else }}User Update{{ end }}
|
||||||
<span id="modal-close" class="pointer button__round">+</span>
|
<span id="modal-close" class="pointer button__round">+</span>
|
||||||
</h1>
|
</h1>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="email" name="email" value="{{ .CurrentUser.Email }}" placeholder="Email" {{ if ne .CurrentUser.Email "" }}disabled{{ end }} />
|
<input type="email" name="email" value="{{ .CurrentUser.Email }}" placeholder="Email" {{ if ne .CurrentUser.Email "" }}disabled{{ end }} />
|
||||||
<input type="password" name="password" value="{{ .CurrentUser.Password }}" placeholder="Password" />
|
<input type="password" name="password" value="{{ .CurrentUser.Password }}" placeholder="Password" {{ if ne .CurrentUser.Email "" }}disabled{{ end }} />
|
||||||
<input type="text" name="role" value="{{ .CurrentUser.Role }}" placeholder="Role" />
|
<input type="text" name="role" value="{{ .CurrentUser.Role }}" placeholder="Role" />
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" name="disabled" {{ if eq .CurrentUser.Disabled true }}checked{{ end }}>
|
<input type="checkbox" name="disabled" {{ if eq .CurrentUser.Disabled true }}checked{{ end }}>
|
||||||
Block
|
Block
|
||||||
</label>
|
</label>
|
||||||
<button class="transparency">
|
<button>
|
||||||
{{ if eq .CurrentUser.Email "" }}Create{{ else }}Update{{ end }}
|
{{ if eq .CurrentUser.Email "" }}Create{{ else }}Update{{ end }}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
<div class="backdrop"></div>
|
|
||||||
|
|
||||||
<h1>User Management <span id="user-add" class="pointer button__round">+</span></h1>
|
<header>
|
||||||
<p class="transparency">Manage your team members and their account permissions here.</p>
|
<h1>User Management <span id="user-add" class="pointer button__round">+</span></h1>
|
||||||
|
<p>Manage your team members and their account permissions</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
{{ $length := len .Users }} {{ if eq $length 0 }}
|
<main>
|
||||||
<p class="banner">
|
{{ $length := len .Users }} {{ if eq $length 0 }}
|
||||||
There is not user yet, create one!
|
<p class="center banner-empty">
|
||||||
</p>
|
There is not user yet, create one!
|
||||||
{{ else }}
|
</p>
|
||||||
<table>
|
{{ else }}
|
||||||
<thead>
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
<th>Email</th>
|
<tr>
|
||||||
<th>Role</th>
|
<th>Email</th>
|
||||||
<th style="width:10px;"></th>
|
<th>Role</th>
|
||||||
<th style="width:10px;"></th>
|
<th style="width:10px;"></th>
|
||||||
</tr>
|
<th style="width:10px;"></th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody class="transparency">
|
</thead>
|
||||||
{{range $user := .Users }}
|
<tbody>
|
||||||
<tr class="{{ if eq $user.Disabled true }}disabled{{ end }}">
|
{{range $user := .Users }}
|
||||||
<td>{{ $user.Email }}</td>
|
<tr class="{{ if eq $user.Disabled true }}disabled{{ end }}">
|
||||||
<td>{{ $user.Role }}</td>
|
<td>{{ $user.Email }}</td>
|
||||||
<td class="center action" onclick="deleteItem('{{ $user.Email }}')">DEL</td>
|
<td>{{ $user.Role }}</td>
|
||||||
<td class="center action" onclick="updateItem('{{ $user.Email }}')">EDIT</td>
|
<td class="center action" onclick="deleteItem('{{ $user.Email }}')">DEL</td>
|
||||||
</tr>
|
<td class="center action" onclick="updateItem('{{ $user.Email }}')">EDIT</td>
|
||||||
{{end}}
|
</tr>
|
||||||
</tbody>
|
{{end}}
|
||||||
</table>
|
</tbody>
|
||||||
{{ end }}
|
</table>
|
||||||
|
{{ end }}
|
||||||
|
</main>
|
||||||
|
|
||||||
{{ if ne .Referer "" }}
|
<a href="{{ .BackURL }}" id="back">< back</a>
|
||||||
<a href="{{ .Referer }}" id="back" class="transparency">< back</a>
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
window.deleteItem = async (email) => {
|
window.deleteItem = async (email) => {
|
||||||
|
|
@ -108,12 +110,21 @@
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
const $dialog = document.querySelector("dialog");
|
const $dialog = document.querySelector("dialog");
|
||||||
|
|
||||||
|
// feature: click the add button
|
||||||
document.getElementById("user-add").onclick = () => $dialog.showModal();
|
document.getElementById("user-add").onclick = () => $dialog.showModal();
|
||||||
|
|
||||||
|
// feature: autoopen modal
|
||||||
|
if(new URLSearchParams(location.search).has("email")) {
|
||||||
|
$dialog.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// feature: modal close button
|
||||||
document.getElementById("modal-close").onclick = () => {
|
document.getElementById("modal-close").onclick = () => {
|
||||||
$dialog.close();
|
$dialog.close();
|
||||||
location.search = "";
|
location.search = "";
|
||||||
};
|
};
|
||||||
|
// feature: modal submit
|
||||||
document.querySelector("form").onsubmit = (e) => {
|
document.querySelector("form").onsubmit = (e) => {
|
||||||
e.target.querySelector("button").setAttribute("disabled", "true");
|
e.target.querySelector("button").setAttribute("disabled", "true");
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue