401 lines
9.7 KiB
Go
401 lines
9.7 KiB
Go
package test
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/google/uuid"
|
|
. "github.com/labstack/echo/v4"
|
|
"test/crud"
|
|
. "test/html_components"
|
|
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const TestPath = "/test"
|
|
|
|
type TestCrud struct {
|
|
e *Echo
|
|
repo *TestRepository
|
|
html *GoHtmlHandler
|
|
}
|
|
|
|
func NewTestCrud(e *Echo, repo *TestRepository, html *GoHtmlHandler) *TestCrud {
|
|
return &TestCrud{e: e, repo: repo, html: html}
|
|
}
|
|
|
|
func (i *TestCrud) AddRoutes() {
|
|
crud.Debug("Adding Test crud routes")
|
|
g := i.e.Group(TestPath)
|
|
g.GET("", i.GetItems)
|
|
g.GET("/:id", i.GetItem)
|
|
g.GET("/create", i.CreateNewItemInputs)
|
|
g.POST("", i.CreateItem)
|
|
|
|
g.GET("/:id/edit", i.EditItem)
|
|
g.PUT("/:id", i.UpdateItem)
|
|
g.DELETE("/:id", i.DeleteItem)
|
|
|
|
}
|
|
|
|
func (i *TestCrud) readItem(c Context) (Test, error) {
|
|
userId := c.Get("userId").(int)
|
|
id := ParseIntWithDefault(c.Param("id"), 1)
|
|
return i.repo.Read(userId, id)
|
|
}
|
|
|
|
func (i *TestCrud) GetItem(c Context) error {
|
|
item, err := i.readItem(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
queryString := GetCurrentUrlQueryParams(c)
|
|
itemDisplay := ItemDisplay{
|
|
Columns: []ItemDisplayColumn{
|
|
|
|
{Label: "Name", Value: item.Name, Type: ItemDisplayTypeText},
|
|
|
|
{Label: "Checked", Value: fmt.Sprint(item.Checked), Type: ItemDisplayTypeText},
|
|
},
|
|
SubItems: i.getSubItemDisplays(item, c),
|
|
EditItemUrl: fmt.Sprint(i.GetEntityUrl(c), "/", item.Id, "/edit", queryString),
|
|
DeleteItemUrl: fmt.Sprint(i.GetEntityUrl(c), "/", item.Id, queryString),
|
|
DeletePushUrl: fmt.Sprint(i.GetEntityUrl(c), queryString),
|
|
HasImages: false,
|
|
BackUrl: fmt.Sprint(i.GetEntityUrl(c), queryString),
|
|
ItemId: item.Id,
|
|
}
|
|
return i.html.RenderPage(c, "test", TestDisplay{
|
|
IsDisplay: true,
|
|
ItemDisplay: itemDisplay,
|
|
})
|
|
}
|
|
|
|
func (i *TestCrud) getSubItemDisplays(item Test, c Context) []ItemDisplaySubItem {
|
|
var items []ItemDisplaySubItem
|
|
|
|
return items
|
|
}
|
|
|
|
type TestDisplay struct {
|
|
IsTable bool
|
|
Table Table
|
|
IsDisplay bool
|
|
ItemDisplay ItemDisplay
|
|
IsEdit bool
|
|
EditItem EditItem
|
|
}
|
|
|
|
func (i *TestCrud) GetItems(c Context) error {
|
|
page, count, err := i.getPage(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
table := i.itemsToTable(c, page, count)
|
|
return i.html.RenderPage(c, "test", TestDisplay{
|
|
IsTable: true,
|
|
Table: table,
|
|
})
|
|
}
|
|
|
|
func (i *TestCrud) GetEntityUrl(c Context) string {
|
|
|
|
return TestPath
|
|
|
|
}
|
|
|
|
func (i *TestCrud) GetParentEntityUrl(c Context) string {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
func (i *TestCrud) CreateNewItemInputs(c Context) error {
|
|
inputs := []EditItemInputs{
|
|
|
|
{Label: "Name", Value: "", Name: "Name", Type: InputTypeText, Options: []SelectInputOption{}},
|
|
|
|
{Label: "Checked", Value: "", Name: "Checked", Type: InputTypeBool, Options: []SelectInputOption{}},
|
|
}
|
|
|
|
url := fmt.Sprint(i.GetEntityUrl(c), "?", c.QueryString())
|
|
s := EditItem{
|
|
Id: "",
|
|
Title: "Create test",
|
|
Url: url,
|
|
CancelUrl: url,
|
|
IsCreate: true,
|
|
SubmitButtonLabel: "Create",
|
|
Inputs: inputs,
|
|
HasFileUpload: false,
|
|
}
|
|
return i.html.RenderPage(c, "test", TestDisplay{
|
|
IsEdit: true,
|
|
EditItem: s,
|
|
})
|
|
}
|
|
|
|
func (i *TestCrud) CreateItem(c Context) error {
|
|
userId := c.Get("userId").(int)
|
|
item := Test{
|
|
UserId: userId,
|
|
|
|
Name: c.FormValue("Name"),
|
|
|
|
Checked: ParseCheckboxWithDefault(c.FormValue("Checked"), false),
|
|
}
|
|
_, err := i.repo.Create(item)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return i.GetItems(c)
|
|
}
|
|
|
|
func (i *TestCrud) EditItem(c Context) error {
|
|
userId := c.Get("userId").(int)
|
|
id := ParseIntWithDefault(c.Param("id"), 1)
|
|
item, err := i.repo.Read(userId, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
inputs := []EditItemInputs{
|
|
|
|
{Label: "Name", Value: item.Name, Name: "Name", Type: InputTypeText, Options: []SelectInputOption{}},
|
|
|
|
{Label: "Checked", Value: fmt.Sprint(item.Checked), Name: "Checked", Type: InputTypeBool, Options: []SelectInputOption{}},
|
|
}
|
|
path := fmt.Sprint(i.GetEntityUrl(c), "/", item.Id)
|
|
queryString := GetCurrentUrlQueryParams(c)
|
|
url := fmt.Sprint(path, queryString)
|
|
cancelUrl := url
|
|
if HasFromTableHeader(c) {
|
|
cancelUrl = fmt.Sprint(i.GetEntityUrl(c), queryString)
|
|
}
|
|
s := EditItem{
|
|
Id: fmt.Sprint(id),
|
|
Title: fmt.Sprint("Update test ", id),
|
|
Url: url,
|
|
CancelUrl: cancelUrl,
|
|
IsCreate: false,
|
|
SubmitButtonLabel: "Update",
|
|
Inputs: inputs,
|
|
HasFileUpload: false,
|
|
FromTable: HasFromTableHeader(c),
|
|
}
|
|
return i.html.RenderPage(c, "test", TestDisplay{
|
|
IsEdit: true,
|
|
EditItem: s,
|
|
})
|
|
}
|
|
|
|
func (i *TestCrud) UpdateItem(c Context) error {
|
|
userId := c.Get("userId").(int)
|
|
id := ParseIntWithDefault(c.Param("id"), 1)
|
|
item, err := i.repo.Read(userId, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
item.Name = c.FormValue("Name")
|
|
|
|
item.Checked = ParseCheckboxWithDefault(c.FormValue("Checked"), false)
|
|
|
|
err = i.repo.Update(userId, item)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if HasFromTableHeader(c) {
|
|
return i.GetItems(c)
|
|
}
|
|
return i.GetItem(c)
|
|
}
|
|
|
|
func (i *TestCrud) DeleteItem(c Context) error {
|
|
userId := c.Get("userId").(int)
|
|
id := ParseIntWithDefault(c.Param("id"), 1)
|
|
err := i.repo.Delete(userId, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return i.GetItems(c)
|
|
}
|
|
|
|
func (i *TestCrud) parseDateTime(since string) time.Time {
|
|
t, err := time.Parse("2006-01-02T15:04", since)
|
|
if err != nil {
|
|
return time.Now()
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (i *TestCrud) renderPage(c Context, repo *TestRepository) error {
|
|
page, count, err := i.getPage(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
table := i.itemsToTable(c, page, count)
|
|
return i.html.RenderPage(c, "test", table)
|
|
}
|
|
|
|
func (i *TestCrud) returnRenderTable(c Context, items []Test, count int) error {
|
|
table := i.itemsToTable(c, items, count)
|
|
return i.html.RenderComponent(c, "table", table)
|
|
}
|
|
|
|
func (i *TestCrud) itemsToTable(c Context, items []Test, count int) Table {
|
|
filter := c.FormValue("filter")
|
|
page := ParseIntWithDefault(c.FormValue("pageNumber"), 1)
|
|
index := (page - 1) * 5
|
|
itemEnd := index + 5
|
|
if itemEnd > count {
|
|
itemEnd = count
|
|
}
|
|
return Table{
|
|
Headers: []string{
|
|
|
|
"Name",
|
|
|
|
"Checked",
|
|
},
|
|
Rows: i.structsToTableRows(c, items),
|
|
EntityUrl: i.GetEntityUrl(c),
|
|
CreateItemUrl: fmt.Sprint(i.GetEntityUrl(c), "/create?", c.QueryString()),
|
|
OrderBy: string(i.getOrderBy(c)),
|
|
OrderDirection: string(i.getOrderDirection(c)),
|
|
FilterValue: c.FormValue("filterValue"),
|
|
FilterSelect: SelectInput{
|
|
Label: "Filter by",
|
|
Name: "filter",
|
|
HideLabel: true,
|
|
Options: []SelectInputOption{
|
|
|
|
{Label: "Name filter", Value: "Name", Selected: filter == "Name"},
|
|
|
|
{Label: "Checked filter", Value: "Checked", Selected: filter == "Checked"},
|
|
},
|
|
},
|
|
Pagination: Pagination{
|
|
CurrenItemStart: index + 1,
|
|
CurrentItemEnd: index + 10,
|
|
TotalNumberOfItems: count,
|
|
PreviousDisabled: index == 0,
|
|
NextDisabled: index+10 >= count,
|
|
Page: page,
|
|
PreviousPage: page - 1,
|
|
NextPage: page + 1,
|
|
},
|
|
ShowBack: false,
|
|
BackUrl: i.GetParentEntityUrl(c),
|
|
}
|
|
}
|
|
|
|
func (i *TestCrud) structsToTableRows(c Context, items []Test) []TableRow {
|
|
var rows []TableRow
|
|
for _, item := range items {
|
|
rows = append(rows, i.structToRow(c, item))
|
|
}
|
|
return rows
|
|
}
|
|
|
|
func (i *TestCrud) structToRow(c Context, item Test) TableRow {
|
|
return TableRow{
|
|
Id: fmt.Sprint(item.Id),
|
|
Columns: []TableColumn{
|
|
|
|
{Value: item.Name, Type: TableColumnTypeText},
|
|
|
|
{Value: fmt.Sprint(item.Checked), Type: TableColumnTypeText},
|
|
},
|
|
EntityUrl: i.GetEntityUrl(c),
|
|
EditItemUrl: fmt.Sprint(i.GetEntityUrl(c), "/", item.Id, "/edit"),
|
|
DeleteItemUrl: fmt.Sprint(i.GetEntityUrl(c), "/", item.Id),
|
|
}
|
|
}
|
|
|
|
func (i *TestCrud) formatDateRangeInputTimeStamp(time time.Time) string {
|
|
return time.Format("2006-01-02T15:04")
|
|
}
|
|
|
|
func (i *TestCrud) dateDisplay(time time.Time) string {
|
|
return time.Format("2006-01-02 15:04:05")
|
|
}
|
|
|
|
func (i *TestCrud) getPage(c Context) ([]Test, int, error) {
|
|
userId := c.Get("userId").(int)
|
|
filter := c.FormValue("filter")
|
|
filterValue := c.FormValue("filterValue")
|
|
page := ParseIntWithDefault(c.FormValue("pageNumber"), 1)
|
|
return i.repo.GetPage(TestPaginationParams{
|
|
RowId: (page - 1) * 10,
|
|
PageSize: 10,
|
|
OrderBy: i.getOrderBy(c),
|
|
OrderDirection: i.getOrderDirection(c),
|
|
|
|
NameFilter: TestNameFilter{
|
|
Active: filter == "Name",
|
|
Value: filterValue,
|
|
},
|
|
|
|
CheckedFilter: TestCheckedFilter{
|
|
Active: filter == "Checked",
|
|
Value: ParseBoolWithDefault(filterValue, false),
|
|
},
|
|
|
|
References: TestReferences{
|
|
UserId: userId,
|
|
},
|
|
})
|
|
}
|
|
|
|
func (i *TestCrud) getOrderBy(c Context) TestField {
|
|
orderBy := c.QueryParam("orderBy")
|
|
if orderBy == "" {
|
|
return TestFieldName
|
|
}
|
|
|
|
return TestField(strings.ToLower(orderBy))
|
|
}
|
|
|
|
func (i *TestCrud) getOrderDirection(c Context) TestOrderDirection {
|
|
orderDirection := c.QueryParam("orderDirection")
|
|
if orderDirection == "" {
|
|
return TestOrderDirectionAsc
|
|
}
|
|
return TestOrderDirection(orderDirection)
|
|
}
|
|
|
|
func (i *TestCrud) saveFileAndReturnFileName(c Context, name string, currentFilename string) string {
|
|
file, err := c.FormFile(name)
|
|
if errors.Is(err, http.ErrMissingFile) {
|
|
return currentFilename
|
|
}
|
|
if err != nil {
|
|
crud.Error("Failed to save file from input", name, "with error", err)
|
|
return currentFilename
|
|
}
|
|
src, err := file.Open()
|
|
if err != nil {
|
|
crud.Error("Failed to save file from input", name, "with error", err)
|
|
return currentFilename
|
|
}
|
|
defer src.Close()
|
|
|
|
err = os.MkdirAll("files", os.ModePerm)
|
|
if err != nil {
|
|
crud.Error("Failed to save file from input", name, "with error", err)
|
|
return currentFilename
|
|
}
|
|
extension := filepath.Ext(file.Filename)
|
|
filename := fmt.Sprint(uuid.New().String(), extension)
|
|
err = CreateFile("files/"+filename, src)
|
|
if err != nil {
|
|
crud.Error("Failed to save file from input", name, "with error", err)
|
|
return currentFilename
|
|
}
|
|
return filename
|
|
}
|