Add notices on action completion
This commit is contained in:
parent
405c18d213
commit
cb37df882e
|
@ -306,6 +306,7 @@ func handleDeleteMailbox(ctx *alps.Context) error {
|
||||||
ctx.Session.DoIMAP(func(c *imapclient.Client) error {
|
ctx.Session.DoIMAP(func(c *imapclient.Client) error {
|
||||||
return c.Delete(mbox.Name)
|
return c.Delete(mbox.Name)
|
||||||
})
|
})
|
||||||
|
ctx.Session.PutNotice("Mailbox deleted.")
|
||||||
return ctx.Redirect(http.StatusFound, "/mailbox/INBOX")
|
return ctx.Redirect(http.StatusFound, "/mailbox/INBOX")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,6 +520,7 @@ func submitCompose(ctx *alps.Context, msg *OutgoingMessage, options *composeOpti
|
||||||
return fmt.Errorf("failed to save message to Sent mailbox: %v", err)
|
return fmt.Errorf("failed to save message to Sent mailbox: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.Session.PutNotice("Message sent.")
|
||||||
return ctx.Redirect(http.StatusFound, "/mailbox/INBOX")
|
return ctx.Redirect(http.StatusFound, "/mailbox/INBOX")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,6 +653,7 @@ func handleCompose(ctx *alps.Context, msg *OutgoingMessage, options *composeOpti
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to save message to Draft mailbox: %v", err)
|
return fmt.Errorf("failed to save message to Draft mailbox: %v", err)
|
||||||
}
|
}
|
||||||
|
ctx.Session.PutNotice("Message saved as draft.")
|
||||||
return ctx.Redirect(http.StatusFound, fmt.Sprintf(
|
return ctx.Redirect(http.StatusFound, fmt.Sprintf(
|
||||||
"/message/%s/%d/edit?part=1", drafts.Name, uid))
|
"/message/%s/%d/edit?part=1", drafts.Name, uid))
|
||||||
} else {
|
} else {
|
||||||
|
@ -981,6 +984,7 @@ func handleMove(ctx *alps.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.Session.PutNotice("Message(s) moved.")
|
||||||
if path := formOrQueryParam(ctx, "next"); path != "" {
|
if path := formOrQueryParam(ctx, "next"); path != "" {
|
||||||
return ctx.Redirect(http.StatusFound, path)
|
return ctx.Redirect(http.StatusFound, path)
|
||||||
}
|
}
|
||||||
|
@ -1032,6 +1036,7 @@ func handleDelete(ctx *alps.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.Session.PutNotice("Message(s) deleted.")
|
||||||
if path := formOrQueryParam(ctx, "next"); path != "" {
|
if path := formOrQueryParam(ctx, "next"); path != "" {
|
||||||
return ctx.Redirect(http.StatusFound, path)
|
return ctx.Redirect(http.StatusFound, path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ type GlobalRenderData struct {
|
||||||
|
|
||||||
HavePlugin func(name string) bool
|
HavePlugin func(name string) bool
|
||||||
|
|
||||||
|
Notice string
|
||||||
|
|
||||||
// additional plugin-specific data
|
// additional plugin-specific data
|
||||||
Extra map[string]interface{}
|
Extra map[string]interface{}
|
||||||
}
|
}
|
||||||
|
@ -95,6 +97,7 @@ func NewBaseRenderData(ectx echo.Context) *BaseRenderData {
|
||||||
if isactx && ctx.Session != nil {
|
if isactx && ctx.Session != nil {
|
||||||
global.LoggedIn = true
|
global.LoggedIn = true
|
||||||
global.Username = ctx.Session.username
|
global.Username = ctx.Session.username
|
||||||
|
global.Notice = ctx.Session.PopNotice()
|
||||||
}
|
}
|
||||||
|
|
||||||
return &BaseRenderData{
|
return &BaseRenderData{
|
||||||
|
|
11
session.go
11
session.go
|
@ -57,6 +57,7 @@ type Session struct {
|
||||||
pings chan struct{}
|
pings chan struct{}
|
||||||
timer *time.Timer
|
timer *time.Timer
|
||||||
store Store
|
store Store
|
||||||
|
notice string
|
||||||
|
|
||||||
imapLocker sync.Mutex
|
imapLocker sync.Mutex
|
||||||
imapConn *imapclient.Client // protected by locker, can be nil
|
imapConn *imapclient.Client // protected by locker, can be nil
|
||||||
|
@ -183,6 +184,16 @@ func (s *Session) PopAttachment(uuid string) *Attachment {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Session) PutNotice(n string) {
|
||||||
|
s.notice = n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) PopNotice() string {
|
||||||
|
n := s.notice
|
||||||
|
s.notice = ""
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
// Store returns a store suitable for storing persistent user data.
|
// Store returns a store suitable for storing persistent user data.
|
||||||
func (s *Session) Store() Store {
|
func (s *Session) Store() Store {
|
||||||
return s.store
|
return s.store
|
||||||
|
|
|
@ -118,6 +118,13 @@ header nav div { float: right; }
|
||||||
header nav div > a{ margin-left: 1rem; }
|
header nav div > a{ margin-left: 1rem; }
|
||||||
header a.active { font-weight: bold; color: black; text-decoration: none; }
|
header a.active { font-weight: bold; color: black; text-decoration: none; }
|
||||||
|
|
||||||
|
header .notice {
|
||||||
|
color: #0c5460;
|
||||||
|
background-color: #d1ecf1;
|
||||||
|
border: 1px solid #bee5eb;
|
||||||
|
padding: 0.5rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
footer { text-align: right; }
|
footer { text-align: right; }
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
{{ $classes = printf "%s %s" $classes "message-list-deleted" }}
|
{{ $classes = printf "%s %s" $classes "message-list-deleted" }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ if not (.HasFlag "\\Deleted") }}
|
{{ if and (not (.HasFlag "\\Deleted")) .Envelope }}
|
||||||
<div class="message-list-checkbox {{$classes}}">
|
<div class="message-list-checkbox {{$classes}}">
|
||||||
<input type="checkbox" name="uids" value="{{.Uid}}" form="messages-form">
|
<input type="checkbox" name="uids" value="{{.Uid}}" form="messages-form">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,4 +30,10 @@
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</nav>
|
</nav>
|
||||||
|
{{ if .GlobalData.Notice }}
|
||||||
|
<div class="notice">
|
||||||
|
{{ .GlobalData.Notice }}
|
||||||
|
<a href="{{.GlobalData.URL.String}}">Dismiss</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
</header>
|
</header>
|
||||||
|
|
Loading…
Reference in a new issue