Better UI for admin settings (#30)

This commit is contained in:
Thomas Miceli 2023-05-11 15:16:05 +02:00 committed by GitHub
parent 089d321898
commit 5fe84164a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 33 deletions

View file

@ -185,6 +185,14 @@ func adminSyncReposFromDB(ctx echo.Context) error {
return redirect(ctx, "/admin-panel")
}
func adminSettings(ctx echo.Context) error {
setData(ctx, "title", "Admin Settings")
setData(ctx, "htmlTitle", "Admin Settings - Admin panel")
setData(ctx, "adminHeaderPage", "settings")
return html(ctx, "admin_settings.html")
}
func adminSetSetting(ctx echo.Context) error {
key := ctx.FormValue("key")
value := ctx.FormValue("value")

View file

@ -188,6 +188,7 @@ func Start() {
g2.POST("/gists/:gist/delete", adminGistDelete)
g2.POST("/sync-fs", adminSyncReposFromFS)
g2.POST("/sync-db", adminSyncReposFromDB)
g2.GET("/settings", adminSettings)
g2.PUT("/set-setting", adminSetSetting)
}

View file

@ -1,7 +1,10 @@
document.addEventListener('DOMContentLoaded', () => {
registerDomSetting(document.getElementById('disable-signup') as HTMLInputElement);
registerDomSetting(document.getElementById('require-login') as HTMLInputElement);
registerDomSetting(document.getElementById('disable-login-form') as HTMLInputElement);
let elems = Array.from(document.getElementsByClassName("toggle-button"));
for (let elem of elems) {
elem.addEventListener('click', () => {
registerDomSetting(elem as HTMLElement)
})
}
});
const setSetting = (key: string, value: string) => {
@ -9,16 +12,21 @@ const setSetting = (key: string, value: string) => {
data.append('key', key);
data.append('value', value);
data.append('_csrf', ((document.getElementsByName('_csrf')[0] as HTMLInputElement).value));
fetch('/admin-panel/set-setting', {
return fetch('/admin-panel/set-setting', {
method: 'PUT',
credentials: 'same-origin',
body: data,
});
};
const registerDomSetting = (el: HTMLInputElement) => {
el.addEventListener('change', () => {
setSetting(el.id, el.checked ? '1' : '0');
});
const registerDomSetting = (el: HTMLElement) => {
// @ts-ignore
el.dataset["bool"] = !(el.dataset["bool"] === 'true');
setSetting(el.id, el.dataset["bool"] === 'true' ? '1' : '0')
.then(() => {
el.classList.toggle("bg-primary-600");
el.classList.toggle("bg-gray-400");
(el.childNodes.item(1) as HTMLElement).classList.toggle("translate-x-5");
});
};

View file

@ -15,6 +15,8 @@
{{ else }} text-gray-400 hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md {{ end }}" aria-current="page">Users</a>
<a href="/admin-panel/gists" class="{{ if eq .adminHeaderPage "gists" }}bg-gray-700 text-slate-300 hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md
{{ else }} text-gray-400 hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md {{ end }}" aria-current="page">Gists</a>
<a href="/admin-panel/settings" class="{{ if eq .adminHeaderPage "settings" }}bg-gray-700 text-slate-300 hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md
{{ else }} text-gray-400 hover:text-slate-300 px-3 py-2 font-medium text-sm rounded-md {{ end }}" aria-current="page">Admin settings</a>
</nav>
</div>
</div>

View file

@ -71,32 +71,7 @@
</div>
</div>
</div>
<div class="sm:overflow-hidden ">
<div class="space-y-2 bg-gray-800 py-6 px-6 rounded-md border border-gray-700">
<div>
<span class="text-base font-bold leading-6 text-slate-300">Settings</span>
</div>
{{ .csrfHtml }}
<div class="space-y-2">
<div>
<label for="disable-signup" class="text-sm text-slate-300">Disable signup</label>
<input type="checkbox" id="disable-signup" name="disable-signup" {{ if .DisableSignup }}checked="checked"{{ end }} class="ml-1 h-4 w-4 rounded border-gray-300 text-primary-600 focus:ring-primary-600" />
</div>
<div>
<label for="require-login" class="text-sm text-slate-300">Require login</label>
<input type="checkbox" id="require-login" name="require-login" {{ if .RequireLogin }}checked="checked"{{ end }} class="ml-1 h-4 w-4 rounded border-gray-300 text-primary-600 focus:ring-primary-600" />
</div>
<div>
<label for="disable-login-form" class="text-sm text-slate-300">Disable login form</label>
<input type="checkbox" id="disable-login-form" name="disable-login-form" {{ if .DisableLoginForm }}checked="checked"{{ end }} class="ml-1 h-4 w-4 rounded border-gray-300 text-primary-600 focus:ring-primary-600" />
</div>
</div>
</div>
</div>
</div>
<script type="module" src="{{ asset "admin.ts" }}"></script>
{{ template "admin_footer" .}}
{{ template "footer" .}}

47
templates/pages/admin_settings.html vendored Normal file
View file

@ -0,0 +1,47 @@
{{ template "header" .}}
{{ template "admin_header" .}}
<div class="mx-auto max-w-lg px-4 py-2 sm:px-6 bg-gray-800 rounded-md border border-gray-700">
<ul role="list" class="divide-y divide-gray-100">
<li class="list-none gap-x-4 py-5">
<div class="flex items-center justify-between">
<span class="flex flex-grow flex-col">
<span class="text-sm font-medium leading-6 text-slate-300">Disable signup</span>
<span class="text-sm text-gray-400">Forbid the creation of new accounts.</span>
</span>
<button type="button" id="disable-signup" data-bool="{{ .DisableSignup }}" class="toggle-button {{ if .DisableSignup }}bg-primary-600{{else}}bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
<span aria-hidden="true" class="{{ if .DisableSignup }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
</button>
</div>
</li>
<li class="list-none gap-x-4 py-5">
<div class="flex items-center justify-between">
<span class="flex flex-grow flex-col">
<span class="text-sm font-medium leading-6 text-slate-300">Require login</span>
<span class="text-sm text-gray-400">Enforce users to be logged in to see gists.</span>
</span>
<button type="button" id="require-login" data-bool="{{ .RequireLogin }}" class="toggle-button {{ if .RequireLogin }}bg-primary-600{{else}}bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
<span aria-hidden="true" class="{{ if .RequireLogin }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
</button>
</div>
</li>
<li class="list-none gap-x-4 py-5">
<div class="flex items-center justify-between">
<span class="flex flex-grow flex-col">
<span class="text-sm font-medium leading-6 text-slate-300">Disable login form</span>
<span class="text-sm text-gray-400">Forbid logging in via the login form to force using OAuth providers instead.</span>
</span>
<button type="button" id="disable-login-form" data-bool="{{ .DisableLoginForm }}" class="toggle-button {{ if .DisableLoginForm }}bg-primary-600{{else}}bg-gray-400{{end}} relative inline-flex h-6 w-11 ml-4 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description">
<span aria-hidden="true" class="{{ if .DisableLoginForm }}translate-x-5{{else}}translate-x-0{{end}} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
</button>
</div>
</li>
</ul>
{{ .csrfHtml }}
</div>
<script type="module" src="{{ asset "admin.ts" }}"></script>
{{ template "admin_footer" .}}
{{ template "footer" .}}