2024-09-19 23:13:04 +00:00
|
|
|
package task
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
|
"github.com/maddalax/htmgo/framework/h"
|
2024-09-21 17:08:23 +00:00
|
|
|
"github.com/maddalax/htmgo/framework/hx"
|
2024-09-29 05:45:54 +00:00
|
|
|
"github.com/maddalax/htmgo/framework/js"
|
2024-09-19 23:13:04 +00:00
|
|
|
"todolist/ent"
|
|
|
|
|
"todolist/internal/tasks"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Tab = string
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
TabAll Tab = "All"
|
|
|
|
|
TabActive Tab = "Active"
|
|
|
|
|
TabComplete Tab = "Complete"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func getActiveTab(ctx *h.RequestContext) Tab {
|
|
|
|
|
if tab := h.GetQueryParam(ctx, "tab"); tab != "" {
|
|
|
|
|
return tab
|
|
|
|
|
}
|
|
|
|
|
return TabAll
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 01:24:44 +00:00
|
|
|
func Card(ctx *h.RequestContext) *h.Element {
|
2024-09-29 06:36:39 +00:00
|
|
|
service := tasks.NewService(ctx)
|
2024-09-19 23:13:04 +00:00
|
|
|
list, _ := service.List()
|
|
|
|
|
|
|
|
|
|
return h.Div(
|
|
|
|
|
h.Id("task-card"),
|
|
|
|
|
h.Class("bg-white w-full rounded shadow-md"),
|
|
|
|
|
CardBody(list, getActiveTab(ctx)),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 01:24:44 +00:00
|
|
|
func CardBody(list []*ent.Task, tab Tab) *h.Element {
|
2024-09-19 23:13:04 +00:00
|
|
|
return h.Div(
|
|
|
|
|
h.Id("tasks-card-body"),
|
|
|
|
|
Input(list),
|
|
|
|
|
List(list, tab),
|
|
|
|
|
Footer(list, tab),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 01:24:44 +00:00
|
|
|
func Input(list []*ent.Task) *h.Element {
|
2024-09-19 23:13:04 +00:00
|
|
|
return h.Div(
|
|
|
|
|
h.Id("task-card-input"),
|
|
|
|
|
h.Class("border border-b-slate-100 relative"),
|
|
|
|
|
h.Input(
|
|
|
|
|
"text",
|
2024-09-29 06:05:22 +00:00
|
|
|
h.Required(),
|
|
|
|
|
h.MaxLength(150),
|
|
|
|
|
h.AutoComplete("off"),
|
|
|
|
|
h.AutoFocus(),
|
|
|
|
|
h.Name("name"),
|
2024-09-19 23:13:04 +00:00
|
|
|
h.Class("pl-12 text-xl p-4 w-full outline-none focus:outline-2 focus:outline-rose-400"),
|
|
|
|
|
h.Placeholder("What needs to be done?"),
|
2024-10-25 15:33:48 +00:00
|
|
|
h.Post(
|
|
|
|
|
h.GetPartialPath(Create),
|
|
|
|
|
),
|
2024-09-21 17:08:23 +00:00
|
|
|
h.HxTrigger(hx.OnEvent(hx.TriggerKeyUpEnter)),
|
2024-09-19 23:13:04 +00:00
|
|
|
),
|
|
|
|
|
CompleteAllIcon(list),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 01:24:44 +00:00
|
|
|
func CompleteAllIcon(list []*ent.Task) *h.Element {
|
2024-10-25 15:33:48 +00:00
|
|
|
notCompletedCount := len(
|
|
|
|
|
h.Filter(list, func(item *ent.Task) bool {
|
|
|
|
|
return item.CompletedAt == nil
|
|
|
|
|
}),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
|
2024-09-24 19:55:07 +00:00
|
|
|
return h.Div(
|
2024-09-26 19:39:34 +00:00
|
|
|
h.ClassX("absolute top-1 left-5 p-2 rotate-90 text-3xl cursor-pointer", map[string]bool{
|
2024-09-24 19:55:07 +00:00
|
|
|
"text-slate-400": notCompletedCount > 0,
|
2024-10-25 15:33:48 +00:00
|
|
|
}),
|
|
|
|
|
h.UnsafeRaw("›"),
|
|
|
|
|
h.PostPartialWithQs(
|
|
|
|
|
CompleteAll,
|
|
|
|
|
h.NewQs(
|
|
|
|
|
"complete",
|
|
|
|
|
h.Ternary(notCompletedCount > 0, "true", "false"),
|
|
|
|
|
),
|
|
|
|
|
),
|
2024-09-19 23:13:04 +00:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 01:24:44 +00:00
|
|
|
func Footer(list []*ent.Task, activeTab Tab) *h.Element {
|
2024-09-19 23:13:04 +00:00
|
|
|
|
2024-10-25 15:33:48 +00:00
|
|
|
notCompletedCount := len(
|
|
|
|
|
h.Filter(list, func(item *ent.Task) bool {
|
|
|
|
|
return item.CompletedAt == nil
|
|
|
|
|
}),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
|
|
|
|
|
tabs := []Tab{TabAll, TabActive, TabComplete}
|
|
|
|
|
|
|
|
|
|
return h.Div(
|
|
|
|
|
h.Id("task-card-footer"),
|
|
|
|
|
h.Class("flex items-center justify-between p-4 border-t border-b-slate-100"),
|
|
|
|
|
h.Div(
|
|
|
|
|
h.TextF("%d items left", notCompletedCount),
|
|
|
|
|
),
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Class("flex items-center gap-4"),
|
2024-09-20 01:24:44 +00:00
|
|
|
h.List(tabs, func(tab Tab, index int) *h.Element {
|
2024-09-19 23:13:04 +00:00
|
|
|
return h.P(
|
2024-10-25 15:33:48 +00:00
|
|
|
h.PostOnClick(
|
|
|
|
|
h.GetPartialPathWithQs(
|
|
|
|
|
ChangeTab,
|
|
|
|
|
h.NewQs("tab", tab),
|
|
|
|
|
),
|
|
|
|
|
),
|
2024-09-19 23:13:04 +00:00
|
|
|
h.ClassX("cursor-pointer px-2 py-1 rounded", map[string]bool{
|
|
|
|
|
"border border-rose-600": activeTab == tab,
|
|
|
|
|
}),
|
|
|
|
|
h.Text(tab),
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
h.Div(
|
|
|
|
|
h.PostPartialOnClick(ClearCompleted),
|
|
|
|
|
h.ClassX("flex gap-2 cursor-pointer", map[string]bool{
|
|
|
|
|
"opacity-0": notCompletedCount == len(list),
|
|
|
|
|
}),
|
|
|
|
|
h.Text("Clear completed"),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 01:24:44 +00:00
|
|
|
func List(list []*ent.Task, tab Tab) *h.Element {
|
2024-09-19 23:13:04 +00:00
|
|
|
return h.Div(
|
|
|
|
|
h.Id("task-card-list"),
|
|
|
|
|
h.Class("bg-white w-full"),
|
|
|
|
|
h.Div(
|
2024-09-20 01:24:44 +00:00
|
|
|
h.List(list, func(item *ent.Task, index int) *h.Element {
|
2024-09-19 23:13:04 +00:00
|
|
|
if tab == TabActive && item.CompletedAt != nil {
|
|
|
|
|
return h.Empty()
|
|
|
|
|
}
|
|
|
|
|
if tab == TabComplete && item.CompletedAt == nil {
|
|
|
|
|
return h.Empty()
|
|
|
|
|
}
|
|
|
|
|
return Task(item, false)
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 01:24:44 +00:00
|
|
|
func Task(task *ent.Task, editing bool) *h.Element {
|
2024-09-19 23:13:04 +00:00
|
|
|
return h.Div(
|
|
|
|
|
h.Id(fmt.Sprintf("task-%s", task.ID.String())),
|
2024-09-20 01:24:44 +00:00
|
|
|
h.ClassX("h-[80px] max-h-[80px] max-w-2xl flex items-center p-4 gap-4 cursor-pointer", h.ClassMap{
|
2024-09-19 23:13:04 +00:00
|
|
|
"border border-b-slate-100": !editing,
|
|
|
|
|
}),
|
|
|
|
|
CompleteIcon(task),
|
2024-10-25 15:33:48 +00:00
|
|
|
h.IfElse(
|
|
|
|
|
editing,
|
2024-09-19 23:13:04 +00:00
|
|
|
h.Div(
|
|
|
|
|
h.Class("flex-1 h-full"),
|
|
|
|
|
h.Form(
|
|
|
|
|
h.Class("h-full"),
|
2024-10-25 15:33:48 +00:00
|
|
|
h.Input(
|
|
|
|
|
"text",
|
2024-09-29 06:05:22 +00:00
|
|
|
h.Name("task"),
|
|
|
|
|
h.Value(task.ID.String()),
|
2024-09-19 23:13:04 +00:00
|
|
|
h.Class("hidden"),
|
|
|
|
|
),
|
|
|
|
|
h.Input(
|
|
|
|
|
"text",
|
2024-09-21 17:08:23 +00:00
|
|
|
h.PostPartial(UpdateName, hx.TriggerBlur, hx.TriggerKeyUpEnter),
|
2024-09-20 01:24:44 +00:00
|
|
|
h.Attributes(&h.AttributeMap{
|
2024-09-29 05:45:54 +00:00
|
|
|
"maxLength": "150",
|
|
|
|
|
"required": "true",
|
2024-09-20 01:24:44 +00:00
|
|
|
"placeholder": "What needs to be done?",
|
|
|
|
|
"autofocus": "true",
|
|
|
|
|
"autocomplete": "off",
|
|
|
|
|
"name": "name",
|
|
|
|
|
"class": h.ClassX("", h.ClassMap{
|
|
|
|
|
"pl-1 h-full w-full text-xl outline-none outline-2 outline-rose-300": true,
|
|
|
|
|
}),
|
|
|
|
|
"value": task.Name,
|
|
|
|
|
}),
|
2024-09-19 23:13:04 +00:00
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
h.P(
|
2024-10-25 15:33:48 +00:00
|
|
|
h.GetPartialWithQs(
|
|
|
|
|
EditNameForm,
|
|
|
|
|
h.NewQs("id", task.ID.String()),
|
|
|
|
|
hx.TriggerDblClick,
|
|
|
|
|
),
|
2024-09-19 23:13:04 +00:00
|
|
|
h.ClassX("text-xl break-all text-wrap truncate", map[string]bool{
|
|
|
|
|
"line-through text-slate-400": task.CompletedAt != nil,
|
|
|
|
|
}),
|
|
|
|
|
h.Text(task.Name),
|
2024-10-25 15:33:48 +00:00
|
|
|
),
|
|
|
|
|
),
|
2024-09-19 23:13:04 +00:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 01:24:44 +00:00
|
|
|
func CompleteIcon(task *ent.Task) *h.Element {
|
2024-09-19 23:13:04 +00:00
|
|
|
return h.Div(
|
2024-09-21 17:08:23 +00:00
|
|
|
h.HxTrigger(hx.OnClick()),
|
2024-10-25 15:33:48 +00:00
|
|
|
h.Post(
|
|
|
|
|
h.GetPartialPathWithQs(
|
|
|
|
|
ToggleCompleted,
|
|
|
|
|
h.NewQs("id", task.ID.String()),
|
|
|
|
|
),
|
|
|
|
|
),
|
2024-09-19 23:13:04 +00:00
|
|
|
h.Class("flex items-center justify-center cursor-pointer"),
|
|
|
|
|
h.Div(
|
|
|
|
|
h.ClassX("w-10 h-10 border rounded-full flex items-center justify-center", map[string]bool{
|
|
|
|
|
"border-green-500": task.CompletedAt != nil,
|
|
|
|
|
"border-slate-400": task.CompletedAt == nil,
|
|
|
|
|
}),
|
2024-10-25 15:33:48 +00:00
|
|
|
h.If(
|
|
|
|
|
task.CompletedAt != nil,
|
|
|
|
|
h.UnsafeRaw(`
|
2024-09-19 23:13:04 +00:00
|
|
|
<svg class="w-6 h-6 text-green-500" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"></path>
|
|
|
|
|
</svg>
|
2024-10-25 15:33:48 +00:00
|
|
|
`),
|
|
|
|
|
),
|
2024-09-19 23:13:04 +00:00
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func UpdateName(ctx *h.RequestContext) *h.Partial {
|
|
|
|
|
id, err := uuid.Parse(ctx.FormValue("task"))
|
|
|
|
|
if err != nil {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("invalid id"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name := ctx.FormValue("name")
|
|
|
|
|
if name == "" {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("name is required"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-29 05:45:54 +00:00
|
|
|
if len(name) > 150 {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("task must be less than 150 characters"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-29 05:45:54 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-29 06:36:39 +00:00
|
|
|
service := tasks.NewService(ctx)
|
2024-09-19 23:13:04 +00:00
|
|
|
task, err := service.Get(id)
|
|
|
|
|
|
|
|
|
|
if task == nil {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("task not found"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
task, err = service.SetName(task.ID, name)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("failed to update"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-20 01:34:50 +00:00
|
|
|
return h.NewPartial(
|
2024-10-25 15:33:48 +00:00
|
|
|
h.OobSwap(ctx, Task(task, false)),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func EditNameForm(ctx *h.RequestContext) *h.Partial {
|
|
|
|
|
id, err := uuid.Parse(ctx.QueryParam("id"))
|
|
|
|
|
if err != nil {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("invalid id"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-29 06:36:39 +00:00
|
|
|
service := tasks.NewService(ctx)
|
2024-09-19 23:13:04 +00:00
|
|
|
task, err := service.Get(id)
|
|
|
|
|
|
|
|
|
|
if task == nil {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("task not found"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return h.NewPartial(
|
|
|
|
|
h.OobSwap(ctx, Task(task, true)),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ToggleCompleted(ctx *h.RequestContext) *h.Partial {
|
|
|
|
|
id, err := uuid.Parse(ctx.QueryParam("id"))
|
|
|
|
|
if err != nil {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("invalid id"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-29 06:36:39 +00:00
|
|
|
service := tasks.NewService(ctx)
|
2024-09-19 23:13:04 +00:00
|
|
|
task, err := service.Get(id)
|
|
|
|
|
|
|
|
|
|
if task == nil {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("task not found"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
2024-10-25 15:33:48 +00:00
|
|
|
task, err = service.SetCompleted(
|
|
|
|
|
task.ID,
|
|
|
|
|
h.
|
|
|
|
|
Ternary(task.CompletedAt == nil, true, false),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
|
|
|
|
|
if err != nil {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("failed to update"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list, _ := service.List()
|
|
|
|
|
|
2024-09-21 17:08:23 +00:00
|
|
|
return h.SwapManyPartial(ctx,
|
|
|
|
|
List(list, getActiveTab(ctx)),
|
|
|
|
|
Footer(list, getActiveTab(ctx)),
|
|
|
|
|
CompleteAllIcon(list),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func CompleteAll(ctx *h.RequestContext) *h.Partial {
|
2024-09-29 06:36:39 +00:00
|
|
|
service := tasks.NewService(ctx)
|
2024-09-24 19:55:07 +00:00
|
|
|
|
2024-09-19 23:13:04 +00:00
|
|
|
service.SetAllCompleted(ctx.QueryParam("complete") == "true")
|
2024-09-24 19:55:07 +00:00
|
|
|
|
|
|
|
|
list, _ := service.List()
|
|
|
|
|
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.OobSwap(ctx, CardBody(list, getActiveTab(ctx))),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ClearCompleted(ctx *h.RequestContext) *h.Partial {
|
2024-09-29 06:36:39 +00:00
|
|
|
service := tasks.NewService(ctx)
|
2024-09-19 23:13:04 +00:00
|
|
|
_ = service.ClearCompleted()
|
|
|
|
|
|
|
|
|
|
list, _ := service.List()
|
|
|
|
|
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.OobSwap(ctx, CardBody(list, getActiveTab(ctx))),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Create(ctx *h.RequestContext) *h.Partial {
|
|
|
|
|
name := ctx.FormValue("name")
|
2024-09-29 01:28:35 +00:00
|
|
|
|
2024-09-29 05:45:54 +00:00
|
|
|
if len(name) > 150 {
|
|
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
2024-10-25 15:33:48 +00:00
|
|
|
h.HxOnLoad(
|
|
|
|
|
js.Alert("Task must be less than 150 characters"),
|
|
|
|
|
),
|
2024-09-29 05:45:54 +00:00
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-29 06:36:39 +00:00
|
|
|
service := tasks.NewService(ctx)
|
2024-09-29 05:45:54 +00:00
|
|
|
|
|
|
|
|
list, _ := service.List()
|
|
|
|
|
|
2024-09-29 06:36:39 +00:00
|
|
|
if list != nil && len(list) >= 100 {
|
2024-09-29 05:45:54 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
2024-10-25 15:33:48 +00:00
|
|
|
h.HxOnLoad(
|
|
|
|
|
js.Alert("There are too many tasks, please complete and clear some."),
|
|
|
|
|
),
|
2024-09-29 05:45:54 +00:00
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-19 23:13:04 +00:00
|
|
|
_, err := service.Create(tasks.CreateRequest{
|
|
|
|
|
Name: name,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.NewPartial(
|
|
|
|
|
h.Div(
|
|
|
|
|
h.Text("failed to create"),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-29 05:45:54 +00:00
|
|
|
list, err = service.List()
|
2024-09-19 23:13:04 +00:00
|
|
|
|
2024-09-21 17:08:23 +00:00
|
|
|
return h.SwapManyPartial(ctx,
|
|
|
|
|
CardBody(list, getActiveTab(ctx)),
|
|
|
|
|
)
|
2024-09-19 23:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ChangeTab(ctx *h.RequestContext) *h.Partial {
|
2024-09-29 06:36:39 +00:00
|
|
|
service := tasks.NewService(ctx)
|
2024-09-19 23:13:04 +00:00
|
|
|
list, _ := service.List()
|
|
|
|
|
|
|
|
|
|
tab := ctx.QueryParam("tab")
|
|
|
|
|
|
2024-10-25 15:33:48 +00:00
|
|
|
return h.SwapManyPartialWithHeaders(
|
|
|
|
|
ctx,
|
|
|
|
|
h.PushQsHeader(
|
|
|
|
|
ctx,
|
|
|
|
|
h.NewQs("tab", tab),
|
|
|
|
|
),
|
2024-09-21 17:08:23 +00:00
|
|
|
List(list, tab),
|
|
|
|
|
Footer(list, tab),
|
2024-09-19 23:13:04 +00:00
|
|
|
)
|
|
|
|
|
}
|