Procházet zdrojové kódy

alps theme: initial layout for calendar

master
Drew DeVault před 4 roky
committed by Simon Ser
rodič
revize
7142da950d
V databázi nebyl nalezen žádný známý klíč pro tento podpis ID GPG klíče: FDE7BE0E88F5E48
4 změnil soubory, kde provedl 262 přidání a 1 odebrání
  1. +60
    -0
      plugins/caldav/routes.go
  2. +100
    -1
      themes/alps/assets/style.css
  3. +18
    -0
      themes/alps/calendar-header.html
  4. +84
    -0
      themes/alps/calendar.html

+ 60
- 0
plugins/caldav/routes.go Zobrazit soubor

@@ -18,9 +18,16 @@ import (
type CalendarRenderData struct { type CalendarRenderData struct {
alps.BaseRenderData alps.BaseRenderData
Time time.Time Time time.Time
Now time.Time
Dates [7 * 6]time.Time
Calendar *caldav.Calendar Calendar *caldav.Calendar
Events []CalendarObject Events []CalendarObject
PrevPage, NextPage string PrevPage, NextPage string
PrevTime, NextTime time.Time

EventsForDate func(time.Time) []CalendarObject
DaySuffix func(n int) string
Sub func(a, b int) int
} }


type EventRenderData struct { type EventRenderData struct {
@@ -96,13 +103,66 @@ func registerRoutes(p *alps.GoPlugin, u *url.URL) {
return fmt.Errorf("failed to query calendar: %v", err) return fmt.Errorf("failed to query calendar: %v", err)
} }


// TODO: Time zones are hard
var dates [7 * 6]time.Time
initialDate := start.UTC()
initialDate = initialDate.AddDate(0, 0, -int(initialDate.Weekday()))
for i := 0; i < len(dates); i += 1 {
dates[i] = initialDate
initialDate = initialDate.AddDate(0, 0, 1)
}

eventMap := make(map[time.Time][]CalendarObject)
for _, ev := range events {
ev := ev // make a copy
// TODO: include event on each date for which it is active
co := ev.Data.Events()[0]
startTime, _ := co.DateTimeStart(nil)
startTime = startTime.UTC().Truncate(time.Hour * 24)
eventMap[startTime] = append(eventMap[startTime], CalendarObject{&ev})
}

return ctx.Render(http.StatusOK, "calendar.html", &CalendarRenderData{ return ctx.Render(http.StatusOK, "calendar.html", &CalendarRenderData{
BaseRenderData: *alps.NewBaseRenderData(ctx), BaseRenderData: *alps.NewBaseRenderData(ctx),
Time: start, Time: start,
Now: time.Now(), // TODO: Use client time zone
Calendar: calendar, Calendar: calendar,
Dates: dates,
Events: newCalendarObjectList(events), Events: newCalendarObjectList(events),
PrevPage: start.AddDate(0, -1, 0).Format(monthPageLayout), PrevPage: start.AddDate(0, -1, 0).Format(monthPageLayout),
NextPage: start.AddDate(0, 1, 0).Format(monthPageLayout), NextPage: start.AddDate(0, 1, 0).Format(monthPageLayout),
PrevTime: start.AddDate(0, -1, 0),
NextTime: start.AddDate(0, 1, 0),

EventsForDate: func(when time.Time) []CalendarObject {
if events, ok := eventMap[when.Truncate(time.Hour * 24)]; ok {
return events
}
return nil
},

DaySuffix: func(n int) string {
if n % 100 >= 11 && n % 100 <= 13 {
return "th"
}
return map[int]string{
0: "th",
1: "st",
2: "nd",
3: "rd",
4: "th",
5: "th",
6: "th",
7: "th",
8: "th",
9: "th",
}[n % 10]
},

Sub: func (a, b int) int {
// Why isn't this built-in, come on Go
return a - b
},
}) })
}) })




+ 100
- 1
themes/alps/assets/style.css Zobrazit soubor

@@ -261,6 +261,11 @@ main.new-contact .actions > *:not(:last-child) {
margin-right: 1rem; margin-right: 1rem;
} }


.actions h3 {
align-self: center;
margin: 0 1.3rem 0 1rem;
}

.message-list-subject a { color: #77c; } .message-list-subject a { color: #77c; }


.message-list-unread.message-list-sender, .message-list-unread.message-list-sender,
@@ -370,7 +375,7 @@ main table tfoot {
padding: 0.3rem 0.5rem; padding: 0.3rem 0.5rem;
} }


.actions-pagination .button-link:first-child:not(:last-child) {
.actions-pagination .button-link:not(:last-child) {
margin-right: 0.3rem; margin-right: 0.3rem;
} }


@@ -444,6 +449,100 @@ main table tfoot {
margin-top: 1rem; margin-top: 1rem;
} }


main.calendar .dates {
flex-grow: 1;
padding: 0.3rem;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: auto 1fr 1fr 1fr 1fr 1fr 1fr auto;
grid-template-areas:
"sunday-top monday-top wednesday-top tuesday-top thursday-top friday-top saturday-top"
"dates dates dates dates dates dates dates"
"dates dates dates dates dates dates dates"
"dates dates dates dates dates dates dates"
"dates dates dates dates dates dates dates"
"dates dates dates dates dates dates dates"
"dates dates dates dates dates dates dates"
"sunday-bottom monday-bottom wednesday-bottom tuesday-bottom thursday-bottom friday-bottom saturday-bottom";
grid-gap: 0.3rem;
}

main.calendar .dates .weekday {
text-align: center;
font-size: 1.1rem;
font-weight: normal;
}

main.calendar .dates .sunday-top { grid-area: sunday-top; }
main.calendar .dates .monday-top { grid-area: monday-top; }
main.calendar .dates .tuesday-top { grid-area: tuesday-top; }
main.calendar .dates .wednesday-top { grid-area: wednesday-top; }
main.calendar .dates .thursday-top { grid-area: thursday-top; }
main.calendar .dates .friday-top { grid-area: friday-top; }
main.calendar .dates .saturday-top { grid-area: saturday-top; }
main.calendar .dates .sunday-bottom { grid-area: sunday-bottom; }
main.calendar .dates .monday-bottom { grid-area: monday-bottom; }
main.calendar .dates .tuesday-bottom { grid-area: tuesday-bottom; }
main.calendar .dates .wednesday-bottom { grid-area: wednesday-bottom; }
main.calendar .dates .thursday-bottom { grid-area: thursday-bottom; }
main.calendar .dates .friday-bottom { grid-area: friday-bottom; }
main.calendar .dates .saturday-bottom { grid-area: saturday-bottom; }

main.calendar .date {
border: 1px solid #eee;
padding: 0.3rem;
background: white;
display: flex;
flex-direction: column;
position: relative;
}

main.calendar .date.active {
background-color: #f6fff6;
border: 1px solid #afa;
}

main.calendar .date .date-link {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
}

main.calendar .date.extra {
background: transparent;
border: none;
}

main.calendar .date ul {
list-style: none;
margin: 0;
padding-left: 0.3rem;
}

main.calendar .date .events {
flex-grow: 1;
}

main.calendar .date.extra .events {
visibility: hidden;
}

main.calendar .events .start-time {
color: #444;
}

main.calendar .events .overflow {
color: #444;
text-align: right;
}

main.calendar .date h4 {
font-weight: normal;
text-align: right;
color: #666;
}

main.calendar .date h4 .da { font-size: 1.2rem; }

input[type="submit"], input[type="submit"],
.button, .button,
button, button,


+ 18
- 0
themes/alps/calendar-header.html Zobrazit soubor

@@ -0,0 +1,18 @@
<div class="actions-wrap">
<div class="actions-pagination" style="margin-left: 0;">
<a href="?month={{.PrevPage}}" class="button-link">« {{.PrevTime.Format "January"}}</a>
<h3>{{.Time.Format "January 2006"}}</h3>
<a href="?month={{.NextPage}}" class="button-link">{{.NextTime.Format "January"}} »</a>
{{if ne .Time.Month .Now.Month}}
<a href="/calendar" class="button-link">Today »</a>
{{end}}
</div>

<form method="get" class="actions-search action-group">
<input
type="text"
name="query"
placeholder="Search {{.Calendar.Name}} events...">
<button>Search</button>
</form>
</div>

+ 84
- 0
themes/alps/calendar.html Zobrazit soubor

@@ -0,0 +1,84 @@
{{template "head.html" .}}
{{template "nav.html" .}}

<div class="page-wrap">
<aside>
<a href="/calendar/create" class="new">New event</a>
<!-- TODO: fetch list of address books -->
<a href="#" class="active">{{.Calendar.Name}}</a>
<a href="#">Personal</a>
</aside>

<div class="container">
<main class="calendar">
<section class="actions">
{{ template "calendar-header.html" . }}
</section>

<section class="dates">
<h4 class="weekday sunday-top">Sunday</h4>
<h4 class="weekday monday-top">Monday</h4>
<h4 class="weekday tuesday-top">Tuesday</h4>
<h4 class="weekday wednesday-top">Wednesday</h4>
<h4 class="weekday thursday-top">Thursday</h4>
<h4 class="weekday friday-top">Friday</h4>
<h4 class="weekday saturday-top">Saturday</h4>

{{$base := .}}
{{range .Dates}}
<div class="date
{{if ne $base.Time.Month .Month}}extra{{end}}
{{if and (eq $base.Now.Month .Month) (eq $base.Now.Day .Day)}}active{{end}}
">
{{if eq $base.Time.Month .Month}}
<a href="#" class="date-link"></a>
{{end}}
<div class="events">
{{$events := (call $base.EventsForDate .)}}
{{if $events}}
<ul>
{{$overflow := 0}}
{{if gt (len $events) 3}}
{{$overflow = call $base.Sub (len $events) 3}}
{{$events = slice $events 0 3}}
{{end}}

{{range $events}}
{{$event := index .Data.Events 0}}
<li>
<span class="start-time">
{{($event.DateTimeStart nil).Format "15:04"}}
</span>
{{$event.Props.Text "SUMMARY"}}
</li>
{{end}}
{{if ne $overflow 0}}
<li class="overflow">...and {{$overflow}} more</li>
{{end}}
</ul>
{{end}}
</div>
<h4>
<span class="mo">{{.Format "Jan"}}</span>
<span class="da">{{.Format "2"}}{{call $base.DaySuffix .Day}}</span>
</h4>
</div>
{{end}}

<h4 class="weekday sunday-bottom">Sunday</h4>
<h4 class="weekday monday-bottom">Monday</h4>
<h4 class="weekday tuesday-bottom">Tuesday</h4>
<h4 class="weekday wednesday-bottom">Wednesday</h4>
<h4 class="weekday thursday-bottom">Thursday</h4>
<h4 class="weekday friday-bottom">Friday</h4>
<h4 class="weekday saturday-bottom">Saturday</h4>
</section>

<section class="actions">
{{ template "calendar-header.html" . }}
</section>
</main>
</div>
</div>

{{template "foot.html"}}

Načítá se…
Zrušit
Uložit