1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-18 01:57:02 +00:00

Many small refinements to front/backend UI

Changes:
 - Added a friendlyTime helper for nicer timestamps
 - Added validation to most action methods
 - Added error flash to several template files
 - Now making use to c.RenderError() to handle action errors
 - Removed message list slideUp() effect, takes too long
 - Fixed a problem with my vim indentation configuration, so CSS and
   HTML should be indented more consistently.
This commit is contained in:
James Hillyerd
2012-10-14 16:02:14 -07:00
parent 264d1d0165
commit da8e0bc508
7 changed files with 279 additions and 218 deletions

View File

@@ -0,0 +1,19 @@
package controllers
import (
"github.com/robfig/revel"
"html/template"
"time"
)
func init() {
rev.TRACE.Println("Registering helpers")
rev.Funcs["friendlyTime"] = func(t time.Time) template.HTML {
ty, tm, td := t.Date()
ny, nm, nd := time.Now().Date()
if (ty == ny) && (tm == nm) && (td == nd) {
return template.HTML(t.Format("03:04:05 PM"))
}
return template.HTML(t.Format("Mon Jan 2, 2006"))
}
}

View File

@@ -10,22 +10,34 @@ type Mailbox struct {
}
func (c Mailbox) Index(name string) rev.Result {
c.Validation.Required(name).Message("Account name is required")
if c.Validation.HasErrors() {
c.Validation.Keep()
c.FlashParams()
return c.Redirect(Application.Index)
}
return c.Render(name)
}
func (c Mailbox) List(name string) rev.Result {
c.Validation.Required(name).Message("Account name is required")
if c.Validation.HasErrors() {
c.Validation.Keep()
c.FlashParams()
return c.Redirect(Application.Index)
}
ds := inbucket.NewDataStore()
mb, err := ds.MailboxFor(name)
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
messages, err := mb.GetMessages()
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
rev.INFO.Printf("Got %v messsages", len(messages))
@@ -34,24 +46,27 @@ func (c Mailbox) List(name string) rev.Result {
}
func (c Mailbox) Show(name string, id string) rev.Result {
c.Validation.Required(name).Message("Account name is required")
c.Validation.Required(id).Message("Message ID is required")
if c.Validation.HasErrors() {
c.Validation.Keep()
c.FlashParams()
return c.Redirect(Application.Index)
}
ds := inbucket.NewDataStore()
mb, err := ds.MailboxFor(name)
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
message, err := mb.GetMessage(id)
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
_, body, err := message.ReadBody()
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
c.Response.Out.Header().Set("Expires", "-1")
@@ -59,47 +74,53 @@ func (c Mailbox) Show(name string, id string) rev.Result {
}
func (c Mailbox) Delete(name string, id string) rev.Result {
c.Validation.Required(name).Message("Account name is required")
c.Validation.Required(id).Message("Message ID is required")
if c.Validation.HasErrors() {
c.Validation.Keep()
c.FlashParams()
return c.Redirect(Application.Index)
}
ds := inbucket.NewDataStore()
mb, err := ds.MailboxFor(name)
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
message, err := mb.GetMessage(id)
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
err = message.Delete()
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
return c.RenderText("OK")
}
func (c Mailbox) Source(name string, id string) rev.Result {
c.Validation.Required(name).Message("Account name is required")
c.Validation.Required(id).Message("Message ID is required")
if c.Validation.HasErrors() {
c.Validation.Keep()
c.FlashParams()
return c.Redirect(Application.Index)
}
ds := inbucket.NewDataStore()
mb, err := ds.MailboxFor(name)
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
message, err := mb.GetMessage(id)
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
raw, err := message.ReadRaw()
if err != nil {
rev.ERROR.Printf(err.Error())
c.Flash.Error(err.Error())
return c.Redirect(Application.Index)
return c.RenderError(err)
}
c.Response.Out.Header().Set("Expires", "-1")

View File

@@ -3,6 +3,8 @@
{{template "menu.html" .}}
<div id="colTwo">
{{template "errors.html" .}}
<p>Inbucket is an email testing service; it will accept email for any email
address and make it available to view without a password.</p>
<p>To view email for a particular address, enter the username portion

View File

@@ -3,54 +3,54 @@
{{template "header.html" .}}
{{$name := .name}}
<script>
function listLoaded() {
$('.listEntry').hover(
function() {
$(this).addClass("listEntryHover")
},
function() {
$(this).removeClass("listEntryHover")
}
).click(
function() {
$('.listEntry').removeClass("listEntrySelected")
$(this).addClass("listEntrySelected")
$('#emailContent').load('/mailbox/show/{{$name}}/' + this.id)
}
)
$("#messageList").slideDown()
}
function listLoaded() {
$('.listEntry').hover(
function() {
$(this).addClass("listEntryHover")
},
function() {
$(this).removeClass("listEntryHover")
}
).click(
function() {
$('.listEntry').removeClass("listEntrySelected")
$(this).addClass("listEntrySelected")
$('#emailContent').load('/mailbox/show/{{$name}}/' + this.id)
}
)
$("#messageList").slideDown()
}
function loadList() {
$('#messageList').load("/mailbox/list/{{$name}}", listLoaded)
}
function reloadList() {
$('#messageList').hide()
loadList()
}
function loadList() {
$('#messageList').load("/mailbox/list/{{$name}}", listLoaded)
}
function listInit() {
$("#messageList").hide()
loadList()
}
function deleteMessage(id) {
$('#emailContent').empty()
$.ajax({
type: 'POST',
url: '/mailbox/delete/{{$name}}/' + id,
success: reloadList
})
}
function reloadList() {
$('#messageList').hide()
loadList()
}
function messageSource(id) {
window.open('/mailbox/source/{{$name}}/' + id, '_blank',
'width=800,height=600,' +
'menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no')
}
function listInit() {
$("#messageList").hide()
loadList()
}
$(document).ready(listInit)
function deleteMessage(id) {
$('#emailContent').empty()
$.ajax({
type: 'POST',
url: '/mailbox/delete/{{$name}}/' + id,
success: reloadList
})
}
function messageSource(id) {
window.open('/mailbox/source/{{$name}}/' + id, '_blank',
'width=800,height=600,' +
'menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no')
}
$(document).ready(listInit)
</script>
<div id="colOne">
@@ -59,12 +59,14 @@
<h2>mail for {{.name}}</h2>
</div>
<div class="box" style="text-align:center; padding-bottom:10px;">
<a href="javascript:reloadList()">Refresh List</a>
<a href="javascript:reloadList()">Refresh List</a>
</div>
<div id="messageList"></div>
</div>
<div id="colTwo">
{{template "errors.html" .}}
<div id="emailContent">
<p>Select a message at left, or enter a different username into the box on upper right.</p>
</div>

View File

@@ -1,9 +1,9 @@
{{$name := .name}}
{{range .messages}}
<div class="box listEntry" id="{{.Id}}">
<div class="subject">{{/*<a href="/mailbox/show/{{$name}}/{{.Id}}">*/}}{{.Subject}}</div>
<div class="subject">{{.Subject}}</div>
<div class="from">{{.From}}</div>
<div class="date">{{.Date}}</div>
<div class="date">{{friendlyTime .Date}}</div>
</div>
{{else}}
<div class="box">

10
app/views/errors.html Normal file
View File

@@ -0,0 +1,10 @@
{{if .errors}}
<div class="errors">
<p>Please fix the following errors and resubmit:<p>
<ul>
{{range .errors}}
<li>{{.Message}}</li>
{{end}}
</ul>
</div>
{{end}}