First pass at group profile pages. Part of #68.

This commit is contained in:
Nick Gerakines 2020-04-03 23:15:48 -04:00
parent 11e863e8d7
commit 04d1423670
No known key found for this signature in database
GPG Key ID: 33D43D854F96B2E4
9 changed files with 250 additions and 81 deletions

View File

@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by herr at 2020-04-03 22:14:36.2860856 -0400 EDT m=+0.009914079
// This file was generated by herr at 2020-04-03 22:46:50.892042017 -0400 EDT m=+0.007694263
package errors
import (

View File

@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by herr at 2020-04-03 22:14:36.316998079 -0400 EDT m=+0.040826470
// This file was generated by herr at 2020-04-03 22:46:50.924488758 -0400 EDT m=+0.040140977
package errors
import (

View File

@ -0,0 +1,83 @@
{{define "head"}}{{end}}
{{define "footer_script"}}{{end}}
{{define "content"}}
{{ $group := .group }}
{{ $groupActor := .group_actor }}
<div class="row pt-3">
<div class="col">
<h1>@{{ .group.Name }}@{{ .domain }}</h1>
{{ if .group.About }}
<p class="lead">{{ .group.About }}</p>
{{ else }}
<p class="text-muted">This group does not have a description.</p>
{{ end }}
</div>
</div>
{{ if and .authenticated (eq .group.OwnerID .user.ID )}}
{{ $user := .user }}
{{ $userActor := .user_actor }}
<div class="row pt-3 border-top">
<div class="col">
<h1 class="display-4">Management</h1>
</div>
</div>
<div class="row pt-3">
<div class="col">
<h3>Update Description</h3>
<form method="POST" action="{{ url "update_group" }}" id="update_about">
<input type="hidden" name="actor_id" value="{{ .group_actor.ActorID }}"/>
<div class="form-group">
<label for="updateGroupAbout">About</label>
<input type="text" class="form-control" id="updateGroupAbout" name="about" required>
</div>
<input type="submit" class="btn btn-dark" name="submit" value="Update"/>
</form>
</div>
</div>
<div class="row pt-3">
<div class="col">
<h3>Invite</h3>
<form method="POST" action="{{ url "group_invite" }}" id="update_about">
<input type="hidden" name="group" value="{{ .group_actor.ActorID }}"/>
<div class="form-group">
<label for="groupInviteActor">Actor</label>
<input type="text" class="form-control" id="groupInviteActor" name="actor"
placeholder="@nick@tavern.town" required>
</div>
<input type="submit" class="btn btn-dark" name="submit" value="Invite"/>
</form>
</div>
</div>
<div class="row pt-3">
<div class="col">
<h3>Members</h3>
<table class="table">
<thead>
<tr>
<th>Actor</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{{ range $m := .members }}
<tr {{- if eq $m.ActorID $userActor.ActorID }} class="table-info" {{- end -}}>
<td>
{{ $m.ActorID }}
</td>
<td>
{{ if not (eq $m.ActorID $userActor.ActorID) }}
<form method="post" action="{{ url "group_kick" }}">
<input type="hidden" name="group" value="{{ $groupActor.ActorID }}"/>
<input type="hidden" name="actor" value="{{ $m.ActorID }}"/>
<input class="btn btn-sm btn-danger" type="submit" name="submit" value="Kick"/>
</form>
{{- end -}}
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
</div>
{{ end }}
{{end}}

View File

@ -379,7 +379,7 @@ func serverCommandAction(cliCtx *cli.Context) error {
if groupConfig.EnableGroups {
manageGroups := manage.Group("/groups")
{
manageGroups.GET("/", h.dashboardGroups)
manageGroups.GET("/", h.manageGroups)
manageGroups.POST("/create", h.dashboardGroupsCreate)
}
}

View File

@ -17,7 +17,7 @@ import (
"github.com/ngerakines/tavern/storage"
)
func (h handler) dashboardGroups(c *gin.Context) {
func (h handler) manageGroups(c *gin.Context) {
data, user, session, cont := h.loggedIn(c, true)
if !cont {
return

View File

@ -12,11 +12,11 @@ import (
)
func (h handler) groupActorInfo(c *gin.Context) {
// accepted := common.ParseAccept(c.GetHeader("Accept"))
// if accepted.MatchHTML(true) {
// h.viewUser(c)
// return
// }
accepted := common.ParseAccept(c.GetHeader("Accept"))
if accepted.MatchHTML(true) {
h.viewGroup(c)
return
}
name := c.Param("name")

View File

@ -0,0 +1,80 @@
package web
import (
"net/http"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/ngerakines/tavern/errors"
)
func (h handler) viewGroup(c *gin.Context) {
session := sessions.Default(c)
ctx := c.Request.Context()
trans, transOK := c.Get("trans")
if !transOK {
panic("trans not found in context")
}
data := gin.H{
"flashes": getFlashes(session),
"Trans": trans,
}
authenticated := true
localUser, err := h.storage.GetUserBySession(ctx, session)
if err != nil {
if !errors.Is(err, errors.NewNotFoundError(nil)) {
h.internalServerErrorJSON(c, err)
return
}
authenticated = false
}
data["authenticated"] = authenticated
data["user"] = localUser
name := c.Param("name")
group, err := h.storage.GetGroupByName(ctx, name)
if err != nil {
if errors.Is(err, errors.NewNotFoundError(nil)) {
h.notFoundJSON(c, err)
return
}
h.internalServerErrorJSON(c, err)
return
}
groupActor, err := h.storage.GetActor(ctx, group.ActorID)
if err != nil {
h.hardFail(c, err)
return
}
data["group"] = group
data["group_actor"] = groupActor
data["domain"] = h.domain
if !authenticated {
c.HTML(http.StatusOK, "group_profile", data)
return
}
userActor, err := h.storage.GetActor(ctx, localUser.ActorID)
if err != nil {
h.hardFail(c, err)
return
}
data["user_actor"] = userActor
members, err := h.storage.GroupMemberActorsForGroupActorID(ctx, group.ActorID)
if err != nil {
h.hardFail(c, err)
return
}
data["members"] = members
c.HTML(http.StatusOK, "group_profile", data)
}

View File

@ -8,84 +8,13 @@ import (
"strings"
"time"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/gofrs/uuid"
"go.uber.org/zap"
"github.com/ngerakines/tavern/common"
"github.com/ngerakines/tavern/errors"
"github.com/ngerakines/tavern/storage"
)
func (h handler) viewUser(c *gin.Context) {
session := sessions.Default(c)
ctx := c.Request.Context()
trans, transOK := c.Get("trans")
if !transOK {
panic("trans not found in context")
}
data := gin.H{
"flashes": getFlashes(session),
"Trans": trans,
}
authenticated := true
localUser, err := h.storage.GetUserBySession(ctx, session)
if err != nil {
if !errors.Is(err, errors.NewNotFoundError(nil)) {
h.internalServerErrorJSON(c, err)
return
}
authenticated = false
}
data["authenticated"] = authenticated
data["user"] = localUser
name := c.Param("name")
viewUser, err := h.storage.GetUserByName(ctx, name)
if err != nil {
if errors.Is(err, errors.NewNotFoundError(nil)) {
h.notFoundJSON(c, err)
return
}
h.internalServerErrorJSON(c, err)
return
}
viewUserActor, err := h.storage.GetActor(ctx, viewUser.ActorID)
if err != nil {
h.hardFail(c, err)
return
}
data["view_user"] = viewUser
data["view_user_actor"] = viewUserActor
data["domain"] = h.domain
data["feed_template"] = "profile"
data["self_url"] = h.url("profile", viewUser.Name)
page := intParam(c, "page", 1)
limit := 20
h.displayObjectFeed(c, false, data, func(user *storage.User) (i int, payloads []storage.Payload, err error) {
total, err := h.storage.CountObjectPayloadsInUserOutbox(ctx, viewUser.ID)
if err != nil {
return 0, nil, err
}
h.logger.Debug("counted objects in feed", zap.Int("total", total))
objects, err := h.storage.ListObjectPayloadsInUserOutbox(ctx, viewUser.ID, limit, (page-1)*limit)
if err != nil {
return 0, nil, err
}
h.logger.Debug("queried objects", zap.Int("count", len(objects)))
return total, objects, nil
})
}
func (h handler) viewObject(c *gin.Context) {
data, localUser, _ /* session */, cont := h.loggedIn(c, false)
if !cont {
@ -271,7 +200,6 @@ func (h handler) viewObject(c *gin.Context) {
return
}
// addViewObject(root *viewObject, parentObjectRowID, objectRowID uuid.UUID, payload storage.Payload)
root := addViewObject(nil, uuid.Nil, topParent, topParentRef)
root.populate(0, allChildren, refs)

View File

@ -0,0 +1,78 @@
package web
import (
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"github.com/ngerakines/tavern/errors"
"github.com/ngerakines/tavern/storage"
)
func (h handler) viewUser(c *gin.Context) {
session := sessions.Default(c)
ctx := c.Request.Context()
trans, transOK := c.Get("trans")
if !transOK {
panic("trans not found in context")
}
data := gin.H{
"flashes": getFlashes(session),
"Trans": trans,
}
authenticated := true
localUser, err := h.storage.GetUserBySession(ctx, session)
if err != nil {
if !errors.Is(err, errors.NewNotFoundError(nil)) {
h.internalServerErrorJSON(c, err)
return
}
authenticated = false
}
data["authenticated"] = authenticated
data["user"] = localUser
name := c.Param("name")
viewUser, err := h.storage.GetUserByName(ctx, name)
if err != nil {
if errors.Is(err, errors.NewNotFoundError(nil)) {
h.notFoundJSON(c, err)
return
}
h.internalServerErrorJSON(c, err)
return
}
viewUserActor, err := h.storage.GetActor(ctx, viewUser.ActorID)
if err != nil {
h.hardFail(c, err)
return
}
data["view_user"] = viewUser
data["view_user_actor"] = viewUserActor
data["domain"] = h.domain
data["feed_template"] = "profile"
data["self_url"] = h.url("profile", viewUser.Name)
page := intParam(c, "page", 1)
limit := 20
h.displayObjectFeed(c, false, data, func(user *storage.User) (i int, payloads []storage.Payload, err error) {
total, err := h.storage.CountObjectPayloadsInUserOutbox(ctx, viewUser.ID)
if err != nil {
return 0, nil, err
}
h.logger.Debug("counted objects in feed", zap.Int("total", total))
objects, err := h.storage.ListObjectPayloadsInUserOutbox(ctx, viewUser.ID, limit, (page-1)*limit)
if err != nil {
return 0, nil, err
}
h.logger.Debug("queried objects", zap.Int("count", len(objects)))
return total, objects, nil
})
}