Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
./TraefikAccessControl
/TraefikAccessControl
*.db
tac_data.json
5 changes: 5 additions & 0 deletions static/js/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

const createBearerButton = document.getElementById("bearerCreateButton");
createBearerButton.onclick = onCreateBearer;

const createBearerButtonMobile = document.getElementById("bearerCreateButtonMobile");
if (createBearerButtonMobile) {
createBearerButtonMobile.onclick = onCreateBearer;
}

function onDeleteBearer(event) {
event.preventDefault();
Expand Down
91 changes: 91 additions & 0 deletions static/style/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,92 @@ main {
.page-footer .container {
font-size: 0.9rem;
}

/* Make tables scrollable on mobile */
.table-wrapper {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
margin-bottom: 1.5rem;
}

table {
min-width: 100%;
font-size: 0.85rem;
}

table th, table td {
padding: 8px 5px;
}

/* Stack form inputs vertically on mobile */
.input-field {
margin-bottom: 1rem;
}

/* Make buttons full width on mobile */
.btn, button {
width: 100%;
margin-bottom: 0.5rem;
}

/* Adjust spacing for headings */
h1 {
font-size: 2rem;
}

h4 {
font-size: 1.5rem;
margin-top: 1.5rem;
}

/* Better spacing for icons in tables */
.material-icons {
font-size: 1.2rem;
}

/* Stack checkboxes and labels better on mobile */
label {
font-size: 0.9rem;
}

/* Improve password change section on mobile */
.change-password-wrapper {
display: flex;
flex-direction: column;
gap: 0.5rem;
}

.change-password-wrapper .input-field {
width: 100%;
}

.change-password-wrapper button {
width: 100%;
}

/* Allow long tokens to wrap on mobile */
table td {
word-break: break-all;
overflow-wrap: break-word;
}

/* Ensure proper spacing for checkbox labels */
[type="checkbox"]+span {
padding-left: 30px;
font-size: 0.9rem;
}

/* Better button spacing on mobile */
.row {
margin-bottom: 10px;
}

/* Ensure inputs don't overflow */
input[type="text"],
input[type="password"],
select {
font-size: 1rem;
}
}

.page-footer {
Expand All @@ -53,6 +139,11 @@ main {
position: relative;
}

/* Ensure select dropdowns are properly styled */
select {
display: block;
}

#infoCard {
-webkit-animation: fadeOut 1.5s forwards;
-webkit-animation-iteration-count: 1;
Expand Down
217 changes: 120 additions & 97 deletions templates/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,107 +6,130 @@ <h1 class="header center orange-text">{{.title}}</h1>

<div>
<h4 class="orange-text">All users:</h4>
<table class="responsive-table striped">
<thead>
<tr>
<th>Username</th>
<th class="right-align">Is Admin</th>
<th class="right-align">Delete</th>
</tr>
</thead>
<tbody>
{{range .users}}
<tr>
<td>{{.Username}}</td>
<td class="right-align">
{{if .IsAdmin}}
<i class="material-icons">done</i>
{{else}}
<i class="material-icons">clear</i>
{{end}}
</td>
<td class="right-align"><a class="userDeleteButton" href="#"><i data-userid={{.ID}}
class="material-icons">delete_forever</i></a></td>
</tr>
{{end}}
<tr>
<td><input type="text" id="userNameField" placeholder="Username"><input type="password"
id="userPasswordField" placeholder="Password"></td>
<td class="right-align"><label><input type="checkbox" class="filled-in"
id="userAdminField" /><span></span></label></td>
<td>
<button class="btn waves-effect waves-light right" id="userCreateButton">
Create New
<i class="material-icons right">add</i>
</button>
</td>
</tr>
</tbody>
</table>
<div class="table-wrapper">
<table class="responsive-table striped">
<thead>
<tr>
<th>Username</th>
<th class="right-align">Is Admin</th>
<th class="right-align">Delete</th>
</tr>
</thead>
<tbody>
{{range .users}}
<tr>
<td>{{.Username}}</td>
<td class="right-align">
{{if .IsAdmin}}
<i class="material-icons">done</i>
{{else}}
<i class="material-icons">clear</i>
{{end}}
</td>
<td class="right-align"><a class="userDeleteButton" href="#"><i data-userid={{.ID}}
class="material-icons">delete_forever</i></a></td>
</tr>
{{end}}
</tbody>
</table>
</div>
<div class="row" style="margin-top: 1rem;">
<div class="input-field col s12">
<input type="text" id="userNameField" placeholder="Username">
</div>
<div class="input-field col s12">
<input type="password" id="userPasswordField" placeholder="Password">
</div>
<div class="col s12 m6">
<label>
<input type="checkbox" class="filled-in" id="userAdminField" />
<span>Is Admin</span>
</label>
</div>
<div class="col s12 m6">
<button class="btn waves-effect waves-light" id="userCreateButton" style="width: 100%;">
Create New User
<i class="material-icons right">add</i>
</button>
</div>
</div>
</div>

<div>
<h4 class="orange-text">All sites:</h4>
<table class="responsive-table striped">
<thead>
<tr>
<th>Host</th>
<th>Path-Prefix</th>
<th class="right-align">Prompt Basic Auth</th>
<th class="right-align">Anonymous Access</th>
<th class="right-align">Config OK</th>
<th class="right-align">Edit</th>
<th class="right-align">Delete</th>
</tr>
</thead>
<tbody>
{{range .sites}}
<tr>
<td>{{.Host}}</td>
<td>{{.PathPrefix}}</td>
<td class="right-align">
{{if .PromptBasicAuth}}
<i class="material-icons">done</i>
{{else}}
<i class="material-icons">clear</i>
{{end}}
</td>
<td class="right-align">
{{if .AnonymousAccess}}
<i class="material-icons">done</i>
{{else}}
<i class="material-icons">clear</i>
{{end}}
</td>
<td class="right-align">
{{if .ConfigOK}}
<i class="material-icons">done</i>
{{else}}
<i class="material-icons">clear</i>
{{end}}
</td>
<td class="right-align"><a href="/site/{{.ID}}"><i class="material-icons">edit</i></a></td>
<td class="right-align"><a class="siteDeleteButton" href="#"><i data-siteid={{.ID}}
class="material-icons">delete_forever</i></a></td>
</tr>
{{end}}
<tr>
<td><input type="text" id="siteHostField" placeholder="Host"></td>
<td><input type="text" id="sitePathPrefixField" placeholder="Path-Prefix"></td>
<td class="right-align"><label><input type="checkbox" class="filled-in"
id="sitePromptBasicAuthField" /><span></span></label></td>
<td class="right-align"><label><input type="checkbox" class="filled-in"
id="siteAnonymousAccessField" /><span></span></label></td>
<td></td>
<td colspan="2">
<button class="btn waves-effect waves-light right" id="siteCreateButton">
Create New
<i class="material-icons right">add</i>
</button>
</td>
</tr>
</tbody>
</table>
<div class="table-wrapper">
<table class="responsive-table striped">
<thead>
<tr>
<th>Host</th>
<th>Path-Prefix</th>
<th class="right-align">Prompt Basic Auth</th>
<th class="right-align">Anonymous Access</th>
<th class="right-align">Config OK</th>
<th class="right-align">Edit</th>
<th class="right-align">Delete</th>
</tr>
</thead>
<tbody>
{{range .sites}}
<tr>
<td>{{.Host}}</td>
<td>{{.PathPrefix}}</td>
<td class="right-align">
{{if .PromptBasicAuth}}
<i class="material-icons">done</i>
{{else}}
<i class="material-icons">clear</i>
{{end}}
</td>
<td class="right-align">
{{if .AnonymousAccess}}
<i class="material-icons">done</i>
{{else}}
<i class="material-icons">clear</i>
{{end}}
</td>
<td class="right-align">
{{if .ConfigOK}}
<i class="material-icons">done</i>
{{else}}
<i class="material-icons">clear</i>
{{end}}
</td>
<td class="right-align"><a href="/site/{{.ID}}"><i class="material-icons">edit</i></a></td>
<td class="right-align"><a class="siteDeleteButton" href="#"><i data-siteid={{.ID}}
class="material-icons">delete_forever</i></a></td>
</tr>
{{end}}
</tbody>
</table>
</div>
<div class="row" style="margin-top: 1rem;">
<div class="input-field col s12 m6">
<input type="text" id="siteHostField" placeholder="Host">
</div>
<div class="input-field col s12 m6">
<input type="text" id="sitePathPrefixField" placeholder="Path-Prefix">
</div>
<div class="col s6 m3">
<label>
<input type="checkbox" class="filled-in" id="sitePromptBasicAuthField" />
<span>Prompt Basic Auth</span>
</label>
</div>
<div class="col s6 m3">
<label>
<input type="checkbox" class="filled-in" id="siteAnonymousAccessField" />
<span>Anonymous Access</span>
</label>
</div>
<div class="col s12 m6">
<button class="btn waves-effect waves-light" id="siteCreateButton" style="width: 100%;">
Create New Site
<i class="material-icons right">add</i>
</button>
</div>
</div>
<p>
If the config for a site is not OK, most probably the Traefik configuration is not set properly.
More information about this can be found in the <a
Expand Down
Loading