diff --git a/backend/README.md b/backend/README.md index 49ef124..19200ff 100644 --- a/backend/README.md +++ b/backend/README.md @@ -4,7 +4,7 @@ docker run -v $(pwd)/postgres:/var/lib/postgresql/data \ -e POSTGRES_PASSWORD=password \ --rm --name postgres \ -p 5432:5432 \ - -d scr.siteworxpro.com/library/postgres:17 + -d postgres:17 ``` ```shell diff --git a/backend/handlers/loads/handler.go b/backend/handlers/loads/handler.go index 6dd0bf0..7c70239 100644 --- a/backend/handlers/loads/handler.go +++ b/backend/handlers/loads/handler.go @@ -10,6 +10,7 @@ import ( "git.siteworxpro.com/reloading-manager/backend/handlers/primers" "git.siteworxpro.com/reloading-manager/backend/models/loads" "github.com/go-jet/jet/v2/postgres" + "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "github.com/labstack/echo/v4" "net/http" @@ -43,13 +44,14 @@ type row struct { } type loadResponseResults struct { - Id string `json:"id"` - Cartridge string `json:"cartridge"` - Col float32 `json:"col"` - Powder handlers.Powder `json:"powder"` - PowderGr float32 `json:"powder_gr"` - Primer primers.PrimerResponse `json:"primer"` - Bullet bullets.BulletResponse `json:"bullet"` + Id string `json:"id"` + Cartridge string `json:"cartridge"` + CartridgeId string `json:"cartridge_id"` + Col float32 `json:"col"` + Powder handlers.Powder `json:"powder"` + PowderGr float32 `json:"powder_gr"` + Primer primers.PrimerResponse `json:"primer"` + Bullet bullets.BulletResponse `json:"bullet"` } type loadResponse struct { @@ -134,15 +136,40 @@ func Post(c echo.Context) error { } func Get(c echo.Context) error { - cTotal := make(chan ResultChan[int64]) + + id := c.Param("id") cResults := make(chan ResultChan[[]loadResponseResults]) + if id != "" { + go execResultsQuery(cResults, c) + results := <-cResults + + if results.Err != nil { + return results.Err + } + + if len(results.Result) == 0 { + return handlers.NotFound(c, "load not found") + } + + return c.JSON(http.StatusOK, handlers.Response[loadResponseResults]{Status: http.StatusText(http.StatusOK), Payload: results.Result[0]}) + } + + cTotal := make(chan ResultChan[int64]) + go func(ch chan ResultChan[int64]) { db := database.GetNewDatabase() - defer db.Db.Close(context.Background()) + defer func(Db *pgx.Conn, ctx context.Context) { + _ = Db.Close(ctx) + }(db.Db, context.Background()) q := getQuery(c, true) + if q == nil { + ch <- ResultChan[int64]{Result: 0} + return + } + sql, params := q.Sql() var total int64 @@ -157,101 +184,7 @@ func Get(c echo.Context) error { } }(cTotal) - - go func(ch chan ResultChan[[]loadResponseResults]) { - db := database.GetNewDatabase() - - defer db.Db.Close(context.Background()) - - q := getQuery(c, false) - - fmt.Println(q.DebugSql()) - - sql, params := q.Sql() - rows, err := db.Db.Query(context.Background(), sql, params...) - - if err != nil { - ch <- ResultChan[[]loadResponseResults]{Err: err} - - return - } - - results := make([]loadResponseResults, 0) - for rows.Next() { - row := row{} - err = rows.Scan( - &row.ID, - &row.Col, - &row.PowderGr, - - &row.CartridgeID, - &row.CartridgeName, - &row.CartridgeMeta, - - &row.BulletID, - &row.BulletName, - &row.BulletDiameter, - &row.BulletWeight, - &row.BulletMeta, - &row.BulletManufacturerName, - &row.BulletManufacturerUrl, - - &row.PrimerID, - &row.PrimerName, - &row.PrimerMeta, - &row.PrimerManufacturerName, - &row.PrimerManufacturerUrl, - - &row.PowderID, - &row.PowderName, - &row.PowderMeta, - &row.PowderManufacturerName, - &row.PowderManufacturerUrl, - ) - - if err != nil { - ch <- ResultChan[[]loadResponseResults]{Err: err} - - return - } - - results = append(results, loadResponseResults{ - Id: row.ID.String(), - Cartridge: row.CartridgeName, - Col: row.Col, - Powder: handlers.Powder{ - Id: row.PowderID.String(), - Name: row.PowderName, - Meta: string(row.PowderMeta), - Manufacturer: handlers.Manufacturer{ - Name: row.PowderManufacturerName, - Url: row.PowderManufacturerUrl.String, - }, - }, - PowderGr: row.PowderGr, - Primer: primers.PrimerResponse{ - ID: row.PrimerID.String(), - Name: row.PrimerName, - Manufacturer: handlers.Manufacturer{ - Name: row.PrimerManufacturerName, - Url: row.PrimerManufacturerUrl.String, - }, - }, - Bullet: bullets.BulletResponse{ - Id: row.BulletID.String(), - Name: row.BulletName, - Diameter: row.BulletDiameter, - Weight: row.BulletWeight, - Manufacturer: handlers.Manufacturer{ - Name: row.BulletManufacturerName, - Url: row.BulletManufacturerUrl.String, - }, - }, - }) - } - - ch <- ResultChan[[]loadResponseResults]{Result: results} - }(cResults) + go execResultsQuery(cResults, c) total := <-cTotal if total.Err != nil { @@ -266,6 +199,108 @@ func Get(c echo.Context) error { return c.JSON(http.StatusOK, handlers.Response[loadResponse]{Status: http.StatusText(http.StatusOK), Payload: loadResponse{Total: int(total.Result), Results: results.Result}}) } +func execResultsQuery(ch chan ResultChan[[]loadResponseResults], c echo.Context) { + db := database.GetNewDatabase() + + defer func(Db *pgx.Conn, ctx context.Context) { + _ = Db.Close(ctx) + }(db.Db, context.Background()) + + q := getQuery(c, false) + + if q == nil { + ch <- ResultChan[[]loadResponseResults]{Result: []loadResponseResults{}} + return + } + + fmt.Println(q.DebugSql()) + + sql, params := q.Sql() + rows, err := db.Db.Query(context.Background(), sql, params...) + + if err != nil { + ch <- ResultChan[[]loadResponseResults]{Err: err} + return + } + + results := make([]loadResponseResults, 0) + for rows.Next() { + row := row{} + err = rows.Scan( + &row.ID, + &row.Col, + &row.PowderGr, + + &row.CartridgeID, + &row.CartridgeName, + &row.CartridgeMeta, + + &row.BulletID, + &row.BulletName, + &row.BulletDiameter, + &row.BulletWeight, + &row.BulletMeta, + &row.BulletManufacturerName, + &row.BulletManufacturerUrl, + + &row.PrimerID, + &row.PrimerName, + &row.PrimerMeta, + &row.PrimerManufacturerName, + &row.PrimerManufacturerUrl, + + &row.PowderID, + &row.PowderName, + &row.PowderMeta, + &row.PowderManufacturerName, + &row.PowderManufacturerUrl, + ) + + if err != nil { + ch <- ResultChan[[]loadResponseResults]{Err: err} + + return + } + + results = append(results, loadResponseResults{ + Id: row.ID.String(), + Cartridge: row.CartridgeName, + CartridgeId: row.CartridgeID.String(), + Col: row.Col, + Powder: handlers.Powder{ + Id: row.PowderID.String(), + Name: row.PowderName, + Meta: string(row.PowderMeta), + Manufacturer: handlers.Manufacturer{ + Name: row.PowderManufacturerName, + Url: row.PowderManufacturerUrl.String, + }, + }, + PowderGr: row.PowderGr, + Primer: primers.PrimerResponse{ + ID: row.PrimerID.String(), + Name: row.PrimerName, + Manufacturer: handlers.Manufacturer{ + Name: row.PrimerManufacturerName, + Url: row.PrimerManufacturerUrl.String, + }, + }, + Bullet: bullets.BulletResponse{ + Id: row.BulletID.String(), + Name: row.BulletName, + Diameter: row.BulletDiameter, + Weight: row.BulletWeight, + Manufacturer: handlers.Manufacturer{ + Name: row.BulletManufacturerName, + Url: row.BulletManufacturerUrl.String, + }, + }, + }) + } + + ch <- ResultChan[[]loadResponseResults]{Result: results} +} + func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement { l := table.Loads.AS("l") ctg := table.Cartridges.AS("c") @@ -289,7 +324,6 @@ func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement { if countOnly { q = tb.SELECT(postgres.COUNT(l.ID).AS("total")) } else { - q = tb.SELECT( // Load l.ID.AS("id"), @@ -329,6 +363,17 @@ func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement { // where expressions expressions := make([]postgres.BoolExpression, 0) + if c.Param("id") != "" { + uuid, err := handlers.ParseUuid(c.Param("id")) + if err != nil { + return nil + } + + q = q.WHERE(l.ID.EQ(postgres.UUID(uuid))) + + return q + } + if c.QueryParam("cartridge_id") != "" { ids := strings.Split(c.QueryParam("cartridge_id"), ",") if len(ids) > 0 { @@ -438,13 +483,15 @@ func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement { if limit == "" { limit = "50" } - offset := c.QueryParam("offset") - if offset == "" { - offset = "0" + + pageInt := handlers.ParseInt64OrDefault(c.QueryParam("page"), 1) + if pageInt < 1 { + pageInt = 1 } + offset := (pageInt - 1) * handlers.ParseInt64OrDefault(limit, 50) q = q.LIMIT(handlers.ParseInt64OrDefault(limit, 50)). - OFFSET(handlers.ParseInt64OrDefault(offset, 0)) + OFFSET(offset) return q } diff --git a/backend/main.go b/backend/main.go index fd9a982..a1d8180 100644 --- a/backend/main.go +++ b/backend/main.go @@ -98,6 +98,7 @@ func main() { // loads e.GET("/load", loads.Get) + e.GET("/load/:id", loads.Get) e.POST("/load", loads.Post) addr := fmt.Sprintf("0.0.0.0:%s", Port.GetEnvString("8080")) diff --git a/frontend/src/components/FullScreenLoader.vue b/frontend/src/components/FullScreenLoader.vue new file mode 100644 index 0000000..3359ee8 --- /dev/null +++ b/frontend/src/components/FullScreenLoader.vue @@ -0,0 +1,49 @@ + + + \ No newline at end of file diff --git a/frontend/src/lib/icons.ts b/frontend/src/lib/icons.ts index 912210e..ec09d49 100644 --- a/frontend/src/lib/icons.ts +++ b/frontend/src/lib/icons.ts @@ -5,4 +5,5 @@ export const icons = { upload: 'fa-thin fa-sharp fa-upload', save: 'fa-thin fa-sharp fa-floppy-disk', delete: 'fa-thin fa-sharp fa-trash', + loading: 'fa-solid fa-sharp fa-cog fa-spin', } \ No newline at end of file diff --git a/frontend/src/pages/loads/Add.vue b/frontend/src/pages/loads/Add.vue index 1b0bd3e..abc0a8d 100644 --- a/frontend/src/pages/loads/Add.vue +++ b/frontend/src/pages/loads/Add.vue @@ -1,7 +1,8 @@ \ No newline at end of file diff --git a/frontend/src/pages/loads/Search.vue b/frontend/src/pages/loads/Search.vue index 0afb9ed..2780f8c 100644 --- a/frontend/src/pages/loads/Search.vue +++ b/frontend/src/pages/loads/Search.vue @@ -8,13 +8,15 @@ :value="loads" filterDisplay="row" paginator + :rowsPerPageOptions="[5, 10, 20, 50]" size="small" :sortField="sortField" :sortOrder="sortOrder" @update:sortField="(e: string) => {sortField = e; fetchLoads()}" @update:sortOrder="(e: number | undefined) => {sortOrder = e; fetchLoads()}" + @page="updatePagination" + :rows="rowsPerPage" lazy - :rows="50" :totalRecords="total" :loading="loading" > @@ -42,7 +44,9 @@ @change="fetchLoads" /> @@ -63,7 +67,9 @@ @change="fetchLoads" /> @@ -83,7 +89,9 @@ @change="fetchLoads" /> @@ -104,8 +112,13 @@ -