Move group to backend and change intervals and such to use 05:00 as start of day.
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
Vendored
+1
-1
@@ -13,7 +13,7 @@ declare namespace App {
|
||||
user?: import("$lib/models/user").default
|
||||
idToken?: string
|
||||
req?: any
|
||||
groupOptions?: import("$lib/utils/items").GroupItemsOptions
|
||||
groupOptions?: import("$lib/models/items").GroupItemsOptions
|
||||
amplifyConfig: any
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { TimeInterval } from "$lib/models/common";
|
||||
import type Item from "$lib/models/item";
|
||||
import type { ItemFilter, ItemInput } from "$lib/models/item";
|
||||
import type { GroupItemsOptions, ItemFilter, ItemGroup, ItemInput } from "$lib/models/item";
|
||||
import type Project from "$lib/models/project";
|
||||
import type { ProjectEntry, ProjectInput, Requirement, RequirementInput } from "$lib/models/project";
|
||||
import type { ScopeInput } from "$lib/models/scope";
|
||||
@@ -73,10 +73,19 @@ export default class SL3APIClient {
|
||||
return this.fetch<{project: Project}>("PUT", `scopes/${scopeId}/projects/${projectId}`, input).then(r => r.project);
|
||||
}
|
||||
|
||||
async listItems(scopeId: number | "ALL", filter: ItemFilter): Promise<Item[]> {
|
||||
async listItems(scopeId: number | "ALL", filter: ItemFilter, grouped: true, groupOptions: GroupItemsOptions): Promise<{items: Item[], groups: ItemGroup[]}>
|
||||
async listItems(scopeId: number | "ALL", filter: ItemFilter, grouped?: false): Promise<Item[]>
|
||||
async listItems(scopeId: number | "ALL", filter: ItemFilter, grouped?: boolean, groupOptions?: GroupItemsOptions): Promise<Item[] | {items: Item[], groups: ItemGroup[]}> {
|
||||
const scopePrefix = (scopeId !== "ALL") ? `scopes/${scopeId}` : "all-scopes";
|
||||
const groupedSuffix = !!grouped ? `&grouped=true&hideCreated=${groupOptions?.hideCreated}&hideAcquired=${groupOptions?.hideAcquired}&hideScheduled=${groupOptions?.hideScheduled}` : "";
|
||||
|
||||
return this.fetch<{items: Item[]}>("GET", `${scopePrefix}/items?filter=${encodeURIComponent(JSON.stringify(filter))}`).then(r => r.items);
|
||||
return this.fetch<{items: Item[], groups: ItemGroup[]}>("GET", `${scopePrefix}/items?filter=${encodeURIComponent(JSON.stringify(filter))}${groupedSuffix}`).then(r => {
|
||||
if (!grouped) {
|
||||
return r.items
|
||||
}
|
||||
|
||||
return {groups: r.groups, items: r.items}
|
||||
});
|
||||
}
|
||||
|
||||
async createItem(scopeId: number, input: ItemInput): Promise<Item> {
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
import { getScopeContext } from "./ScopeContext.svelte";
|
||||
import type Item from "$lib/models/item";
|
||||
import type { ItemFilter, ItemGroup } from "$lib/models/item";
|
||||
import { groupItems } from "$lib/utils/items";
|
||||
|
||||
export let items: Item[];
|
||||
export let groups: ItemGroup[];
|
||||
@@ -50,9 +49,9 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const newItems = await sl3(fetch).listItems($scope.id, filter)
|
||||
itemsWritable.set(newItems);
|
||||
groupsWritable.set(groupItems(newItems, filter.scheduledDate.min))
|
||||
const res = await sl3(fetch).listItems($scope.id, filter, true)
|
||||
itemsWritable.set(res.items);
|
||||
groupsWritable.set(res.groups);
|
||||
} catch(_) {}
|
||||
|
||||
loading = false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { formatFormTime } from "$lib/utils/date";
|
||||
import parseInterval from "$lib/utils/timeinterval";
|
||||
import parseInterval, { morningInterval } from "$lib/utils/timeinterval";
|
||||
|
||||
export let from: string;
|
||||
export let to: string;
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
$: {
|
||||
if (intervalName !== "specific_dates") {
|
||||
const int = parseInterval(intervalName, openDate);
|
||||
const int = morningInterval(parseInterval(intervalName, openDate));
|
||||
from = formatFormTime(int.min);
|
||||
to = formatFormTime(int.max);
|
||||
}
|
||||
|
||||
@@ -68,9 +68,17 @@ export interface ItemGroup {
|
||||
export interface ItemGroupReference {
|
||||
idx: number
|
||||
event: "created" | "acquired" | "scheduled"
|
||||
time: string
|
||||
|
||||
sortKey?: string
|
||||
}
|
||||
|
||||
export interface GroupItemsOptions {
|
||||
hideCreated?: boolean
|
||||
hideAcquired?: boolean
|
||||
hideScheduled?: boolean
|
||||
}
|
||||
|
||||
// this_week
|
||||
// this_month
|
||||
// all_time
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
import type { ItemGroup, ItemGroupReference } from "$lib/models/item";
|
||||
import type Item from "$lib/models/item";
|
||||
import { formatDate, formatDateTime, formatTime, formatWeekdayDate } from "./date";
|
||||
|
||||
export interface GroupItemsOptions {
|
||||
hideCreated?: boolean
|
||||
hideScheduled?: boolean
|
||||
hideAcquired?: boolean
|
||||
}
|
||||
|
||||
export function groupItemOptionsQuery(opts: GroupItemsOptions): string {
|
||||
return `hideCreated=${opts.hideCreated},hideScheduled=${opts.hideScheduled},hideAcquired=${opts.hideAcquired}`;
|
||||
}
|
||||
|
||||
export function groupItems(items: Item[], minDate?: string, opts: GroupItemsOptions = {}): ItemGroup[] {
|
||||
let groups: Record<string, ItemGroup> = {};
|
||||
|
||||
for (let i = 0; i < items.length; ++i) {
|
||||
const item = items[i];
|
||||
const createKey = formatDate(item.createdTime)
|
||||
const createSortKey = `${createKey} ${formatTime(item.createdTime)}`
|
||||
|
||||
if (!opts.hideCreated) {
|
||||
if (!item.acquiredTime || item.acquiredTime >= item.createdTime) {
|
||||
addItem(groups, createKey, i, createSortKey, item, "created");
|
||||
}
|
||||
}
|
||||
|
||||
if (!opts.hideScheduled) {
|
||||
if (item.scheduledDate) {
|
||||
addItem(groups, item.scheduledDate, i, `${item.scheduledDate} 23:59:59`, item, "scheduled");
|
||||
}
|
||||
}
|
||||
|
||||
if (!opts.hideAcquired) {
|
||||
if (item.acquiredTime) {
|
||||
addItem(groups, formatDate(item.acquiredTime), i, formatDateTime(item.acquiredTime), item, "acquired");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Object.keys(groups).sort((a,b) => (
|
||||
b.localeCompare(a)
|
||||
)).map(k => ({
|
||||
...groups[k],
|
||||
list: groups[k].list.sort((a, b) => {
|
||||
return b.sortKey.localeCompare(a.sortKey);
|
||||
}).map(r => ({...r, sortKey: void(0)})),
|
||||
})).filter(g => minDate == null || g.label > minDate);
|
||||
}
|
||||
|
||||
function addItem(groups: Record<string, ItemGroup>, key: string, index: number, sortKey: string, item: Item, event: ItemGroupReference["event"]) {
|
||||
if (groups[key] == null) {
|
||||
groups[key] = {
|
||||
label: formatWeekdayDate(sortKey),
|
||||
list: [],
|
||||
}
|
||||
}
|
||||
|
||||
const i = groups[key].list.findIndex(r => r.idx === index)
|
||||
if (i == -1) {
|
||||
groups[key].list.push({
|
||||
idx: index,
|
||||
event: event,
|
||||
sortKey: sortKey,
|
||||
})
|
||||
} else {
|
||||
groups[key].list[i].event = event;
|
||||
groups[key].list[i].sortKey = sortKey;
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,19 @@ export default function parseInterval(s: string, date: Date): TimeInterval<Date>
|
||||
case "last_year":
|
||||
return {display: "year", min: startOfYear(addYears(date, -1)), max: startOfYear(date)}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function morningInterval(interval: TimeInterval<Date>) {
|
||||
if (!interval) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
min: new Date(interval.min.getTime() + 3600000 * 5),
|
||||
max: new Date(interval.max.getTime() + 3600000 * 5),
|
||||
}
|
||||
}
|
||||
|
||||
export function intervalLabel(s: string): string {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
import { sl3 } from "$lib/clients/sl3";
|
||||
import parseInterval, { datesOf, intervalLabel } from "$lib/utils/timeinterval";
|
||||
import { groupItemOptionsQuery, groupItems, type GroupItemsOptions } from "$lib/utils/items";
|
||||
import type Item from "$lib/models/item";
|
||||
import type { ItemFilter, ItemGroup } from "$lib/models/item";
|
||||
|
||||
@@ -16,13 +15,12 @@
|
||||
acquiredTime: interval,
|
||||
scheduledDate: datesOf(interval),
|
||||
};
|
||||
const items = await sl3(fetch).listItems(scopeId, filter);
|
||||
const {items, groups} = await sl3(fetch).listItems(scopeId, filter, true, session.groupOptions);
|
||||
|
||||
return {
|
||||
props: {
|
||||
items, filter,
|
||||
items, groups, filter,
|
||||
intervalString: params.interval,
|
||||
groups: groupItems(items, datesOf(interval)?.min, session.groupOptions || {}),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -41,7 +39,6 @@
|
||||
import ItemListContext from "$lib/components/contexts/ItemListContext.svelte";
|
||||
import HistoryGroupList from "$lib/components/history/HistoryGroupList.svelte";
|
||||
import ToggleIcon from "$lib/components/history/ToggleIcon.svelte";
|
||||
import Status from "$lib/models/status";
|
||||
|
||||
export let intervalString: string
|
||||
export let items: Item[]
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
scheduledDate: datesOf(parseInterval("next:7d", now)),
|
||||
},
|
||||
acquiredFilter: {
|
||||
acquiredTime: parseInterval("today", now),
|
||||
acquiredTime: morningInterval(parseInterval("today", now)),
|
||||
},
|
||||
looseFilter: {
|
||||
loose: true,
|
||||
@@ -35,6 +35,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { sl3 } from "$lib/clients/sl3";
|
||||
import { getScopeContext } from "$lib/components/contexts/ScopeContext.svelte";
|
||||
import Column from "$lib/components/layout/Column.svelte";
|
||||
import Columns from "$lib/components/layout/Columns.svelte";
|
||||
@@ -44,8 +45,7 @@
|
||||
import StatSubSection from "$lib/components/scope/StatSubSection.svelte";
|
||||
import DeletionModal from "$lib/modals/DeletionModal.svelte";
|
||||
import StatCreateEditModal from "$lib/modals/StatCreateEditModal.svelte";
|
||||
import { sl3 } from "$lib/clients/sl3";
|
||||
import parseInterval, { datesOf } from "$lib/utils/timeinterval";
|
||||
import parseInterval, { datesOf, morningInterval } from "$lib/utils/timeinterval";
|
||||
import type Item from "$lib/models/item";
|
||||
import ItemCreateModal from "$lib/modals/ItemCreateModal.svelte";
|
||||
import Card from "$lib/components/common/Card.svelte";
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
scheduledDate: datesOf(parseInterval("next:7d", now)),
|
||||
},
|
||||
acquiredFilter: {
|
||||
acquiredTime: parseInterval("today", now),
|
||||
acquiredTime: morningInterval(parseInterval("today", now)),
|
||||
},
|
||||
looseFilter: {
|
||||
loose: true,
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
export const load: Load = async({ fetch, session }) => {
|
||||
export const load: Load = async({ fetch }) => {
|
||||
const scopes = await sl3(fetch).listScopes();
|
||||
|
||||
const {acquiredFilter, looseFilter, scheduledFilter} = generateItemFilters(new Date());
|
||||
@@ -45,7 +45,7 @@
|
||||
import OptionsRow from "$lib/components/layout/OptionsRow.svelte";
|
||||
import Option from "$lib/components/layout/Option.svelte";
|
||||
import ScopeListContext from "$lib/components/contexts/ScopeListContext.svelte";
|
||||
import parseInterval, { datesOf } from "$lib/utils/timeinterval";
|
||||
import parseInterval, { datesOf, morningInterval } from "$lib/utils/timeinterval";
|
||||
import ItemMultiListContext from "$lib/components/contexts/ItemMultiListContext.svelte";
|
||||
import type Item from "$lib/models/item";
|
||||
import DeletionModal from "$lib/modals/DeletionModal.svelte";
|
||||
@@ -58,7 +58,7 @@
|
||||
import SprintCreateUpdateModal from "$lib/modals/SprintCreateUpdateModal.svelte";
|
||||
import SprintListContext from "$lib/components/contexts/SprintListContext.svelte";
|
||||
import type Sprint from "$lib/models/sprint";
|
||||
import Icon from "$lib/components/layout/Icon.svelte";
|
||||
import Icon from "$lib/components/layout/Icon.svelte";
|
||||
|
||||
export let scopes: Scope[] = [];
|
||||
export let acquiredItems: Item[];
|
||||
|
||||
@@ -8,3 +8,12 @@ func Map[I any, O any](arr []I, cb func(a I) O) []O {
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func MapValues[K comparable, V any](m map[K]V) []V {
|
||||
res := make([]V, 0, len(m))
|
||||
for _, v := range m {
|
||||
res = append(res, v)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -46,6 +46,14 @@ func (d Date) ToTime() time.Time {
|
||||
return time.Date(d[0], time.Month(d[1]), d[2], 0, 0, 0, 0, time.UTC)
|
||||
}
|
||||
|
||||
func (d Date) WithTime(hh, mm, ss int) time.Time {
|
||||
return d.WithTimeAndLocation(hh, mm, ss, time.UTC)
|
||||
}
|
||||
|
||||
func (d Date) WithTimeAndLocation(hh, mm, ss int, loc *time.Location) time.Time {
|
||||
return time.Date(d[0], time.Month(d[1]), d[2], hh, mm, ss, 0, loc)
|
||||
}
|
||||
|
||||
func (d *Date) UnmarshalJSON(b []byte) error {
|
||||
var str string
|
||||
err := json.Unmarshal(b, &str)
|
||||
|
||||
@@ -55,6 +55,10 @@ func getterHandler[O any](key, idKey string, callback func(ctx context.Context,
|
||||
}
|
||||
|
||||
func handler(key string, callback func(c *gin.Context) (interface{}, error)) gin.HandlerFunc {
|
||||
type overrider interface {
|
||||
OverrideJSONResponse() bool
|
||||
}
|
||||
|
||||
return func(c *gin.Context) {
|
||||
res, err := callback(c)
|
||||
if err != nil {
|
||||
@@ -82,6 +86,11 @@ func handler(key string, callback func(c *gin.Context) (interface{}, error)) gin
|
||||
return
|
||||
}
|
||||
|
||||
if o, ok := res.(overrider); ok && o.OverrideJSONResponse() {
|
||||
c.JSON(200, res)
|
||||
return
|
||||
}
|
||||
|
||||
resJson := make(map[string]interface{}, 1)
|
||||
resJson[key] = res
|
||||
|
||||
|
||||
+51
-10
@@ -12,25 +12,50 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func ItemsAllScopes(g *gin.RouterGroup, items *items.Service) {
|
||||
type groupedRes struct {
|
||||
Items []items.Result `json:"items"`
|
||||
Groups []items.Group `json:"groups"`
|
||||
}
|
||||
|
||||
func (g groupedRes) OverrideJSONResponse() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func ItemsAllScopes(g *gin.RouterGroup, itemService *items.Service) {
|
||||
g.GET("", handler("items", func(c *gin.Context) (interface{}, error) {
|
||||
filter, err := getItemFilterFromQuery(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items.ListAllScopes(c.Request.Context(), filter)
|
||||
res, err := itemService.ListAllScopes(c.Request.Context(), filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.Query("grouped") == "true" {
|
||||
return groupedRes{
|
||||
Items: res,
|
||||
Groups: items.GenerateGroups(res, items.GroupOptions{
|
||||
HideCreated: c.Query("hideCreated") == "true",
|
||||
HideAcquired: c.Query("hideAcquired") == "true",
|
||||
HideScheduled: c.Query("hideScheduled") == "true",
|
||||
}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}))
|
||||
}
|
||||
|
||||
func Items(g *gin.RouterGroup, items *items.Service) {
|
||||
func Items(g *gin.RouterGroup, itemService *items.Service) {
|
||||
g.GET("/:item_id", handler("project", func(c *gin.Context) (interface{}, error) {
|
||||
id, err := reqInt(c, "item_id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items.Find(c.Request.Context(), id)
|
||||
return itemService.Find(c.Request.Context(), id)
|
||||
}))
|
||||
|
||||
g.GET("", handler("items", func(c *gin.Context) (interface{}, error) {
|
||||
@@ -39,7 +64,23 @@ func Items(g *gin.RouterGroup, items *items.Service) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items.ListScoped(c.Request.Context(), filter)
|
||||
res, err := itemService.ListScoped(c.Request.Context(), filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.Query("grouped") == "true" {
|
||||
return groupedRes{
|
||||
Items: res,
|
||||
Groups: items.GenerateGroups(res, items.GroupOptions{
|
||||
HideCreated: c.Query("hideCreated") == "true",
|
||||
HideAcquired: c.Query("hideAcquired") == "true",
|
||||
HideScheduled: c.Query("hideScheduled") == "true",
|
||||
}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}))
|
||||
|
||||
g.POST("", handler("item", func(c *gin.Context) (interface{}, error) {
|
||||
@@ -55,7 +96,7 @@ func Items(g *gin.RouterGroup, items *items.Service) {
|
||||
}
|
||||
}
|
||||
|
||||
return items.Create(c.Request.Context(), input.Item, input.Stats)
|
||||
return itemService.Create(c.Request.Context(), input.Item, input.Stats)
|
||||
}))
|
||||
|
||||
g.PUT("/:item_id", handler("item", func(c *gin.Context) (interface{}, error) {
|
||||
@@ -76,7 +117,7 @@ func Items(g *gin.RouterGroup, items *items.Service) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items.Update(c.Request.Context(), id, input.ItemUpdate, input.Stats)
|
||||
return itemService.Update(c.Request.Context(), id, input.ItemUpdate, input.Stats)
|
||||
}))
|
||||
|
||||
g.PUT("/:item_id/stats/:stat_id", handler("item", func(c *gin.Context) (interface{}, error) {
|
||||
@@ -100,7 +141,7 @@ func Items(g *gin.RouterGroup, items *items.Service) {
|
||||
|
||||
input.StatID = statID
|
||||
|
||||
return items.UpdateStat(c.Request.Context(), itemID, input)
|
||||
return itemService.UpdateStat(c.Request.Context(), itemID, input)
|
||||
}))
|
||||
|
||||
g.DELETE("/:item_id/stats/:stat_id", handler("item", func(c *gin.Context) (interface{}, error) {
|
||||
@@ -113,7 +154,7 @@ func Items(g *gin.RouterGroup, items *items.Service) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items.DeleteStat(c.Request.Context(), itemID, statID)
|
||||
return itemService.DeleteStat(c.Request.Context(), itemID, statID)
|
||||
}))
|
||||
|
||||
g.DELETE("/:item_id", handler("item", func(c *gin.Context) (interface{}, error) {
|
||||
@@ -122,7 +163,7 @@ func Items(g *gin.RouterGroup, items *items.Service) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items.Delete(c.Request.Context(), id)
|
||||
return itemService.Delete(c.Request.Context(), id)
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
package items
|
||||
|
||||
import (
|
||||
"git.aiterp.net/stufflog3/stufflog3/internal/genutils"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Group struct {
|
||||
Label string `json:"label,omitempty"`
|
||||
List []GroupReference `json:"list,omitempty"`
|
||||
}
|
||||
|
||||
type GroupOptions struct {
|
||||
HideCreated bool `json:"hideCreated,omitempty"`
|
||||
HideScheduled bool `json:"hideScheduled,omitempty"`
|
||||
HideAcquired bool `json:"hideAcquired,omitempty"`
|
||||
}
|
||||
|
||||
type GroupReference struct {
|
||||
Index int `json:"idx"`
|
||||
Event string `json:"event"`
|
||||
Time string `json:"time"`
|
||||
|
||||
sortKey string
|
||||
}
|
||||
|
||||
func GenerateGroups(items []Result, opts GroupOptions) []Group {
|
||||
groups := make(map[string]Group, 16)
|
||||
|
||||
// TODO: Get the scope from somewhere else, if necessary.
|
||||
|
||||
for i, item := range items {
|
||||
if !opts.HideCreated && (item.AcquiredTime == nil || item.AcquiredTime.After(item.CreatedTime)) {
|
||||
addItem(groups, i, "created", item.CreatedTime, tz)
|
||||
}
|
||||
if !opts.HideScheduled && item.ScheduledDate != nil {
|
||||
addItem(groups, i, "scheduled", item.ScheduledDate.WithTimeAndLocation(23, 59, 59, tz), tz)
|
||||
}
|
||||
if !opts.HideAcquired && item.AcquiredTime != nil {
|
||||
addItem(groups, i, "acquired", *item.AcquiredTime, tz)
|
||||
}
|
||||
}
|
||||
|
||||
for _, group := range groups {
|
||||
sort.Slice(group.List, func(i, j int) bool {
|
||||
return group.List[j].sortKey < group.List[i].sortKey
|
||||
})
|
||||
}
|
||||
|
||||
groupSlice := genutils.MapValues(groups)
|
||||
sort.Slice(groupSlice, func(i, j int) bool {
|
||||
return groupSlice[j].Label < groupSlice[i].Label
|
||||
})
|
||||
|
||||
return groupSlice
|
||||
}
|
||||
|
||||
func addItem(groups map[string]Group, index int, event string, eventDate time.Time, tz *time.Location) {
|
||||
groupDate := eventDate.In(tz).Add(-time.Minute * 300)
|
||||
eventDate = eventDate.In(tz)
|
||||
|
||||
groupKey := groupDate.Format("2006-01-02")
|
||||
var sortKey string
|
||||
if event == "scheduled" {
|
||||
sortKey = eventDate.Format("2006-01-02") + " 23:59:59.999"
|
||||
} else {
|
||||
sortKey = eventDate.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
// Why, Go, must you be so.
|
||||
group, ok := groups[groupKey]
|
||||
if !ok {
|
||||
group = Group{
|
||||
Label: groupDate.Format("2006-01-02 (Monday)"),
|
||||
List: make([]GroupReference, 0, 16),
|
||||
}
|
||||
}
|
||||
|
||||
for i, ref := range group.List {
|
||||
if ref.Index == index {
|
||||
group.List = append(group.List[:i], group.List[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
group.List = append(group.List, GroupReference{
|
||||
Index: index,
|
||||
Event: event,
|
||||
Time: eventDate.Format("15:04"),
|
||||
sortKey: sortKey,
|
||||
})
|
||||
groups[groupKey] = group
|
||||
}
|
||||
|
||||
var tz *time.Location
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
|
||||
tz, err = time.LoadLocation("Europe/Oslo")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user