render.gno

2.95 Kb ยท 132 lines
  1package events
  2
  3import (
  4	"bytes"
  5
  6	"time"
  7
  8	"gno.land/p/demo/ufmt"
  9	"gno.land/p/moul/md"
 10)
 11
 12const (
 13	MaxWidgetSize = 5
 14)
 15
 16// RenderEventWidget shows up to eventsToRender of the latest events to a caller
 17func RenderEventWidget(eventsToRender int) (string, error) {
 18	numOfEvents := len(events)
 19	if numOfEvents == 0 {
 20		return "No events.", nil
 21	}
 22
 23	if eventsToRender > MaxWidgetSize {
 24		return "", ErrMaxWidgetSize
 25	}
 26
 27	if eventsToRender < 1 {
 28		return "", ErrMinWidgetSize
 29	}
 30
 31	if eventsToRender > numOfEvents {
 32		eventsToRender = numOfEvents
 33	}
 34
 35	output := ""
 36
 37	for _, event := range events[:eventsToRender] {
 38		output += ufmt.Sprintf("- [%s](%s)\n", event.name, event.link)
 39	}
 40
 41	return output, nil
 42}
 43
 44// renderHome renders the home page of the events realm
 45func renderHome(admin bool) string {
 46	output := "# gno.land events\n\n"
 47
 48	if len(events) == 0 {
 49		output += "No upcoming or past events."
 50		return output
 51	}
 52
 53	output += "Below is a list of all gno.land events, including in progress, upcoming, and past ones.\n\n"
 54	output += "---\n\n"
 55
 56	var (
 57		inProgress []string
 58		upcoming   []string
 59		past       []string
 60		now        = time.Now()
 61	)
 62
 63	for _, e := range events {
 64		if now.Before(e.startTime) {
 65			upcoming = append(upcoming, e.Render(admin))
 66		} else if now.After(e.endTime) {
 67			past = append(past, e.Render(admin))
 68		} else {
 69			inProgress = append(inProgress, e.Render(admin))
 70		}
 71	}
 72
 73	if len(upcoming) != 0 {
 74		// Add upcoming events
 75		output += "## Upcoming events\n\n"
 76		output += md.ColumnsN(upcoming, 3, true)
 77		output += "---\n\n"
 78	}
 79
 80	if len(inProgress) != 0 {
 81		output += "## Currently in progress\n\n"
 82		output += md.ColumnsN(inProgress, 3, true)
 83		output += "---\n\n"
 84	}
 85
 86	if len(past) != 0 {
 87		// Add past events
 88		output += "## Past events\n\n"
 89		output += md.ColumnsN(past, 3, true)
 90	}
 91
 92	return output
 93}
 94
 95// Render returns the markdown representation of a single event instance
 96func (e Event) Render(admin bool) string {
 97	var buf bytes.Buffer
 98
 99	buf.WriteString(ufmt.Sprintf("### %s\n\n", e.name))
100	buf.WriteString(ufmt.Sprintf("%s\n\n", e.description))
101	buf.WriteString(ufmt.Sprintf("**Location:** %s\n\n", e.location))
102
103	_, offset := e.startTime.Zone() // offset is in seconds
104	hoursOffset := offset / (60 * 60)
105	sign := ""
106	if offset >= 0 {
107		sign = "+"
108	}
109
110	buf.WriteString(ufmt.Sprintf("**Starts:** %s UTC%s%d\n\n", e.startTime.Format("02 Jan 2006, 03:04 PM"), sign, hoursOffset))
111	buf.WriteString(ufmt.Sprintf("**Ends:** %s UTC%s%d\n\n", e.endTime.Format("02 Jan 2006, 03:04 PM"), sign, hoursOffset))
112
113	if admin {
114		buf.WriteString(ufmt.Sprintf("[EDIT](/r/gnoland/events$help&func=EditEvent&id=%s)\n\n", e.id))
115		buf.WriteString(ufmt.Sprintf("[DELETE](/r/gnoland/events$help&func=DeleteEvent&id=%s)\n\n", e.id))
116	}
117
118	if e.link != "" {
119		buf.WriteString(ufmt.Sprintf("[See more](%s)\n\n", e.link))
120	}
121
122	return buf.String()
123}
124
125// Render is the main rendering entry point
126func Render(path string) string {
127	if path == "admin" {
128		return renderHome(true)
129	}
130
131	return renderHome(false)
132}