diff --git a/api/schedule_history_list_by_day.go b/api/schedule_history_list_by_day.go new file mode 100644 index 0000000..8339fb9 --- /dev/null +++ b/api/schedule_history_list_by_day.go @@ -0,0 +1,53 @@ +package api + +import ( + "context" + "time" + + "github.com/stephenafamo/bob" + "github.com/stephenafamo/bob/dialect/sqlite/dialect" + "github.com/tigorlazuardi/redmage/models" + "github.com/tigorlazuardi/redmage/pkg/errs" +) + +type ScheduleHistoryListByDateParams struct { + Date time.Time +} + +func (params *ScheduleHistoryListByDateParams) FillFromQuery(query Queryable) { + var err error + params.Date, err = time.Parse("2006-01-02", query.Get("date")) + if err != nil { + params.Date = time.Now() + } +} + +func (params *ScheduleHistoryListByDateParams) CountQuery() (expr []bob.Mod[*dialect.SelectQuery]) { + unixTopTime := time.Date(params.Date.Year(), params.Date.Month(), params.Date.Day(), 23, 59, 59, 0, params.Date.Location()).Unix() + unixLowTime := time.Date(params.Date.Year(), params.Date.Month(), params.Date.Day(), 0, 0, 0, 0, params.Date.Location()).Unix() + expr = append(expr, models.SelectWhere.ScheduleHistories.CreatedAt.GTE(unixLowTime)) + expr = append(expr, models.SelectWhere.ScheduleHistories.CreatedAt.LTE(unixTopTime)) + return +} + +func (params *ScheduleHistoryListByDateParams) Query() (expr []bob.Mod[*dialect.SelectQuery]) { + expr = params.CountQuery() + return +} + +func (api *API) ScheduleHistoryListByDate(ctx context.Context, params ScheduleHistoryListByDateParams) (result ScheduleHistoryListResult, err error) { + ctx, span := tracer.Start(ctx, "*API.ScheduleHistoryListByDate") + defer span.End() + + result.Schedules, err = models.ScheduleHistories.Query(ctx, api.db, params.Query()...).All() + if err != nil { + return result, errs.Wrapw(err, "failed to list schedule histories", "query", params) + } + + result.Total, err = models.ScheduleHistories.Query(ctx, api.db, params.CountQuery()...).Count() + if err != nil { + return result, errs.Wrapw(err, "failed to count schedule histories", "query", params) + } + + return +} diff --git a/server/routes/page_schedule_history.go b/server/routes/page_schedule_history.go index 7a66614..1480afa 100644 --- a/server/routes/page_schedule_history.go +++ b/server/routes/page_schedule_history.go @@ -2,13 +2,11 @@ package routes import ( "net/http" - "time" - "github.com/tigorlazuardi/redmage/api" "github.com/tigorlazuardi/redmage/pkg/errs" "github.com/tigorlazuardi/redmage/pkg/log" "github.com/tigorlazuardi/redmage/views" - "github.com/tigorlazuardi/redmage/views/schedulehistoriesview" + "github.com/tigorlazuardi/redmage/views/schedulehistories" ) func (routes *Routes) PageScheduleHistory(rw http.ResponseWriter, req *http.Request) { @@ -17,36 +15,24 @@ func (routes *Routes) PageScheduleHistory(rw http.ResponseWriter, req *http.Requ c := views.NewContext(routes.Config, req) - var data schedulehistoriesview.Data - if tz := req.URL.Query().Get("tz"); tz == "" { - data.Timezone = time.Local - } else { - var err error - data.Timezone, err = time.LoadLocation(tz) - if err != nil { - data.Timezone = time.Local - } - } + var data schedulehistories.Data - var params api.ScheduleHistoryListParams - params.FillFromQuery(req.URL.Query()) - - result, err := routes.API.ScheduleHistoryList(ctx, params) + data.Params.FillFromQuery(req.URL.Query()) + result, err := routes.API.ScheduleHistoryListByDate(ctx, data.Params) if err != nil { log.New(ctx).Err(err).Error("Failed to list schedule histories") code, message := errs.HTTPMessage(err) rw.WriteHeader(code) data.Error = message - if err := schedulehistoriesview.ScheduleHistoriesview(c, data).Render(ctx, rw); err != nil { + if err := schedulehistories.View(c, data).Render(ctx, rw); err != nil { log.New(ctx).Err(err).Error("Failed to render schedule histories view") } return } - data.Schedules = result.Schedules - data.Total = result.Total + data.ScheduleHistories = result.Schedules - if err := schedulehistoriesview.ScheduleHistoriesview(c, data).Render(ctx, rw); err != nil { + if err := schedulehistories.View(c, data).Render(ctx, rw); err != nil { log.New(ctx).Err(err).Error("Failed to render schedule histories view") } } diff --git a/views/icons/chevrons_bold.templ b/views/icons/chevrons_bold.templ new file mode 100644 index 0000000..eb173ab --- /dev/null +++ b/views/icons/chevrons_bold.templ @@ -0,0 +1,46 @@ +package icons + +import "strings" + +templ ChevronBoldRight(class ...string) { + 0 { + class={ strings.Join(class, " ") } + } + > + Created with Sketch Beta. + + + + + + + +} + +templ ChevronBoldLeft(class ...string) { + 0 { + class={ strings.Join(class, " ") } + } + > + chevron-left + Created with Sketch Beta. + + + + + + + +} diff --git a/views/icons/refresh.templ b/views/icons/refresh.templ new file mode 100644 index 0000000..90ee9b1 --- /dev/null +++ b/views/icons/refresh.templ @@ -0,0 +1,22 @@ +package icons + +import "strings" + +templ Refresh(class ...string) { + 0 { + class={ strings.Join(class, " ") } + } + > + + +} diff --git a/views/schedulehistories/view.templ b/views/schedulehistories/view.templ new file mode 100644 index 0000000..c2287c7 --- /dev/null +++ b/views/schedulehistories/view.templ @@ -0,0 +1,151 @@ +package schedulehistories + +import "github.com/tigorlazuardi/redmage/views" +import "github.com/tigorlazuardi/redmage/views/components" +import "github.com/tigorlazuardi/redmage/models" +import "github.com/tigorlazuardi/redmage/api" +import "fmt" +import "time" +import "github.com/tigorlazuardi/redmage/views/icons" + +type Data struct { + ScheduleHistories models.ScheduleHistorySlice + Params api.ScheduleHistoryListByDateParams + Error string +} + +func (data Data) isCurrentDay() bool { + now := time.Now() + + return now.Format(time.DateOnly) == data.Params.Date.Format(time.DateOnly) +} + +templ View(c *views.Context, data Data) { + @components.Doctype() { + @components.Head(c, + components.HeadTitle("Schedule History"), + ) + @components.Body(c) { + @components.Container() { + @Content(c, data) + } + @components.NotificationContainer() { + if data.Error != "" { + @components.ErrorNotication(data.Error) + } + } + } + } +} + +templ Content(c *views.Context, data Data) { +
+

Schedule History ({ time.Local.String() })

+
+
+ if data.isCurrentDay() { + + @icons.Refresh("w-6 h-6") + + } else { + + @icons.ChevronBoldLeft("w-6 h-6") + + } + { data.Params.Date.Format("Monday, 02 January 2006") } + { data.Params.Date.Format("Mon, 02 Jan") } + +
+ if len(data.ScheduleHistories) == 0 { +

There are no history schedules found for current date.

+ } + if len(data.ScheduleHistories) > 0 { +
+ Time + Event + for i, schedule := range data.ScheduleHistories { + if i > 0 { +
+ } +
+

+ { time.Unix(schedule.CreatedAt, 0).Format("15:04:05") } +

+
+ if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusDisabled { + + Subreddit + @subredditLink(schedule.Subreddit) + scheduler has been set to { api.ScheduleStatusDisabled.String() } status. + + } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusEnabled { + + Subreddit + @subredditLink(schedule.Subreddit) + { " " } + has been { api.ScheduleStatusEnabled.String() } { "for" } automatic scheduling. + + } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusStandby { + + Subreddit + @subredditLink(schedule.Subreddit) + { " " } + has finished + { api.ScheduleStatusDownloading.String() } + and turned to { api.ScheduleStatusStandby.String() } status. + + } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusEnqueued { + + Subreddit + @subredditLink(schedule.Subreddit) + { " " } + is { api.ScheduleStatusEnqueued.String() } { "for" } downloading. + + } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusDownloading { + + Subreddit + @subredditLink(schedule.Subreddit) + { " " } + has started { api.ScheduleStatusDownloading.String() }. + + } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusError { + + Subreddit + @subredditLink(schedule.Subreddit) + { " " } + finishes { api.ScheduleStatusDownloading.String() } + with { api.ScheduleStatusError.String() } of "{ schedule.ErrorMessage }". + + } + } +
+ } +
+} + +templ subredditLink(subreddit string) { + { subreddit } +} diff --git a/views/schedulehistoriesview/data.go b/views/schedulehistoriesview/data.go deleted file mode 100644 index fca3296..0000000 --- a/views/schedulehistoriesview/data.go +++ /dev/null @@ -1,46 +0,0 @@ -package schedulehistoriesview - -import ( - "time" - - "github.com/tigorlazuardi/redmage/models" -) - -type Data struct { - Error string - Schedules models.ScheduleHistorySlice - Total int64 - Timezone *time.Location -} - -func (data *Data) splitByDays() (out []*splitByDaySchedules) { - for _, schedule := range data.Schedules { - day := time.Unix(schedule.CreatedAt, 0).In(data.Timezone) - date := time.Date(day.Year(), day.Month(), day.Day(), 0, 0, 0, 0, day.Location()) - - var found bool - inner: - for _, split := range out { - if split.Date.Equal(date) { - found = true - split.Schedules = append(split.Schedules, schedule) - break inner - } - } - if !found { - out = append(out, &splitByDaySchedules{ - Day: day, - Date: date, - Schedules: models.ScheduleHistorySlice{schedule}, - }) - } - } - - return out -} - -type splitByDaySchedules struct { - Day time.Time - Date time.Time - Schedules models.ScheduleHistorySlice -} diff --git a/views/schedulehistoriesview/view.templ b/views/schedulehistoriesview/view.templ deleted file mode 100644 index 7ff51ab..0000000 --- a/views/schedulehistoriesview/view.templ +++ /dev/null @@ -1,109 +0,0 @@ -package schedulehistoriesview - -import "github.com/tigorlazuardi/redmage/views" -import "github.com/tigorlazuardi/redmage/views/components" -import "time" -import "github.com/tigorlazuardi/redmage/api" -import "fmt" - -templ ScheduleHistoriesview(c *views.Context, data Data) { - @components.Doctype() { - @components.Head(c, - components.HeadTitle("Schedule History"), - ) - @components.Body(c) { - @ScheduleHistoriesContent(c, data) - } - } -} - -templ ScheduleHistoriesContent(c *views.Context, data Data) { -
- @components.Container() { - if data.Error != "" { - @components.ErrorToast(data.Error) - } else { -

Schedule History ({ time.Local.String() })

-
- if data.Total < 1 { -

There are no history schedules to be found. You can populate this page's history by manually trigger a Subreddit { "for" } downloading.

- } - if data.Total > 0 { -
- for _, scheduleGroup := range data.splitByDays() { -

{ scheduleGroup.Day.Format("Monday, _2 January 2006") }

-
- - for _, schedule := range scheduleGroup.Schedules { -
- -
- { time.Unix(schedule.CreatedAt, 10).In(time.Local).Format("15:04:05") } -
-
- if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusDisabled { - - Subreddit - @subredditLink(schedule.Subreddit) - scheduler has been set to { api.ScheduleStatusDisabled.String() } status. - - } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusEnabled { - - Subreddit - @subredditLink(schedule.Subreddit) - { " " } - has been { api.ScheduleStatusEnabled.String() } { "for" } automatic scheduling. - - } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusStandby { - - Subreddit - @subredditLink(schedule.Subreddit) - { " " } - has finished - { api.ScheduleStatusDownloading.String() } - and turned to { api.ScheduleStatusStandby.String() } status. - - } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusEnqueued { - - Subreddit - @subredditLink(schedule.Subreddit) - { " " } - is { api.ScheduleStatusEnqueued.String() } { "for" } downloading. - - } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusDownloading { - - Subreddit - @subredditLink(schedule.Subreddit) - { " " } - has started { api.ScheduleStatusDownloading.String() }. - - } else if api.ScheduleStatus(schedule.Status) == api.ScheduleStatusError { - - Subreddit - @subredditLink(schedule.Subreddit) - { " " } - finishes { api.ScheduleStatusDownloading.String() } - with { api.ScheduleStatusError.String() } of "{ schedule.ErrorMessage }". - - } -
- } - } -
- - } - } - } -
-} - -templ subredditLink(subreddit string) { - { subreddit } -}