Skip to content

Commit

Permalink
Make invite links editable
Browse files Browse the repository at this point in the history
  • Loading branch information
foodelevator committed Aug 19, 2024
1 parent 8464a1b commit fb6df59
Show file tree
Hide file tree
Showing 8 changed files with 863 additions and 431 deletions.
33 changes: 33 additions & 0 deletions pkg/database/invite.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions pkg/database/sql/invite.sql
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ where id = $1;
update invites
set current_uses = current_uses + 1
where id = $1;

-- name: UpdateInvite :one
update invites
set name = $2, expires_at = $3, max_uses = $4
where id = $1
returning *;
3 changes: 3 additions & 0 deletions services/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ func NewService(db *database.Queries) (*service, error) {
http.Handle("DELETE /admin/oidc-clients/{id}", s.auth(httputil.Route(s.deleteOIDCClient)))

http.Handle("GET /admin/invites", s.auth(httputil.Route(s.invites)))
http.Handle("GET /admin/invites/{id}", s.auth(httputil.Route(s.invite)))
http.Handle("POST /admin/invites", s.auth(httputil.Route(s.createInvite)))
http.Handle("DELETE /admin/invites/{id}", s.auth(httputil.Route(s.deleteInvite)))
http.Handle("GET /admin/invites/{id}/edit", s.auth(httputil.Route(s.editInviteForm)))
http.Handle("PUT /admin/invites/{id}", s.auth(httputil.Route(s.updateInvite)))

return s, nil
}
Expand Down
115 changes: 24 additions & 91 deletions services/admin/admin.templ
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package admin

import (
"github.com/datasektionen/logout/pkg/config"
"github.com/datasektionen/logout/pkg/database"
"github.com/datasektionen/logout/pkg/templates"
"github.com/datasektionen/logout/services/static"
"strconv"
"time"
)

templ admin() {
Expand All @@ -31,6 +27,29 @@ templ oidcClients() {
}
}

templ page() {
@templates.Page() {
<nav
class="
w-full h-12 bg-gray-700 flex uppercase
[&>a:not(:first-child)]:flex [&>a]:items-center [&>a:not(:first-child)]:px-3 hover:[&>a]:bg-gray-600 [&>a]:transition-colors
"
>
<a href="/admin" class="h-full block aspect-square grid place-items-center fill-cerise-regular bg-gray-600">
@templ.Raw(static.PublicAsString("delta.svg"))
</a>
<a href="/admin/members">Members</a>
<a href="/admin/oidc-clients">OIDC Clients</a>
<a href="/admin/invites">Invites</a>
</nav>
<div class="flex justify-center min-h-[calc(100vh-3rem)]">
<main class="bg-gray-800 w-[1000px] md:max-w-[calc(100vw-8rem)]">
{ children... }
</main>
</div>
}
}

var input = `
border border-neutral-500 grow
outline-none focus:border-cerise-strong hover:border-cerise-light
Expand All @@ -48,91 +67,5 @@ var roundButton = `
grid place-items-center pointer
border border-transparent outline-none focus:border-cerise-strong hover:border-cerise-light relative
[&>img]:w-3/5 [&>img]:h-3/5 [&>img]:invert
[&>p]:text-center [&>p]:leading-none
`

templ invite(invite database.Invite) {
<li class="grid grid-cols-subgrid col-span-full odd:bg-white/5 p-1">
<p>{ invite.Name }</p>
<p>{ strconv.Itoa(int(invite.CurrentUses)) }</p>
<p>
if invite.MaxUses.Valid {
{ strconv.Itoa(int(invite.MaxUses.Int32)) }
}
</p>
<p>{ invite.CreatedAt.Time.Format(time.DateOnly) }</p>
<p>{ invite.ExpiresAt.Time.Format(time.DateOnly) }</p>
<div class="flex items-center gap-1">
<button
class={ roundButton }
hx-delete={ "/admin/invites/" + invite.ID.String() }
hx-target="closest li"
hx-swap="outerHTML"
><img src="/public/x.svg"/></button>
<button
class={ roundButton }
onclick={ templ.ComponentScript{Call: templ.SafeScript(
"navigator.clipboard.writeText",
config.Config.Origin.String()+"/invite/"+invite.ID.String(),
)} }
><img src="/public/clipboard.svg"/></button>
</div>
</li>
}

templ invites(invites []database.Invite) {
@page() {
<div class="p-8">
<ul class="grid grid-cols-6 p-2">
<li class="grid grid-cols-subgrid col-span-full border-b">
<p>Name</p>
<p>Uses</p>
<p>Max uses</p>
<p>Created at</p>
<p>Expires at</p>
<p></p>
</li>
for _, inv := range invites {
@invite(inv)
}
</ul>
<form
class="flex justify-center items-center gap-2 flex-wrap"
hx-post="/admin/invites"
hx-target="previous ul"
hx-swap="beforeend"
>
<div>
<label for="invite-name">Name:</label>
<input id="invite-name" required type="text" name="name" class={ input }/>
</div>
<div>
<label for="invite-expires-at">Expires at:</label>
<input id="invite-expires-at" required type="date" name="expires-at" class={ input }/>
</div>
<div>
<label for="invite-max-uses">Max uses:</label>
<input id="invite-max-uses" type="number" name="max-uses" class={ input }/>
</div>
<button class={ button }>Create</button>
</form>
</div>
}
}

templ page() {
@templates.Page() {
<nav class="w-full h-12 bg-gray-700 flex uppercase">
<div class="h-full aspect-square flex items-center grid place-items-center fill-cerise-regular bg-gray-600">
@templ.Raw(static.PublicAsString("delta.svg"))
</div>
<a class="flex items-center px-3 hover:bg-gray-600 transition-colors" href="/admin/members">Members</a>
<a class="flex items-center px-3 hover:bg-gray-600 transition-colors" href="/admin/oidc-clients">OIDC Clients</a>
<a class="flex items-center px-3 hover:bg-gray-600 transition-colors" href="/admin/invites">Invites</a>
</nav>
<div class="flex justify-center min-h-[calc(100vh-3rem)]">
<main class="bg-gray-800 w-[1000px] md:max-w-[calc(100vw-8rem)]">
{ children... }
</main>
</div>
}
}
Loading

0 comments on commit fb6df59

Please sign in to comment.